1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections; 6 using System.Runtime.InteropServices; 7 8 namespace System.Management 9 { 10 //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC// 11 /// <summary> 12 /// <para> Represents the set of methods available in the collection.</para> 13 /// </summary> 14 /// <example> 15 /// <code lang='C#'>using System; 16 /// using System.Management; 17 /// 18 /// // This sample demonstrates enumerate all methods in a ManagementClass object. 19 /// class Sample_MethodDataCollection 20 /// { 21 /// public static int Main(string[] args) { 22 /// ManagementClass diskClass = new ManagementClass("win32_logicaldisk"); 23 /// MethodDataCollection diskMethods = diskClass.Methods; 24 /// foreach (MethodData method in diskMethods) { 25 /// Console.WriteLine("Method = " + method.Name); 26 /// } 27 /// return 0; 28 /// } 29 /// } 30 /// </code> 31 /// <code lang='VB'>Imports System 32 /// Imports System.Management 33 /// 34 /// ' This sample demonstrates enumerate all methods in a ManagementClass object. 35 /// Class Sample_MethodDataCollection 36 /// Overloads Public Shared Function Main(args() As String) As Integer 37 /// Dim diskClass As New ManagementClass("win32_logicaldisk") 38 /// Dim diskMethods As MethodDataCollection = diskClass.Methods 39 /// Dim method As MethodData 40 /// For Each method In diskMethods 41 /// Console.WriteLine("Method = " & method.Name) 42 /// Next method 43 /// Return 0 44 /// End Function 45 /// End Class 46 /// </code> 47 /// </example> 48 //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC// 49 public class MethodDataCollection : ICollection, IEnumerable 50 { 51 private ManagementObject parent; 52 53 private class enumLock 54 { 55 } //used to lock usage of BeginMethodEnum/NextMethod 56 MethodDataCollection(ManagementObject parent)57 internal MethodDataCollection(ManagementObject parent) : base() 58 { 59 this.parent = parent; 60 } 61 62 // 63 //ICollection 64 // 65 66 /// <summary> 67 /// <para>Represents the number of objects in the <see cref='System.Management.MethodDataCollection'/>.</para> 68 /// </summary> 69 /// <value> 70 /// <para> The number of objects in the <see cref='System.Management.MethodDataCollection'/>. </para> 71 /// </value> 72 public int Count 73 { 74 get 75 { 76 int i = 0; 77 IWbemClassObjectFreeThreaded inParameters = null, outParameters = null; 78 string methodName; 79 int status = (int)ManagementStatus.Failed; 80 81 #pragma warning disable CA2002 82 lock(typeof(enumLock)) 83 #pragma warning restore CA2002 84 { 85 try 86 { 87 status = parent.wbemObject.BeginMethodEnumeration_(0); 88 89 if (status >= 0) 90 { 91 methodName = ""; // Condition primer to branch into the while loop. 92 while (methodName != null && status >= 0 && status != (int)tag_WBEMSTATUS.WBEM_S_NO_MORE_DATA) 93 { 94 methodName = null; inParameters = null; outParameters = null; 95 status = parent.wbemObject.NextMethod_(0, out methodName, out inParameters, out outParameters); 96 if (status >= 0 && status != (int)tag_WBEMSTATUS.WBEM_S_NO_MORE_DATA) 97 i++; 98 } 99 parent.wbemObject.EndMethodEnumeration_(); // Ignore status. 100 } 101 } 102 catch (COMException e) 103 { 104 ManagementException.ThrowWithExtendedInfo(e); 105 } 106 } // lock 107 108 if ((status & 0xfffff000) == 0x80041000) 109 { 110 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 111 } 112 else if ((status & 0x80000000) != 0) 113 { 114 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 115 } 116 117 return i; 118 } 119 } 120 121 /// <summary> 122 /// <para>Indicates whether the object is synchronized.</para> 123 /// </summary> 124 /// <value> 125 /// <para><see langword='true'/> if the object is synchronized; 126 /// otherwise, <see langword='false'/>.</para> 127 /// </value> 128 public bool IsSynchronized { get { return false; } 129 } 130 131 /// <summary> 132 /// <para>Represents the object to be used for synchronization.</para> 133 /// </summary> 134 /// <value> 135 /// <para>The object to be used for synchronization.</para> 136 /// </value> 137 public object SyncRoot { get { return this; } 138 } 139 140 /// <overload> 141 /// <para>Copies the <see cref='System.Management.MethodDataCollection'/> into an array.</para> 142 /// </overload> 143 /// <summary> 144 /// <para> Copies the <see cref='System.Management.MethodDataCollection'/> into an array.</para> 145 /// </summary> 146 /// <param name='array'>The array to which to copy the collection. </param> 147 /// <param name='index'>The index from which to start. </param> CopyTo(Array array, int index)148 public void CopyTo(Array array, int index) 149 { 150 //Use an enumerator to get the MethodData objects and attach them into the target array 151 foreach (MethodData m in this) 152 array.SetValue(m, index++); 153 } 154 155 /// <summary> 156 /// <para>Copies the <see cref='System.Management.MethodDataCollection'/> to a specialized <see cref='System.Management.MethodData'/> 157 /// array.</para> 158 /// </summary> 159 /// <param name='methodArray'>The destination array to which to copy the <see cref='System.Management.MethodData'/> objects.</param> 160 /// <param name=' index'>The index in the destination array from which to start the copy.</param> CopyTo(MethodData[] methodArray, int index)161 public void CopyTo(MethodData[] methodArray, int index) 162 { 163 CopyTo((Array)methodArray, index); 164 } 165 166 // 167 // IEnumerable 168 // IEnumerable.GetEnumerator()169 IEnumerator IEnumerable.GetEnumerator() 170 { 171 return (IEnumerator)(new MethodDataEnumerator(parent)); 172 } 173 174 /// <summary> 175 /// <para>Returns an enumerator for the <see cref='System.Management.MethodDataCollection'/>.</para> 176 /// </summary> 177 /// <remarks> 178 /// <para> Each call to this method 179 /// returns a new enumerator on the collection. Multiple enumerators can be obtained 180 /// for the same method collection. However, each enumerator takes a snapshot 181 /// of the collection, so changes made to the collection after the enumerator was 182 /// obtained are not reflected.</para> 183 /// </remarks> 184 /// <returns>An <see cref="System.Collections.IEnumerator"/> to enumerate through the collection.</returns> GetEnumerator()185 public MethodDataEnumerator GetEnumerator() 186 { 187 return new MethodDataEnumerator(parent); 188 } 189 190 //Enumerator class 191 /// <summary> 192 /// <para>Represents the enumerator for <see cref='System.Management.MethodData'/> 193 /// objects in the <see cref='System.Management.MethodDataCollection'/>.</para> 194 /// </summary> 195 /// <example> 196 /// <code lang='C#'>using System; 197 /// using System.Management; 198 /// 199 /// // This sample demonstrates how to enumerate all methods in 200 /// // Win32_LogicalDisk class using MethodDataEnumerator object. 201 /// 202 /// class Sample_MethodDataEnumerator 203 /// { 204 /// public static int Main(string[] args) 205 /// { 206 /// ManagementClass diskClass = new ManagementClass("win32_logicaldisk"); 207 /// MethodDataCollection.MethodDataEnumerator diskEnumerator = 208 /// diskClass.Methods.GetEnumerator(); 209 /// while(diskEnumerator.MoveNext()) 210 /// { 211 /// MethodData method = diskEnumerator.Current; 212 /// Console.WriteLine("Method = " + method.Name); 213 /// } 214 /// return 0; 215 /// } 216 /// } 217 /// </code> 218 /// <code lang='VB'>Imports System 219 /// Imports System.Management 220 /// 221 /// ' This sample demonstrates how to enumerate all methods in 222 /// ' Win32_LogicalDisk class using MethodDataEnumerator object. 223 /// 224 /// Class Sample_MethodDataEnumerator 225 /// Overloads Public Shared Function Main(args() As String) As Integer 226 /// Dim diskClass As New ManagementClass("win32_logicaldisk") 227 /// Dim diskEnumerator As _ 228 /// MethodDataCollection.MethodDataEnumerator = _ 229 /// diskClass.Methods.GetEnumerator() 230 /// While diskEnumerator.MoveNext() 231 /// Dim method As MethodData = diskEnumerator.Current 232 /// Console.WriteLine("Method = " & method.Name) 233 /// End While 234 /// Return 0 235 /// End Function 236 /// End Class 237 /// </code> 238 /// </example> 239 public class MethodDataEnumerator : IEnumerator 240 { 241 private ManagementObject parent; 242 private ArrayList methodNames; //can't use simple array because we don't know the size... 243 private IEnumerator en; 244 245 //Internal constructor 246 //Because WMI doesn't provide a "GetMethodNames" for methods similar to "GetNames" for properties, 247 //We have to walk the methods list and cache the names here. 248 //We lock to ensure that another thread doesn't interfere in the Begin/Next sequence. MethodDataEnumerator(ManagementObject parent)249 internal MethodDataEnumerator(ManagementObject parent) 250 { 251 this.parent = parent; 252 methodNames = new ArrayList(); 253 IWbemClassObjectFreeThreaded inP = null, outP = null; 254 string tempMethodName; 255 int status = (int)ManagementStatus.Failed; 256 257 #pragma warning disable CA2002 258 lock(typeof(enumLock)) 259 #pragma warning restore CA2002 260 { 261 try 262 { 263 status = parent.wbemObject.BeginMethodEnumeration_(0); 264 265 if (status >= 0) 266 { 267 tempMethodName = ""; // Condition primer to branch into the while loop. 268 while (tempMethodName != null && status >= 0 && status != (int)tag_WBEMSTATUS.WBEM_S_NO_MORE_DATA) 269 { 270 tempMethodName = null; 271 status = parent.wbemObject.NextMethod_(0, out tempMethodName, out inP, out outP); 272 if (status >= 0 && status != (int)tag_WBEMSTATUS.WBEM_S_NO_MORE_DATA) 273 methodNames.Add(tempMethodName); 274 } 275 parent.wbemObject.EndMethodEnumeration_(); // Ignore status. 276 } 277 } 278 catch (COMException e) 279 { 280 ManagementException.ThrowWithExtendedInfo(e); 281 } 282 en = methodNames.GetEnumerator(); 283 } 284 285 if ((status & 0xfffff000) == 0x80041000) 286 { 287 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 288 } 289 else if ((status & 0x80000000) != 0) 290 { 291 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 292 } 293 } 294 295 /// <internalonly/> 296 object IEnumerator.Current { get { return (object)this.Current; } } 297 298 /// <summary> 299 /// <para>Returns the current <see cref='System.Management.MethodData'/> in the <see cref='System.Management.MethodDataCollection'/> 300 /// enumeration.</para> 301 /// </summary> 302 /// <value>The current <see cref='System.Management.MethodData'/> item in the collection.</value> 303 public MethodData Current 304 { 305 get 306 { 307 return new MethodData(parent, (string)en.Current); 308 } 309 } 310 311 /// <summary> 312 /// <para>Moves to the next element in the <see cref='System.Management.MethodDataCollection'/> enumeration.</para> 313 /// </summary> 314 /// <returns><see langword='true'/> if the enumerator was successfully advanced to the next method; <see langword='false'/> if the enumerator has passed the end of the collection.</returns> MoveNext()315 public bool MoveNext () 316 { 317 return en.MoveNext(); 318 } 319 320 /// <summary> 321 /// <para>Resets the enumerator to the beginning of the <see cref='System.Management.MethodDataCollection'/> enumeration.</para> 322 /// </summary> Reset()323 public void Reset() 324 { 325 en.Reset(); 326 } 327 328 }//MethodDataEnumerator 329 330 331 // 332 //Methods 333 // 334 335 /// <summary> 336 /// <para>Returns the specified <see cref='System.Management.MethodData'/> from the <see cref='System.Management.MethodDataCollection'/>.</para> 337 /// </summary> 338 /// <param name='methodName'>The name of the method requested.</param> 339 /// <value>A <see cref='System.Management.MethodData'/> instance containing all information about the specified method.</value> 340 public virtual MethodData this[string methodName] 341 { 342 get 343 { 344 if (null == methodName) 345 throw new ArgumentNullException ("methodName"); 346 347 return new MethodData(parent, methodName); 348 } 349 } 350 351 352 /// <summary> 353 /// <para>Removes a <see cref='System.Management.MethodData'/> from the <see cref='System.Management.MethodDataCollection'/>.</para> 354 /// </summary> 355 /// <param name='methodName'>The name of the method to remove from the collection.</param> 356 /// <remarks> 357 /// <para> 358 /// Removing <see cref='System.Management.MethodData'/> objects from the <see cref='System.Management.MethodDataCollection'/> 359 /// can only be done when the class has no 360 /// instances. Any other case will result in an exception.</para> 361 /// </remarks> Remove(string methodName)362 public virtual void Remove(string methodName) 363 { 364 if (parent.GetType() == typeof(ManagementObject)) //can't remove methods from instance 365 throw new InvalidOperationException(); 366 367 int status = (int)ManagementStatus.Failed; 368 369 try 370 { 371 status = parent.wbemObject.DeleteMethod_(methodName); 372 } 373 catch (COMException e) 374 { 375 ManagementException.ThrowWithExtendedInfo(e); 376 } 377 378 if ((status & 0xfffff000) == 0x80041000) 379 { 380 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 381 } 382 else if ((status & 0x80000000) != 0) 383 { 384 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 385 } 386 } 387 388 //This variant takes only a method name and assumes a void method with no in/out parameters 389 /// <overload> 390 /// <para>Adds a <see cref='System.Management.MethodData'/> to the <see cref='System.Management.MethodDataCollection'/>.</para> 391 /// </overload> 392 /// <summary> 393 /// <para>Adds a <see cref='System.Management.MethodData'/> to the <see cref='System.Management.MethodDataCollection'/>. This overload will 394 /// add a new method with no parameters to the collection.</para> 395 /// </summary> 396 /// <param name='methodName'>The name of the method to add.</param> 397 /// <remarks> 398 /// <para> Adding <see cref='System.Management.MethodData'/> objects to the <see cref='System.Management.MethodDataCollection'/> can only 399 /// be done when the class has no instances. Any other case will result in an 400 /// exception.</para> 401 /// </remarks> Add(string methodName)402 public virtual void Add(string methodName) 403 { 404 Add(methodName, null, null); 405 } 406 407 408 409 //This variant takes the full information, i.e. the method name and in & out param objects 410 /// <summary> 411 /// <para>Adds a <see cref='System.Management.MethodData'/> to the <see cref='System.Management.MethodDataCollection'/>. This overload will add a new method with the 412 /// specified parameter objects to the collection.</para> 413 /// </summary> 414 /// <param name='methodName'>The name of the method to add.</param> 415 /// <param name=' inParameters'>The <see cref='System.Management.ManagementBaseObject'/> holding the input parameters to the method.</param> 416 /// <param name=' outParameters'>The <see cref='System.Management.ManagementBaseObject'/> holding the output parameters to the method.</param> 417 /// <remarks> 418 /// <para> Adding <see cref='System.Management.MethodData'/> objects to the <see cref='System.Management.MethodDataCollection'/> can only be 419 /// done when the class has no instances. Any other case will result in an 420 /// exception.</para> 421 /// </remarks> Add(string methodName, ManagementBaseObject inParameters, ManagementBaseObject outParameters)422 public virtual void Add(string methodName, ManagementBaseObject inParameters, ManagementBaseObject outParameters) 423 { 424 IWbemClassObjectFreeThreaded wbemIn = null, wbemOut = null; 425 426 if (parent.GetType() == typeof(ManagementObject)) //can't add methods to instance 427 throw new InvalidOperationException(); 428 429 if (inParameters != null) 430 wbemIn = inParameters.wbemObject; 431 if (outParameters != null) 432 wbemOut = outParameters.wbemObject; 433 434 int status = (int)ManagementStatus.Failed; 435 436 try 437 { 438 status = parent.wbemObject.PutMethod_(methodName, 0, wbemIn, wbemOut); 439 } 440 catch (COMException e) 441 { 442 ManagementException.ThrowWithExtendedInfo(e); 443 } 444 445 if ((status & 0xfffff000) == 0x80041000) 446 { 447 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 448 } 449 else if ((status & 0x80000000) != 0) 450 { 451 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 452 } 453 } 454 455 }//MethodDataCollection 456 } 457