Files
envi-code/temp-file-naming.md
T
company-desktop-computer 8caea9e6bd fix: 水池截面中转文件 JMSJ.sat 按进程隔离,补临时文件命名文档
JMDBDlg、JMSJDlg、HZQTDlg 共 7 处共用固定的 JMSJ.sat,两个 CAD 实例
同时运行时会互相覆盖,acisIn 可能读到另一个实例写的截面。

新增 Pool3dCmd/PoolSectionTemp.h 的 GetPoolSectionSatPath(),文件名改为
JMSJ_<pid>.sat。同一进程内所有调用点路径一致,acisOut 写、ShowLastSection
读的隐式链路不受影响;进程之间用 PID 隔离。顺带去掉无意义的 MakeLower。

同时新增 temp-file-naming.md,记录临时文件命名规则、全库现状,以及
DGJM.sat 已废弃、不再改造的结论。
2026-10-22 09:03:11 +08:00

66 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 临时文件命名与多实例安全
> 记录全库临时文件(ACIS SAT、DWG 中转等)的命名规则、现状与遗留项。
> 最后更新:2026-10-22
## 规则
1. 文件名必须带 `GetCurrentProcessId()`。同一进程内需要多次独立使用、彼此不能共享的,再加原子递增序号。
2. 用完即删(`::DeleteFile`)。写读双方跨函数隐式传递的文件除外,见下文 `JMSJ.sat`。
3. 路径统一用 `FilePath::getSystemTemporaryFolder()`,不要落到安装目录。
4. 从 DWG 里读回来的文件名不可信,必须只取纯文件名,拒绝 `..\`、盘符等路径成分。
5. 从文件读进缓冲区再当字符串用时:分配 `nLen + 1`、清零,按 `Read` 实际返回的长度构造 `CString`,不要直接 `CString = pszTxt`。
## 现状
| 位置 | 改前 | 改后 | 状态 |
| --- | --- | --- | --- |
| `CoreCommand/CoreTools.cpp` `MakeTempSatPath` | — | `x3d_<pid>_<seq>.sat` | 已符合,调用方负责删除 |
| `CoreLibrary/AcDbX3dSolid.cpp` `CreateFromSat` | `temp\temp.sat` | `temp_<pid>_<seq>.sat` | 已修,用完删除 |
| `CoreLibrary/AecDbEwPipeBase.cpp` `RegionAcisoutDwgOutFields` | `Region_<handle>.dat` | `Region_<pid>_<tag>.dat` | 已修;未入库实体无句柄时用序号 `N<n>` |
| `Pool3dCmd/JMDBDlg.cpp` `JMSJDlg.cpp` `HZQTDlg.cpp` | `JMSJ.sat` | `JMSJ_<pid>.sat` | 已修,见下文 |
| `CoreCommand/KTEarthWormCmd.cpp` `CO_RGCSCmdFnc` | `Region_<handle>.dat` | 未改 | 测试命令,不在产品链路,暂不处理 |
| `DGJM.sat` 20 处 | `DGJM.sat` | 未改 | 代码已废弃,见下文 |
| `PipelineCmd` `temp_$_$_.equ`、`tmp_dwg_$$%d.dwg` | 固定名 | 未改 | 界面导出路径,多实例会冲突,低优先级 |
## DGJM.sat:废弃代码,不再处理
分布:`AcDbX3dSolid.cpp`(2)、`AecDbEarthWormFitting.cpp`(2)、`AcDbX3dGroup.cpp`(3)、`EarthWormCmd/*`(13)。
这是写方 `acisOut` 和读方 `acisIn` 之间的隐式约定:A 函数把 region 写到固定文件,B 函数再从同一个文件读回来。加 PID 或序号会让读方找不到文件,必须先把接口改成「写方返回路径、读方接收路径」才能动。
该链路已整体废弃,**文件名保持原样,不再改造**。只在 PR #31 中修了读取越界:`new char[n]` 后直接赋给 `CString` 会把堆里的随机字节当字符串读,现改为 `new char[n+1]` + 清零 + 按实际长度构造。涉及 `AcDbX3dSolid`、`AecDbEarthWormFitting`、`DGJMDlg`、`GJYXJMDlg`、`JMDBDlg`、`JMSJDlg` 共 6 处。
若将来这段代码被复用,先改接口,再按本文规则命名。
## JMSJ.sat:水池截面中转
7 处,分布在 3 个文件:
| 文件 | 用途 |
| --- | --- |
| `JMDBDlg.cpp` | 从标准库选截面(写)→ `acisIn`;`acisOut` 导出截面字符串(读) |
| `JMSJDlg.cpp` | `ShowLastSection` 读上次截面;入库时 `acisOut` 导出;从标准库选截面(写)→ `acisIn` |
| `HZQTDlg.cpp` | 从标准库选截面(写)→ `acisIn`,两处 |
目录原本分两套:`JMDBDlg` / `JMSJDlg` 用 `FilePath::getSystemTemporaryFolder()`,`HZQTDlg` 用 `FilePath::GetSysDir()`(安装目录下的 `sys`)。两套互不相干,本次只加 PID 后缀,目录未动。
统一走 `Pool3dCmd/PoolSectionTemp.h`:
```cpp
inline CString GetPoolSectionSatPath(LPCTSTR lpszDir)
{
CString sPath;
sPath.Format(_T("%s\\JMSJ_%lu.sat"), lpszDir, (unsigned long)::GetCurrentProcessId());
return sPath;
}
```
同一进程内所有调用点返回同一路径,所以 `acisOut` 写完、`ShowLastSection` 再读这条隐式链路仍然成立;进程之间用 PID 隔离,两个 CAD 实例不会再互相覆盖。
**已知取舍**:`CJMSJDlg::ShowLastSection` 在 `OnInitDialog` 里读这个文件,本意是恢复上一次用的截面。加 PID 后只能读到本进程内上一次写的,跨进程/跨会话恢复失效。这个能力原本也不可靠——temp 目录会被清理,多实例还会互相覆盖。如果确实需要跨会话记忆,应改存注册表、ini 或文档数据库,而不是靠临时文件。
## 待处理
- `PipelineCmd` 的 `temp_$_$_.equ`、`tmp_dwg_$$%d.dwg`:界面导出路径,多实例会冲突,暂未改。