将数组传递给WMI方法的正确方法是什么?

本文关键字:方法 是什么 WMI 数组 | 更新日期: 2023-09-27 18:18:18

我正在c#中编写一个查询WMI的函数,使用从WMI返回的对象作为参数到不同WMI类中的方法。

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。从这里的文档中,该方法将ccm_softwareupdate对象数组作为参数,我已经成功地从不同的类中查询了该对象(并且正在对集合运行foreach),因此我知道对象存在。

任何,因为这些是系统更新,我希望一次安装一个,至少在测试期间,但是当我将单个对象数组传递给方法

object[] args = { o };
c.InvokeMethod("InstallUpdates", args);

我得到一个强制转换错误:

无法强制转换system.management类型的对象。管理对象

显然在某个地方它只把数组看作一个对象。我知道它没有进入WMI方法,因为我没有看到更新开始安装。

从网上阅读,我也尝试了什么是现在的功能:

object[] args = { o };
object[] methodArgs = { args, null };
c.InvokeMethod("InstallUpdates", methodArgs);
这里的关键是创建一个第二个数组,它保存第一个数组和一个空值作为第二个值。这实际上是有效的,并且调用了WMI方法,但是它从来没有从方法中返回,代码只是挂起。切换 周围的参数
object[] methodArgs = { null, args };

显示它实际上挂在null参数上,因为这里的更新从未开始安装。我也尝试过这作为一个完整性检查

object[] args = { o, o };
c.InvokeMethod("InstallUpdates", args);

但是我得到了相同的强制转换错误,所以我必须在正确的轨道上使用双数组方法。此外,使用

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 

将数组传递给WMI方法的正确方法是什么?

我在寻找一种c#方法来触发CCM Agent安装更新时遇到了这个问题。以下是我在生产应用程序中运行的代码。

using (var searcher = new ManagementObjectSearcher(string.Format(@"''{0}'root'CCM'ClientSDK", strComputerName), string.Format("SELECT * FROM CCM_SoftwareUpdate WHERE Name='"{0}'"", strUpdateName)))
foreach (var obj in searcher.Get())
    using (var mInv = new ManagementClass(string.Format(@"''{0}'root'CCM'ClientSDK", strComputerName), "CCM_SoftwareUpdatesManager", null))
        mInv.InvokeMethod("InstallUpdates", new object[] { new ManagementBaseObject[] { obj } });