Wmi.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Reflection;
  5. using System.Management;
  6. using DynamicProxy;
  7. namespace WMI
  8. {
  9. //Reference: http://msdn2.microsoft.com/en-us/library/aa389390(VS.85).aspx
  10. public enum ReturnValue
  11. {
  12. Success = 0,
  13. NotSupported = 1,
  14. AccessDenied = 2,
  15. DependentServicesRunning = 3,
  16. InvalidServiceControl = 4,
  17. ServiceCannotAcceptControl = 5,
  18. ServiceNotActive = 6,
  19. ServiceRequestTimeout = 7,
  20. UnknownFailure = 8,
  21. PathNotFound = 9,
  22. ServiceAlreadyRunning = 10,
  23. ServiceDatabaseLocked = 11,
  24. ServiceDependencyDeleted = 12,
  25. ServiceDependencyFailure = 13,
  26. ServiceDisabled = 14,
  27. ServiceLogonFailure = 15,
  28. ServiceMarkedForDeletion = 16,
  29. ServiceNoThread = 17,
  30. StatusCircularDependency = 18,
  31. StatusDuplicateName = 19,
  32. StatusInvalidName = 20,
  33. StatusInvalidParameter = 21,
  34. StatusInvalidServiceAccount = 22,
  35. StatusServiceExists = 23,
  36. ServiceAlreadyPaused = 24,
  37. NoSuchService = 200
  38. }
  39. /// <summary>
  40. /// Signals a problem in WMI related operations
  41. /// </summary>
  42. public class WmiException : Exception
  43. {
  44. public readonly ReturnValue ErrorCode;
  45. public WmiException(string msg, ReturnValue code)
  46. : base(msg)
  47. {
  48. ErrorCode = code;
  49. }
  50. public WmiException(ReturnValue code)
  51. : this(code.ToString(), code)
  52. {
  53. }
  54. }
  55. /// <summary>
  56. /// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
  57. /// </summary>
  58. public class WmiClassName : Attribute
  59. {
  60. public readonly string Name;
  61. public WmiClassName(string name) { this.Name = name; }
  62. }
  63. /// <summary>
  64. /// Marker interface to denote a collection in WMI.
  65. /// </summary>
  66. public interface IWmiCollection {}
  67. /// <summary>
  68. /// Marker interface to denote an individual managed object
  69. /// </summary>
  70. public interface IWmiObject
  71. {
  72. /// <summary>
  73. /// Reflect updates made to this object to the WMI provider.
  74. /// </summary>
  75. void Commit();
  76. }
  77. public class WmiRoot
  78. {
  79. private readonly ManagementScope scope;
  80. public WmiRoot() : this(null) { }
  81. public WmiRoot(string machineName)
  82. {
  83. ConnectionOptions options = new ConnectionOptions();
  84. options.EnablePrivileges = true;
  85. options.Impersonation = ImpersonationLevel.Impersonate;
  86. options.Authentication = AuthenticationLevel.PacketPrivacy;
  87. string path;
  88. if (machineName != null)
  89. path = String.Format(@"\\{0}\root\cimv2", machineName);
  90. else
  91. path = @"\root\cimv2";
  92. scope = new ManagementScope(path, options);
  93. scope.Connect();
  94. }
  95. private static string capitalize(string s)
  96. {
  97. return char.ToUpper(s[0]) + s.Substring(1);
  98. }
  99. abstract class BaseHandler : IProxyInvocationHandler
  100. {
  101. public abstract object Invoke(object proxy, MethodInfo method, object[] args);
  102. protected void CheckError(ManagementBaseObject result)
  103. {
  104. int code = Convert.ToInt32(result["returnValue"]);
  105. if (code != 0)
  106. throw new WmiException((ReturnValue)code);
  107. }
  108. }
  109. class InstanceHandler : BaseHandler, IWmiObject
  110. {
  111. private readonly ManagementObject mo;
  112. public InstanceHandler(ManagementObject o) { this.mo = o; }
  113. public override object Invoke(object proxy, MethodInfo method, object[] args)
  114. {
  115. if (method.DeclaringType == typeof(IWmiObject))
  116. {
  117. return method.Invoke(this, args);
  118. }
  119. // TODO: proper property support
  120. if (method.Name.StartsWith("set_"))
  121. {
  122. mo[method.Name.Substring(4)] = args[0];
  123. return null;
  124. }
  125. if (method.Name.StartsWith("get_"))
  126. {
  127. return mo[method.Name.Substring(4)];
  128. }
  129. // method invocations
  130. ParameterInfo[] methodArgs = method.GetParameters();
  131. ManagementBaseObject wmiArgs = mo.GetMethodParameters(method.Name);
  132. for (int i = 0; i < args.Length; i++)
  133. wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
  134. CheckError(mo.InvokeMethod(method.Name, wmiArgs, null));
  135. return null;
  136. }
  137. public void Commit()
  138. {
  139. mo.Put();
  140. }
  141. }
  142. class ClassHandler : BaseHandler
  143. {
  144. private readonly ManagementClass mc;
  145. private readonly string wmiClass;
  146. public ClassHandler(ManagementClass mc, string wmiClass) { this.mc = mc; this.wmiClass = wmiClass; }
  147. public override object Invoke(object proxy, MethodInfo method, object[] args)
  148. {
  149. ParameterInfo[] methodArgs = method.GetParameters();
  150. if (method.Name.StartsWith("Select"))
  151. {
  152. // select method to find instances
  153. string query = "SELECT * FROM " + wmiClass + " WHERE ";
  154. for (int i = 0; i < args.Length; i++)
  155. {
  156. if (i != 0) query += " AND ";
  157. query += ' ' + capitalize(methodArgs[i].Name) + " = '" + args[i] + "'";
  158. }
  159. ManagementObjectSearcher searcher = new ManagementObjectSearcher(mc.Scope, new ObjectQuery(query));
  160. ManagementObjectCollection results = searcher.Get();
  161. // TODO: support collections
  162. foreach (ManagementObject manObject in results)
  163. return ProxyFactory.GetInstance().Create(new InstanceHandler(manObject), method.ReturnType, true);
  164. return null;
  165. }
  166. ManagementBaseObject wmiArgs = mc.GetMethodParameters(method.Name);
  167. for (int i = 0; i < args.Length; i++)
  168. wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
  169. CheckError(mc.InvokeMethod(method.Name, wmiArgs, null));
  170. return null;
  171. }
  172. }
  173. /// <summary>
  174. /// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
  175. /// </summary>
  176. public T GetCollection<T>() where T : IWmiCollection
  177. {
  178. WmiClassName cn = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
  179. ObjectGetOptions getOptions = new ObjectGetOptions();
  180. ManagementPath path = new ManagementPath(cn.Name);
  181. ManagementClass manClass = new ManagementClass(scope, path, getOptions);
  182. return (T)ProxyFactory.GetInstance().Create(new ClassHandler(manClass, cn.Name), typeof(T), true);
  183. }
  184. }
  185. }