我在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。从文档here开始,该方法将ccm_softwareupdate对象的数组作为参数,我从一个不同的类中成功查询(并在集合上运行foreach),因此我知道对象存在。
任何,因为这些是系统更新,我想一次安装一个,至少在测试期间,但是当我将单个对象数组传递给方法时
object[] args = { o };
c.InvokeMethod("InstallUpdates", args);
我收到施法错误:
无法转换类型&system; system.management.managementobject&#39;到system.array
所以在某个地方它显然只将我的数组视为一个对象。我知道它没有使用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
答案 0 :(得分:1)
我在寻找一种C#方式来触发CCM代理安装更新时遇到了这个问题。这就是我在生产应用程序中运行的内容。
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 } });