IFileSystemBindData实现未完全工作

本文关键字:工作 实现 IFileSystemBindData | 更新日期: 2023-09-27 18:19:34

我正在使用IFileOperation(Windows shell)API来批量复制/删除文件。到目前为止一切都很好。然而,将文件复制/移动到一个还不存在的目标会稍微复杂一些——您需要使用IFileSystemBindData接口为目标创建一个shell项。它能间歇性地工作。其他时候,它在IfileOperation.MoveItem方法中抛出异常。

欢迎任何建议。

注:

  • 绑定的WIN_32_FIND_DATA在SetFindData中似乎已损坏在绑定上下文中调用的函数
  • 这个线程是有用的,以及我从哪里获得原始信息:使用IFileOperation在复制过程中创建目录

接口:

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)

用于创建带有目的地和绑定上下文的shell项的函数-

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

函数在此处调用。它在MoveItem行上抛出"值不在预期范围内"

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

IFileSystemBindData实现未完全工作

解决了它-在接口中以另一种方式翻转函数的顺序,它们就会被正确调用。以前的数据损坏是由于函数被反转而发生的(调用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