Solved

File Shell Operations

Posted on 2001-07-27
6
1,028 Views
Last Modified: 2007-12-19
Hi, I'm trying to use the
 
 SHFileOperation function (in unit ShellAPI).

What I want to accomplish is:
1) SHMoveFile(SourceFile, TargetFile: String): Boolean;

2) SHCopyFile(SourceFile, TargetFile: String): Boolean;

This is my current code:

-------- BEGIN CODE SNIPPET ------------

function SHOper(Operator: Cardinal; const SourceFile, TargetFile: String): Boolean;
var
 Info: TSHFileOpStruct;

begin
 with Info do begin
  Wnd := frmSort.Handle;
  wFunc := Operator;
  pFrom := PChar(SourceFile);
  pTo := PChar(TargetFile);
  fFlags := FOF_ALLOWUNDO;
 end;

 Result := (SHFileOperation(Info) = 0);
end;

function SHCopyFile(const SourceFile, TargetFile: string): Boolean;
begin
 Result := SHOper(FO_COPY, SourceFile, TargetFile);
end;

function SHMoveFile(const SourceFile, TargetFile: string): Boolean;
begin
 Result := SHOper(FO_MOVE, SourceFile, TargetFile);
end;

-------- END CODE SNIPPET ------------

And, it works SOMETIMES!?!? ...I get the error:
An error occured in the filesystem (error no 1026),
but ONLY on some files (it seems almost random??).

I don't have any faulty disks/filesystems; it's the
same on all machines i've tried; and I can copy
the file in Windows Explorer, which i assume use the
very same function.

The CopyFile(); and MoveFile(); of Windows unit seems
to work perfect, on ALL files. But I need the l33t
progressbar and so on..

So what am I doing wrong?

I simply call my procedures like:

SHCopyFile('c:\autoexec.bat', 'c:\files\autoexec.bat')

I know the destination directory already exist (i did a ForceDirectories before the call).

What might be wrong? Please help me :]
0
Comment
Question by:blasse
  • 3
  • 2
6 Comments
 
LVL 5

Expert Comment

by:scrapdog
Comment Utility
I don't know if this is what is causing your problem, but I noticed that you didn't clear the TSHFileOpStruct before you began populating it.  This means that the members of the structure you didn't assign (such as hNameMappings) will probably contain random garbage.

Do this:

FillChar(Info, sizeof(Info), 0);

before you start filling the Info structure.
0
 
LVL 5

Expert Comment

by:scrapdog
Comment Utility
function SHOper(Operator: Cardinal; const SourceFile, TargetFile: String): Boolean;
var
Info: TSHFileOpStruct;

begin
FillChar(Info, sizeof(Info), 0);
with Info do begin
 Wnd := frmSort.Handle;
 wFunc := Operator;
 pFrom := PChar(SourceFile);
 pTo := PChar(TargetFile);
 fFlags := FOF_ALLOWUNDO;
end;

0
 
LVL 1

Accepted Solution

by:
malsoft earned 80 total points
Comment Utility
Blasse,

The online help forgets to mention one vital piece of information! The filename(s) you pass into the ShellFile Operation are classed as a null separated list, terminating with a null character:

EG

For a single file this means a double null character:

SourceFile := 'Afile.txt'#0#0;

If you want to perform the operation on more than one file at once, this statement would follow this:

SourceFiles:= 'FirstFile.txt'#0'...'#0'LastFile.txt'#0#0

Taking that into account, I'd change your code to the following

-- Begin new code segment --

function SHOper(Operator: Cardinal; const SourceFile, TargetFile: String): Boolean;
var
Info: TSHFileOpStruct;
begin
  // Do a little initialisation first...
  FillChar(Info, sizeof(TSHFileOpStruct), 0);
  SourceFile := SourceFile + ''#0#0;
  TargetFile := TargetFile + ''#0#0;

  with Info do begin
    Wnd := frmSort.Handle;
    wFunc := Operator;
    pFrom := PChar(SourceFile);
    pTo := PChar(TargetFile);
    fFlags := FOF_ALLOWUNDO;
    end;
  Result := (SHFileOperation(Info) = 0);
end;

function SHCopyFile(const SourceFile, TargetFile: string): Boolean;
begin
  Result := SHOper(FO_COPY, SourceFile, TargetFile);
end;

function SHMoveFile(const SourceFile, TargetFile: string): Boolean;
begin
  Result := SHOper(FO_MOVE, SourceFile, TargetFile);
end;

-- End new code segment --

The reasoning behind it actually working sometimes, is that occasionally, the memory area in which the filenames are stored actually contain the proper double-null terminator.

Regards,
Mark Allott
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:blasse
Comment Utility
Hmm, they really should mention that in the Win32.hlp :]
0
 
LVL 5

Expert Comment

by:scrapdog
Comment Utility
I was wondering about that too...the Win32 Help DOES mention that, but in any Delphi example code (such as in the Delphi 4 Developer's Guide), it ignores this fact.
0
 
LVL 1

Expert Comment

by:malsoft
Comment Utility
To be honest, it's been a while since I looked at the latest Win32.hlp file for that function. You are correct, it does now state that the list is null-separated! When I first encountered the problem using Delphi 3, the help wasn't much use at all and MSDN didn't have the correct information either (that is now correct as well).
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
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 this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

772 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now