Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

File Shell Operations

Posted on 2001-07-27
6
Medium Priority
?
1,052 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

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…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

610 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