Using the SHFILEOPSTRUCT structure

J

Just Me

Can anyone fix the code below?

I need to set pTo to NULL and pFrom to a fullfilepath followed by two NULLs
Below Filename is a string
With FileOperation

..wFunc = FO_DELETE

..pFrom = FileName??

..pTo = ??

..fFlags = FOF_ALLOWUNDO Or FOF_SIMPLEPROGRESS

End With



My guess for the structure:

Public Structure SHFILEOPSTRUCT

Public hwnd As IntPtr

Public wFunc As Integer

<VB.VBFixedString(MAX_PATH), MarshalAs(UnmanagedType.ByValTStr,
SizeConst:=MAX_PATH)> _

Public pFrom As String

<VB.VBFixedString(MAX_PATH), MarshalAs(UnmanagedType.ByValTStr,
SizeConst:=MAX_PATH)> _

Public pTo As String

Public fFlags As Short

Public fAnyOperationsAborted As Boolean

Public hNameMappings As IntPtr

Public lpszProgressTitle As String

End Structure
 
K

Ken Tucker [MVP]

Hi,

Here is the structure, dll declare, and sample code. It will allow
you to select a file to delete with an open file dialog and send it to the
recycle bin.

Structure SHFILEOPSTRUCT

Dim hwnd As Integer

Dim wFunc As Integer

Dim pFrom As String

Dim pTo As String

Dim fFlags As Short

Dim fAnyOperationsAborted As Integer

Dim hNameMappings As Integer

Dim lpszProgressTitle As String ' only used if FOF_SIMPLEPROGRESS

End Structure



<DllImport("shell32.dll", entrypoint:="SHFileOperationA", _

setlasterror:=True, CharSet:=CharSet.Auto, exactspelling:=True, _

CallingConvention:=CallingConvention.StdCall)> _

Public Shared Function SHFileOperation(ByRef lpFileOp As SHFILEOPSTRUCT) As
Integer

End Function



Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

If OpenFileDialog1.ShowDialog() = DialogResult.OK Then

Dim sh As New SHFILEOPSTRUCT

With sh

..wFunc = FO_DELETE

..pFrom = OpenFileDialog1.FileName

..fFlags = FOF_ALLOWUNDO Or FOF_SIMPLEPROGRESS

End With

If SHFileOperation(sh) <> 0 Then

MessageBox.Show("Error deleting file")

End If

End If

End Sub



Ken

-----------------------------

Can anyone fix the code below?

I need to set pTo to NULL and pFrom to a fullfilepath followed by two NULLs
Below Filename is a string
With FileOperation

..wFunc = FO_DELETE

..pFrom = FileName??

..pTo = ??

..fFlags = FOF_ALLOWUNDO Or FOF_SIMPLEPROGRESS

End With



My guess for the structure:

Public Structure SHFILEOPSTRUCT

Public hwnd As IntPtr

Public wFunc As Integer

<VB.VBFixedString(MAX_PATH), MarshalAs(UnmanagedType.ByValTStr,
SizeConst:=MAX_PATH)> _

Public pFrom As String

<VB.VBFixedString(MAX_PATH), MarshalAs(UnmanagedType.ByValTStr,
SizeConst:=MAX_PATH)> _

Public pTo As String

Public fFlags As Short

Public fAnyOperationsAborted As Boolean

Public hNameMappings As IntPtr

Public lpszProgressTitle As String

End Structure
 
H

Herfried K. Wagner [MVP]

Ken,

* "Ken Tucker said:
Here is the structure, dll declare, and sample code. It will allow
you to select a file to delete with an open file dialog and send it to the
recycle bin.

Structure SHFILEOPSTRUCT

Notice that this structure has byte-aligned members, so I would specify
'Pack:=1' in the attributes.
 
J

Just Me

I'm going to try this of course, but I'm surprised that no consideration
seems to be given to the fact that pFrom is supposed to be a string that is
terminated with an extra zero?
As I remember, it is a list of filenames separated by semicolons. Maybe this
takes the chance that the byte after the file name does not happen to be a
semicolon??

Also, is there some reason a C# declare of the function was given. I'll need
to convert to VB and hope there is no special reason it was given in C#

Also, I believe fAnyOperationsAborted is BOOL. why map to Integer instead
of Boolean?


Thanks very much
 
J

Just Me

Is it needed because of the "short"?


Structure SHFILEOPSTRUCT

Dim hwnd As Integer

Dim wFunc As Integer

Dim pFrom As String

Dim pTo As String

Dim fFlags As Short

Dim fAnyOperationsAborted As Integer

Dim hNameMappings As Integer

Dim lpszProgressTitle As String ' only used if FOF_SIMPLEPROGRESS

End Structure


Thanks
 
H

Herfried K. Wagner [MVP]

* " Just Me said:
Is it needed because of the "short"?

Yes. Use this instead:

\\\
<StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Auto)> _
Private Structure SHFILEOPSTRUCT
Public hWnd As IntPtr
Public wFunc As Integer
Public pFrom As String
Public pTo As String
Public fFlags As Short
Public fAnyOperationsAborted As Boolean
Public hNameMappings As IntPtr
Public lpszProgressTitle As String
End Structure
///
 
J

Just Me

Ken, I replied but inadvertingly put it in the wrong place. This is a copy.


I'm going to try this of course, but I'm surprised that no consideration
seems to be given to the fact that pFrom is supposed to be a string that is
terminated with an extra zero? As I remember, it is a list of filenames
separated by semicolons. Maybe this takes the chance that the byte after the
file name does not happen to be a semicolon??

Also, is there some reason a C# declare of the function was given. I'll need
to convert to VB and hope there is no special reason it was given in C#

Also, I believe fAnyOperationsAborted is BOOL. why map to Integer instead
of Boolean?


Thanks very much
 
J

Just Me

Ken, I replied twice but the note ends up under Herfried's note. Here's a
copy (revised).

I did try this of course, but I'm surprised that no consideration
seems to be given to the fact that pFrom is supposed to be a string that is
terminated with an extra zero? As I remember, it is a list of filenames
separated by semicolons. Maybe this takes the chance that the byte after the
file name does not happen to be a semicolon??


Thanks very much


Also, when I tried it I get "Cannot delete file: Cannot read from source
file or disk." error.

I've included the code below:




Imports System.Runtime.InteropServices



Public Class Form1

Inherits System.Windows.Forms.Form

Public Const FO_DELETE As Integer = &H3

Public Const FOF_ALLOWUNDO As Integer = &H40

Public Const FOF_SIMPLEPROGRESS As Integer = &H100



#Region " Windows Form Designer generated code "

Public Sub New()

MyBase.New()

'This call is required by the Windows Form Designer.

InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'Required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

Friend WithEvents Button1 As System.Windows.Forms.Button

Friend WithEvents OpenFileDialog1 As System.Windows.Forms.OpenFileDialog

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

Me.Button1 = New System.Windows.Forms.Button

Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog

Me.SuspendLayout()

'

'Button1

'

Me.Button1.Location = New System.Drawing.Point(128, 160)

Me.Button1.Name = "Button1"

Me.Button1.Size = New System.Drawing.Size(104, 40)

Me.Button1.TabIndex = 0

Me.Button1.Text = "Button1"

'

'Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

Me.ClientSize = New System.Drawing.Size(292, 266)

Me.Controls.Add(Me.Button1)

Me.Name = "Form1"

Me.Text = "Form1"

Me.ResumeLayout(False)

End Sub

#End Region

Structure SHFILEOPSTRUCT

Dim hwnd As Integer

Dim wFunc As Integer

Dim pFrom As String

Dim pTo As String

Dim fFlags As Short

Dim fAnyOperationsAborted As Integer

Dim hNameMappings As Integer

Dim lpszProgressTitle As String ' only used if FOF_SIMPLEPROGRESS

End Structure

<DllImport("shell32.dll", entrypoint:="SHFileOperationA", _

setlasterror:=True, CharSet:=CharSet.Auto, exactspelling:=True, _

CallingConvention:=CallingConvention.StdCall)> _

Public Shared Function SHFileOperation(ByRef lpFileOp As SHFILEOPSTRUCT) As
Integer

End Function

Private Sub Button1_Click1(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Button1.Click

If OpenFileDialog1.ShowDialog() = DialogResult.OK Then

Dim sh As New SHFILEOPSTRUCT

With sh

..wFunc = FO_DELETE

..pFrom = OpenFileDialog1.FileName

..fFlags = FOF_ALLOWUNDO Or FOF_SIMPLEPROGRESS

End With

If SHFileOperation(sh) <> 0 Then

MessageBox.Show("Error deleting file")

End If

End If

End Sub

End Class
 
J

Just Me

I wonder if you know the answer to the following:

I'm surprised that no consideration
seems to be given to the fact that pFrom is supposed to be a string that is
terminated with an extra zero?

As I remember, it is a list of filenames separated by semicolons.

Maybe this takes the chance that the byte after the file name does not
happen to be a semicolon??
 
K

Ken Tucker [MVP]

Hi,

The Structure should be public not private.

Ken
------------------
* " Just Me said:
Is it needed because of the "short"?

Yes. Use this instead:

\\\
<StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Auto)> _
Private Structure SHFILEOPSTRUCT
Public hWnd As IntPtr
Public wFunc As Integer
Public pFrom As String
Public pTo As String
Public fFlags As Short
Public fAnyOperationsAborted As Boolean
Public hNameMappings As IntPtr
Public lpszProgressTitle As String
End Structure
///
 
K

Ken Tucker [MVP]

Hi,

You can use dll import with vb.net as well as c# so I posted a
vb.net version of the api. As for pFrom it should end with chr(0) not 0.
That is added automatically.

Ken
---------------
I'm going to try this of course, but I'm surprised that no consideration
seems to be given to the fact that pFrom is supposed to be a string that is
terminated with an extra zero?
As I remember, it is a list of filenames separated by semicolons. Maybe this
takes the chance that the byte after the file name does not happen to be a
semicolon??

Also, is there some reason a C# declare of the function was given. I'll need
to convert to VB and hope there is no special reason it was given in C#

Also, I believe fAnyOperationsAborted is BOOL. why map to Integer instead
of Boolean?


Thanks very much
 
J

Just Me

Ken Tucker said:
Hi,

You can use dll import with vb.net as well as c# so I posted a
I figured that out as some as I ran your code and didn't get a build error.

vb.net version of the api. As for pFrom it should end with chr(0) not 0.
That is added automatically.
But the doc says there should be two NULLs at the end, not one.
It's how to get the extra zero that I wonder about.

The code I posted at 11:37 (really yours) always gives me an error when I
try to delete a file.

Thanks for all the answers
 
J

Just Me

To both MVP's,

"I fixed it. I'd appreciate comments on when it's OK to just use String in
a Structure and when Marshal must be used.


This is what I did to the structure:

<StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Auto)> _

Public Structure SHFILEOPSTRUCT

Public hWnd As IntPtr

Public wFunc As Integer

<MarshalAs(UnmanagedType.LPStr)> Public pFrom As String

<MarshalAs(UnmanagedType.LPStr)> Public pTo As String

'Public pFrom As String

'Public pTo As String

Public fFlags As Short

Public fAnyOperationsAborted As Boolean

Public hNameMappings As IntPtr

Public lpszProgressTitle As String

End Structure



I also had to add Chr(0) as follows:

..pFrom = OpenFileDialog1.FileName & Chr(0)

but that I understand.



Thansk for the help.
 
H

Herfried K. Wagner [MVP]

* " Just Me said:
I also had to add Chr(0) as follows:

.pFrom = OpenFileDialog1.FileName & Chr(0)

.... or 'ControlChars.NullChar', 'vbNullChar'.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top