using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Management;
using DynamicProxy;
namespace WMI
{
//Reference: http://msdn2.microsoft.com/en-us/library/aa389390(VS.85).aspx
public enum ReturnValue
{
Success = 0,
NotSupported = 1,
AccessDenied = 2,
DependentServicesRunning = 3,
InvalidServiceControl = 4,
ServiceCannotAcceptControl = 5,
ServiceNotActive = 6,
ServiceRequestTimeout = 7,
UnknownFailure = 8,
PathNotFound = 9,
ServiceAlreadyRunning = 10,
ServiceDatabaseLocked = 11,
ServiceDependencyDeleted = 12,
ServiceDependencyFailure = 13,
ServiceDisabled = 14,
ServiceLogonFailure = 15,
ServiceMarkedForDeletion = 16,
ServiceNoThread = 17,
StatusCircularDependency = 18,
StatusDuplicateName = 19,
StatusInvalidName = 20,
StatusInvalidParameter = 21,
StatusInvalidServiceAccount = 22,
StatusServiceExists = 23,
ServiceAlreadyPaused = 24,
NoSuchService = 200
}
///
/// Signals a problem in WMI related operations
///
public class WmiException : Exception
{
public readonly ReturnValue ErrorCode;
public WmiException(string msg, ReturnValue code)
: base(msg)
{
ErrorCode = code;
}
public WmiException(ReturnValue code)
: this(code.ToString(), code)
{
}
}
///
/// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
///
public class WmiClassName : Attribute
{
public readonly string Name;
public WmiClassName(string name) { this.Name = name; }
}
///
/// Marker interface to denote a collection in WMI.
///
public interface IWmiCollection {}
///
/// Marker interface to denote an individual managed object
///
public interface IWmiObject
{
///
/// Reflect updates made to this object to the WMI provider.
///
void Commit();
}
public class WmiRoot
{
private readonly ManagementScope scope;
public WmiRoot() : this(null) { }
public WmiRoot(string machineName)
{
ConnectionOptions options = new ConnectionOptions();
options.EnablePrivileges = true;
options.Impersonation = ImpersonationLevel.Impersonate;
options.Authentication = AuthenticationLevel.PacketPrivacy;
string path;
if (machineName != null)
path = String.Format(@"\\{0}\root\cimv2", machineName);
else
path = @"\root\cimv2";
scope = new ManagementScope(path, options);
scope.Connect();
}
private static string capitalize(string s)
{
return char.ToUpper(s[0]) + s.Substring(1);
}
abstract class BaseHandler : IProxyInvocationHandler
{
public abstract object Invoke(object proxy, MethodInfo method, object[] args);
protected void CheckError(ManagementBaseObject result)
{
int code = Convert.ToInt32(result["returnValue"]);
if (code != 0)
throw new WmiException((ReturnValue)code);
}
}
class InstanceHandler : BaseHandler, IWmiObject
{
private readonly ManagementObject mo;
public InstanceHandler(ManagementObject o) { this.mo = o; }
public override object Invoke(object proxy, MethodInfo method, object[] args)
{
if (method.DeclaringType == typeof(IWmiObject))
{
return method.Invoke(this, args);
}
// TODO: proper property support
if (method.Name.StartsWith("set_"))
{
mo[method.Name.Substring(4)] = args[0];
return null;
}
if (method.Name.StartsWith("get_"))
{
return mo[method.Name.Substring(4)];
}
// method invocations
ParameterInfo[] methodArgs = method.GetParameters();
ManagementBaseObject wmiArgs = mo.GetMethodParameters(method.Name);
for (int i = 0; i < args.Length; i++)
wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
CheckError(mo.InvokeMethod(method.Name, wmiArgs, null));
return null;
}
public void Commit()
{
mo.Put();
}
}
class ClassHandler : BaseHandler
{
private readonly ManagementClass mc;
private readonly string wmiClass;
public ClassHandler(ManagementClass mc, string wmiClass) { this.mc = mc; this.wmiClass = wmiClass; }
public override object Invoke(object proxy, MethodInfo method, object[] args)
{
ParameterInfo[] methodArgs = method.GetParameters();
if (method.Name.StartsWith("Select"))
{
// select method to find instances
string query = "SELECT * FROM " + wmiClass + " WHERE ";
for (int i = 0; i < args.Length; i++)
{
if (i != 0) query += " AND ";
query += ' ' + capitalize(methodArgs[i].Name) + " = '" + args[i] + "'";
}
ManagementObjectSearcher searcher = new ManagementObjectSearcher(mc.Scope, new ObjectQuery(query));
ManagementObjectCollection results = searcher.Get();
// TODO: support collections
foreach (ManagementObject manObject in results)
return ProxyFactory.GetInstance().Create(new InstanceHandler(manObject), method.ReturnType, true);
return null;
}
ManagementBaseObject wmiArgs = mc.GetMethodParameters(method.Name);
for (int i = 0; i < args.Length; i++)
wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
CheckError(mc.InvokeMethod(method.Name, wmiArgs, null));
return null;
}
}
///
/// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
///
public T GetCollection() where T : IWmiCollection
{
WmiClassName cn = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
ObjectGetOptions getOptions = new ObjectGetOptions();
ManagementPath path = new ManagementPath(cn.Name);
ManagementClass manClass = new ManagementClass(scope, path, getOptions);
return (T)ProxyFactory.GetInstance().Create(new ClassHandler(manClass, cn.Name), typeof(T), true);
}
}
}