﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客网-玄铁剑-文章分类-Temp</title><link>http://www.cnitblog.com/MartinYao/category/4550.html</link><description>欢迎您的到来...</description><language>zh-cn</language><lastBuildDate>Wed, 07 Mar 2007 19:55:49 GMT</lastBuildDate><pubDate>Wed, 07 Mar 2007 19:55:49 GMT</pubDate><ttl>60</ttl><item><title>WMI access operating system information</title><link>http://www.cnitblog.com/MartinYao/articles/21320.html</link><dc:creator>玄铁剑</dc:creator><author>玄铁剑</author><pubDate>Fri, 29 Dec 2006 14:21:00 GMT</pubDate><guid>http://www.cnitblog.com/MartinYao/articles/21320.html</guid><wfw:comment>http://www.cnitblog.com/MartinYao/comments/21320.html</wfw:comment><comments>http://www.cnitblog.com/MartinYao/articles/21320.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/MartinYao/comments/commentRss/21320.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/MartinYao/services/trackbacks/21320.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td width="100%">
										<table width="100%">
												<tbody>
														<tr valign="top">
																<td class="SmallText" nowrap="">
																</td>
																<td nowrap="" align="right">
																		<a name="__top">
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
						<tr>
								<td class="ArticlePane">
										<span id="intelliTXT">
												<div id="contentdiv">
														<!-- Article Starts -->
														<ul class="download">
																<li>
																		<a href="http://www.codeproject.com/cs/system/WMI/WMI_src.zip">
																				<font color="#002c99">Download source files - 44 Kb</font>
																		</a>
																</li>
																<li>
																		<a href="http://www.codeproject.com/cs/system/WMI/WMI_demo.zip">
																				<font color="#002c99">Download demo project - 21.2 Kb</font>
																		</a>
																</li>
														</ul>
														<p>
																<img height="361" src="http://www.codeproject.com/cs/system/WMI/WMIApplication.jpg" width="500" />
														</p>
														<h2>Introduction</h2>
														<p>This is a continuation of where I left off with Windows Management Instrumentation (WMI) in my last article 'My Explorer'. I will show how to access operating system information, services, and processes running on your machine as well as on a remote machine on your network, provided you have administration rights to them. Also I will show you how to start and stop services, terminate processes, and create new processes from WMI.</p>
														<h2>Getting Started</h2>
														<p>In this WMI application, I have created a <code lang="cs">WMIControlLibrary</code> which contains four user controls. The four user controls are as follows: <code lang="cs">Explorer</code>, <code lang="cs">SystemInfo</code>, <code lang="cs">Services</code>, and <code lang="cs">Processes</code>. Each one of these controls does its own specific task. Here is a brief description of what each one of these control does.</p>
														<ul>
																<li>
																		<code lang="cs">Explorer</code> Control - I converted 'My Explorer' to a user control, it still display your system drives, directories, and files information. 
</li>
																<li>
																		<code lang="cs">SystemInfo</code> Control* - This control display operating system information and hardware data and specifications. 
</li>
																<li>
																		<code lang="cs">Services</code> Control* - This control display services currently running on the system. 
</li>
																<li>
																		<code lang="cs">Process</code> Control* - This control display processes currently running on the system. </li>
														</ul>
														<p>(* Note: This control can be used to monitor local or remote system on the network.)</p>
														<p>Every one of these controls uses the <code lang="cs">System.Management</code> namespace to access their own specific system information.</p>
														<h2>Control's Status Event</h2>
														<p>Some of these controls take time to retrieve information back from the system, so I implemented the <code lang="cs">UpdateStatus(<span class="cs-keyword">string</span> e)</code> event in each control. This will allow each control to update the status bar in the main application, to allow the user to see what the control is doing.</p>
														<pre lang="cs">
																<span class="cs-comment">//Control Code</span>
																<span class="cs-comment">//delegate status event</span>
																<span class="cs-keyword">public</span>
																<span class="cs-keyword">delegate</span>
																<span class="cs-keyword">void</span> Status(<span class="cs-keyword">string</span> e);
<span class="cs-keyword">public</span><span class="cs-keyword">event</span> Status UpdateStatus;
<span class="cs-comment">//Update status bar</span>
UpdateStatus(<span class="cpp-string">"Hello world."</span>);

<span class="cs-comment">//Main Application Code</span><span class="cs-comment">//Set all control UpdateStatus event to this fuction</span><span class="cs-keyword">private</span><span class="cs-keyword">void</span> refreshStatusBar(<span class="cs-keyword">string</span> stringStatus)
{
    <span class="cs-comment">//update status bar</span>
    statusBarStatus.Text = stringStatus;
}
</pre>
														<h2>Explorer Control</h2>
														<p>
																<img height="361" src="http://www.codeproject.com/cs/system/WMI/Explorer.gif" width="500" />
														</p>
														<p>In the Explorer control, I used the WMI <code lang="cs">Win32_LogicalDisk</code> class to get all the local and mapped drives on the local machine. To get access to drives information, I need to use the <code lang="cs">ManagementObjectSearcher</code> class to obtain a <code lang="cs">ManagementOjbectCollection</code> class containing the drive information I requested. We now have all the available drives' information at our disposal (such as drive name, type, volume, description, etc...). You can also just look for drives that have less then 1 Meg by changing the <code lang="cs">ManagementObjectSearcher</code> parameter to: </p>
														<pre lang="text">Select * From Win32_LogicalDisk Where FreeSpace &lt; 1000000</pre>
														<div class="precollapse" id="premain2" style="WIDTH: 100%">
																<img id="preimg2" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="2" />
																<span id="precollapse2" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="2"> Collapse</span>
														</div>
														<pre lang="cs" id="pre2" style="MARGIN-TOP: 0px">
																<span class="cs-comment">//get drive collection </span>
ManagementObjectSearcher query = <span class="cs-keyword">new</span> ManagementObjectSearcher
    (<span class="cpp-string">"SELECT * From Win32_LogicalDisk "</span>); 
ManagementObjectCollection queryCollection = query.Get(); 

<span class="cs-comment">//loop throught each object to get drive information</span><span class="cs-keyword">foreach</span> ( ManagementObject mo <span class="cs-keyword">in</span> queryCollection) 
{ 
    <span class="cs-keyword">switch</span> (<span class="cs-keyword">int</span>.Parse( mo[<span class="cpp-string">"DriveType"</span>].ToString())) 
    { 
        <span class="cs-keyword">case</span> Removable: <span class="cs-comment">//removable drives </span>
            imageIndex = <span class="cs-literal">5</span>; 
            selectIndex = <span class="cs-literal">5</span>; 
            <span class="cs-keyword">break</span>; 
        <span class="cs-keyword">case</span> LocalDisk: <span class="cs-comment">//Local drives </span>
            imageIndex = <span class="cs-literal">6</span>; 
            selectIndex = <span class="cs-literal">6</span>; 
            <span class="cs-keyword">break</span>; 
        <span class="cs-keyword">case</span> CD: <span class="cs-comment">//CD rom drives </span>
            imageIndex = <span class="cs-literal">7</span>; 
            selectIndex = <span class="cs-literal">7</span>; 
            <span class="cs-keyword">break</span>; 
        <span class="cs-keyword">case</span> Network: <span class="cs-comment">//Network drives </span>
            imageIndex = <span class="cs-literal">8</span>; 
            selectIndex = <span class="cs-literal">8</span>; 
            <span class="cs-keyword">break</span>; 
        <span class="cs-keyword">default</span>: <span class="cs-comment">//defalut to folder </span>
            imageIndex = <span class="cs-literal">2</span>; 
            selectIndex = <span class="cs-literal">3</span>; 
            <span class="cs-keyword">break</span>; 
    } 
        
    <span class="cs-comment">//get drive name</span>
    Console.WriteLine(<span class="cpp-string">"Drive: "</span> + mo[<span class="cpp-string">"Name"</span>].ToString()); 
} 
</pre>
														<h2>SystemInfo Control</h2>
														<p>
																<img height="349" src="http://www.codeproject.com/cs/system/WMI/WMIApplication.gif" width="500" />
														</p>
														<p>The <code lang="cs">SystemInfo</code> control display many different types of information about your local machine or a remote machine on the network. It first establishes a <code lang="cs">ConnectionOptions</code> object with the <code lang="cs">UserName</code> and <code lang="cs">Password</code> properties set. Then it creates a <code lang="cs">ManagementScope</code> object with the local or remote host name and the <code lang="cs">ConnectionOptions</code> object as the parameters.</p>
														<pre lang="cs">
																<span class="cs-comment">//Connect to the remote computer</span>
ConnectionOptions co = <span class="cs-keyword">new</span> ConnectionOptions();

co.Username = textUserID.Text;
co.Password = textPassword.Text;

<span class="cs-comment">//Point to machine</span>
System.Management.ManagementScope ms = <span class="cs-keyword">new</span> System.Management.
    ManagementScope(<span class="cpp-string">"\\\\"</span> + stringHostName + <span class="cpp-string">"\\root\\cimv2"</span>, co);      
</pre>
														<p>Now we are ready to access the system information by creating an <code lang="cs">ObjectQuery</code> member object and passing it along with the <code lang="cs">ManagementScope</code> object in to the <code lang="cs">ManagementObjectSearcher</code> member object and invoke the <code lang="cs">Get()</code> method to execute the command. Then I get back a <code lang="cs">ManagementObject</code> collection containing the query information.</p>
														<pre lang="cs">
																<span class="cs-comment">//Query system for Operating System information</span>
oq = <span class="cs-keyword">new</span> System.Management.ObjectQuery(
    <span class="cpp-string">"SELECT * FROM Win32_OperatingSystem"</span>);
query = <span class="cs-keyword">new</span> ManagementObjectSearcher(ms,oq);

queryCollection = query.Get();
<span class="cs-keyword">foreach</span> ( ManagementObject mo <span class="cs-keyword">in</span> queryCollection)
{
    <span class="cs-comment">//create child node for operating system</span>
    createChildNode(nodeCollection, <span class="cpp-string">"Operating System: "</span> + 
        mo[<span class="cpp-string">"Caption"</span>]);
    createChildNode(nodeCollection, <span class="cpp-string">"Version: "</span> + mo[<span class="cpp-string">"Version"</span>]);
    createChildNode(nodeCollection, <span class="cpp-string">"Manufacturer : "</span> + 
        mo[<span class="cpp-string">"Manufacturer"</span>]);
    createChildNode(nodeCollection, <span class="cpp-string">"Computer Name : "</span> + 
        mo[<span class="cpp-string">"csname"</span>]);
    createChildNode(nodeCollection, <span class="cpp-string">"Windows Directory : "</span> + 
        mo[<span class="cpp-string">"WindowsDirectory"</span>]);
}
</pre>
														<p>If you are only concerned about the local host information, you can avoid the creation of  <code lang="cs">ConnectionOption</code>, <code lang="cs">ManagementScope</code>, and <code lang="cs">ObjectQuery</code> objects. All you need to do is just call the <code lang="cs">ManagementObjectSearcher</code> member object with the query string and execute the <code lang="cs">ManagementObjectSearcher.Get()</code> method to get the <code lang="cs">ManagementObjectCollection</code> result back, for the local machine.</p>
														<pre lang="cs">ManagementObjectSearcher query = <span class="cs-keyword">new</span> ManagementObjectSearcher
    (<span class="cpp-string">"SELECT * From Win32_OperatingSystem"</span>);
ManagementObjectCollection queryCollection = query.Get();
</pre>
														<p>The <code lang="cs">SystemInfo</code> control also displays the following information about the computer system being accessed: System Manufacturer, Processor, Bios, Time Zone, Memory, Network Connection, and Video Controller. The codes for these different queries are repetitive, it's just the query string and the result properties are different. So I will not display the code here to save space. You can download the code and look at them.</p>
														<h2>Service Control</h2>
														<p>
																<img height="361" alt="Services Image" src="http://www.codeproject.com/cs/system/WMI/Services.gif" width="500" />
														</p>
														<p>The <code lang="cs">Service</code> control uses the query:</p>
														<pre lan="cs">SELECT * FROM Win32_Service</pre>
														<p>to retrieve all the services information in the system. To start or stop a service, I dynamically create a popup menu to the <code lang="cs">ListView</code>. When you right click on an item, a start or stop menu pops up, depending on the service state. When the <code lang="cs">MenuItem</code> is clicked, I need to get the <code lang="cs">ManagementObject</code> for that service with this query:</p>
														<pre lang="cs">SELECT * FROM Win32_Service WHERE Name = 'ServiceName'.</pre>
														<p>Then I call the <code lang="cs">ManagementObject.InvokeMethod()</code> to start or stop the service. The first parameter in the <code lang="cs">InvokeMethod</code> method is the <code lang="cs">Observer</code> parameter. I pass in a <code lang="cs">ManagementOperationObserver</code> class to manage asynchronous operations and handle management information and events received asynchronously. By checking the <code lang="cs">returnValue</code> property in <code lang="cs">completionHandlerObj.ReturnObject</code>, I can determine if the operation was successful or not.</p>
														<div class="precollapse" id="premain8" style="WIDTH: 100%">
																<img id="preimg8" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="8" />
																<span id="precollapse8" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="8"> Collapse</span>
														</div>
														<pre lang="cs" id="pre8" style="MARGIN-TOP: 0px">
																<span class="cs-comment">/// &lt;summary&gt;</span>
																<span class="cs-comment">/// List view mouse down event to built </span>
																<span class="cs-comment">/// context menu dynamically </span>
																<span class="cs-comment">/// &lt;/summary&gt;</span>
																<span class="cs-comment">/// <param name="sender" /></span>
																<span class="cs-comment">/// <param name="e" /></span>
																<span class="cs-keyword">private</span>
																<span class="cs-keyword">void</span> listViewServices_MouseDown(<span class="cs-keyword">object</span> sender, 
    System.Windows.Forms.MouseEventArgs e)
{
    System.Windows.Forms.ListView listViewObject = 
        (System.Windows.Forms.ListView) sender;
    ContextMenu mnuContextMenu = <span class="cs-keyword">new</span> ContextMenu();
    MenuItem menuItem = <span class="cs-keyword">new</span> MenuItem();
    ManagementObjectCollection queryCollection;

    <span class="cs-comment">//check if right button</span><span class="cs-keyword">if</span> (e.Button == System.Windows.Forms.MouseButtons.Right) 
    {
        <span class="cs-comment">//get service name</span>
        ServiceName = listViewObject.GetItemAt(e.X, e.Y).Text;
        <span class="cs-comment">//set list view item</span>
        ServiceItem = listViewObject.GetItemAt(e.X,e.Y);

        <span class="cs-comment">//create popup menu</span>
        listViewObject.ContextMenu = mnuContextMenu;
        <span class="cs-keyword">try</span>
        {
            <span class="cs-comment">//get specific service object</span>
            queryCollection = getServiceCollection(<span class="cpp-string">"SELECT * FROM 
                Win32_Service Where Name = '"</span> + ServiceName + <span class="cpp-string">"'"</span>);
            <span class="cs-keyword">foreach</span> ( ManagementObject mo <span class="cs-keyword">in</span> queryCollection)
            {
                <span class="cs-comment">//create menu depending on service state</span><span class="cs-keyword">if</span> (mo[<span class="cpp-string">"Started"</span>].Equals(<span class="cs-keyword">true</span>))
                {
                    menuItem.Text = <span class="cpp-string">"Stop"</span>;
                    <span class="cs-comment">//set action property</span>
                    ServiceAction = <span class="cpp-string">"StopService"</span>;
                }
                <span class="cs-keyword">else</span>
                {
                    menuItem.Text = <span class="cpp-string">"Start"</span>;
                    ServiceAction = <span class="cpp-string">"StartService"</span>;
                }
                mnuContextMenu.MenuItems.Add(menuItem);

                <span class="cs-comment">// Add functionality to the menu items </span><span class="cs-comment">//using the Click event. </span>
                menuItem.Click  += <span class="cs-keyword">new</span> System.EventHandler
                    (<span class="cs-keyword">this</span>.menuItem_Click);
            }
        }
        <span class="cs-keyword">catch</span> (Exception e1)
        {
            MessageBox.Show(<span class="cpp-string">"Error: "</span> + e1);
        }
    }
}

<span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// List view context menu click event to invoke start/stop service</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-comment">/// <param name="sender" /></span><span class="cs-comment">/// <param name="e" /></span><span class="cs-keyword">private</span><span class="cs-keyword">void</span> menuItem_Click(<span class="cs-keyword">object</span> sender, System.EventArgs e)
{   
    ManagementObjectCollection queryCollection;
    ListViewItem lvItem;

    <span class="cs-comment">//Set up a handler for the asynchronous callback</span>
    ManagementOperationObserver observer = <span class="cs-keyword">new</span> 
        ManagementOperationObserver(); 
    completionHandler.MyHandler completionHandlerObj = <span class="cs-keyword">new</span> 
        completionHandler.MyHandler(); 
    observer.ObjectReady += <span class="cs-keyword">new</span> ObjectReadyEventHandler
        (completionHandlerObj.Done);

    <span class="cs-comment">//get specific service object</span>
    queryCollection = getServiceCollection(<span class="cpp-string">"Select * 
        from Win32_Service Where Name ='"</span> + ServiceName + <span class="cpp-string">"'"</span>);
    
    <span class="cs-comment">//Status </span>
    updateStatus(<span class="cpp-string">"Starting/Stopping service..."</span>); 
    
    <span class="cs-keyword">foreach</span> ( ManagementObject mo <span class="cs-keyword">in</span> queryCollection)  
    { 
        <span class="cs-comment">//start or stop  service </span>
        mo.InvokeMethod(observer, ServiceAction, <span class="cs-keyword">null</span>); 
    } 
    <span class="cs-comment">//wait until invoke method is complete  or 5 sec timeout </span><span class="cs-keyword">int</span> intCount = <span class="cs-literal">0</span>;  
    <span class="cs-keyword">while</span>
    (!completionHandlerObj.IsComplete) 
    { 
        <span class="cs-keyword">if</span> 
        (intCount &gt;  <span class="cs-literal">10</span>)
        {
            MessageBox.Show(<span class="cpp-string">"Terminate process timed out."</span>, 
                <span class="cpp-string">"Terminate Process Status"</span>);
            <span class="cs-keyword">break</span>;
        }
        <span class="cs-comment">//wait 1/2 sec.</span>
        System.Threading.Thread.Sleep(<span class="cs-literal">500</span>); 
    
        <span class="cs-comment">//increment counter</span>
        intCount++;
    } 

    <span class="cs-comment">//see if call was successful.</span><span class="cs-keyword">if</span> (completionHandlerObj.ReturnObject.
        Properties[<span class="cpp-string">"returnValue"</span>].Value.ToString() == <span class="cpp-string">"0"</span>)
    { 
        <span class="cs-comment">//succeeded</span>
        lvItem = ServiceItem;

        <span class="cs-keyword">if</span> (ServiceAction == <span class="cpp-string">"StartService"</span>)
            lvItem.SubItems[<span class="cs-literal">2</span>].Text = <span class="cpp-string">"Started"</span>;
        <span class="cs-keyword">else</span>
            lvItem.SubItems[<span class="cs-literal">2</span>].Text = <span class="cpp-string">"Stop"</span>;
    }
    <span class="cs-keyword">else</span>
    {
        <span class="cs-comment">//error message</span><span class="cs-keyword">string</span> stringAction;

        <span class="cs-keyword">if</span> (ServiceAction == <span class="cpp-string">"StartService"</span>)
            stringAction = <span class="cpp-string">"start"</span>;
        <span class="cs-keyword">else</span>
            stringAction = <span class="cpp-string">"stop"</span>;

        MessageBox.Show(<span class="cpp-string">"Failed to "</span> + stringAction + 
            <span class="cpp-string">" service "</span> + ServiceName + <span class="cpp-string">"."</span>, 
            <span class="cpp-string">"Start/Stop Service Failure"</span>);
    }

    <span class="cs-comment">//clean-up objects</span>
    ServiceName = <span class="cpp-string">""</span>;
    ServiceAction = <span class="cpp-string">""</span>;
    ServiceItem = <span class="cs-keyword">null</span>;

    <span class="cs-comment">//Status</span>
    updateStatus(<span class="cpp-string">"Ready"</span>);
    <span class="cs-keyword">this</span>.Update();
}


<span class="cs-comment">//----------------------------------</span><span class="cs-comment">// Completion Handler </span><span class="cs-comment">//----------------------------------</span><span class="cs-keyword">using</span> System;
<span class="cs-keyword">using</span> System.Management;

<span class="cs-keyword">namespace</span> completionHandler
{
    <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// MyHandler class handle notification </span><span class="cs-comment">/// when InvokeMethod call is complete</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-keyword">public</span><span class="cs-keyword">class</span> MyHandler
    {
        <span class="cs-keyword">private</span><span class="cs-keyword">bool</span> isComplete = <span class="cs-keyword">false</span>;
        <span class="cs-keyword">private</span> ManagementBaseObject returnObject;
             
        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Trigger Done event when InvokeMethod is complete</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-keyword">public</span><span class="cs-keyword">void</span> Done(<span class="cs-keyword">object</span> sender, ObjectReadyEventArgs e)
        { 
            isComplete = <span class="cs-keyword">true</span>;
            returnObject = e.NewObject;
        }


        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Get property IsComplete</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-keyword">public</span><span class="cs-keyword">bool</span> IsComplete 
        {
            <span class="cs-keyword">get</span> 
            {
                <span class="cs-keyword">return</span> isComplete;
            }
        }

        <span class="cs-comment">/// &lt;summary&gt;</span><span class="cs-comment">/// Property allows accessing the result </span><span class="cs-comment">/// object in the main function</span><span class="cs-comment">/// &lt;/summary&gt;</span><span class="cs-keyword">public</span> ManagementBaseObject ReturnObject 
        {
            <span class="cs-keyword">get</span> 
            {
                <span class="cs-keyword">return</span> returnObject;
            }
        }

    }
}
</pre>
														<h2>Process Control</h2>
														<p>
																<img height="360" alt="Processes Image" src="http://www.codeproject.com/cs/system/WMI/Processes.gif" width="500" />
														</p>
														<p>The <code lang="cs">Process</code> control display the system running processes, user that started the process, CPU utilization, and memory usage. To get the process user, I need to call the <code lang="cs">GetOwner(User, Domain)</code> method. The <code lang="cs">User</code> and <code lang="cs">Domain</code> parameters are output parameters. How do we get to these output parameters from <code lang="cs">InvokeMethod</code>? This depends on how we implement the <code lang="cs">InvokeMethod</code>. If we do not need to manage asynchronous operations, then we need to pass in a <code lang="cs"><span class="cs-keyword">string</span>[]</code> to the <code lang="cs">InvokeMethod</code> method to retrieve the output parameters. But if we need to manage asynchronous operations, then we do not need to pass in any parameters to <code lang="cs">InvokeMethod</code> method. You will get the output parameters from the <code lang="cs">completionHandlerObj.ReturnObject</code> properties collection.</p>
														<div class="precollapse" id="premain9" style="WIDTH: 100%">
																<img id="preimg9" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="9" />
																<span id="precollapse9" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="9"> Collapse</span>
														</div>
														<pre lang="cs" id="pre9" style="MARGIN-TOP: 0px">
																<span class="cs-comment">//------------------------------------------------- </span>
																<span class="cs-comment">//Get process owner info without the observer object </span>
																<span class="cs-comment">//-------------------------------------------------- </span>
																<span class="cs-comment">//Createan array containing all arguments for the method</span>
																<span class="cs-keyword">string</span>[] methodArgs = {<span class="cpp-string">""</span>, <span class="cpp-string">""</span>}; 

<span class="cs-comment">//Get process owner info </span>
mo.InvokeMethod(<span class="cpp-string">"GetOwner"</span>, methodArgs); 

<span class="cs-comment">//methodArgs[0] - contain process user </span><span class="cs-comment">//methodArgs[1] = contain process domain </span><span class="cs-comment">//-----------------------------------------------</span><span class="cs-comment">//Getprocess owner info with the observer object</span><span class="cs-comment">//-----------------------------------------------</span>
mo.InvokeMethod(observer,<span class="cpp-string">"GetOwner"</span>, <span class="cs-keyword">null</span>);

<span class="cs-keyword">while</span> (!completionHandlerObj.IsComplete) 
{ 
    System.Threading.Thread.Sleep(<span class="cs-literal">500</span>); 
} 

<span class="cs-keyword">if</span> (completionHandlerObj.ReturnObject[<span class="cpp-string">"returnValue"</span>].
    ToString() == <span class="cpp-string">"0"</span>) 
    
    structProcess.stringUserName = completionHandlerObj.
        ReturnObject.Properties[<span class="cpp-string">"User"</span>].Value.ToString();
<span class="cs-keyword">else</span>
    structProcess.stringUserName = <span class="cpp-string">""</span>;
</pre>
														<h3>Terminating process</h3>
														<p>Terminating a specific process is the same as starting or stopping a service. First get the <code lang="cs">ManagementObject</code> for the selected process then call the <code lang="cs">InvokeMethod(observer, <span class="cpp-string">"Terminate"</span>, <span class="cs-keyword">null</span>)</code> to kill the process.</p>
														<div class="precollapse" id="premain10" style="WIDTH: 100%">
																<img id="preimg10" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="10" />
																<span id="precollapse10" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="10"> Collapse</span>
														</div>
														<pre lang="cs" id="pre10" style="MARGIN-TOP: 0px">
																<span class="cs-comment">//Set up a handler for the asynchronous callback</span>
ManagementOperationObserver observer = <span class="cs-keyword">new</span> 
    ManagementOperationObserver(); 
completionHandler.MyHandler completionHandlerObj = <span class="cs-keyword">new</span> 
    completionHandler.MyHandler(); 
observer.ObjectReady  += <span class="cs-keyword">new</span> ObjectReadyEventHandler
    (completionHandlerObj.Done);

<span class="cs-comment">//Get ManagementObject for process</span>
queryCollection = getProcessCollection(<span class="cpp-string">"Select * from 
    Win32_Process Where ProcessID = '"</span> + ProcessID + <span class="cpp-string">"'"</span>);

<span class="cs-comment">//Status</span>
updateStatus(<span class="cpp-string">"Invoking terminate process"</span>);

<span class="cs-keyword">foreach</span> ( ManagementObject mo <span class="cs-keyword">in</span> queryCollection)
{
    <span class="cs-comment">//start or stop service</span>
    mo.InvokeMethod(observer, <span class="cpp-string">"Terminate"</span>, <span class="cs-keyword">null</span>);
}

<span class="cs-comment">//wait until invoke method is complete or 5 sec timeout</span><span class="cs-keyword">int</span> intCount = <span class="cs-literal">0</span>;
<span class="cs-keyword">while</span> (!completionHandlerObj.IsComplete) 
{ 
    <span class="cs-keyword">if</span> (intCount == <span class="cs-literal">10</span>)
    {
        MessageBox.Show(<span class="cpp-string">"Terminate process timed out."</span>, 
            <span class="cpp-string">"Terminate Process Status"</span>);
        <span class="cs-keyword">break</span>;
    }
    <span class="cs-comment">//wait 1/2 sec.</span>
    System.Threading.Thread.Sleep(<span class="cs-literal">500</span>); 
    
    <span class="cs-comment">//increment counter</span>
    intCount++;
} 

<span class="cs-keyword">if</span> (intCount != <span class="cs-literal">10</span>)
{
    <span class="cs-comment">//InvokeMethod did not time out</span><span class="cs-keyword">if</span> (completionHandlerObj.ReturnObject.Properties
        [<span class="cpp-string">"returnValue"</span>].Value.ToString() == <span class="cpp-string">"0"</span>)
    { 
        lvItem = ProcessItem;
        lvItem.Remove();
    }
    <span class="cs-keyword">else</span>
    {
        MessageBox.Show(<span class="cpp-string">"Error terminating process."</span>, 
            <span class="cpp-string">"Terminate Process"</span>);
    }
}
</pre>
														<h3>Creating process</h3>
														<p>To create a new process, we need to call the <code lang="cs">InvokeMethod</code> method from the <code lang="cs">ManagementClass</code> class. We can get the <code lang="cs">ManagementClass</code> object as:</p>
														<pre lang="cs">ManagementClass processClass = New ManagementClass(ms,path,<span class="cs-keyword">null</span>);</pre>
														<p>Here ms is the <code lang="cs">ManagementScope</code> class and path is the <code lang="cs">ManagementPath</code> class. The <code lang="cs">ManagementScope</code> represents a scope for management operations. The <code lang="cs">ManagementPath</code> class provides a wrapper for parsing and building paths to <code lang="cs">Win32_Process</code>. We still need one more thing before calling the <code lang="cs">ManagementClass.InvokeMethod(observer, methodName, inParameters)</code>. We need to pass four parameters in to <code lang="cs">inParameters</code> as an array of <code lang="cs">Object</code>s.</p>
														<pre lang="cs">uint32 Create(<span class="cs-keyword">string</span> CommandLine,
    <span class="cs-keyword">string</span> CurrentDirectory,
    Win32_ProcessStartup ProcessStartupInformation,
    uint32* ProcessId);
</pre>
														<h3>Parameters</h3>
														<ul>
																<li>
																		<code lang="cs">CommandLine</code> - [in] Command line to execute. The system adds a null character to the command line, trimming the <code lang="cs"><span class="cs-keyword">string</span></code> if necessary, to indicate which file was actually used. 
</li>
																<li>
																		<code lang="cs">CurrentDirectory</code> - [in] Current drive and directory for the child process. The <code lang="cs"><span class="cs-keyword">string</span></code> requires that the current directory resolves to a known path. A user can specify an absolute path or a path relative to the current working directory. If this parameter is <code lang="cs">NULL</code>, the new process will have the same path as the calling process. This option is provided primarily for shells that must start an application and specify the application's initial drive and working directory. 
</li>
																<li>
																		<code lang="cs">ProcessStartupInformation</code> - [in] The startup configuration of a Windows process. For more information see <code lang="cs">Win32_ProcessStartup</code>. 
</li>
																<li>
																		<code lang="cs">ProcessId</code> - [out] Global process identifier that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated. </li>
														</ul>
														<pre lang="cs">
																<span class="cs-comment">//Create an array containing all arguments for the method</span>
																<span class="cs-keyword">object</span>[] methodArgs = {stringCommandLine, <span class="cs-keyword">null</span>, <span class="cs-keyword">null</span>, <span class="cs-literal">0</span>};

<span class="cs-comment">//Execute the method</span>
processClass.InvokeMethod (observer, <span class="cpp-string">"Create"</span>, methodArgs);
</pre>
														<p>Here is the code for implementing the Create process. I created a <code lang="cs">CreateProcess</code> function which accepts a <code lang="cs">stringCommandLine</code> parameter. When you call the <code lang="cs">CreateProcess(<span class="cpp-string">"Calc.exe"</span>)</code>, you will create a new calculator process. It's that simple.</p>
														<div class="precollapse" id="premain14" style="WIDTH: 100%">
																<img id="preimg14" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="14" />
																<span id="precollapse14" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="14"> Collapse</span>
														</div>
														<pre lang="cs" id="pre14" style="MARGIN-TOP: 0px">
																<span class="cs-comment">/// &lt;summary&gt;</span>
																<span class="cs-comment">/// Invoke method 'Create' on local or remote machine</span>
																<span class="cs-comment">/// &lt;/summary&gt;</span>
																<span class="cs-comment">/// <param name="stringCommandLine" /></span>
																<span class="cs-keyword">private</span>
																<span class="cs-keyword">void</span> CreateProcess(<span class="cs-keyword">string</span> stringCommandLine)
{   
    <span class="cs-comment">//Set up a handler for the asynchronous callback</span>
    ManagementOperationObserver observer = <span class="cs-keyword">new</span> 
        ManagementOperationObserver(); 
    completionHandler.MyHandler completionHandlerObj = <span class="cs-keyword">new</span> 
        completionHandler.MyHandler(); 
    observer.ObjectReady  += <span class="cs-keyword">new</span> ObjectReadyEventHandler
        (completionHandlerObj.Done);

    <span class="cs-keyword">string</span> stringMachineName = <span class="cpp-string">""</span>;

    <span class="cs-comment">//Connect to the remote computer</span>
    ConnectionOptions co = <span class="cs-keyword">new</span> ConnectionOptions();

    <span class="cs-keyword">if</span> (radioMachine.Checked == <span class="cs-keyword">true</span>)
    {
        stringMachineName = <span class="cpp-string">"localhost"</span>;
    }
    <span class="cs-keyword">else</span>
    {
        stringMachineName = textIP.Text;
    }

    <span class="cs-keyword">if</span> (stringMachineName.Trim().Length == <span class="cs-literal">0</span>)
    {
        MessageBox.Show(<span class="cpp-string">"Must enter machine IP address or name."</span>);
        <span class="cs-keyword">return</span>;
    }

    <span class="cs-comment">//get user and password</span><span class="cs-keyword">if</span> (textUserID.Text.Trim().Length   &gt; <span class="cs-literal">0</span>)
    {
        co.Username = textUserID.Text;
        co.Password = textPassword.Text;
    }

    <span class="cs-comment">//Point to machine</span>
    System.Management.ManagementScope ms = <span class="cs-keyword">new</span> System.
        Management.ManagementScope(<span class="cpp-string">"\\\\"</span> + 
        stringMachineName + <span class="cpp-string">"\\root\\cimv2"</span>, co);      
    <span class="cs-comment">//get process path</span>
    ManagementPath path = <span class="cs-keyword">new</span> ManagementPath( <span class="cpp-string">"Win32_Process"</span>);

    <span class="cs-comment">//Get the object on which the method will be invoked</span>
    ManagementClass processClass = <span class="cs-keyword">new</span> ManagementClass
        (ms,path,<span class="cs-keyword">null</span>);

    <span class="cs-comment">//Status</span>
    updateStatus(<span class="cpp-string">"Create process "</span> + stringCommandLine + <span class="cpp-string">"."</span>);
    
    <span class="cs-comment">//Create an array containing all arguments for the method</span><span class="cs-keyword">object</span>[] methodArgs = {stringCommandLine, <span class="cs-keyword">null</span>, <span class="cs-keyword">null</span>, <span class="cs-literal">0</span>};

    <span class="cs-comment">//Execute the method</span>
    processClass.InvokeMethod (observer, <span class="cpp-string">"Create"</span>, methodArgs);

    <span class="cs-comment">//wait until invoke method is complete or 5 sec timeout</span><span class="cs-keyword">int</span> intCount = <span class="cs-literal">0</span>;
    <span class="cs-keyword">while</span> (!completionHandlerObj.IsComplete) 
    { 
        <span class="cs-keyword">if</span> (intCount &gt; <span class="cs-literal">10</span>)
        {
            MessageBox.Show(<span class="cpp-string">"Create process timed out."</span>, 
                <span class="cpp-string">"Terminate Process Status"</span>);
            <span class="cs-keyword">break</span>;
        }
        <span class="cs-comment">//wait 1/2 sec.</span>
        System.Threading.Thread.Sleep(<span class="cs-literal">500</span>); 
        
        <span class="cs-comment">//increment counter</span>
        intCount++;
    } 

    <span class="cs-keyword">if</span> (intCount != <span class="cs-literal">10</span>)
    {
        <span class="cs-comment">//InvokeMethod did not time out</span><span class="cs-comment">//check for error</span><span class="cs-keyword">if</span> (completionHandlerObj.ReturnObject.Properties
            [<span class="cpp-string">"returnValue"</span>].Value.ToString() == <span class="cpp-string">"0"</span>)
        {
            <span class="cs-comment">//refresh process list</span><span class="cs-keyword">this</span>.Refresh();
        }
        <span class="cs-keyword">else</span>
        {
            MessageBox.Show(<span class="cpp-string">"Error creating new process."</span>, 
                <span class="cpp-string">"Create New Process"</span>);
        }
    }

    <span class="cs-comment">//Status</span>
    updateStatus(<span class="cpp-string">"Ready"</span>);
    <span class="cs-keyword">this</span>.Update();
}
</pre>
														<h2>Conclusion</h2>
														<p>This was a fun experience for me creating this WMI demo application. This is just a small sample of what WMI could do. I think I have commented the code pretty well so it is easier to understand.</p>
														<p>Here is a list of things you could use WMI for:</p>
														<ul>
																<li>Controlling Hardware and Software 
</li>
																<li>Monitoring Events 
</li>
																<li>Running a Script Based on an Event 
</li>
																<li>Sending E-mail Based on an Event </li>
														</ul>
														<p>Here is a link to learn more about WMI:</p>
														<p>
																<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp">
																		<font color="#002c99">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp</font>
																</a>
														</p>
														<!-- Article Ends -->
												</div>
										</span>
										<script src="/script/togglePre.js" type="text/javascript">
										</script>
										<h2>Paul Li</h2>
										<div style="OVERFLOW: hidden">
												<table border="0">
														<tbody>
																<tr valign="top">
																		<td class="smallText" nowrap="">
																				<br />
																		</td>
																		<td class="smallText">
																				<p class="smallText">Click <a href="http://www.codeproject.com/script/profile/whos_who.asp?vt=arts&amp;id=43916"><font color="#002c99">here</font></a> to view Paul Li's online profile.</p>
																		</td>
																</tr>
														</tbody>
												</table>
										</div>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/MartinYao/aggbug/21320.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/MartinYao/" target="_blank">玄铁剑</a> 2006-12-29 22:21 <a href="http://www.cnitblog.com/MartinYao/articles/21320.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>