title: What's the proper way to pass an array to a WMI Method?
body: <p>I'm writing a function in C# that queries WMI, uses the objects returned from WMI as parameters to a method in a different WMI class. </p>
  
  <pre><code>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 &lt; 2");
      c.Scope = s.Scope = sc;
  
      ManagementObjectCollection col = s.Get();
      List&lt;ManagementObject&gt; lUpdates = new List&lt;ManagementObject&gt;();
  
      //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 &lt;=  7)
          {
              progressBar1.Value = (intProgress &lt;= 100) ? (int)intProgress : 100;
              evalState = (UInt32)o.Properties["EvaluationState"].Value;
              intProgress = (UInt32)o.Properties["PercentComplete"].Value;
              lblCurrentAction.Text = lblCurrentAction.Text + " EvalState: " + evalState;
          }
  
          ++index;
  
      }
  
  
  
  
  
  }
  </code></pre>
  
  <p>I pasted the entire function for reference, but the problem lines are #1,2, and 4 inside the foreach loop. From the documentation <a href="http://msdn.microsoft.com/en-us/library/jj155394.aspx" rel="nofollow">here</a> the method takes as a parameter an array of ccm_softwareupdate objects, which I've successfully queried from a different class (and am running a foreach on the collection), so I know that the objects exist. </p>
  
  <p>Any, as these are system updates, I'd like to install them one at a time, at least during testing, but when I pass a single object array to the method</p>
  
  <pre><code>object[] args = { o };
  
  c.InvokeMethod("InstallUpdates", args);
  </code></pre>
  
  <p>I get a cast error:</p>
  
  <blockquote>
    <p>unable to cast object of type 'system.management.managementobject' to system.array</p>
  </blockquote>
  
  <p>So somewhere it's obviously seeing my array as only one object. I know it's not making it to the WMI method because I don't see the update starting to install. </p>
  
  <p>From reading on the internet, I've also tried what's in the function now:</p>
  
  <pre><code>object[] args = { o };
  
  object[] methodArgs = { args, null };
  
  c.InvokeMethod("InstallUpdates", methodArgs);
  </code></pre>
  
  <p>The key here was to create a <em>second</em> array that holds the first array and a null value as the second value. This actually works and the WMI method is invoked, but it never <em>returns</em> from the method, the code just hangs. Switching the arguments around</p>
  
  <pre><code>object[] methodArgs = { null, args };
  </code></pre>
  
  <p>Reveals that it actually hangs on the null argument, because here the update never starts installing. I've also tried this as a sanity check</p>
  
  <pre><code>object[] args = { o, o };
  
  c.InvokeMethod("InstallUpdates", args);
  </code></pre>
  
  <p>But I get the same casting error, so I must be on the right track with the double array method. Also, using</p>
  
  <pre><code>object[] methodArgs = { args, 0};
  </code></pre>
  
  <p>or</p>
  
  <pre><code>object[] methodArgs = { args };
  </code></pre>
  
  <p>Doesn't work. </p>
  
  <p>To reiterate, I'm looking for a way to pass an array to a WMI Method using C#.</p>
  
  <hr>
  
  <p><strong>Update</strong></p>
  
  <p>This powershell script does the same thing, and actually works. The only difference is that it's initial array has more than one object, but that shouldn't matter.</p>
  
  <pre><code>    #    '=================================================================== 
  #    ' 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 
  </code></pre>