1

WMI をクエリし、WMI から返されたオブジェクトを別の WMI クラスのメソッドへのパラメーターとして使用する関数を C# で作成しています。

private void InstallUpdates()
{
    ManagementScope sc = new ManagementScope(@"\\.\root\ccm\clientsdk");
    ManagementClass c = new ManagementClass(@"CCM_SoftwareUpdatesManager");
    ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM CCM_SOFTWAREUPDATE WHERE COMPLIANCESTATE=0 AND EVALUATIONSTATE < 2");
    c.Scope = s.Scope = sc;

    ManagementObjectCollection col = s.Get();
    List<ManagementObject> lUpdates = new List<ManagementObject>();

    //Install each update individually and track progress
    int index = 1;
    foreach (ManagementObject o in col)
    {


        object[] args = { o };

        object[] methodArgs = { args, null };

        lblCurrentAction.Text = "Now running method: Install Updates " + o.Properties["Name"].Value + " EvalState=" + (UInt32)o.Properties["EvaluationState"].Value;

        c.InvokeMethod("InstallUpdates",methodArgs);

        lblCurrentUpdate.Text = "Now Installing Update " + index + " of " + col.Count + ": " + o.Properties["name"].Value;

        UInt32 intProgress = (UInt32)o.Properties["PercentComplete"].Value;

        UInt32 evalState = (UInt32)o.Properties["EvaluationState"].Value;

        lblCurrentAction.Text = lblCurrentAction.Text + " EvalState: " + evalState;

        while (evalState <=  7)
        {
            progressBar1.Value = (intProgress <= 100) ? (int)intProgress : 100;
            evalState = (UInt32)o.Properties["EvaluationState"].Value;
            intProgress = (UInt32)o.Properties["PercentComplete"].Value;
            lblCurrentAction.Text = lblCurrentAction.Text + " EvalState: " + evalState;
        }

        ++index;

    }





}

参照用に関数全体を貼り付けましたが、問題の行は foreach ループ内の #1、2、および 4 です。ドキュメントhereから、メソッドはパラメーターとして ccm_softwareupdate オブジェクトの配列を受け取ります。これは、別のクラスから正常にクエリされた (そしてコレクションに対して foreach を実行している) ため、オブジェクトが存在することがわかります。

これらはシステム アップデートであるため、少なくともテスト中は一度に 1 つずつインストールしたいのですが、単一のオブジェクト配列をメソッドに渡すと、

object[] args = { o };

c.InvokeMethod("InstallUpdates", args);

キャスト エラーが発生します。

タイプ「system.management.managementobject」のオブジェクトをsystem.arrayにキャストできません

そのため、明らかに私の配列を 1 つのオブジェクトとして認識しています。更新プログラムのインストールが開始されていないため、WMI メソッドに到達していないことはわかっています。

インターネットで読んだことから、現在の機能にあるものも試しました:

object[] args = { o };

object[] methodArgs = { args, null };

c.InvokeMethod("InstallUpdates", methodArgs);

ここで重要なのは、最初の配列と 2 番目の値として null 値を保持する2 番目の配列を作成することでした。これは実際に機能し、WMI メソッドが呼び出されますが、メソッドから戻ることはなく、コードがハングするだけです。引数を切り替える

object[] methodArgs = { null, args };

ここでは更新プログラムのインストールが開始されないため、null 引数で実際にハングすることが明らかになります。私もサニティチェックとしてこれを試しました

object[] args = { o, o };

c.InvokeMethod("InstallUpdates", args);

しかし、同じキャスト エラーが発生するため、double 配列メソッドを使用して正しい方向に進んでいる必要があります。また、

object[] methodArgs = { args, 0};

また

object[] methodArgs = { args };

うまくいきません。

繰り返しになりますが、C# を使用して配列を WMI メソッドに渡す方法を探しています。


アップデート

この PowerShell スクリプトは同じことを行い、実際に機能します。唯一の違いは、初期配列に複数のオブジェクトがあることですが、それは問題ではありません。

    #    '=================================================================== 
#    ' DISCLAIMER: 
#    '------------------------------------------------------------------- 
#    ' 
#    ' This sample is provided as is and is not meant for use on a  
#    ' production environment. It is provided only for illustrative  
#    ' purposes. The end user must test and modify the sample to suit  
#    ' their target environment. 
#    '  
#    ' Microsoft can make no representation concerning the content of  
#    ' this sample. Microsoft is providing this information only as a  
#    ' convenience to you. This is to inform you that Microsoft has not  
#    ' tested the sample and therefore cannot make any representations  
#    ' regarding the quality, safety, or suitability of any code or  
#    ' information found here. 
#    '  
#    '=================================================================== 

# This is a simpple get of all instances of CCM_SoftwareUpdate from root\CCM\ClientSDK 
$MissingUpdates = Get-WmiObject -Class CCM_SoftwareUpdate -Filter ComplianceState=0 -Namespace root\CCM\ClientSDK 

# The following is done to do 2 things: Get the missing updates (ComplianceState=0)  
# and take the PowerShell object and turn it into an array of WMI objects 
$MissingUpdatesReformatted = @($MissingUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}}) 

# The following is the invoke of the CCM_SoftwareUpdatesManager.InstallUpdates with our found updates 
# NOTE: the command in the ArgumentList is intentional, as it flattens the Object into a System.Array for us 
# The WMI method requires it in this format. 
$InstallReturn = Invoke-WmiMethod -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace root\ccm\clientsdk 
4

1 に答える 1