?
Solved

File Shell Operations

Posted on 2001-07-27
6
Medium Priority
?
1,047 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
[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
  • 3
  • 2
6 Comments
 
LVL 5

Expert Comment

by:scrapdog
ID: 6328252
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
ID: 6328263
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 320 total points
ID: 6329648
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

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

Expert Comment

by:scrapdog
ID: 6330494
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
ID: 6330937
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

Enroll in August's Course of the Month

August's CompTIA IT Fundamentals course includes 19 hours of basic computer principle modules and prepares you for the certification exam. It's free for Premium Members, Team Accounts, and Qualified Experts!

Question has a verified solution.

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

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
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…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses
Course of the Month13 days, 17 hours left to enroll

801 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