2

Windowsコマンド「diskpart」からの出力結果を解析する必要があるプログラムを作成しています。特に、VB.NETでディスクとボリューム情報を解析する(「リストディスク」と「リストボリューム」を使用)

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

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 に答える