Solved

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

Posted on 2004-04-11
21
5,282 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
0
Comment
Question by:enumaelis
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
21 Comments
 
LVL 20

Expert Comment

by:Madshi
ID: 10801361
If Notepad can open the file, then CopyFile must work, too.
0
 
LVL 6

Expert Comment

by:Sergio_Hdez
ID: 10804120
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.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10804130
When using TFileStream you have to add fmShareDenyNone to the flags. But the CopyFile API should work just fine, as well.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:enumaelis
ID: 10812125

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 ?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10812158
(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!
0
 

Author Comment

by:enumaelis
ID: 10813875

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...


0
 
LVL 20

Expert Comment

by:Madshi
ID: 10814189
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.
0
 

Author Comment

by:enumaelis
ID: 10815033

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 !
0
 

Author Comment

by:enumaelis
ID: 10820995

Nobody can resolve my problem ?

I understand...

It's very very strange....

Ok bye...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10821388
I've just tried it with Outlook 2002. And you know what? CopyFile worked just fine - just as I said.
0
 

Author Comment

by:enumaelis
ID: 10821679
I've tried with outlook xp... I don't know if there is some differences...

When you have tried outlook was opened ?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10821811
Yes, Outlook was opened. Please try CopyFile again. If Notepad can read the file, CopyFile *MUST* work.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 10821814
Perhaps you had the parameters of CopyFile in the wrong order?
0
 

Author Comment

by:enumaelis
ID: 10821986

Nothing :-( :-(

0
 
LVL 20

Expert Comment

by:Madshi
ID: 10822028
How does your CopyFile code look like? Does CopyFile return true or false? If it returns false, what does GetLastError say?
0
 

Author Comment

by:enumaelis
ID: 10823150

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 :-)

0
 
LVL 3

Expert Comment

by:fibdev
ID: 10847323
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;
0
 

Accepted Solution

by:
hutelihut earned 125 total points
ID: 11136650
Maybe you can use this article:

http://www.delphicorner.f9.co.uk/articles/misc4.htm

Here are one of the examples from the page:

procedure CopyFile(const FileName, DestName: TFileName);
var
  CopyBuffer: Pointer; { buffer for copying }
  TimeStamp, BytesCopied: Longint;
  Source, Dest: Integer; { handles }
  Destination: TFileName; { holder for expanded destination name }
const
  ChunkSize: Longint = 8192; { copy in 8K chunks }
begin
  Destination := ExpandFileName(DestName); { expand the destination path }
  if HasAttr(Destination, faDirectory) then { if destination is a directory... }
    Destination := Destination + '\' + ExtractFileName(FileName); { ...clone file name }
  TimeStamp := FileAge(FileName); { get source's time stamp }
  GetMem(CopyBuffer, ChunkSize); { allocate the buffer }
  try
    Source := FileOpen(FileName, fmShareDenyWrite); { open source file }
    if Source < 0 then raise EFOpenError.Create(FmtLoadStr(SFOpenError, [FileName]));
    try
      Dest := FileCreate(Destination); { create output file; overwrite existing }
      if Dest < 0 then raise EFCreateError.Create(FmtLoadStr(SFCreateError, [Destination]));
      try
        repeat
          BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk }
          if BytesCopied > 0 then { if we read anything... }
            FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk }
        until BytesCopied < ChunkSize; { until we run out of chunks }
      finally
        FileClose(Dest); { close the destination file }
      end;
    finally
      FileClose(Source); { close the source file }
    end;
  finally
    FreeMem(CopyBuffer, ChunkSize); { free the buffer }
  end;
end;
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Working this component WebCopy with proxy, help 3 103
Magic Software info 18 144
SUM 2 INTEGER ARRAYS INTO 1 10 111
update joined tables 2 64
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question