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); } } }