Archived Forum Post

Index of archived forum posts

Question:

Random access denied error while updating file inside zip containter

Oct 29 '15 at 14:17

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.


Answer

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.


Answer

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?


Answer

Did you remove Delete permission from the Temp path?


Answer

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

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