namespace Microsoft.VSDesigner.WMI {
using System.Runtime.Serialization;
using System.Diagnostics;
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using Microsoft.VSDesigner;
using Microsoft.VSDesigner.ServerExplorer;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Resources;
using System.Reflection;
using System.Management;
using System.Threading;
using System.Net;
using EnvDTE;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
//
//
// This represents the wmi classes node under a server node.
//
//
[UserContextAttribute("serveritem", "wmiclass")]
internal class WMIClassNode : Node, ISerializable {
//
// FIELDS
//
private Image icon = null;
public static readonly Type parentType = typeof(WMIClassesNode);
private string label = string.Empty;
public readonly string path = string.Empty;
public readonly string pathNoServer = string.Empty;
private string serverName = string.Empty;
private string nsName = string.Empty;
private string className = string.Empty;
private string connectAs = null;
private string password = null;
private ManagementClass mgmtObj = null;
// private NewChildNode newChildNode = null;
//
// CONSTRUCTORS
//
//
//
// Main constructor.
// Parameters:
// string server (in, machine name)
// string pathIn (in, WMI path without the server name , e.g. "root\default:MyClass")
//
//
public WMIClassNode(string pathIn, string user, string pw) {
try
{
path = pathIn;
connectAs = user;
password = pw;
//parse the path to get server, namespace and class name
Int32 separ = path.IndexOf ("\\", 2 );
if (separ == -1)
{
//invalid path
throw (new ArgumentException(WMISys.GetString("WMISE_InvalidPath", pathIn), "pathIn"));
}
serverName = path.Substring(2, separ - 2);
pathNoServer = path.Substring(separ + 1, path.Length - separ - 1);
//split pathNoServer into namespace and classname parts (':' is the separator)
Int32 colon = pathNoServer.IndexOf(':', 0);
if (colon == -1)
{
//invalid path
throw (new ArgumentException(WMISys.GetString("WMISE_InvalidPath, pathIn"), "pathIn"));
}
nsName = pathNoServer.Substring(0,colon);
className = pathNoServer.Substring(colon + 1, pathNoServer.Length - colon - 1);
//Get and cache mgmtObj
ConnectionOptions connectOpts = new ConnectionOptions(
"", //locale
this.connectAs, //username
this.password, //password
"", //authority
ImpersonationLevel.Impersonate,
AuthenticationLevel.Connect,
true, //enablePrivileges
null //context
);
ManagementScope scope = (this.serverName == WmiHelper.DNS2UNC(Dns.GetHostName())) ?
new ManagementScope(WmiHelper.MakeNSPath(serverName, nsName)):
new ManagementScope(WmiHelper.MakeNSPath(serverName, nsName), connectOpts);
mgmtObj = new ManagementClass(scope,
new ManagementPath(path),
new ObjectGetOptions(null,
true) //use amended
);
//NOTE: let's exercise the retrieved object to validate it
//This will throw if object is invalid
string classPath = mgmtObj.ClassPath.Path;
}
catch (Exception exc)
{
//MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
throw (exc);
}
}
///
/// The object retrieves its serialization info.
///
public WMIClassNode(SerializationInfo info, StreamingContext context) {
try
{
path = info.GetString("Path");
connectAs = info.GetString("ConnectAs");
password = info.GetString("Password");
//parse the path to get server, namespace and class name
Int32 separ = path.IndexOf ("\\", 2);
if (separ == -1)
{
//invalid path
throw (new ArgumentException(WMISys.GetString("WMISE_InvalidPath", path), "Path"));
}
serverName = path.Substring(2, separ - 2);
pathNoServer = path.Substring(separ + 1, path.Length - separ - 1);
//split pathNoServer into namespace and classname parts (':' is the separator)
Int32 colon = pathNoServer.IndexOf(':', 0);
if (colon == -1)
{
//invalid path
throw (new ArgumentException(WMISys.GetString("WMISE_InvalidPath", path), "Path"));
}
nsName = pathNoServer.Substring(0,colon);
className = pathNoServer.Substring(colon + 1, pathNoServer.Length - colon - 1);
//Get and cache mgmtObj
ConnectionOptions connectOpts = new ConnectionOptions(
"", //locale
this.connectAs, //username
this.password, //password
"", //authority
ImpersonationLevel.Impersonate,
AuthenticationLevel.Connect,
true, //enablePrivileges
null //context
);
ManagementScope scope = (this.serverName == WmiHelper.DNS2UNC(Dns.GetHostName())) ?
new ManagementScope(WmiHelper.MakeNSPath(serverName, nsName)):
new ManagementScope(WmiHelper.MakeNSPath(serverName, nsName), connectOpts);
mgmtObj = new ManagementClass(scope,
new ManagementPath(path),
new ObjectGetOptions(null,
true) //use amended
);
//NOTE: let's exercise the retrieved object to validate it
//This will throw if object is invalid (e.g., has been deleted
// since devenv was run last time)
string classPath = mgmtObj.ClassPath.Path;
}
catch (Exception exc) {
throw (exc);
}
}
//
// PROPERTIES
//
//
//
// Returns icon for this node.
//
//
public override Image Icon {
get {
if (icon == null)
{
icon = WmiHelper.GetClassIconFromResource(this.pathNoServer, true, GetType());
if (icon == null)
{
icon = WmiHelper.defaultClassIcon;
}
}
return icon;
}
}
///
/// Context menu for a class object contains static method names
///
public override ContextMenuItem[] GetContextMenuItems()
{
try
{
//System.Threading.Thread.CurrentThread.ApartmentState = ApartmentState.MTA;
ManagementClass localObj = mgmtObj;
MethodCollection methods = null;
try
{
int methodCount = localObj.Methods.Count;
}
catch (Exception)
{
ConnectionOptions connectOpts = new ConnectionOptions(
"", //locale
this.connectAs, //username
this.password, //password
"", //authority
ImpersonationLevel.Impersonate,
AuthenticationLevel.Connect,
true, //enablePrivileges
null //context
);
ManagementScope scope = (this.serverName == WmiHelper.DNS2UNC(Dns.GetHostName())) ?
new ManagementScope(WmiHelper.MakeNSPath(serverName, nsName)):
new ManagementScope(WmiHelper.MakeNSPath(serverName, nsName), connectOpts);
localObj = new ManagementClass(scope,
new ManagementPath(path),
new ObjectGetOptions(null,
true) //use amended
);
}
methods = localObj.Methods;
/*
string propNames = "";
foreach (System.Management.Property prop in mgmtObj.Properties)
{
propNames += prop.Name + "\n";
}
MessageBox.Show(propNames);
MessageBox.Show("class has " + mgmtObj.Properties.Count + " properties");
string methNames = "";
foreach (Method meth in methods)
{
methNames += meth.Name + "\n";
}
MessageBox.Show(methNames);
*/
Project[] projects = VSUtils.GetProjects(GetNodeSite());
bool enableCodeGen = false;
if (projects != null && projects.Length != 0)
{
ICodeGenerator codeGen = VSUtils.MapProjectGuidToCodeGenerator(new Guid(projects[0].Kind));
if (codeGen == null)
{
MessageBox.Show("codeGen is null, project is: " + projects[0].Kind);
}
enableCodeGen = (codeGen != null);
}
ContextMenuItem[] theMenu = new ContextMenuItem[methods.Count + 2];
//theMenu[0] = new ContextMenuItem("&View All Instances...", new EventHandler(OnExpandAll));
//theMenu[1] = new ContextMenuItem("&Filter Instances...", new EventHandler(OnAddInstanceFilter));
theMenu[0] = new ContextMenuItem(WMISys.GetString("WMISE_ClassNode_CreateNewInstance"),
new EventHandler(OnCreateNewInstance),
false);
theMenu[1] = new ContextMenuItem(WMISys.GetString("WMISE_ClassNode_GenerateWrapper"),
new EventHandler(OnGenerateWrapper),
enableCodeGen);
int i = 2;
//Retrieve static methods for the class and add them to context menu
MethodCollection.MethodEnumerator methEnum = methods.GetEnumerator();
while (methEnum.MoveNext())
{
Method meth = methEnum.Current;
if (WmiHelper.IsStaticMethod(meth) && WmiHelper.IsImplementedMethod(meth))
{
//add method name to context menu
theMenu[i] = new ContextMenuItem("&" + i.ToString() + " " + meth.Name + "...", //TODO: hotkey???
new EventHandler(OnExecuteMethod));
i++;
}
}
methEnum = null;
return theMenu;
}
/*
catch (ManagementException exc)
{
MessageBox.Show("ManagementException hr is " + exc.ErrorCode.ToString());
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
return null;
}
*/
catch (Exception exc)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
return null;
}
}
public override bool CanDeleteNode()
{
return true;
}
public override bool ConfirmDeletingNode()
{
DialogResult res = MessageBox.Show(WMISys.GetString("WMISE_ClassNode_RemovePrompt", className),
/*SR.GetString("SE_MessageBoxTitle_ServerExplorer"), */ string.Empty,
MessageBoxButtons.YesNo);
return (res == DialogResult.Yes);
}
//
//
// Returns label constant for this node.
//
//
public override string Label {
get {
if (label == null || label.Length == 0) {
label = className;
if (WmiHelper.UseFriendlyNames)
{
string strFriendly = WmiHelper.GetDisplayName(mgmtObj, this.connectAs, this.password);
if (strFriendly != string.Empty)
{
label = strFriendly;
}
}
}
return label;
}
set {
}
}
//
// METHODS
//
//
//
// Create instance nodes under this node.
//
//
public override Node[] CreateChildren() {
try
{
GetInstancesOptions opts = new GetInstancesOptions(null, //context
new TimeSpan(Int64.MaxValue), //timeout:30 sec
50, //block size
false, //non-rewindable
false, //return immediately
true, //use amended
true, //enumerate deep
false //direct read
);
ManagementObjectCollection instCollection = mgmtObj.GetInstances(opts);
ArrayList arNodes = new ArrayList(50);
foreach (ManagementObject obj in instCollection)
{
arNodes.Add(new WMIInstanceNode(obj,
mgmtObj,
this.connectAs,
this.password));
}
Node[] nodes = new Node[arNodes.Count];
arNodes.CopyTo(nodes);
return nodes;
}
catch(Exception exc)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
return null;
}
}
//
//
// This node is a singleton.
//
//
public override int CompareUnique(Node node) {
if (this.path == ((WMIClassNode)node).path)
{
return 0;
}
return Label.CompareTo(node.Label);
}
private void OnExpandAll(object sender, EventArgs e) {
try
{
//TODO: this needs to be changed to do something more meaningful
GetNodeSite().Expand();
}
catch(Exception exc)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
}
}
private void OnAddInstanceFilter(object sender, EventArgs e) {
try
{
MessageBox.Show("Not implemented yet");
}
catch(Exception exc)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
}
}
///
/// Get component to be displayed in PB window
///
public override Object GetBrowseComponent()
{
return new WMIObjectComponent(mgmtObj, mgmtObj);
}
///
/// Execute static method against WMI class
///
///
///
private void OnExecuteMethod(object sender, EventArgs e)
{
try
{
//trim the ordinal prefix (all up to first space)
//and 3 dots off the end of the context menu text to get method name
String methName = ((ContextMenuItem)sender).Text.Substring(0, ((ContextMenuItem)sender).Text.Length - 3);
int spaceIndex = methName.IndexOf(' ', 0);
methName = methName.Substring(spaceIndex + 1);
//get method object
Method meth = ((ManagementClass)mgmtObj).Methods[methName];
ExecuteMethodDialog dlg = new ExecuteMethodDialog(mgmtObj, meth, mgmtObj);
DialogResult res = dlg.ShowDialog();
}
catch(Exception exc)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
}
}
///
/// Generates early-bound object wrapper
///
///
///
private void OnGenerateWrapper (object sender, EventArgs e)
{
try
{
//Get current Project:
Project[] projects = VSUtils.GetProjects(GetNodeSite());
if (projects == null || projects.Length == 0)
{
return;
}
//This is an assumtion that's working so far.
//TODO: verify if this is the right way to determine the startup project
//in the solution:
Project curProject = projects[0];
string curProjSuffix = VSUtils.MapProjectGuidToSuffix(new Guid(curProject.Kind));
if (curProjSuffix == string.Empty)
{
//neither a VB nor a CS project
throw new Exception(WMISys.GetString("WMISE_Invalid_Project_Type_For_CodeGen"));
}
ProjectItems projItems = curProject.ProjectItems;
if (projItems == null)
{
throw new Exception(WMISys.GetString("WMISE_Could_Not_Add_File_to_Project"));
}
Guid curProjectType = new Guid(curProject.Kind);
string wrapperFileName = className + "."+ curProjSuffix;
if(!mgmtObj.GetStronglyTypedClassCode(VSUtils.MapProjectGuidToCodeLanguage(curProjectType),
Path.GetTempPath() + "\\" + wrapperFileName))
{
throw new Exception(WMISys.GetString("WMISE_Code_Generation_Failed"));
}
ProjectItem newItem = projItems.AddFromFileCopy(Path.GetTempPath() + "\\" + wrapperFileName);
if (newItem == null)
{
throw new Exception(WMISys.GetString("WMISE_Could_Not_Add_File_to_Project"));
}
File.Delete(Path.GetTempPath() + "\\" + wrapperFileName);
}
catch (Exception exc)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
}
}
///
/// Create new instance of the class
///
///
///
private void OnCreateNewInstance(object sender, EventArgs e)
{
try
{
if (this.GetNodeSite().GetChildCount() == 0)
{
Node[] children = this.CreateChildren();
for (int i = 0; i < children.Length; i++)
{
GetNodeSite().AddChild(children[i]);
}
}
//spawn new object and add it as a child node
ManagementObject newInst = ((ManagementClass)mgmtObj).CreateInstance();
WMIInstanceNode childNode = new WMIInstanceNode(newInst, mgmtObj, this.connectAs, this.password);
childNode.Label = WMISys.GetString("WMISE_ClassNode_NewInstanceLbl", this.label);
GetNodeSite().AddChild(childNode);
childNode.GetNodeSite().Select();
}
catch(Exception exc)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", exc.Message, exc.StackTrace));
}
}
///
/// To determine whether this node supports drag and drop.
///
///
/// TRUE to indicate ProcessNode supports drag and drop.
///
public override bool HasDragComponents() {
return false; //disable d&d for Beta1
}
//disable d&d for Beta1
/*
public override IComponent[] CreateDragComponents(IDesignerHost designerHost) {
Object comp = null;
//trim the ordinal prefix (all up to first space)
comp = new WMIObjectComponent(wmiObj);
return new IComponent[] {(IComponent)comp};
}
*/
///
/// The object should write the serialization info.
///
public virtual void GetObjectData(SerializationInfo si, StreamingContext context) {
si.AddValue("Path", path);
si.AddValue("ConnectAs", this.connectAs);
si.AddValue("Password", this.password);
}
}
}