【发布时间】:2015-11-09 23:55:17
【问题描述】:
我正在使用 IFileOperation (Windows shell) API 来批量复制/删除文件。到目前为止一切都很好。但是,将文件复制/移动到尚不存在的目标会稍微复杂一些 - 您需要使用 IFileSystemBindData 接口为目标创建一个 shell 项。它工作 - 间歇性。其他时候它会在 IfileOperation.MoveItem 方法中引发异常。
欢迎任何建议。
注意事项:
- 绑定的 WIN_32_FIND_DATA 在 SetFindData 中出现损坏 在绑定上下文中调用它的函数
- 这个帖子很有用, 以及我从哪里获得原始信息: Creating directories during a copy using 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)
使用目标和绑定上下文创建外壳项目的功能-
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
【问题讨论】:
-
FileSystemBindData类的成员函数似乎没有做任何事情。您需要将传入的WIN32_FIND_DATA存储到SetFindData并在GetFindData中返回。 -
谢谢。 FileSystemBindData 中的函数不只是将值传递给接口吗?另外,我认为没有使用 GetFindData。 SetFindData 函数存储 WIN32_FIND_DATA 项,然后由 RegisterObjectParam 使用。 msdn.microsoft.com/en-us/library/windows/desktop/…
-
您认为他们是如何准确传递信息的?渗透?
-
嗯 - 好吧,也许我以错误的方式实现了这个接口。我认为它应该激活一个 _IFileSystemBindData 对象并通过它传递,而不是继承 IFileSystemBindData 的类。现在我只需要弄清楚如何让接口传递给 Activator 的类型!
-
暂缓我的最后一条评论,我已经在上面更新了它以获取和设置建议的值。它仍然抛出异常,但并非总是如此。