login about faq

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.

asked Oct 16 '15 at 06:21

roan98dk's gravatar image

roan98dk
326192034


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.

link

answered Oct 16 '15 at 10:17

TracyP's gravatar image

TracyP
1062

I have added my comment to you as an answer.

(Oct 16 '15 at 15:21) roan98dk

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:

  1. Write to the final zip directly. I don't know if this is actually the default, but because I specify a temp directory in the code, that may be what is causing CkZip to write to the temporary file.
  2. Write the new zip in memory and then save it directly to the final zip in disk. I know this method cannot be default in any way, since that might cause problems writing very large zip containers. Even some Word documents could become quite large, but mostly this is not an issue for me or my customers. I will most likely use this method as a workaround is I can find no other stable method.

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?

link

answered Oct 16 '15 at 15:20

roan98dk's gravatar image

roan98dk
326192034

I want to add that I tried to remove Delete permission for the final destination directory in my test environment. Then I get the same error as the end user, but for obvious reasons. But by doing testing this way I can also confirm that the final zip gets deleted successfully under normal circumstances, because I get additional error messages from my own application if the delete also fails.

(Oct 16 '15 at 15:35) roan98dk

P.S. Though I now seem to have a possible workaround, I obviously cannot be certain that this will not cause other problems. Especially in restrictive Citrix environments where memory resources could be under tight control. Though as I mentioned I use this only for Word documents of mostly very limited size.

(Oct 16 '15 at 15:59) roan98dk

Did you remove Delete permission from the Temp path?

link

answered Oct 16 '15 at 15:43

TracyP's gravatar image

TracyP
1062

No, only from the final path. More importantly I ran a test where instead of using WriteZipAndClose() I used WriteToMemory(), CloseZip() and then wrote the CkByteData directly to the final zip file using CkFileAccess (I prefer that over the saveFile() method integrated in CkByteData). This works even if the Delete permission has been restricted on the final destination directory.

(Oct 16 '15 at 15:52) roan98dk

It works in your Delete scenario. Is it going to work in the other scenario where the original file is "locked" by another process causing the delete failure?

I was asking if you tested the Delete Permission in the temp path, to verify you get the same error message from both scenarios.

(Oct 16 '15 at 16:34) TracyP

I am not certain I understand your question/comment properly, but I am aware that my experiment with CkFileAccess for "updating" the original file w/o deleting it first, would also not work if the original file is locked for writing entirely. However that does not seem to be a problem in my case, so that is why I am focusing on the delete first/write new scenario as an issue.

(Oct 29 '15 at 14:15) roan98dk

I'd very much like to see a comment from Chilkat.

Matt: Can anything be done about this or is it intentional / common practice?

link

answered Oct 29 '15 at 14:17

roan98dk's gravatar image

roan98dk
326192034

Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or __italic__
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×20
×6
×3
×3
×2

Asked: Oct 16 '15 at 06:21

Seen: 627 times

Last updated: Oct 29 '15 at 14:17

powered by OSQA