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 已废弃、不再改造的结论。
4.1 KiB
临时文件命名与多实例安全
记录全库临时文件(ACIS SAT、DWG 中转等)的命名规则、现状与遗留项。 最后更新:2026-10-22
规则
- 文件名必须带
GetCurrentProcessId()。同一进程内需要多次独立使用、彼此不能共享的,再加原子递增序号。 - 用完即删(
::DeleteFile)。写读双方跨函数隐式传递的文件除外,见下文JMSJ.sat。 - 路径统一用
FilePath::getSystemTemporaryFolder(),不要落到安装目录。 - 从 DWG 里读回来的文件名不可信,必须只取纯文件名,拒绝
..\、盘符等路径成分。 - 从文件读进缓冲区再当字符串用时:分配
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:
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:界面导出路径,多实例会冲突,暂未改。