We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Copy a File that is in use/locked by another program

enumaelis
enumaelis asked
on
Medium Priority
6,286 Views
Last Modified: 2007-12-19
Hi

I want to know if there is a method, with delphi, to copy a file that is in use/locked by another application: I can make some examples:

I've tried to copy some types of locked files, like:

1. A Microsoft Access .mdb file opened by access with exclusive access

2. Some .aspx, .dll files of an opened Visual Studio.net solution

3. The Outlook.pst file while Microsoft Outlook is opened


I've tried with the following methods:

1. Using Windows API function (ShellOp)

2. Using CopyFile e CopyFileW functions

3. Using FileStream, MemoryStream, FileBlock, FileSeek Methods

4. Using Assign File Method


None of theese methods has worked with the Outlook.pst file.

The windows API funtion works for all, but not for Outlook.pst, but has a very bad issue: it prompts the user if there is an error or a overwrite conflict (also if I've set the right flags for NO ERROR UI and NO PROMPTS/NI CONFIRMATION).

The only method for copy the Outlook.pst file is to open it with the notepad (it works !) and then save the file to another location (!?). So copy that file is possible! How with delphi ? (I can accept also a c++ solution, i could make an external .dll)

Thanks
Comment
Watch Question

Commented:
If Notepad can open the file, then CopyFile must work, too.
Have you opened with a TFileStream.create with the ReadOnly falg to copy it fo another Stream?

Something like this (may not compile at first, not tested in delphi):

F2:= TMemoryStream.Create;
F1:= TFileStream.Create( OldFileName,  fmReadOnly );
F2.CopyFrom(F1, 0);
F1.free;
F2.SaveToFile(NewFileName);
F2.free;

If notepad opens it, it has to be done like this or similar.

Commented:
When using TFileStream you have to add fmShareDenyNone to the flags. But the CopyFile API should work just fine, as well.

Author

Commented:

Does not function... :-)

Here the code of my function:

function CopyFileWithFileStream(sourcefilename, targetfilename: String ): boolean;
Var
  S: TFileStream;
  T: TMemoryStream;
  bReturn:Boolean;
Begin
bReturn:=False;

  try
   //With fmShareDenyNone I don't have the open error (so ok Madshi)
    S := TFileStream.Create( sourcefilename, fmOpenRead or fmShareDenyNone );
  except
    Result :=False;
    Exit;
  end;

  try
  //The following row cause an Stream Read Error
  T.CopyFrom(S, 0);
  S.free;
  T.SaveToFile(targetfilename);
  T.free;

  //The following row raise an exception EFopenError
  //T := TFileStream.Create( targetfilename , fmOpenWrite or fmCreate );
  except
    Result :=False;
    Exit;
  end;

[..............]


Any idea ?

Commented:
(1) When calling T.CopyFrom you have not yet created a T instance.
(2) Use either fmOpenWrite or fmCreate, but not both.

Why are not using CopyFile? Would be much easier!

Author

Commented:

I have fixed the function, but the problem is the same:


function CopyFileWithFileStream(sourcefilename, targetfilename: String ): boolean;
Var
  S: TFileStream;
  T: TMemoryStream;
  bReturn:Boolean;
Begin
bReturn:=False;

  try
    S := TFileStream.Create( sourcefilename, fmOpenRead or fmShareDenyNone);
  except
    Result :=False;
    Exit;
  end;

  try
    showmessage(IntToStr(s.Size));        //This return the exact size (!)
    T := TMemoryStream.Create();
    T.CopyFrom(S, 0);                            //This raise an exception
    S.free;
    T.SaveToFile(targetfilename);
    T.free;
  except
    Result :=False;
    Exit;
  end;

Result:=bReturn;

End;


I cannot use CopyFile: this function doesn't work with locked files...


Commented:
If CopyFile doesn't work, then Notepad can't open it, either. And then your stream stuff won't work, either. It's all the same.

Author

Commented:

Also you can try simply this:

Open Outlook

Try to copy the file outlook.pst with copyfile function or stream functions: you'll have an error in any case.

Try, with windows right click menu, to do "Open With..." and then select Notepad: the notepad opens the file ! And you can save the file with another name !

Author

Commented:

Nobody can resolve my problem ?

I understand...

It's very very strange....

Ok bye...

Commented:
I've just tried it with Outlook 2002. And you know what? CopyFile worked just fine - just as I said.

Author

Commented:
I've tried with outlook xp... I don't know if there is some differences...

When you have tried outlook was opened ?

Commented:
Yes, Outlook was opened. Please try CopyFile again. If Notepad can read the file, CopyFile *MUST* work.

Commented:
Perhaps you had the parameters of CopyFile in the wrong order?

Author

Commented:

Nothing :-( :-(

Commented:
How does your CopyFile code look like? Does CopyFile return true or false? If it returns false, what does GetLastError say?

Author

Commented:

CopyFile(PChar(sSourceFile), PChar(sDestFile), False)

The function return false. No exception is raised.

GetLastError return that the file is in use or locked by another process, or a similar message...

If it can interest, my operating system is Win 2000 Professional SP4 with NTFS filesystem.

And i have seen another thing: also if the notepad can open the file and save it to a new file, the new file result "corrupted": outlook don't recognize it anymore...

I'm beginning to think that this thing is not possible...

I would that anyone give me a portion of code that functions with every file.
I ask too much, that's right? :-)  :-)

Thanks in any case for your patience. :-)

P.S. : and sorry for my bad english :-)

Commented:
I haven't read this whole thread, but have you tried setting the file attributes before you copy the file?

procedure TForm1.DoCopy(Source, Dest: string);
var
  SrcFile : Integer;
  DestFile : Integer;
  S : string;
  RetCode : Longint;
  OpenFileBuf   : TOFStruct;
  FName : array[ 0..255 ] of Char;
begin
FileSetAttr(Source, not SysUtils.faReadOnly);  
StrPCopy( FName, Source );
  SrcFile := LZOpenFile( FName, OpenFileBuf, of_Read );
  StrPCopy( FName, Dest );
  DestFile := LZOpenFile( FName, OpenFileBuf, of_Create );

  RetCode := LZCopy( SrcFile, DestFile );
  if RetCode >= 0 then
  begin
    LZClose( SrcFile );
    LZClose( DestFile );
  end
  else
  begin
    Str( RetCode, S );
    MessageDlg( 'Could not copy ' + Source + ' to ' +
                Dest + #13 + 'Error Code = ' + S, mtError, [mbOk], 0 );
  end;
end;
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.