我正在努力尝试获得一段简单的代码作为一个非常新手的程序员,这就是我想要的:
递归搜索目录(例如D:\ Site_Data),查找具有给定扩展名的所有文件(例如.xrl)并删除它们。
我想使用Win32API的原因是因为我处理埋藏在260多个字母深处的directorys中的文件,并且搜索了高低,无法找到解决方案。 VB.NET是我一直在学习的东西,所以我想坚持下去。
我设法复制了一些代码并进行了调整以删除了一个"单个"使用Kernel32.dll DeleteFile函数的文件,但只有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
我明白我要找的是&#34; FindFirstFile&#34;函数但不知道如何编写代码以在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的文件,另一个按钮按钮可以列出所有目录,现在它是组合它们的情况,所以我设法用第二个按钮执行下面的操作,但是调试输出不显示它是&#34;假设&#34;删除,这是我到目前为止所得到的,对它应该如何工作有点困惑:
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弹出两个目录,&#34; VeryLongFilenameHandler.GetFoldernames&#34;是您在下面提供的功能调整,仅用于获取目录。我基本上复制了公共共享功能并进行了必要的调整。
更新:工作 好的,现在它可以工作,感谢你,你在示例代码上做的最后一次编辑是完美的,将它链接到一个按钮,我只是将代码从模块内部移动到一个按钮。我当然不会对显而易见的事情视而不见,你基本上为我编写了整个代码块,我非常感谢,很长一段时间我都没有看到这样的帮助。因为我只是一个新手程序员,所以我学得更快的方法是找到工作代码,并分解其工作原理,我比阅读MSDN文章要快得多。
再次感谢你,这里是我的最终代码(由一个Form和一个Button组成) 进口System.IO Imports System.Runtime.InteropServices 公共类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
结束班
答案 0 :(得分:0)
如果你使用循环,你可以让程序继续,直到满足某个条件(例如删除所有扩展名为.example的文件) 研究while循环,他们应该能够做你想要的程序。
循环结构: https://msdn.microsoft.com/en-GB/library/ezk76t25.aspx
答案 1 :(得分:0)
这些方面的某些内容可能有所帮助:
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
类VeryLongFilenameHandler有一个函数GetFilenames,它将返回使用Win32 API指定的文件夹中的文件列表。然后,您可以迭代这些文件名,检查扩展名并删除(如果适用)(再次使用Win32调用)。