Solved

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

Posted on 2004-04-11
21
5,216 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
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
Back Up Your Microsoft Windows Server®

Back up all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

 

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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

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

Suggested Solutions

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…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

803 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