0

物理ディスクを通過し、WMI 設定を表示する以下のコードがあります。

WMI パラメーターが存在しない場合、何も表示されないことに気付きました (これは問題ありません) が、これは、サーバー上に存在する後続の WMI パラメーターに干渉し、何も表示されません...表示されるべきであっても..以下の例。

つまり、コードは次の部分を通過するということです。

 lblcapability_desc.Text = "Capability Description: " + moDisk["CapabilityDescription"].ToString();
                    lblAvailability.Text = "Availability: " + moDisk["Availability"].ToString();
                    lblbytepersector.Text = "Bytes per Sector: " + moDisk["BytesPerSector"].ToString();
                    lbl_deviceid.Text = "Device ID: " + moDisk["systemname"].ToString();

最初に SystemName を取得し、次に Type を取得します。

次に、コンピューターに「可用性」などの WMI パラメーターが存在しない場合、それは表示されません。それは結構です。ただし、「可用性」の直後に「セクターあたりのバイト数」パラメーターなどがあります。これらのパラメータも何も表示しません(サーバー上に存在するため、何かを表示する必要があることはわかっていますが、powershellでテストされています)。

「Availability」からの情報の欠如がパラメータに干渉し、何も表示しないようです。

これを修正する瞬間に私が考えることができる唯一の方法は (たとえ可用性が何も示していなくても、後続のパラメーターが必要なデータを示している場合でも)、各 WMI パラメーター内に IF THEN を追加することです。これを修正する方法。

したがって、例としては、IF [Availability] の次にメッセージ "Avialbility = anything" ELSE "WMI parameter not found" が表示されます。このように、各 WMI パラメータには独自のエラー チェックがあります。私が想像する素敵なコーディングではありません..

WMI パラメータが存在しない場合のエラー キャプチャがすでに存在し、コメントがエンド ユーザーに表示されます。

コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Management;
using Microsoft.Win32;

namespace diskdrive_info
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Get all the disk drives
            ManagementObjectSearcher mosDisk = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
            // Loop through each object (disk) retrieved by WMI
            foreach (ManagementObject moDisk in mosDisk.Get())
            {
                cmbHdd.Items.Add(moDisk["Model"].ToString());
            }
        }

        private void cmbHdd_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                ManagementObjectSearcher mosDisks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE Model = '" + cmbHdd.SelectedItem + "'");
                foreach (ManagementObject moDisk in mosDisks.Get())
                {

                    lblSystemName.Text = "SystemName: " + moDisk["systemname"];
                    lblType.Text = "Type: " + moDisk["MediaType"].ToString();
                    lblModel.Text = "Model: " + moDisk["Model"].ToString();
                    lblCapacity.Text = "Capacity: " + moDisk["Size"].ToString() + " bytes (" + Math.Round(((((double)Convert.ToDouble(moDisk["Size"]) / 1024) / 1024) / 1024), 2) + " GB)";
                    lblPartitions.Text = "Partitions: " + moDisk["Partitions"].ToString();
                    lblSectors.Text = "Sectors: " + moDisk["SectorsPerTrack"].ToString();
                    lblSignature.Text = "Signature: " + moDisk["Signature"].ToString();
                    lblFirmware.Text = "Firmware: " +moDisk["FirmwareRevision"].ToString();
                    lblFirmware.Text = "Firmware: " + moDisk["FirmwareRevision"] == null ? "Not Available" : moDisk["FirmwareRevision"].ToString();
                    lblcapability_desc.Text = "Capability Description: " + moDisk["CapabilityDescription"].ToString();
                    lblAvailability.Text = "Availability: " + moDisk["Availability"].ToString();
                    lblbytepersector.Text = "Bytes per Sector: " + moDisk["BytesPerSector"].ToString();
                    lbl_deviceid.Text = "Device ID: " + moDisk["systemname"].ToString();
                }
            }
            catch (Exception exp)
            {
                lblError.Text = "Some properties were not shown due to WMI errors or member not available on this system";
            }

        }

        private void btn_clear_Click(object sender, EventArgs e)
        {
            //lblSystemName.Text = string.Empty;
            lblSystemName.Text = "SystemName: " + "";
            lblType.Text = "Type: " + "";
            lblModel.Text = "Model: " + "";
            lblCapacity.Text = "Capacity: " + "";
            lblPartitions.Text = "Partitions: " + "";
            lblSectors.Text = "Sectors: " + "";
            lblSignature.Text = "Signature: " + "";
            lblFirmware.Text = "Firmware: " + "";
            lblError.Text = String.Empty;
            cmbHdd.Items.Clear();
            cmbHdd.Text = "";
            ManagementObjectSearcher mosDisk = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
            foreach (ManagementObject moDisk in mosDisk.Get())
            {
                cmbHdd.Items.Add(moDisk["Model"].ToString());
            }
        }
    }
}
4

1 に答える 1

2

発生している問題

「Availability」からの情報の欠如がパラメータに干渉し、何も表示しないようです。

これは部分的に当てはまります。「可用性」が存在せず、NullReferenceException がスローされます。ラベルを割り当てる前に、null かどうかを確認してください (コードは FirmwareRevision でこれを行っているようです)。

lblAvailability.Text = "Availability: " + moDisk["Availability"] != null ? moDisk["Availability"].ToString() : string.Empty;

問題の 2 番目の部分は、try-catch の反復ステートメントを含め、メソッド本体全体をラップしていることです。ブロックで未処理の例外が発生した場合、try実行はブロックに切り替わりますcatch

追加クレジット: ジェネリックとリフレクションを使用して WMI レポートを簡素化

UI に次のようなものが数千回表示される WMI クエリ オブジェクトから直接 UI に WMI 情報が表示されるかなりの数のインスタンスを見てきました。

lblName.Text = mgmtObjQuery["Name"]

これにより望ましい結果が得られますが、早期脱毛に至らない、より効率的な方法があります。PM が要件を拡張して、root\cimv2 からさらに 20 個のクラスを含めるまで待ちます。

ジェネリック、厳密に型指定されたクラス、およびリフレクションを使用して WMI 情報を取得する解決策を思いついたので、私のコードは次のようになりました。

lblName.Text = disk.Name;

まず、WMI クラスのモデルを作成します。クラス名とそのフィールド名はすべて、同じ WMI クラス名とフィールドに対応している必要があります。クラスとフィールドはパブリックである必要があり、データ型も C# データ型と一致する必要があります。

Win32_DiskDriveのMSDN リファレンスに移動し、次のようなクラスを生成します。

/// <summary>
/// A Win32_DiskDrive class based on 
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa394132(v=vs.85).aspx
/// </summary>
public class Win32_DiskDrive 
{
    public UInt16 Availability;
    public UInt32 BytesPerSector;
    public UInt16[] Capabilities ;
    public string[] CapabilityDescriptions ;
    public string Caption;
    public string CompressionMethod;
    public UInt32 ConfigManagerErrorCode;
    public bool ConfigManagerUserConfig;
    public string CreationClassName;
    public UInt64 DefaultBlockSize;
    public string Description;
    public string DeviceID;
    public bool ErrorCleared;
    public string ErrorDescription;
    public string ErrorMethodology;
    public string FirmwareRevision;
    public UInt32 Index;
    public DateTime InstallDate;
    public string InterfaceType;
    public UInt32 LastErrorCode;
    public string Manufacturer;
    public UInt64 MaxBlockSize;
    public UInt64 MaxMediaSize;
    public bool MediaLoaded;
    public string MediaType;
    public UInt64 MinBlockSize;
    public string Model;
    public string Name;
    public bool NeedsCleaning;
    public UInt32 NumberOfMediaSupported;
    public UInt32 Partitions;
    public string PNPDeviceID;
    public UInt16[] PowerManagementCapabilities ;
    public bool PowerManagementSupported;
    public UInt32 SCSIBus;
    public UInt16 SCSILogicalUnit;
    public UInt16 SCSIPort;
    public UInt16 SCSITargetId;
    public UInt32 SectorsPerTrack;
    public string SerialNumber;
    public UInt32 Signature;
    public UInt64 Size;
    public string Status;
    public UInt16 StatusInfo;
    public string SystemCreationClassName;
    public string SystemName;
    public UInt64 TotalCylinders;
    public UInt32 TotalHeads;
    public UInt64 TotalSectors;
    public UInt64 TotalTracks;
    public UInt32 TracksPerCylinder;

    public Win32_DiskDrive()
    {

    }
}

この一般的なメソッドは、面倒な作業を行います。この方法では、リフレクションを使用して、フィールド名を WMI クエリの結果にマップします。Null チェックと日時変換はすべて 1 か所で処理されます。

/// <summary>
/// Generic method that uses reflection for wiring up a local class to the corresponding win32_class and properties.
/// </summary>
/// <typeparam name="T">A class who's name and fields correspond to those of a WMI class.</typeparam>
/// <returns>A collection of WMI data.</returns>
public static IEnumerable<T> WmiSnapshot<T>()
{
    // The name of T must match that of the WMI class
    var searcher = new ManagementObjectSearcher(new SelectQuery(Activator.CreateInstance<T>().GetType().Name));

    foreach (ManagementObject managementObject in searcher.Get())
    {
        // Creates an instance of T
        var listItem = Activator.CreateInstance<T>();
        // an array of PUBLIC FIELDS of T
        var fields = listItem.GetType().GetFields();
        // matches a value from the WMI query to a field name
        foreach (FieldInfo field in fields)
        {
            if (managementObject[field.Name] != null)
            {
                field.SetValue(listItem,
                    field.FieldType == typeof(DateTime)
                        ? ManagementDateTimeConverter.ToDateTime(managementObject[field.Name].ToString())
                        : Convert.ChangeType(managementObject[field.Name], field.FieldType));
            }
        }
        yield return listItem;
    }
}

UI から呼び出すために、WMI クラスと WMI ヘルパー メソッドを独自のクラスに保持しています。UI コードは読みやすく、デバッグもはるかに簡単です。

このスナップショットの結果をコンソールに出力する簡単なサンプルを次に示します。

var disks = WmiHelper.WmiSnapshot<Win32_DiskDrive>().ToList(); 

StringBuilder sb = new StringBuilder(); 

foreach (Win32_DiskDrive disk in disks)
{
    sb.AppendFormat("SystemName: {0}\r\n", disk.SystemName);
    sb.AppendFormat("Type: {0}\r\n",  disk.MediaType);
    sb.AppendFormat("Model: {0}\r\n",  disk.Model);
    sb.AppendFormat("Capacity: {0}\r\n", disk.Size );
    sb.AppendFormat("Partitions: {0}\r\n", disk.Partitions);
    sb.AppendFormat("Sectors: {0}\r\n",  disk.SectorsPerTrack);
    sb.AppendFormat("Signature: {0}\r\n", disk.Signature);
    sb.AppendFormat("Firmware: {0}\r\n",  string.IsNullOrEmpty(disk.FirmwareRevision) ? "Not Available" : disk.FirmwareRevision);
    sb.AppendFormat("Capability Description: {0}\r\n", string.Join("\r\n", disk.CapabilityDescriptions));
    sb.AppendFormat("Availability: {0}\r\n", disk.Availability);
    sb.AppendFormat("Bytes per Sector: {0}\r\n", disk.BytesPerSector);
    sb.AppendFormat("Device ID: {0}\r\n", disk.DeviceID);
    sb.AppendLine();
}

Console.WriteLine(sb.ToString());

出力は次のようになります。

システム名: UVVXWVXXWV
タイプ: 固定ハードディスク メディア
モデル: ST9500420AS
容量: 500105249280
パーティション: 4
セクター: 63
署名: 2210653369
ファームウェア: 0006
機能の説明: ランダム アクセス
書き込みをサポート
SMART通知
可用性: 0
セクターあたりのバイト数: 512
デバイス ID: \\.\PHYSICALDRIVE0

Win32_ComputerSystemWin32_Productに対して同じことを繰り返します。

それがあなたを正しい方向に導くかどうか教えてください。

于 2012-09-24T21:06:09.930 に答える