VB.NET Win32API 查找和删除文件(超过 260 个字符限制)
VB.NET Win32API Find and Delete Files(Over 260 Char Limit)
作为一个非常新手的程序员,我正在努力尝试让一段简单的代码工作,这就是我想要的:
递归搜索目录(例如 D:\Site_Data),找到具有给定扩展名(例如 .xrl)的所有文件并删除它们。
我想使用 Win32API 的原因是因为我正在处理隐藏在超过 260 个字符的目录中的文件,并且搜索了高低,但找不到解决方案。 VB.NET是我一直在学习的,所以这是我想坚持的。
我已经设法复制了一些代码并调整它以使用 Kernel32.dll DeleteFile 函数删除一个 "single" 文件,但这只删除了 1 个文件,它不能接受通配符,这里是我得到了什么:
Imports System
Imports System.Runtime.InteropServices
Imports System.IO
Public Class Form1
Public Property delFile As String
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)> _
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
delFile = "D:\Site_Data\Test.JPG"
Try
Dim boolResult As Boolean
Dim delName As String = "\?\" + delFile
boolResult = DeleteFile(delName)
Debug.WriteLine("Result: " & boolResult.ToString)
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
我知道我要找的是 "FindFirstFile" 函数,但不知道如何编写代码来在 VB.NET 中实现它。
如果有人能提供帮助,将不胜感激。
更新 2,工作代码:
Imports System.IO
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim longFolderName As String = "\?\c:\users\user1\desktop\pics\"
Dim extensionsToDelete As String = ".jpg"
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(longFolderName)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionsToDelete) Then
VeryLongFilenameHandler.DeleteFile(longFolderName + filename)
Debug.WriteLine("Result: " & longFolderName, filename)
End If
Next
End Sub
End Class
Class VeryLongFilenameHandler
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
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
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindFirstFile(lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
End Function
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindNextFile(hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)>
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Public Shared Function GetFilenames(folderName As String) As List(Of String)
Dim filenames As New List(Of String)
Dim findData As New WIN32_FIND_DATA
Dim findHandle As New IntPtr
Dim INVALID_HANDLE_VALUE As New IntPtr(-1)
' Add wildcard to foldername to get all files
folderName += "*"
findHandle = FindFirstFile(folderName, findData)
If findHandle <> INVALID_HANDLE_VALUE Then
Do
If findData.cFileName <> "." AndAlso findData.cFileName <> ".." AndAlso (findData.dwFileAttributes And FileAttributes.Directory) <> FileAttributes.Directory Then
filenames.Add(findData.cFileName)
End If
Loop While (FindNextFile(findHandle, findData))
FindClose(findHandle)
End If
Return filenames
End Function
End Class
所以上面的方法适用于删除扩展名为 .JPG 的文件夹中的所有文件,但不会递归执行。
更新 3:
再次感谢theduck的帮助,非常感谢,我想我差不多大功告成了,我已经设法将2个功能分成2个按钮,1个按钮可以列出所有带有.jpg的文件,另一个按钮可以列出所有目录,现在是合并它们的情况,所以我设法用第二个按钮执行了以下操作,但调试输出没有显示要删除的文件 "suppose",这就是我得到的到目前为止,对于它应该如何工作有点困惑:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim longFolderName As String = "\?\c:\users\Administrator\Desktop\TestDir\"
Dim foldernames As List(Of String) = VeryLongFilenameHandler.GetFoldernames(longFolderName)
For Each foldername As String In foldernames
Dim longFolderName1 As String = (longFolderName + foldername)
Dim extensionsToDelete As String = ".jpg"
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(longFolderName1)
MsgBox(longFolderName1)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionsToDelete) Then
'VeryLongFilenameHandler.DeleteFile(longFolderName + filename)
Debug.WriteLine("Deleted: " & longFolderName1 + filename)
End If
Next
Next
End Sub
MsgBox 会弹出两个目录,"VeryLongFilenameHandler.GetFoldernames" 是您在下面提供的功能调整,用于仅返回目录。我基本上复制了 Public 共享函数并进行了必要的调整。
更新:工作中
好的,现在可以使用了,多亏了 theduck,您对示例代码所做的最后一次编辑是完美的,link 它变成了一个按钮,我只是将代码从模块内部移到了一个按钮中。当然我不是盲目的,你基本上为我写了整个代码块,对此我非常感谢,我已经很久没有看到这样的帮助了。因为我只是一个新手程序员,所以我学得更快的方法是找到工作代码,然后分解它的工作原理,我比阅读 MSDN 文章更快地掌握了这一点。
所以再次感谢你,这是我的最终代码(由一个表单和一个按钮组成)
进口 System.IO
进口 System.Runtime.InteropServices
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim longFolderName As String = "\?\c:\users\administrator\Desktop\TestDir\"
Dim extensionToDelete As String = ".jpg"
RecursiveDelete(longFolderName, extensionToDelete)
End Sub
Sub RecursiveDelete(path As String, extensionToDelete As String)
If Not path.EndsWith("\") Then path += "\"
' Handle all folders below this one
Dim folders As List(Of String) = VeryLongFilenameHandler.GetFolders(path)
For Each folder As String In folders
RecursiveDelete(path + folder, extensionToDelete)
Next
' Delete any applicable files
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(path)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionToDelete) Then
VeryLongFilenameHandler.DeleteFile(path + filename)
End If
Next
End Sub
End Class
Class VeryLongFilenameHandler
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
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
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindFirstFile(lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
End Function
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindNextFile(hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)>
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Public Shared Function GetFilenames(folderName As String) As List(Of String)
Return GetNames(folderName, False)
End Function
Public Shared Function GetFolders(folderName As String) As List(Of String)
Return GetNames(folderName, True)
End Function
Private Shared Function GetNames(folderName As String, getDirectories As Boolean) As List(Of String)
Dim names As New List(Of String)
Dim findData As New WIN32_FIND_DATA
Dim findHandle As New IntPtr
Dim INVALID_HANDLE_VALUE As New IntPtr(-1)
If Not folderName.EndsWith("\") Then folderName += "\"
' Add wildcard to foldername to get all files
folderName += "*"
findHandle = FindFirstFile(folderName, findData)
If findHandle <> INVALID_HANDLE_VALUE Then
Do
If findData.cFileName <> "." AndAlso findData.cFileName <> ".." Then
Dim isDirectory As Boolean = (findData.dwFileAttributes And FileAttributes.Directory) = FileAttributes.Directory
If (getDirectories AndAlso isDirectory) Or (Not getDirectories AndAlso Not isDirectory) Then
names.Add(findData.cFileName)
End If
End If
Loop While (FindNextFile(findHandle, findData))
FindClose(findHandle)
End If
Return names
End Function
结束Class
如果您使用循环,您可以让程序继续执行直到满足特定条件(例如,删除所有扩展名为 .example 的文件)
研究 while 循环,它们应该能够执行您希望程序执行的操作。
循环结构:
https://msdn.microsoft.com/en-GB/library/ezk76t25.aspx
以下内容可能会有所帮助:
Imports System.IO
Imports System.Runtime.InteropServices
Module Module1
Sub Main()
Dim longFolderName As String = "\?\c:\temp\"
Dim extensionToDelete As String = ".xrl"
RecursiveDelete(longFolderName, extensionToDelete)
End Sub
Sub RecursiveDelete(path As String, extensionToDelete As String)
If Not path.EndsWith("\") Then path += "\"
' Handle all folders below this one
Dim folders As List(Of String) = VeryLongFilenameHandler.GetFolders(path)
For Each folder As String In folders
RecursiveDelete(path + folder, extensionToDelete)
Next
' Delete any applicable files
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(path)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionToDelete) Then
VeryLongFilenameHandler.DeleteFile(path + filename)
End If
Next
End Sub
End Module
Class VeryLongFilenameHandler
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
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
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindFirstFile(lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
End Function
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindNextFile(hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)>
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Public Shared Function GetFilenames(folderName As String) As List(Of String)
Return GetNames(folderName, False)
End Function
Public Shared Function GetFolders(folderName As String) As List(Of String)
Return GetNames(folderName, True)
End Function
Private Shared Function GetNames(folderName As String, getDirectories As Boolean) As List(Of String)
Dim names As New List(Of String)
Dim findData As New WIN32_FIND_DATA
Dim findHandle As New IntPtr
Dim INVALID_HANDLE_VALUE As New IntPtr(-1)
If Not folderName.EndsWith("\") Then folderName += "\"
' Add wildcard to foldername to get all files
folderName += "*"
findHandle = FindFirstFile(folderName, findData)
If findHandle <> INVALID_HANDLE_VALUE Then
Do
If findData.cFileName <> "." AndAlso findData.cFileName <> ".." Then
Dim isDirectory As Boolean = (findData.dwFileAttributes And FileAttributes.Directory) = FileAttributes.Directory
If (getDirectories AndAlso isDirectory) Or (Not getDirectories AndAlso Not isDirectory) Then
names.Add(findData.cFileName)
End If
End If
Loop While (FindNextFile(findHandle, findData))
FindClose(findHandle)
End If
Return names
End Function
End Class
class VeryLongFilenameHandler 有一个 GetFilenames 函数,它将 return 您使用 Win32 API 指定的文件夹中的文件列表。然后您可以遍历这些文件名,检查扩展名并在适当时删除(再次使用 Win32 调用)。
作为一个非常新手的程序员,我正在努力尝试让一段简单的代码工作,这就是我想要的:
递归搜索目录(例如 D:\Site_Data),找到具有给定扩展名(例如 .xrl)的所有文件并删除它们。
我想使用 Win32API 的原因是因为我正在处理隐藏在超过 260 个字符的目录中的文件,并且搜索了高低,但找不到解决方案。 VB.NET是我一直在学习的,所以这是我想坚持的。
我已经设法复制了一些代码并调整它以使用 Kernel32.dll DeleteFile 函数删除一个 "single" 文件,但这只删除了 1 个文件,它不能接受通配符,这里是我得到了什么:
Imports System
Imports System.Runtime.InteropServices
Imports System.IO
Public Class Form1
Public Property delFile As String
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)> _
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
delFile = "D:\Site_Data\Test.JPG"
Try
Dim boolResult As Boolean
Dim delName As String = "\?\" + delFile
boolResult = DeleteFile(delName)
Debug.WriteLine("Result: " & boolResult.ToString)
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
我知道我要找的是 "FindFirstFile" 函数,但不知道如何编写代码来在 VB.NET 中实现它。
如果有人能提供帮助,将不胜感激。
更新 2,工作代码:
Imports System.IO
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim longFolderName As String = "\?\c:\users\user1\desktop\pics\"
Dim extensionsToDelete As String = ".jpg"
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(longFolderName)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionsToDelete) Then
VeryLongFilenameHandler.DeleteFile(longFolderName + filename)
Debug.WriteLine("Result: " & longFolderName, filename)
End If
Next
End Sub
End Class
Class VeryLongFilenameHandler
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
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
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindFirstFile(lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
End Function
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindNextFile(hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)>
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Public Shared Function GetFilenames(folderName As String) As List(Of String)
Dim filenames As New List(Of String)
Dim findData As New WIN32_FIND_DATA
Dim findHandle As New IntPtr
Dim INVALID_HANDLE_VALUE As New IntPtr(-1)
' Add wildcard to foldername to get all files
folderName += "*"
findHandle = FindFirstFile(folderName, findData)
If findHandle <> INVALID_HANDLE_VALUE Then
Do
If findData.cFileName <> "." AndAlso findData.cFileName <> ".." AndAlso (findData.dwFileAttributes And FileAttributes.Directory) <> FileAttributes.Directory Then
filenames.Add(findData.cFileName)
End If
Loop While (FindNextFile(findHandle, findData))
FindClose(findHandle)
End If
Return filenames
End Function
End Class
所以上面的方法适用于删除扩展名为 .JPG 的文件夹中的所有文件,但不会递归执行。
更新 3:
再次感谢theduck的帮助,非常感谢,我想我差不多大功告成了,我已经设法将2个功能分成2个按钮,1个按钮可以列出所有带有.jpg的文件,另一个按钮可以列出所有目录,现在是合并它们的情况,所以我设法用第二个按钮执行了以下操作,但调试输出没有显示要删除的文件 "suppose",这就是我得到的到目前为止,对于它应该如何工作有点困惑:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim longFolderName As String = "\?\c:\users\Administrator\Desktop\TestDir\"
Dim foldernames As List(Of String) = VeryLongFilenameHandler.GetFoldernames(longFolderName)
For Each foldername As String In foldernames
Dim longFolderName1 As String = (longFolderName + foldername)
Dim extensionsToDelete As String = ".jpg"
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(longFolderName1)
MsgBox(longFolderName1)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionsToDelete) Then
'VeryLongFilenameHandler.DeleteFile(longFolderName + filename)
Debug.WriteLine("Deleted: " & longFolderName1 + filename)
End If
Next
Next
End Sub
MsgBox 会弹出两个目录,"VeryLongFilenameHandler.GetFoldernames" 是您在下面提供的功能调整,用于仅返回目录。我基本上复制了 Public 共享函数并进行了必要的调整。
更新:工作中 好的,现在可以使用了,多亏了 theduck,您对示例代码所做的最后一次编辑是完美的,link 它变成了一个按钮,我只是将代码从模块内部移到了一个按钮中。当然我不是盲目的,你基本上为我写了整个代码块,对此我非常感谢,我已经很久没有看到这样的帮助了。因为我只是一个新手程序员,所以我学得更快的方法是找到工作代码,然后分解它的工作原理,我比阅读 MSDN 文章更快地掌握了这一点。
所以再次感谢你,这是我的最终代码(由一个表单和一个按钮组成) 进口 System.IO 进口 System.Runtime.InteropServices Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim longFolderName As String = "\?\c:\users\administrator\Desktop\TestDir\"
Dim extensionToDelete As String = ".jpg"
RecursiveDelete(longFolderName, extensionToDelete)
End Sub
Sub RecursiveDelete(path As String, extensionToDelete As String)
If Not path.EndsWith("\") Then path += "\"
' Handle all folders below this one
Dim folders As List(Of String) = VeryLongFilenameHandler.GetFolders(path)
For Each folder As String In folders
RecursiveDelete(path + folder, extensionToDelete)
Next
' Delete any applicable files
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(path)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionToDelete) Then
VeryLongFilenameHandler.DeleteFile(path + filename)
End If
Next
End Sub
End Class
Class VeryLongFilenameHandler
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
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
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindFirstFile(lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
End Function
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindNextFile(hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)>
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Public Shared Function GetFilenames(folderName As String) As List(Of String)
Return GetNames(folderName, False)
End Function
Public Shared Function GetFolders(folderName As String) As List(Of String)
Return GetNames(folderName, True)
End Function
Private Shared Function GetNames(folderName As String, getDirectories As Boolean) As List(Of String)
Dim names As New List(Of String)
Dim findData As New WIN32_FIND_DATA
Dim findHandle As New IntPtr
Dim INVALID_HANDLE_VALUE As New IntPtr(-1)
If Not folderName.EndsWith("\") Then folderName += "\"
' Add wildcard to foldername to get all files
folderName += "*"
findHandle = FindFirstFile(folderName, findData)
If findHandle <> INVALID_HANDLE_VALUE Then
Do
If findData.cFileName <> "." AndAlso findData.cFileName <> ".." Then
Dim isDirectory As Boolean = (findData.dwFileAttributes And FileAttributes.Directory) = FileAttributes.Directory
If (getDirectories AndAlso isDirectory) Or (Not getDirectories AndAlso Not isDirectory) Then
names.Add(findData.cFileName)
End If
End If
Loop While (FindNextFile(findHandle, findData))
FindClose(findHandle)
End If
Return names
End Function
结束Class
如果您使用循环,您可以让程序继续执行直到满足特定条件(例如,删除所有扩展名为 .example 的文件) 研究 while 循环,它们应该能够执行您希望程序执行的操作。
循环结构: https://msdn.microsoft.com/en-GB/library/ezk76t25.aspx
以下内容可能会有所帮助:
Imports System.IO
Imports System.Runtime.InteropServices
Module Module1
Sub Main()
Dim longFolderName As String = "\?\c:\temp\"
Dim extensionToDelete As String = ".xrl"
RecursiveDelete(longFolderName, extensionToDelete)
End Sub
Sub RecursiveDelete(path As String, extensionToDelete As String)
If Not path.EndsWith("\") Then path += "\"
' Handle all folders below this one
Dim folders As List(Of String) = VeryLongFilenameHandler.GetFolders(path)
For Each folder As String In folders
RecursiveDelete(path + folder, extensionToDelete)
Next
' Delete any applicable files
Dim filenames As List(Of String) = VeryLongFilenameHandler.GetFilenames(path)
For Each filename As String In filenames
If filename.ToLower.EndsWith(extensionToDelete) Then
VeryLongFilenameHandler.DeleteFile(path + filename)
End If
Next
End Sub
End Module
Class VeryLongFilenameHandler
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
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
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindFirstFile(lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
End Function
<DllImport("kernel32", CharSet:=CharSet.Unicode)>
Public Shared Function FindNextFile(hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=False, SetLastError:=True)>
Public Shared Function DeleteFile(ByVal path As String) As Boolean
End Function
Public Shared Function GetFilenames(folderName As String) As List(Of String)
Return GetNames(folderName, False)
End Function
Public Shared Function GetFolders(folderName As String) As List(Of String)
Return GetNames(folderName, True)
End Function
Private Shared Function GetNames(folderName As String, getDirectories As Boolean) As List(Of String)
Dim names As New List(Of String)
Dim findData As New WIN32_FIND_DATA
Dim findHandle As New IntPtr
Dim INVALID_HANDLE_VALUE As New IntPtr(-1)
If Not folderName.EndsWith("\") Then folderName += "\"
' Add wildcard to foldername to get all files
folderName += "*"
findHandle = FindFirstFile(folderName, findData)
If findHandle <> INVALID_HANDLE_VALUE Then
Do
If findData.cFileName <> "." AndAlso findData.cFileName <> ".." Then
Dim isDirectory As Boolean = (findData.dwFileAttributes And FileAttributes.Directory) = FileAttributes.Directory
If (getDirectories AndAlso isDirectory) Or (Not getDirectories AndAlso Not isDirectory) Then
names.Add(findData.cFileName)
End If
End If
Loop While (FindNextFile(findHandle, findData))
FindClose(findHandle)
End If
Return names
End Function
End Class
class VeryLongFilenameHandler 有一个 GetFilenames 函数,它将 return 您使用 Win32 API 指定的文件夹中的文件列表。然后您可以遍历这些文件名,检查扩展名并在适当时删除(再次使用 Win32 调用)。