Embarcadero C++ Builder中DeleteFile()无法删除文件问题求助
解决Gnostice pdfToolkit Vcl签名后无法删除原PDF文件的问题
问题背景
在Embarcadero C++中使用Gnostice pdfToolkit Vcl对PDF文件进行数字签名后,无法删除未签名的原PDF文件,系统提示:
The process does not have access to the file because it is being used by another process.
原实现代码如下:
gtPDFDocumento->LoadFromFile("no_firmado.pdf"); gtPDFDocumento->AddSignature(firma_digital.pfx); gtPDFDocumento->SaveToFile("firmado.pdf"); //You have to reload the pdf because if it does not give an error gtPDFDocumento->LoadFromFile("firmado.pdf"); // if(!DeleteFile("no_firmado.pdf")){ int e = GetLastError(); AnsiString error = SysErrorMessage(e); ShowMessage(error); return; }
已尝试调用Reset()和FreeAndNil()释放资源,但问题依旧:
gtPDFDocument->LoadFromFile("not_signed.pdf"); gtPDFDocument->AddSignature(digital_signature.pfx); gtPDFDocument->SaveToFile("signed.pdf"); //You have to reload the pdf because if it does not give an error gtPDFDocument->LoadFromFile("signed.pdf"); // // Free Resources gtPDFDocument->Reset(); // Destroy PDF document object FreeAndNil(gtPDFDocument); // After this point gtPDFDocument can not be used unless reinitialized. if(!DeleteFile("not_signed.pdf")){ int e = GetLastError(); AnsiString error = SysErrorMessage(e); ShowMessage(error); return; }
解决方案
方案1:调整资源释放顺序,避免重复加载干扰
原代码中保存签名文件后立即加载新PDF,可能导致原文件句柄未被正确释放。修改为先释放原PDF资源,再尝试删除文件:
gtPDFDocumento->LoadFromFile("no_firmado.pdf"); gtPDFDocumento->AddSignature(firma_digital.pfx); gtPDFDocumento->SaveToFile("firmado.pdf"); // 先释放原PDF的资源,解除文件锁定 gtPDFDocumento->Reset(); // 尝试删除原文件 if(!DeleteFile("no_firmado.pdf")){ int e = GetLastError(); AnsiString error = SysErrorMessage(e); ShowMessage(error); return; } // 若后续需要操作签名后的PDF,再重新加载 gtPDFDocumento->LoadFromFile("firmado.pdf");
方案2:通过内存流加载原PDF,彻底释放文件句柄
如果方案1无效,可将原文件读取到内存流中加载,文件句柄会立即被释放,从根源避免文件锁定:
TFileStream* fs = new TFileStream("no_firmado.pdf", fmOpenRead | fmShareDenyNone); try { // 从内存流加载PDF,原文件句柄不会被长期占用 gtPDFDocumento->LoadFromStream(fs); } __finally { // 立即释放文件流,原文件不再被锁定 delete fs; } gtPDFDocumento->AddSignature(firma_digital.pfx); gtPDFDocumento->SaveToFile("firmado.pdf"); gtPDFDocumento->Reset(); // 此时可正常删除原文件 if(!DeleteFile("no_firmado.pdf")){ int e = GetLastError(); AnsiString error = SysErrorMessage(e); ShowMessage(error); return; }
方案说明
fmShareDenyNone参数确保加载文件时不限制其他进程对文件的访问,同时让我们的进程在释放流后可以立即删除文件。- 避免在释放原PDF资源前加载新的PDF,防止Gnostice内部资源管理冲突导致原文件句柄无法释放。
内容的提问来源于stack exchange,提问作者Fco. Javier Bermejo Cogolludo
相关产品推荐
相关产品推荐

