Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Access Violation using SendToRecycleBin

Posted on 1999-07-12
10
Medium Priority
?
462 Views
Last Modified: 2010-08-05
Here is an interesting one:

I use a SendToRecycleBin routine in one of my projects, the file comes from the Inprise FAQ. I made a slight modification to allow confirmation to be switched off. When running this in a project or unit of it's own it runs fine. Alas, once I call it from a certain unit, it gives me an Access Violation. I can even run it in a different unit in the project without a problem.

I am running Delphi 3.2.

The complete error message is:

*******************
Access violation at address 7FDC98CE in module ‘shell32.dll'. Read of address 5053542F.
*******************

Unfortunately I cannot paste the entire unit giving the error, since it exceeds 3800 lines, but I include the uses list.

*******************
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, IniFiles, jpeg, Serial3, ShellApi, Math, FMXUtils;
*******************
Here Serial3 is a shareware component to access the serial port.

Any ideas?

A unit that runs it successfully is:
*******************

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, ShellApi;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    BitBtn1: TBitBtn;
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}


procedure SendToRecycleBin(FileName: string; Confirm : Boolean);
// Sends the file Filename to the recycle bin. File taken from inprise FAQ
// In it's current form it only does one file at a time
var
   SHF: TSHFileOpStruct;
   P : String;
begin
   P := FileName + #0;   // Note without the zero characters, it doesn't see
                         // the end of the string;
   with SHF do begin
     Wnd := Application.Handle;
     wFunc := FO_DELETE;
     pFrom := PChar(P);
     fFlags := FOF_SILENT or FOF_ALLOWUNDO;
     if not Confirm then
       fFlags := fFlags or FOF_NOCONFIRMATION;
   end;
   SHFileOperation(SHF);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
     SendToRecycleBin(OpenDialog1.FileName,false);
end;

end.
*******************
0
Comment
Question by:bra033098
[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
  • 4
  • 2
  • 2
  • +1
10 Comments
 
LVL 17

Expert Comment

by:inthe
ID: 1387782
hi,
looks good to me???
try this one:

function  MoveFileToTrash(aFilename : String; aConfirmation : BOOLEAN) : BOOLEAN;
var alpFileOp : ^shFileOpStruct;
    lname : String;
begin
  getmem(alpfileop, sizeOf(shFileOPStruct));
  lname := afilename + #0+#0+#0;
  alpFileOp^.Wnd := 0;
  alpFileop^.wFunc := fo_Delete;
  alpFileOp^.pFrom := @lname[1];
  alpFileOp^.fflags := FOF_ALLOWUNDO;
  IF aConfirmation = FALSE then
  begin
    alpFileOP^.fflags := FOF_ALLOWUNDO + FOF_NoConfirmation;
  end;
  ShFileOperation(alpFileOp^);
  result := not alpFileOp^.fAnyOperationsAborted; // Abgebrochen oder nicht   freemem(alpfileop, sizeOf(shFileOPStruct));
end;


does that make any difference?
Regards Barry
0
 
LVL 15

Accepted Solution

by:
simonet earned 200 total points
ID: 1387783
Try this instead:

uses
   ShellApi;


function DeleteFileWithUndo(sFileName : string ) : boolean;
var
  fos : TSHFileOpStruct;
begin
  FillChar( fos, SizeOf( fos ), 0 );
  with fos do
  begin
    Wnd := application.handle;
    wFunc  := FO_DELETE;
    pFrom  := PChar( sFileName );
    fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT;
  end;
  Result := ( 0 = ShFileOperation( fos ) );
end;

Yours,

Alex
Athena's Place: http://www.bhnet.com.br/~simonet

0
 
LVL 17

Expert Comment

by:inthe
ID: 1387784
what timing ;-)
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!

 
LVL 13

Expert Comment

by:Epsylon
ID: 1387785
No no guys, this is the one   :o)


procedure SendToRecycleBin(FileName: string; Confirm : Boolean);
var
   SHF: TSHFileOpStruct;
   P : array[0..MAX_PATH] of Char;
begin
   StrPCopy(P, FileName);
   with SHF do begin
     Wnd := Application.Handle;
     wFunc := FO_DELETE;
     pFrom := P;
     fFlags := FOF_SILENT or FOF_ALLOWUNDO;
     if not Confirm then
       fFlags := fFlags or FOF_NOCONFIRMATION;
   end;
   SHFileOperation(SHF);
end;

Epsylon.

0
 

Author Comment

by:bra033098
ID: 1387786
Simonet

OK, it works. But why????? The only difference between your routine and mine is that yours fill the entire space with zero's beforehand. I still do not know what caused the access violation and it worries me that it only happened under certain circumstances. Since our routines are so much alike, would that not mean that yours would again not work under other circumstances? Any ideas why I get the access violations?

InThe

I had to change a line or two in your code to get it to compile, that is:
var alpFileOp : ^shFileOpStruct;
to
var alpFileOp : ^TshFileOpStruct;

and

 getmem(alpfileop, sizeOf(shFileOPStruct))
to
 getmem(alpfileop, sizeOf(TshFileOPStruct))

Unfortunately it gives the same violation.



Epsylon

Only saw your answer now when I came online again. Will try it later. But does anybody have an idea WHY?

bra
0
 

Author Comment

by:bra033098
ID: 1387787
Simonet

OK, it works. But why????? The only difference between your routine and mine is that yours fill the entire space with zero's beforehand. I still do not know what caused the access violation and it worries me that it only happened under certain circumstances. Since our routines are so much alike, would that not mean that yours would again not work under other circumstances? Any ideas why I get the access violations?

InThe

I had to change a line or two in your code to get it to compile, that is:
var alpFileOp : ^shFileOpStruct;
to
var alpFileOp : ^TshFileOpStruct;

and

 getmem(alpfileop, sizeOf(shFileOPStruct))
to
 getmem(alpfileop, sizeOf(TshFileOPStruct))

Unfortunately it gives the same violation.



Epsylon

Only saw your answer now when I came online again. Will try it later. But does anybody have an idea WHY?

bra
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1387788
The way you add a #0 to the sting is not valid.
0
 

Author Comment

by:bra033098
ID: 1387789
Epsylon

Also works fine.

bra
0
 
LVL 15

Expert Comment

by:simonet
ID: 1387790
That's right. You cannot simply add #0's to the string. It doesn't work that way in Delphi, unless you're using an array of chars.

The important thing is that it's working. As I took the procedure right out of a program I have, it doesn't have the confirmation parameter your function has. You can easily change the one I sent you with to have that feature. Here's the modified code:

function DeleteFileWithUndo(sFileName : string; Confirm : boolean ) : boolean;
var
  fos : TSHFileOpStruct;
begin
  FillChar( fos, SizeOf( fos ), 0 );
  with fos do
  begin
    Wnd := application.handle;
    wFunc  := FO_DELETE;
    pFrom  := PChar( sFileName );
    fFlags := FOF_ALLOWUNDO or FOF_SILENT;
    if (not Confirm) then
        fFlags := fFlags or FOF_NOCONFIRMATION;
  end;
  Result := ( 0 = ShFileOperation( fos ) );
end;

I forgot to mention: The function above returns true if the operation was successful and falso otherwise. This way you can take the adequate measures if something went wrong.

Yours,

Alex
Athena's Place: http://www.bhnet.com.br/~simonet

0
 

Author Comment

by:bra033098
ID: 1387791
Mmm, interesting that the Inprise FAQ does not fill the string with zero's. See

http://www.borland.com/devsupport/delphi/qanda/FAQ2787D.html

Thanks all
0

Featured Post

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.

Question has a verified solution.

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

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 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…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
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

660 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