2015-10-28 41 views
0

我正在使用IFileOperation(Windows shell)API批量複製/刪除文件。到目前爲止都很好。但是,將文件複製/移動到尚不存在的目標位置會稍微複雜一點 - 您需要使用IFileSystemBindData接口爲目標創建一個shell項目。它可以間歇性地工作。其他時候,它會在IfileOperation.MoveItem方法中引發異常。IFileSystemBindData實現不完全工作

歡迎任何意見。

注:

接口:

Namespace Shell 
<ComImport> _ 
<Guid("01E18D10-4D8B-11d2-855D-006008059367")> _ 
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _ 
Public Interface IFileSystemBindData 
    Function GetFindData(ByRef wfd As WIN32_FIND_DATA) As UInteger 
    Function SetFindData(ByRef wfd As WIN32_FIND_DATA) As UInteger 
End Interface 

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ 
Public Structure WIN32_FIND_DATA 
    Public dwFileAttributes As UInteger 
    Public ftCreationTime As System.Runtime.InteropServices.ComTypes.FILETIME 
    Public ftLastAccessTime As System.Runtime.InteropServices.ComTypes.FILETIME 
    Public ftLastWriteTime As System.Runtime.InteropServices.ComTypes.FILETIME 
    Public nFileSizeHigh As UInteger 
    Public nFileSizeLow As UInteger 
    Public dwReserved0 As UInteger 
    Public dwReserved1 As UInteger 
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> Public cFileName As String 
    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> Public cAlternateFileName As String 
End Structure 
End Namespace 

實現:

Namespace Shell 
Public Class FileSystemBindData 
    Implements IFileSystemBindData 

Dim wf As WIN32_FIND_DATA 

    Public Function GetFindData(ByRef pfd As WIN32_FIND_DATA) As UInteger Implements IFileSystemBindData.GetFindData 
     pfd = wf 
     Return 0 
    End Function 

    Public Function SetFindData(ByVal pfd As WIN32_FIND_DATA) As UInteger Implements IFileSystemBindData.SetFindData 
     wf = pfd 
     Return 0 
    End Function 

    <DllImport("ole32.dll")> _ 
    Public Shared Function CreateBindCtx(reserved As UInteger, ByRef ppbc As IBindCtx) As Integer 
    End Function 
End Class 
End Namespace 

創建綁定上下文:

Dim wfd As New WIN32_FIND_DATA 
wfd.dwFileAttributes = &H10 'FILE_ATTRIBUTE_DIRECTORY' 
fsbd.SetFindData(wfd) 
Const STR_FILE_SYS_BIND_DATA As String = "File System Bind Data" 
FileSystemBindData.CreateBindCtx(0, bc) 
bc.RegisterObjectParam(STR_FILE_SYS_BIND_DATA, fsbd) 

函數用於創建與目標殼項目,並結合上下文

Private Function CreateShellItemNew(destination As String) As ComReleaser(Of IShellItem) 
Return New ComReleaser(Of IShellItem)(DirectCast(SHCreateItemFromParsingName(destination, bc, _shellItemGuid), IShellItem)) 
End Function 

功能這裏所說的。它拋出的移動選項行「值沒有在預期範圍內」

Public Sub MoveItemCreateDest(source As String, destination As String, newName As String) 
ThrowIfDisposed() 
Try 
    Using sourceItem As ComReleaser(Of IShellItem) = CreateShellItem(source) 
     Using destinationItem As ComReleaser(Of IShellItem) = CreateShellItemNew(destination) 
      _fileOperation.MoveItem(sourceItem.Item, destinationItem.Item, newName, Nothing) 
     End Using 
    End Using 
Catch ex As Exception 
    MsgBox("Moveitem error: " & ex.Message) 
End Try 
End Sub 
+0

您的'FileSystemBindData'類的成員函數似乎沒有做任何事情。您需要將傳入的'WIN32_FIND_DATA'存儲到'SetFindData'中,並將其返回到'GetFindData'中。 –

+0

謝謝。 FileSystemBindData中的函數是否僅將值傳遞給接口?另外,我不認爲使用GetFindData。 SetFindData函數存儲由RegisterObjectParam使用的WIN32_FIND_DATA項目。 https://msdn.microsoft.com/en-us/library/windows/desktop/bb775673%28v=vs.85%29.aspx –

+0

你認爲他們完全通過它?滲透? –

回答

0

解決它 - 翻轉的功能才能在接口的其它方式,並且正確地調用。之前由於功能被顛倒而發生數據損壞(Set被調用而不是Get)。我不知道在COM接口中的函數順序是有效的。

<ComImport()> _ 
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _ 
<Guid("01E18D10-4D8B-11d2-855D-006008059367")> _ 
Public Interface IFileSystemBindData 
    <PreserveSig()> Function SetFindData(ByVal pfd As WIN32_FIND_DATA) As <MarshalAs(UnmanagedType.Error)> Integer 
    <PreserveSig()> Function GetFindData(<Out()> ByRef pfd As WIN32_FIND_DATA) As <MarshalAs(UnmanagedType.Error)> Integer 
End Interface