Question:
From time to time I experience an issue where CkZip fail to update a file inside a zip container. The zip container in this scenario is always a Microsoft Word document (docx). I am attempting to replace the content of the internal file docProps/custom.xml using the CkZipEntry methods unzipToString and ReplaceString.
This mostly works flawlessly, but ever once in a while some users receive an error message and it tends to repeat several times. Mostly is goes away suddenly and I have a few theories of course. One is conflict with anti-virus software or similar. Another is related to the common use in Terminal Server/Citrix environment, but the big question is how to find out.
I do not have any results from the newest release of Chilkat 9.5.0.52 just yet, but unless significant changes have been made that relates to this issue, I do not believe that matters at all.
Here is a simplified version of the code that I use:
CkZip zip;
zip.UnlockComponent("...");
zip.put_TempDir("a directory in Windows user's temp dir");
zip.OpenZip("UNC path to the Word document");
unique_ptr<CkZipEntry> zipentry(zip.GetEntryByName("docProps/custom.xml"));
zipentry->put_Utf8(false);
auto strXml = zipentry->unzipToString(0, "utf-8");
...xml is modified...
zipentry->ReplaceString(strXml, "utf-8");
zip.SetCompressionLevel(9);
zip.WriteZipAndClose();
And more importantly here is the error message:
ChilkatLog:
WriteZipAndClose(78ms):
DllDate: Oct 1 2014
ChilkatVersion: 9.5.0.44
UnlockPrefix: XXX
Username: XXX:XXX
Architecture: Little Endian; 32-bit
Language: Visual C++ 12.0 (32-bit)
VerboseLogging: 1
targetZipPath: \\dkdsn400nt.intern\shares\Modules\Main Manual\checkout\CLC&F-Doc-5.1-8.1970.docx.T101615-112435.docx
openedZipPath: \\dkdsn400nt.intern\shares\Modules\Main Manual\checkout\CLC&F-Doc-5.1-8.1970.docx.T101615-112435.docx
File already exists at target zip path.
Will first write to temp file, then if successful,
will delete existing zip and move new zip into its place.
tempDir_ifNeeded: C:\Users\XXX\AppData\Local\Temp\29\XXX\1\Docx\
tempZipPath: C:\Users\XXX\AppData\Local\Temp\29\XXX\1\Docx\ckz_7BGA.tmp
writeZipToOutput(78ms):
oemCodePage: 850
encryption: 0
passwordProtected: 0
totalSize64: 5018528
numEntries: 34
mapped_writeLfhAndData:
lfh_location: 0
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 1149
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 1970
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData(62ms):
lfh_location: 2737
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 263383
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 263846
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 266308
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 266771
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 267268
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 267766
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 268011
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 270163
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 270626
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 271089
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 272844
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 273572
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 275162
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 276043
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 298195
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 298536
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 298856
Simple LFH rewrite...
--mapped_writeLfhAndData
data_writeLfhAndData:
pathUtf8_qp: docProps/custom.xml
Writing the local file header...
pathCodePage_qp: docProps/custom.xml
firstChunkNumBytes: 2863
End of data source.
Finalizing compressed output...
outputChunkSize: 506
outputComplete: 1
outputByteCount: 506
inputUncompressedSize: 2863
outputCompressedSize: 506
rewriteCompressedSize: 506
rewriteUncompressedSize: 2863
--data_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 300216
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 303154
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 307082
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 307600
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 307829
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 308655
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 311741
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 312039
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 312856
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 326482
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 340267
Simple LFH rewrite...
--mapped_writeLfhAndData
mapped_writeLfhAndData:
lfh_location: 340584
Simple LFH rewrite...
--mapped_writeLfhAndData
----------------------------
Writing central directory...
----------------------------
base_writeCentralDirEntry:
entryName: docProps/custom.xml
compressedSize: 0x1fa
uncompressedSize: 0xb2f
--base_writeCentralDirEntry
numCentralDirRecords: 34
Finished writing zip
--writeZipToOutput
moveFromTempZipToTarget:
Moving just-created temp zip to target...
tempZipPath: C:\Users\XXX\AppData\Local\Temp\29\XXX\1\Docx\ckz_7BGA.tmp
targetZipPath: \\dkdsn400nt.intern\shares\Modules\Main Manual\checkout\CLC&F-Doc-5.1-8.1970.docx.T101615-112435.docx
A file already exists at the target path. Deleting...
Already-existing target zip deleted.
Moving temp zip to target zip...
WindowsError: Access is denied.
WindowsErrorCode: 0x5
Failed to move temp zip to target.
Removing temp zip...
--moveFromTempZipToTarget
Failed.
--WriteZipAndClose
--ChilkatLog
As you can see, CkZip receives an "Access is denied" error from the Windows system while attempting to copy the temporary zip file to the final destination after successful deletion of the target zip.
Maybe there should be a short delay between the removal and the final move?
I could most likely work around this issue by loading the entire zip into memory, update it, delete the target zip from the file system, wait for a short while, then write the zip from memory to the target. Or something like that, but it seems wrong unless there is no other way. If the UNC location causes problems, I could also copy to the local Windows temp first, update it and then copy back to the UNC destination.
Just to verify the original file is deleted? If this is the case, then the temp file is locked and unable to be moved. This is would be caused by something like an anti-virus or on-demand backup software.
I would presume so, since that is what the ChilkatLog states, though I know that I do not know if I can truly trust that message. I have to admit that I have not checked, since this only happens remotely, where I do not easily have such access. I cannot provoke the error myself in my test environment.
In any case the big question is how to work around the issue. I feel lately that locked files have become a really annoying issue in Windows, but there have to be some solutions. After all, end users never get any error while saving an open Word document from within Microsoft Word. What I am trying here is essentially the same, but I suppose the way zip containers are updated happens differently that how Microsoft Word saves changes.
Reviewing my post makes me wonder why updating an entry within a zip container using CkZip is handled the way that it is. First of all; Why does create a temporary file? I would prefer one of two other ways to handle the files in question:
I want to avoid the process where the target zip is deleted before the new zip can be written. What if permissions on the file system permit creating new files, editing them, but not deleting any files? Is this scenario even supported?
Did you remove Delete permission from the Temp path?
I'd very much like to see a comment from Chilkat.
Matt: Can anything be done about this or is it intentional / common practice?