EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Zip an already opened file

Also by EldoS: CallbackRegistry
A component to monitor and control Windows registry access and create virtual registry keys.
#32668
Posted: 03/19/2015 13:56:33
by Eduardo Helminsky (Standard support level)
Joined: 08/20/2010
Posts: 102

I am trying to zip a file that is already opened by other user/process.

I am using TElZipWriter and receive an error message #103456 (indicating the file is already opened by other users). I am developing a backup routine that will run when users are using the files. I agree this is not a perfect solution but the changes were blocked during the backup.

Is there any property (in TElZipWriter) I can change to solve my problem ?
#32669
Posted: 03/19/2015 14:31:46
by Eugene Mayevski (EldoS Corp.)

You can feed TElZipWriter with streams instead of file names, which means that you can open the file for reading with the flags you need. However, if the file is opened in exclusive mode by the other process, standard CreateFile() WinAPI function (and all functions and methods that use it, including FileStream class and alike) won't work.

To bypass the limitations we offer RawDisk product ( https://www.eldos.com/rawdisk/ ). This is a driver-based solution that lets you open files not accessible with CreateFile because of their security settings or because they are exclusively opened by other applications.

RawDisk has its own CreateFile() method that returns a file handle. You can then create a FileStream() class instance with the given handle (THandleStream in VCL) and pass this stream to TElZipWriter.


Sincerely yours
Eugene Mayevski
#32670
Posted: 03/19/2015 15:15:46
by Eduardo Helminsky (Standard support level)
Joined: 08/20/2010
Posts: 102

Eugene Mayevski

Thanks for answer.

I will change the method to add files. So far I have changed the source code and replace ssmDenyWrite to ssNone in procedure DoCompressionStreamNeeded in SBArcZip unit. It solve the problem and I know the risk and consequences of that.

I know about exclusive rights that blocks the WinApi and I will check RawDisk sooned.
#32671
Posted: 03/19/2015 15:20:22
by Eduardo Helminsky (Standard support level)
Joined: 08/20/2010
Posts: 102

Eugene Mayevski

One more doubt about it:

To use stream should I use one stream for each file ? When I have to create/free the stream ?

F := TFileStream.Create('file',flags);
try
Zip.Add(F);
finally
F.Free;
end;
#32672
Posted: 03/19/2015 15:39:25
by Eugene Mayevski (EldoS Corp.)

The stream can be disposed only after the procedure of packing all data is complete. This is because TElZipWriter doesn't make a copy of the stream, neither it duplicates any handles. It just uses what you have passed (F in your case) directly and does *not* close the streams itself. So the best approach is to create a TList for opened streams and close all streams in the list after you have finished compressing the data.


Sincerely yours
Eugene Mayevski
#32680
Posted: 03/20/2015 05:32:49
by Eduardo Helminsky (Standard support level)
Joined: 08/20/2010
Posts: 102

Eugene Mayevski

The code below is working as expected. My doubt is if this way is correct.

F is an array of TFileStream

Code
     ZIP := TElZipWriter.Create(nil);
     try
        ZIP.CreateArchive;
        ZIP.OnProgress := ZipProgress;
        for nR := 0 to LTables.Items.Count-1 do begin
           if not LTables.Checked[nR] then begin
              continue;
           end;

           // Inclui o arquivo DAT
           cAux := LTables.Items[nR] + '.dat';
           SetLength(F,Length(F)+1);
           F[High(F)] := TFileStream.Create(SystemBackupDir + cAux,fmOpenRead + fmShareDenyNone);
           Zip.Add(F[High(F)],cAux);

           // Inclui o arquivo BLB (se existir)
           cAux := LTables.Items[nR] + '.blb';
           if FileExists(SystemBackupDir + cAux) then begin
              SetLength(F,Length(F)+1);
              F[High(F)] := TFileStream.Create(SystemBackupDir + cAux,fmOpenRead + fmShareDenyNone);
              Zip.Add(F[High(F)],cAux);
           end;

           // Inclui o arquivo IDX (se necessário)
           cAux := LTables.Items[nR] + '.idx';
           if IsIndices.Checked then begin
              SetLength(F,Length(F)+1);
              F[High(F)] := TFileStream.Create(SystemBackupDir + cAux,fmOpenRead + fmShareDenyNone);
              Zip.Add(F[High(F)],cAux);
           end;
        end;

        if Length(F) = 0 then begin
           HideWait;
           beep;
           atencao('O sistema NÃO obteve acesso às tabelas;;Verifique direitos de acesso e tente novamente');
           ZIP.Close;
           exit;
        end;

        try
           ZIP.Compress(cPak);
           ZIP.Close;
        finally
           for nR := 0 to High(F) do begin
              F[nR].Free;
           end;
           SetLength(F,0);
        end;
     finally
        ZIP.Free;
     end;
#32682
Posted: 03/20/2015 08:49:22
by Eugene Mayevski (EldoS Corp.)

I don't see any obvious problems with this code, though I prefer using FreeAndNil wherever possible (instead of ZIP.Free, for example) and I'd move that ZIP disposal above the code which disposes the streams. Just an extra check...

On a side note please use CODE button to mark the beginning and the end of the code block in your messages.


Sincerely yours
Eugene Mayevski
#32683
Posted: 03/20/2015 09:28:23
by Eduardo Helminsky (Standard support level)
Joined: 08/20/2010
Posts: 102

Eugene Mayevski

Thanks for the tips.

And next time I will use CODE when needed.
Also by EldoS: RawDisk
Access locked and protected files in Windows, read and write disks and partitions and more.

Reply

Statistics

Topic viewed 671 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!