2

我正在编写一个程序,它需要解析 Windows 命令“diskpart”的输出结果,特别是在使用 VB.NET 解析磁盘和卷信息(使用“list disk”和“list volume”)时

我设法通过使用 dos 命令使用 diskpart 将结果输出到文本文件中diskpart /s myscript.scp > result.txt

现在在 VB.NET 中,我需要解析“result.txt”以将“卷号”、“驱动器号”、“驱动器标签”、“类型”、“大小”和“大小单元”检索到一个数组中以进行进一步处理。

检索所有这些数据的最佳方法是什么?我尝试在 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
4

3 回答 3

5

你能从 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();
于 2013-06-26T08:17:42.153 回答
3

我将首先创建一个代表您的数据的类:

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")

现在您可以填写List(Of DiskPartResult)

Dim alldata = New List(Of DiskPartResult)
For Each line As String In dataLines
    Dim columns = line.Trim().Split({vbTab}, StringSplitOptions.RemoveEmptyEntries)
    If columns.Length <> 9 Then Continue For
    Dim data = New DiskPartResult()
    data.Volume = columns(0)
    data.Number = Int32.Parse(columns(1))
    data.Ltr = columns(2)
    data.Label = columns(3)
    data.Fs = columns(4)
    data.Type = columns(5)
    Dim sizeInfo = columns(6)
    data.Size = Double.Parse(sizeInfo.Split()(0).Trim())
    data.SizeUnit = sizeInfo.Split()(1).Trim()
    data.Status = columns(7)
    data.Info = columns(8)
    alldata.Add(data)
Next

如果你想输出它:

For Each dpr As DiskPartResult In alldata
    Console.WriteLine("vol({0})", dpr.Volume)
    Console.WriteLine("   .volnum={0}", dpr.Number)
    Console.WriteLine("   .letter={0}", dpr.Ltr)
    Console.WriteLine("   .label={0}", dpr.Label)
    Console.WriteLine("   .type={0}", dpr.Type)
    Console.WriteLine("   .size={0}", dpr.Size)

    ' and so on ... '
Next

显然,分隔符不是制表符,是所有空格。有任何想法吗?

然后你可以在你可以从标题行获得的双空白索引上“拆分”,因为数据行使用相同的索引。

我创建了以下扩展方法来获取文本中给定分隔符字符串的所有索引:

<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

现在您可以使用此代码查询所需的信息:

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)

然后枚举查询,初始化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

请注意,For Each未测试,但它应该给你的想法。

于 2013-06-26T08:26:22.237 回答
1

'Get Disk Number Dim query Dim objWMI Dim diskDrives Dim diskDrive Dim partitions Dim partition ' 将包含驱动器和分区号 Dim logicalDisks Dim logicalDisk ' 将包含驱动器号 Dim stroutput As New 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)
于 2014-11-30T11:40:12.880 回答