From e3fff2ad66eecbafaf194097f0384920839c0720 Mon Sep 17 00:00:00 2001 From: company-desktop-computer Date: Wed, 21 Oct 2026 23:39:47 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20SAT=20=E4=B8=B4=E6=97=B6=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=94=AF=E4=B8=80=E5=8C=96=EF=BC=8C=E4=BF=AE=20DGJM.s?= =?UTF-8?q?at=20=E8=AF=BB=E5=8F=96=E8=B6=8A=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. AcDbX3dSolid::CreateFromSat 的 temp\temp.sat 改为 temp__<原子序号>.sat,用完 DeleteFile。原来固定名且从不删除, 两个 CAD 实例同时从 SAT 重建时会互相覆盖。 2. DGJM.sat 的读取统一改成「分配时补终止符 + 按实际读到的长度赋值」: new char[n] 之后直接赋给 CString 会把未初始化内存当字符串读到终止符, 现在 new char[n+1] + memset,再用 CString(pszTxt, nRead) 明确长度。 涉及 AcDbX3dSolid、AecDbEarthWormFitting、DGJMDlg、GJYXJMDlg、 JMDBDlg、JMSJDlg 共 6 处。 DGJM.sat 本身仍是固定文件名,写读双方靠它隐式传递,本次不改名。 --- .../Code2026/CoreLibrary/AcDbX3dSolid.cpp | 18 ++++++++++++++---- .../CoreLibrary/AecDbEarthWormFitting.cpp | 10 +++++++--- SourceCode/Code2026/EarthWormCmd/DGJMDlg.cpp | 10 +++++++--- SourceCode/Code2026/EarthWormCmd/GJYXJMDlg.cpp | 10 +++++++--- SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp | 10 +++++++--- SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp | 10 +++++++--- 6 files changed, 49 insertions(+), 19 deletions(-) diff --git a/SourceCode/Code2026/CoreLibrary/AcDbX3dSolid.cpp b/SourceCode/Code2026/CoreLibrary/AcDbX3dSolid.cpp index 615fd80..5b181d4 100644 --- a/SourceCode/Code2026/CoreLibrary/AcDbX3dSolid.cpp +++ b/SourceCode/Code2026/CoreLibrary/AcDbX3dSolid.cpp @@ -129,11 +129,15 @@ bool FormatScriptFromSection(CString& sScr,STSection* pSection) if (file.Open(sFullPath,CFile::modeRead)) { ULONGLONG dwFileLength = file.GetLength(); - char* pszTxt = new char[dwFileLength]; + int nLen = (int)dwFileLength; - file.Read(pszTxt,(UINT)dwFileLength); + // 补终止符并按实际读到的长度赋值,避免把未初始化内存当字符串读 + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); - sRegionScrp = pszTxt; + UINT nRead = file.Read(pszTxt, nLen); + + sRegionScrp = CString(pszTxt, (int)nRead); delete [] pszTxt; file.Close(); @@ -2900,7 +2904,11 @@ bool AcDbX3dSolid::CreateFromSat(LPCTSTR pszSatFile,double dUnitScale) //上一级目录 int nPos = sFullPath.ReverseFind(_T('\\')); CString sPath = sFullPath.Mid(0,nPos + 1); - sFullPath = sPath + _T("temp\\temp.sat"); + + // 每次用唯一文件名:多个 CAD 实例同时从 SAT 重建时不会互相覆盖 + static LONG s_nSatSeq = 0; + sFullPath.Format(_T("%stemp\\temp_%lu_%ld.sat"),(LPCTSTR)sPath + ,(unsigned long)::GetCurrentProcessId(),(long)::InterlockedIncrement(&s_nSatSeq)); CFile file; if (file.Open(sFullPath,CFile::modeCreate|CFile::modeWrite)) @@ -2912,6 +2920,8 @@ bool AcDbX3dSolid::CreateFromSat(LPCTSTR pszSatFile,double dUnitScale) AcDbVoidPtrArray arPtr; AcDbBody::acisIn(sFullPath,arPtr); + ::DeleteFile(sFullPath); + //按照体积从大到小排序 Sort3dSolidByVol(arPtr); diff --git a/SourceCode/Code2026/CoreLibrary/AecDbEarthWormFitting.cpp b/SourceCode/Code2026/CoreLibrary/AecDbEarthWormFitting.cpp index fb28f14..3ae20db 100644 --- a/SourceCode/Code2026/CoreLibrary/AecDbEarthWormFitting.cpp +++ b/SourceCode/Code2026/CoreLibrary/AecDbEarthWormFitting.cpp @@ -580,11 +580,15 @@ CString GetSectionScr(AcDbRegion* pReg) if (file.Open(sFullPath,CFile::modeRead)) { ULONGLONG dwFileLength = file.GetLength(); - char* pszTxt = new char[dwFileLength]; + int nLen = (int)dwFileLength; - file.Read(pszTxt,(UINT)dwFileLength); + // 补终止符并按实际读到的长度赋值,避免把未初始化内存当字符串读 + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); - sRegionScrp = pszTxt; + UINT nRead = file.Read(pszTxt, nLen); + + sRegionScrp = CString(pszTxt, (int)nRead); delete [] pszTxt; file.Close(); diff --git a/SourceCode/Code2026/EarthWormCmd/DGJMDlg.cpp b/SourceCode/Code2026/EarthWormCmd/DGJMDlg.cpp index 7f5e0b3..237efea 100644 --- a/SourceCode/Code2026/EarthWormCmd/DGJMDlg.cpp +++ b/SourceCode/Code2026/EarthWormCmd/DGJMDlg.cpp @@ -951,11 +951,15 @@ void CDGJMDlg::OnBnClickedBtaddtodb() if (file.Open(sFullPath,CFile::modeRead)) { ULONGLONG dwFileLength = file.GetLength(); - char* pszTxt = new char[dwFileLength]; + int nLen = (int)dwFileLength; - file.Read(pszTxt,dwFileLength); + // 补终止符并按实际读到的长度赋值,避免把未初始化内存当字符串读 + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); - sRegionScrp = pszTxt; + UINT nRead = file.Read(pszTxt, nLen); + + sRegionScrp = CString(pszTxt, (int)nRead); delete [] pszTxt; file.Close(); diff --git a/SourceCode/Code2026/EarthWormCmd/GJYXJMDlg.cpp b/SourceCode/Code2026/EarthWormCmd/GJYXJMDlg.cpp index 9dc4c40..e2f6004 100644 --- a/SourceCode/Code2026/EarthWormCmd/GJYXJMDlg.cpp +++ b/SourceCode/Code2026/EarthWormCmd/GJYXJMDlg.cpp @@ -9418,11 +9418,15 @@ bool FormatScriptFromSection(CString& sScr,STSection* pSection) if (file.Open(sFullPath,CFile::modeRead)) { ULONGLONG dwFileLength = file.GetLength(); - char* pszTxt = new char[dwFileLength]; + int nLen = (int)dwFileLength; - file.Read(pszTxt,dwFileLength); + // 补终止符并按实际读到的长度赋值,避免把未初始化内存当字符串读 + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); - sRegionScrp = pszTxt; + UINT nRead = file.Read(pszTxt, nLen); + + sRegionScrp = CString(pszTxt, (int)nRead); delete [] pszTxt; file.Close(); diff --git a/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp b/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp index 47b59ca..e504960 100644 --- a/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp @@ -186,11 +186,15 @@ void CJMDBDlg::OnBnClickedButton2() if (file.Open(sFullPath, CFile::modeRead)) { ULONGLONG dwFileLength = file.GetLength(); - char* pszTxt = new char[dwFileLength]; + int nLen = (int)dwFileLength; - file.Read(pszTxt, dwFileLength); + // 补终止符并按实际读到的长度赋值,避免把未初始化内存当字符串读 + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); - m_sRegScr = pszTxt; + UINT nRead = file.Read(pszTxt, nLen); + + m_sRegScr = CString(pszTxt, (int)nRead); DELETE_ARR_(pszTxt); file.Close(); diff --git a/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp b/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp index 93f196c..d6e8cb3 100644 --- a/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp @@ -152,11 +152,15 @@ void CJMSJDlg::OnBnClickedBtaddtodb() if (file.Open(sFullPath, CFile::modeRead)) { ULONGLONG dwFileLength = file.GetLength(); - char* pszTxt = new char[dwFileLength]; + int nLen = (int)dwFileLength; - file.Read(pszTxt, dwFileLength); + // 补终止符并按实际读到的长度赋值,避免把未初始化内存当字符串读 + char* pszTxt = new char[nLen + 1]; + ::memset(pszTxt, 0, nLen + 1); - sRegionScrp = pszTxt; + UINT nRead = file.Read(pszTxt, nLen); + + sRegionScrp = CString(pszTxt, (int)nRead); DELETE_ARR_(pszTxt); file.Close(); -- 2.54.0 From 8caea9e6bddc92a3e29deebb63d9af93ac86bcf6 Mon Sep 17 00:00:00 2001 From: company-desktop-computer Date: Thu, 22 Oct 2026 09:03:11 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=E6=B0=B4=E6=B1=A0=E6=88=AA=E9=9D=A2?= =?UTF-8?q?=E4=B8=AD=E8=BD=AC=E6=96=87=E4=BB=B6=20JMSJ.sat=20=E6=8C=89?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E9=9A=94=E7=A6=BB=EF=BC=8C=E8=A1=A5=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E6=96=87=E4=BB=B6=E5=91=BD=E5=90=8D=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JMDBDlg、JMSJDlg、HZQTDlg 共 7 处共用固定的 JMSJ.sat,两个 CAD 实例 同时运行时会互相覆盖,acisIn 可能读到另一个实例写的截面。 新增 Pool3dCmd/PoolSectionTemp.h 的 GetPoolSectionSatPath(),文件名改为 JMSJ_.sat。同一进程内所有调用点路径一致,acisOut 写、ShowLastSection 读的隐式链路不受影响;进程之间用 PID 隔离。顺带去掉无意义的 MakeLower。 同时新增 temp-file-naming.md,记录临时文件命名规则、全库现状,以及 DGJM.sat 已废弃、不再改造的结论。 --- SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp | 9 +-- SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp | 7 +- SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp | 11 ++-- .../Code2026/Pool3dCmd/PoolSectionTemp.h | 11 ++++ temp-file-naming.md | 65 +++++++++++++++++++ 5 files changed, 86 insertions(+), 17 deletions(-) create mode 100644 SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h create mode 100644 temp-file-naming.md diff --git a/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp b/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp index 98e2c3c..6219c97 100644 --- a/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp @@ -4,6 +4,7 @@ #include "JMSJDlg.h" #include "GLTKDlg.h" #include "KTSetting.h" +#include "PoolSectionTemp.h" DLLIMPEXP CString IDCreate(); @@ -270,9 +271,7 @@ void CHZQTDlg::OnBnClickedCheck1() CString sScr; if (dlg.GetCrossSectionScr(sScr)) { - CString sFullPath = FilePath::GetSysDir(); - sFullPath.MakeLower(); - sFullPath += _T("\\JMSJ.sat"); + CString sFullPath = GetPoolSectionSatPath(FilePath::GetSysDir()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) @@ -394,9 +393,7 @@ void CHZQTDlg::SetFromWall(AcDbObjectId& id) m_bUserDefSec = TRUE; pWall->GetSpecialtyData(AcDb::kForRead)->GetAt(KEY_SECTIONSCR,m_sRegScr); - CString sFullPath = FilePath::GetSysDir(); - sFullPath.MakeLower(); - sFullPath += _T("\\JMSJ.sat"); + CString sFullPath = GetPoolSectionSatPath(FilePath::GetSysDir()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) diff --git a/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp b/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp index e504960..07dea9b 100644 --- a/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp @@ -3,6 +3,7 @@ #include "JMDBDlg.h" #include "GLTKDlg.h" #include "CoreTools.h" +#include "PoolSectionTemp.h" IMPLEMENT_DYNAMIC(CJMDBDlg, CDialog) @@ -87,9 +88,7 @@ void CJMDBDlg::OnBnClickedButton1() CString sScr; if (dlg.GetCrossSectionScr(sScr)) { - CString sFullPath = FilePath::GetSysDir(); - sFullPath.MakeLower(); - sFullPath += _T("\\JMSJ.sat"); + CString sFullPath = GetPoolSectionSatPath(FilePath::GetSysDir()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) @@ -173,7 +172,7 @@ void CJMDBDlg::OnBnClickedButton2() if (m_pSectionReg != NULL && bSuccess) { - CString sFullPath = FilePath::getSystemTemporaryFolder() + _T("\\JMSJ.sat"); + CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); CString sRegionScrp = _T(""); CString sLine; diff --git a/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp b/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp index d6e8cb3..5795b75 100644 --- a/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "JMSJDlg.h" #include "CoreTools.h" +#include "PoolSectionTemp.h" #include "JUXCDlg.h" #include "GLTKDlg.h" #include "BYCDlg.h" @@ -78,9 +79,7 @@ BOOL CJMSJDlg::OnInitDialog() void CJMSJDlg::ShowLastSection() { //1.截面 - CString sFullPath = FilePath::getSystemTemporaryFolder(); - sFullPath.MakeLower(); - sFullPath += _T("\\JMSJ.sat"); + CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); AcDbVoidPtrArray arBodyPtrs; if ( Acad::eOk == AcDbBody::acisIn(sFullPath,arBodyPtrs) ) @@ -139,7 +138,7 @@ void CJMSJDlg::OnBnClickedBtaddtodb() UpdateData(TRUE); if (!m_curSection.pReg) return; - CString sFullPath = FilePath::getSystemTemporaryFolder() + _T("\\JMSJ.sat"); + CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); CString sRegionScrp = _T(""); CString sLine; @@ -425,9 +424,7 @@ void CJMSJDlg::OnBnClickedBtselfromdb() CString sScr,sScrT; if (dlg.GetCrossSectionScr(sScr)) { - CString sFullPath = FilePath::getSystemTemporaryFolder(); - sFullPath.MakeLower(); - sFullPath += _T("\\JMSJ.sat"); + CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) diff --git a/SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h b/SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h new file mode 100644 index 0000000..b4dc544 --- /dev/null +++ b/SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h @@ -0,0 +1,11 @@ +#pragma once + +// 水池截面 SAT 中转文件路径。 +// 同一个 CAD 进程内所有调用点返回同一路径;不同进程用 PID 区分, +// 避免两个实例同时写同一个 JMSJ.sat 互相覆盖。 +inline CString GetPoolSectionSatPath(LPCTSTR lpszDir) +{ + CString sPath; + sPath.Format(_T("%s\\JMSJ_%lu.sat"), lpszDir, (unsigned long)::GetCurrentProcessId()); + return sPath; +} diff --git a/temp-file-naming.md b/temp-file-naming.md new file mode 100644 index 0000000..5df2001 --- /dev/null +++ b/temp-file-naming.md @@ -0,0 +1,65 @@ +# 临时文件命名与多实例安全 + +> 记录全库临时文件(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__.sat` | 已符合,调用方负责删除 | +| `CoreLibrary/AcDbX3dSolid.cpp` `CreateFromSat` | `temp\temp.sat` | `temp__.sat` | 已修,用完删除 | +| `CoreLibrary/AecDbEwPipeBase.cpp` `RegionAcisoutDwgOutFields` | `Region_.dat` | `Region__.dat` | 已修;未入库实体无句柄时用序号 `N` | +| `Pool3dCmd/JMDBDlg.cpp` `JMSJDlg.cpp` `HZQTDlg.cpp` | `JMSJ.sat` | `JMSJ_.sat` | 已修,见下文 | +| `CoreCommand/KTEarthWormCmd.cpp` `CO_RGCSCmdFnc` | `Region_.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`:界面导出路径,多实例会冲突,暂未改。 -- 2.54.0 From 4e658a8ae950c2e04547a46d326bf28a773afa1a Mon Sep 17 00:00:00 2001 From: company-desktop-computer Date: Thu, 22 Oct 2026 10:06:51 +0800 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=E6=B0=B4=E6=B1=A0=E6=88=AA?= =?UTF-8?q?=E9=9D=A2=E4=B8=AD=E8=BD=AC=E6=96=87=E4=BB=B6=E6=94=B9=E7=94=A8?= =?UTF-8?q?=20CoreTools::getTempFilePath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除 Pool3dCmd/PoolSectionTemp.h,JMDBDlg、JMSJDlg、HZQTDlg 共 7 处 改为 CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), 目录)。 同时修 getTempFilePath 自身的问题: - 传了有效父目录时 sParentPath 没有赋值,会拼出 "\JMSJ_xxx.sat" - 父目录为空时仍对 pszParentPath 调 _taccess,参数可能是 NULL - return sPath(); 语法错误 - objId 用 %lu 格式化 Adesk::ULongPtr,64 位下会截断,改 %I64u temp-file-naming.md 同步改为介绍这个通用函数。 --- SourceCode/Code2026/CoreCommand/CoreTools.cpp | 42 +++++++++++++++++++ SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp | 6 +-- SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp | 5 +-- SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp | 7 ++-- .../Code2026/Pool3dCmd/PoolSectionTemp.h | 11 ----- SourceCode/Code2026/inc/CoreTools.h | 13 ++++++ temp-file-naming.md | 17 ++++---- 7 files changed, 71 insertions(+), 30 deletions(-) delete mode 100644 SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h diff --git a/SourceCode/Code2026/CoreCommand/CoreTools.cpp b/SourceCode/Code2026/CoreCommand/CoreTools.cpp index 6278f2d..fdc5d1a 100644 --- a/SourceCode/Code2026/CoreCommand/CoreTools.cpp +++ b/SourceCode/Code2026/CoreCommand/CoreTools.cpp @@ -6189,3 +6189,45 @@ extern "C" return pRegAll; } } + +CString CoreTools::getTempFilePath(LPCTSTR pszFileMainName + , LPCTSTR pszFileSuffix + , LPCTSTR pszParentPath + , const bool & bUsePID + , const AcDbObjectId & objId) +{ + CString sPath(_T("")), sTemp; + + if (!pszFileMainName || !pszFileSuffix) + return sPath; + + CString sParentPath(_T("")); + if (pszParentPath == NULL || _taccess(pszParentPath, 0x00) != 0x00) + sParentPath = FilePath::getSystemTemporaryFolder(); + else + sParentPath = pszParentPath; + + if (_taccess(sParentPath, 0x00) != 0x0) + return sPath; + + CString sFileName(pszFileMainName); + + if (bUsePID) + { + unsigned long pid = (unsigned long)::GetCurrentProcessId(); + sTemp.Format(_T("%lu"), pid); + sFileName += sTemp; + } + + if (objId.isValid()) + { + sTemp.Format(_T("%I64u"), (unsigned __int64)objId.asOldId()); + sFileName += sTemp; + } + + sFileName += pszFileSuffix; + + sPath = sParentPath + _T("\\") + sFileName; + + return sPath; +} diff --git a/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp b/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp index 6219c97..32fb4c8 100644 --- a/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/HZQTDlg.cpp @@ -4,7 +4,7 @@ #include "JMSJDlg.h" #include "GLTKDlg.h" #include "KTSetting.h" -#include "PoolSectionTemp.h" +#include "CoreTools.h" DLLIMPEXP CString IDCreate(); @@ -271,7 +271,7 @@ void CHZQTDlg::OnBnClickedCheck1() CString sScr; if (dlg.GetCrossSectionScr(sScr)) { - CString sFullPath = GetPoolSectionSatPath(FilePath::GetSysDir()); + CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), FilePath::GetSysDir()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) @@ -393,7 +393,7 @@ void CHZQTDlg::SetFromWall(AcDbObjectId& id) m_bUserDefSec = TRUE; pWall->GetSpecialtyData(AcDb::kForRead)->GetAt(KEY_SECTIONSCR,m_sRegScr); - CString sFullPath = GetPoolSectionSatPath(FilePath::GetSysDir()); + CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), FilePath::GetSysDir()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) diff --git a/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp b/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp index 07dea9b..d78e9ce 100644 --- a/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/JMDBDlg.cpp @@ -3,7 +3,6 @@ #include "JMDBDlg.h" #include "GLTKDlg.h" #include "CoreTools.h" -#include "PoolSectionTemp.h" IMPLEMENT_DYNAMIC(CJMDBDlg, CDialog) @@ -88,7 +87,7 @@ void CJMDBDlg::OnBnClickedButton1() CString sScr; if (dlg.GetCrossSectionScr(sScr)) { - CString sFullPath = GetPoolSectionSatPath(FilePath::GetSysDir()); + CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), FilePath::GetSysDir()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) @@ -172,7 +171,7 @@ void CJMDBDlg::OnBnClickedButton2() if (m_pSectionReg != NULL && bSuccess) { - CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); + CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), FilePath::getSystemTemporaryFolder()); CString sRegionScrp = _T(""); CString sLine; diff --git a/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp b/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp index 5795b75..744132f 100644 --- a/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp +++ b/SourceCode/Code2026/Pool3dCmd/JMSJDlg.cpp @@ -1,7 +1,6 @@ #include "stdafx.h" #include "JMSJDlg.h" #include "CoreTools.h" -#include "PoolSectionTemp.h" #include "JUXCDlg.h" #include "GLTKDlg.h" #include "BYCDlg.h" @@ -79,7 +78,7 @@ BOOL CJMSJDlg::OnInitDialog() void CJMSJDlg::ShowLastSection() { //1.截面 - CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); + CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), FilePath::getSystemTemporaryFolder()); AcDbVoidPtrArray arBodyPtrs; if ( Acad::eOk == AcDbBody::acisIn(sFullPath,arBodyPtrs) ) @@ -138,7 +137,7 @@ void CJMSJDlg::OnBnClickedBtaddtodb() UpdateData(TRUE); if (!m_curSection.pReg) return; - CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); + CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), FilePath::getSystemTemporaryFolder()); CString sRegionScrp = _T(""); CString sLine; @@ -424,7 +423,7 @@ void CJMSJDlg::OnBnClickedBtselfromdb() CString sScr,sScrT; if (dlg.GetCrossSectionScr(sScr)) { - CString sFullPath = GetPoolSectionSatPath(FilePath::getSystemTemporaryFolder()); + CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat"), FilePath::getSystemTemporaryFolder()); CStdioFile file; if (file.Open(sFullPath,CFile::modeCreate |CFile::modeWrite )) diff --git a/SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h b/SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h deleted file mode 100644 index b4dc544..0000000 --- a/SourceCode/Code2026/Pool3dCmd/PoolSectionTemp.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -// 水池截面 SAT 中转文件路径。 -// 同一个 CAD 进程内所有调用点返回同一路径;不同进程用 PID 区分, -// 避免两个实例同时写同一个 JMSJ.sat 互相覆盖。 -inline CString GetPoolSectionSatPath(LPCTSTR lpszDir) -{ - CString sPath; - sPath.Format(_T("%s\\JMSJ_%lu.sat"), lpszDir, (unsigned long)::GetCurrentProcessId()); - return sPath; -} diff --git a/SourceCode/Code2026/inc/CoreTools.h b/SourceCode/Code2026/inc/CoreTools.h index 8b7cf2f..7e4159a 100644 --- a/SourceCode/Code2026/inc/CoreTools.h +++ b/SourceCode/Code2026/inc/CoreTools.h @@ -485,5 +485,18 @@ public: // arInput 里面的曲线必须是同一平面内的,没有悬空边线 // 并且确实组成了一个或者多个闭合的轮廓 static AcDbPolyline* getOuterContour(const AcDbVoidPtrArray &arInput); + + // 获得一个临时文件路径 + // pszFileMainName 是文件名称的主体部分,不包含后缀名, 在后面根据 bUsePID 决定是否加上进程号 + // pszFileSuffix 是文件后缀名, 例如 ".txt" 或者 ".jpg" + // pszParentPath 是文件所在的父目录,如果为空,则使用系统临时目录 + // bUsePID 是否在文件名中加入进程号,避免同名冲突 + // objId 是实体id,如果不为空,则在文件名中加入实体id,避免同名冲突 + static CString getTempFilePath(LPCTSTR pszFileMainName + , LPCTSTR pszFileSuffix + , LPCTSTR pszParentPath = NULL + , const bool &bUsePID = true + , const AcDbObjectId &objId = AcDbObjectId::kNull + ); }; diff --git a/temp-file-naming.md b/temp-file-naming.md index 5df2001..c1e5d40 100644 --- a/temp-file-naming.md +++ b/temp-file-naming.md @@ -5,7 +5,7 @@ ## 规则 -1. 文件名必须带 `GetCurrentProcessId()`。同一进程内需要多次独立使用、彼此不能共享的,再加原子递增序号。 +1. 文件名必须带 `GetCurrentProcessId()`,直接用 `CoreTools::getTempFilePath()` 生成。同一进程内需要多次独立使用、彼此不能共享的,再加原子递增序号。 2. 用完即删(`::DeleteFile`)。写读双方跨函数隐式传递的文件除外,见下文 `JMSJ.sat`。 3. 路径统一用 `FilePath::getSystemTemporaryFolder()`,不要落到安装目录。 4. 从 DWG 里读回来的文件名不可信,必须只取纯文件名,拒绝 `..\`、盘符等路径成分。 @@ -45,20 +45,19 @@ 目录原本分两套:`JMDBDlg` / `JMSJDlg` 用 `FilePath::getSystemTemporaryFolder()`,`HZQTDlg` 用 `FilePath::GetSysDir()`(安装目录下的 `sys`)。两套互不相干,本次只加 PID 后缀,目录未动。 -统一走 `Pool3dCmd/PoolSectionTemp.h`: +统一走 `CoreTools::getTempFilePath()`(`CoreCommand/CoreTools.cpp`): ```cpp -inline CString GetPoolSectionSatPath(LPCTSTR lpszDir) -{ - CString sPath; - sPath.Format(_T("%s\\JMSJ_%lu.sat"), lpszDir, (unsigned long)::GetCurrentProcessId()); - return sPath; -} +CString sFullPath = CoreTools::getTempFilePath(_T("JMSJ_"), _T(".sat") + , FilePath::getSystemTemporaryFolder()); +// -> \JMSJ_.sat ``` +`getTempFilePath` 是通用工具:主名 + 可选进程号 + 可选实体 id + 后缀;父目录为空或不存在时落到系统临时目录。 + 同一进程内所有调用点返回同一路径,所以 `acisOut` 写完、`ShowLastSection` 再读这条隐式链路仍然成立;进程之间用 PID 隔离,两个 CAD 实例不会再互相覆盖。 -**已知取舍**:`CJMSJDlg::ShowLastSection` 在 `OnInitDialog` 里读这个文件,本意是恢复上一次用的截面。加 PID 后只能读到本进程内上一次写的,跨进程/跨会话恢复失效。这个能力原本也不可靠——temp 目录会被清理,多实例还会互相覆盖。如果确实需要跨会话记忆,应改存注册表、ini 或文档数据库,而不是靠临时文件。 +**已知取舍**:`CJMSJDlg::ShowLastSection` 在 `OnInitDialog` 里读这个文件,只用于对话框打开时显示上一个设计好的截面,不是功能数据。加 PID 后新进程读不到上个进程留下的截面,已确认可接受。 ## 待处理 -- 2.54.0