使用.NET解析Diskpart输出
我正在编写一个程序,需要解析windows命令“diskpart”的输出结果,特别是在用VB.NET解析磁盘和卷信息(使用“列表磁盘”和“列表卷”)时 我使用dos命令使用.NET解析Diskpart输出,.net,regex,vb.net,parsing,.net,Regex,Vb.net,Parsing,我正在编写一个程序,需要解析windows命令“diskpart”的输出结果,特别是在用VB.NET解析磁盘和卷信息(使用“列表磁盘”和“列表卷”)时 我使用dos命令diskpart/s myscript.scp>result.txt将结果输出到文本文件中 现在在VB.NET中,我需要解析'result.txt'以将'volume number'、'drive letter'、'drive label'、'type'、'size'和'size_unit'检索到一个数组中,以便进一步处理 检索所
diskpart/s myscript.scp>result.txt将结果输出到文本文件中
现在在VB.NET中,我需要解析'result.txt'以将'volume number'、'drive letter'、'drive label'、'type'、'size'和'size_unit'检索到一个数组中,以便进一步处理
检索所有这些数据的最佳方法是什么?我试图在MSDN上阅读有关.NET正则表达式(Regex)的文章,这让我感到困惑,并且不确定在我的案例中应该使用什么模式
希望有人能帮助我,欢迎任何其他解析方法
*2013年6月26日更新-出于某些技术原因,我需要坚持使用“diskpart”,并依靠其输出结果进行解析。
输入示例(result.txt)
输出
Microsoft DiskPart version 6.1.7601
Copyright (C) 1999-2008 Microsoft Corporation.
On computer: PC1
Disk ### Status Size Free Dyn Gpt
-------- ------------- ------- ------- --- ---
Disk 0 Online 1863 GB 1024 KB
Disk 1 No Media 0 B 0 B
Disk 2 Online 7424 MB 0 B
Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ----- ---------- ------- --------- --------
Volume 0 E DVD-ROM 0 B No Media
Volume 1 C SYSTEM NTFS Partition 100 GB Healthy System
Volume 2 D TEMP NTFS Partition 1606 GB Healthy Pagefile
Volume 3 G Removable 0 B No Media
Volume 4 F GSFKEY NTFS Removable 7423 MB Healthy
disk(0)
.disknum=0
.size=1863
.size_unit="GB
disk(0)
.disknum=1
.size=0
.size_unit="B"
..and so on
vol(0)
.volnum=0
.letter="E"
.label=""
.type="DVD-ROM"
.size=0
.size_unit="B"
vol(1)
.volnum=1
.letter="C"
.label="SYSTEM"
.type="Partition"
.size=100
.size_unit="GB"
..and so on
您可以从System.IO.DriveInfo获取此信息吗
public DriveInfo(string driveName);
public long AvailableFreeSpace
public string DriveFormat
public DriveType DriveType
public DirectoryInfo RootDirectory
public long TotalFreeSpace
public long TotalSize
public string VolumeLabel
public static DriveInfo[] GetDrives();
我首先创建一个表示您的数据的类:
Public Class DiskPartResult
Public Property Volume As String
Public Property Number As Int32
Public Property Ltr As String
Public Property Label As String
Public Property Fs As String
Public Property Type As String
Public Property SizeUnit As String
Public Property Status As String
Public Property Info As String
End Class
现在,您可以使用File.ReadLines
和以下Linq查询来获取相关数据行:
Dim diskPartFileLines = File.ReadLines("Results.txt")
Dim dataLines = From line In diskPartFileLines
Skip While Not line.TrimStart().StartsWith("----------") Skip (1)
Take While line.TrimStart().StartsWith("Volume")
现在,您可以填写(DiskPartResult)的列表:
显然,分隔符不是制表符,而是所有空格。任何
想法
然后您可以“分割”从标题行获得的双空白索引,因为数据行使用相同的索引
我创建了以下扩展方法来获取文本中给定分隔符字符串的所有索引:
<System.Runtime.CompilerServices.Extension()> _
Public Function AllIndexOf(text As String, str As String, comparisonType As StringComparison) As IList(Of Integer)
Dim allIndeces As IList(Of Integer) = New List(Of Integer)()
Dim index As Integer = text.IndexOf(str, comparisonType)
While index <> -1
allIndeces.Add(index)
index = text.IndexOf(str, index + str.Length, comparisonType)
End While
Return allIndeces
End Function
然后枚举查询,初始化DiskPartResults
,并将它们添加到列表中:
For Each line In dataLines
Dim data = New DiskPartResult()
Dim lastIndex = 0
For i As Int32 = 0 To colStartIndices.Count - 1
Dim index = colStartIndices(i)
Select Case i
Case 0
data.Volume = line.Substring(lastIndex, index - lastIndex).Trim()
Case 1
data.Number = Int32.Parse(line.Substring(lastIndex, index - lastIndex).Trim())
Case 2
data.Ltr = line.Substring(lastIndex, index - lastIndex).Trim()
Case 3
data.Label = line.Substring(lastIndex, index - lastIndex).Trim()
Case 4
data.Fs = line.Substring(lastIndex, index - lastIndex).Trim()
Case 5
data.Type = line.Substring(lastIndex, index - lastIndex).Trim()
Case 6
Dim sizeInfo = line.Substring(lastIndex, index - lastIndex).Trim()
data.Size = Double.Parse(sizeInfo.Split()(0).Trim())
data.SizeUnit = sizeInfo.Split()(1).Trim()
Case 7
data.Status = line.Substring(lastIndex, index - lastIndex).Trim()
Case 8
data.Info = line.Substring(lastIndex, index - lastIndex).Trim()
End Select
lastIndex = index
Next
Next
请注意,每个
的都没有经过测试,但它应该会告诉您答案。获取磁盘号
模糊查询
Dim objWMI
暗磁盘驱动器
暗磁盘驱动器
暗分区
Dim partition'将包含驱动器和分区号
模糊逻辑磁盘
Dim logicalDisk'将包含驱动器号
Dim stroutput作为新的StringBuilder
objWMI = GetObject("winmgmts:\\.\root\cimv2")
diskDrives = objWMI.ExecQuery("SELECT * FROM Win32_DiskDrive") ' First get out the physical drives
For Each diskDrive In diskDrives
query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + diskDrive.DeviceID + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition" ' link the physical drives to the partitions
partitions = objWMI.ExecQuery(query)
For Each partition In partitions
query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition.DeviceID + "'} WHERE AssocClass = Win32_LogicalDiskToPartition" ' link the partitions to the logical disks
logicalDisks = objWMI.ExecQuery(query)
For Each logicalDisk In logicalDisks
stroutput.Append(logicalDisk.DeviceID & " - " & partition.Caption)
' Wscript.Echo(logicalDisk.DeviceID & " - " & partition.Caption)
Next
Next
Next
MessageBox.Show(stroutput.ToString)
出于某些技术原因,我需要坚持争论什么是技术原因?您是否被告知“唯一的方法是解析文本文件”?这是另一个团队的设计要求,最有可能是因为diskpart将用于执行进程中的磁盘分区…因此在这种情况下,提供正确且一致的“磁盘号”至关重要您认为diskpart负责分配磁盘号吗?如果是,是否有文件证明在分配这些号码时是一致的?是否因为“其他团队”不知道DriveInfo?TBH,直到你的问题出现,我才知道:-)这是技术原因“如果他们更改了diskpart
的输出格式,我需要确保我的代码是脆弱的”?如果分隔符不是制表符,你就有问题了。因为很难检测到新列(String.Split()
甚至会将“磁盘0”拆分为两列)。显然,分隔符不是制表符,而是所有空格。有什么想法吗?@Dennis:编辑了我的答案。我在执行代码时遇到了问题,“headerLine”是什么?代码是否仍然适用于没有“drive ltr”和“label”的卷?对不起,我错误地忽略了headerline查询。稍后我会添加它。输出将显示Diskpart中使用的磁盘号,以及磁盘信息和分区信息。
Dim diskPartFileLines = File.ReadAllLines("Results.txt")
Dim headerLine = (From line In diskPartFileLines
Skip While Not line.TrimStart().StartsWith("----------")).First().Trim()
Dim colStartIndices As IList(Of Int32) = headerLine.AllIndexOf(" ", StringComparison.OrdinalIgnoreCase)
Dim dataLines = From line In diskPartFileLines
Skip While Not line.TrimStart().StartsWith("----------") Skip 1
Take While line.TrimStart().StartsWith("Volume")
Select line.Trim()
Dim alldata = New List(Of DiskPartResult)
For Each line In dataLines
Dim data = New DiskPartResult()
Dim lastIndex = 0
For i As Int32 = 0 To colStartIndices.Count - 1
Dim index = colStartIndices(i)
Select Case i
Case 0
data.Volume = line.Substring(lastIndex, index - lastIndex).Trim()
Case 1
data.Number = Int32.Parse(line.Substring(lastIndex, index - lastIndex).Trim())
Case 2
data.Ltr = line.Substring(lastIndex, index - lastIndex).Trim()
Case 3
data.Label = line.Substring(lastIndex, index - lastIndex).Trim()
Case 4
data.Fs = line.Substring(lastIndex, index - lastIndex).Trim()
Case 5
data.Type = line.Substring(lastIndex, index - lastIndex).Trim()
Case 6
Dim sizeInfo = line.Substring(lastIndex, index - lastIndex).Trim()
data.Size = Double.Parse(sizeInfo.Split()(0).Trim())
data.SizeUnit = sizeInfo.Split()(1).Trim()
Case 7
data.Status = line.Substring(lastIndex, index - lastIndex).Trim()
Case 8
data.Info = line.Substring(lastIndex, index - lastIndex).Trim()
End Select
lastIndex = index
Next
Next
objWMI = GetObject("winmgmts:\\.\root\cimv2")
diskDrives = objWMI.ExecQuery("SELECT * FROM Win32_DiskDrive") ' First get out the physical drives
For Each diskDrive In diskDrives
query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + diskDrive.DeviceID + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition" ' link the physical drives to the partitions
partitions = objWMI.ExecQuery(query)
For Each partition In partitions
query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition.DeviceID + "'} WHERE AssocClass = Win32_LogicalDiskToPartition" ' link the partitions to the logical disks
logicalDisks = objWMI.ExecQuery(query)
For Each logicalDisk In logicalDisks
stroutput.Append(logicalDisk.DeviceID & " - " & partition.Caption)
' Wscript.Echo(logicalDisk.DeviceID & " - " & partition.Caption)
Next
Next
Next
MessageBox.Show(stroutput.ToString)