<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Windows Management Infrastructure Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/wmi/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/wmi/feed.xml</link>
    <description>Managing your IT infrastructure remotely, securely, reliably and efficiently</description>
    <lastBuildDate>Thu, 30 Jul 2015 14:17:07 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Move to PowerShell for WinRM Management</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/move-to-powershell-for-winrm-management</link>
      <pubDate>Wed, 01 Apr 2015 13:42:00 GMT</pubDate>
      <dc:creator><![CDATA[]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2015/04/01/move-to-powershell-for-winrm-management/</guid>
      <description><![CDATA[As most people are aware, PowerShell provides two ways of managing the Windows Remote Management...]]></description>
      <content:encoded><![CDATA[<p>As most people are aware, PowerShell provides two ways of managing the Windows Remote Management (WinRM) infrastructure: the <a href="https://technet.microsoft.com/en-us/library/hh847813(v=wps.620).aspx">WSMan Provider</a> and the <a href="https://go.microsoft.com/fwlink/?LinkID=245863">WS-Management Cmdlets</a>. (As you are no doubt aware, WinRM is the Windows implementation of the WS-Management standard, which is why these cmdlets are named Ws-Management.) Together, the WSMan Provider and WS-Management cmdlets give administrators the ability to enable, configure, manage, and test WinRM easily from within PowerShell, and are the best way for building scripts to manage WinRM.</p>
<p>Prior to the release of the WS-Management cmdlets, the only way to perform some WinRM management tasks was to use the WinRM.VBS scripting interface and WinRM.CMD. However, with the proven success of the PowerShell cmdlets, it is time to move away from those older tools. No development is planned for either WinRM.CMD or WinRM.VBS, and while they are still a part of Windows (to support backwards compatibility), no new scripts or development should be based on them. &nbsp;</p>
<p>This is a small part of the long-established strategy to move to PowerShell for management of the Windows platforms. PowerShell has become the Windows scripting choice for IT Professionals, and is being more broadly adopted by developers with the addition of Desired State Configuration.</p>
<p>The WS-Management Cmdlets and WSMan Provider give PowerShell a complete mechanism for both local and remote management of WinRM, CredSSP, and PowerShell Sessions that is unavailable from VBScript. For more information on these, you will find links to both the WS-Management cmdlets and the WS-Man provider <a href="https://technet.microsoft.com/en-us/library/hh847832.aspx">here</a>&nbsp;on TechNet. There is also a very good article titled &ldquo;<a href="https://blogs.technet.com/b/heyscriptingguy/archive/2012/12/30/understanding-powershell-remote-management.aspx">Understanding PowerShell Remote Management</a>&rdquo; that covers these topics quite well.</p>
<p>To reiterate the key point: while WinRM.VBS and WinRM.CMD will ship in Windows to support backwards compatibility, new scripts developed to manage WinRM should be created using the <a href="https://technet.microsoft.com/en-us/library/hh847813(v=wps.620).aspx">WSMan Provider</a> and the <a href="https://technet.microsoft.com/en-us/library/hh849876.aspx">PowerShell WS-Management cmdlets</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>WS-Man (Web Services for Management) 1.2 Published</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/ws-man-web-services-for-management-1-2-published</link>
      <pubDate>Wed, 22 Oct 2014 13:07:05 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lee [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2014/10/22/ws-man-web-services-for-management-1-2-published/</guid>
      <description><![CDATA[The DMTF recently published the Web Services for Management (WS-Man) standard version 1.2. This...]]></description>
      <content:encoded><![CDATA[<p>The <a href="https://dmtf.org">DMTF</a> recently published the <a href="https://dmtf.org/sites/default/files/standards/documents/DSP0226_1.2.0.pdf">Web Services for Management (WS-Man) standard version 1.2</a>. This release of the WS-Man specification clarifies support for the latest encryption protocols, which has been required by organizations and governmental agencies such as the US Government <a href="https://www.nist.gov/index.html">NIST</a> program. </p>  <p>WS-Man is a SOAP-based protocol that can be used with any transport, although it is primarily used with HTTP and HTTPS.&#160; The older versions of the WS-Man specification made specific references to older versions of TLS (Transport Layer Security) that have proven to be insufficient.&#160; The updated version more clearly decouples the protocol and the transport to ensure that interoperability is not dependent on specific versions of encryption algorithms, including TLS.&#160; There is no functional change with the updated WS-Man 1.2 specification.&#160;&#160; </p>  <p>Microsoft, an active member of the DMTF, contributed and edited the updated WS-Man specification. The Microsoft implementation of WS-Man is known as Windows Remote Management (<a href="https://msdn.microsoft.com/en-us/library/aa384426(v=vs.85).aspx">WinRM</a>), and has been a part of Windows since Windows 7 / Windows Server 2008 R2.&#160; The WinRM implementation of WS-Man conforms with the latest NIST requirements described in <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r1.pdf">NIST Special Publication 800 -52r1</a><strong>.</strong> WinRM leverages HTTP.SYS, which implements and enables configuration of the most recent and industry-standard secure transport protocol layer, as described in these two articles: </p>  <p>· <a href="https://support.microsoft.com/kb/2019527">Configuring WINRM for HTTPS</a></p>  <p>· The Configuring WinRM to Use HTTPS section of <a href="https://technet.microsoft.com/en-us/library/cc782312(v=WS.10).aspx">Configuration and Security</a></p>  <p>Note that if HTTPS is not used, WinRM still encrypts the payload over HTTP by default unless explicitly set to not use encryption.</p>  <p>WinRM has been, and should continue to be relied on in secure environments that are configured to meet the government and industry recommended cryptographic algorithms. Due to the lack of clarity in the previous releases of the WS-Man specification, some users were confused about whether or not WS-Man and WinRM supported recent and more secure implementations of the Transport-Layer Security (TLS), which it does. While this has not been an issue for the Microsoft implementation in WinRM, the WS-Man version 1.2 specification update has addressed that, and removed the confusing elements.</p>  <p>Steve Lee   <br />Principal Engineering Manager    <br />Windows Server    <br />    <br />Keith Bankston    <br />Senior Program Manager    <br />Windows Server</p>]]></content:encoded>
    </item>
    <item>
      <title>Enumerating and getting WMI provider class instances with performance in mind</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/enumerating-and-getting-wmi-provider-class-instances-with-performance-in-mind</link>
      <pubDate>Thu, 10 Apr 2014 17:47:00 GMT</pubDate>
      <dc:creator><![CDATA[Milena Natanov]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2014/04/10/enumerating-and-getting-wmi-provider-class-instances-with-performance-in-mind/</guid>
      <description><![CDATA[&nbsp;
Performance of CIM_DataFile and Win32_Directory enumeration depends on the number of files...]]></description>
      <content:encoded><![CDATA[<p>&nbsp;</p>
<p>Performance of <strong>CIM_DataFile </strong>and<strong> Win32_Directory</strong> enumeration depends on the number of files or directories that are being enumerated, and, hence, can be very slow and can take hours.</p>
<p>In following example, we run the Get-CimInstance cmdlet to enumerate all the instances of the class CIM_DataFile. On a brand-new virtual machine, the operation took 38<strong> </strong>minutes.</p>
<table style="width: 600px;" border="0" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="color: white;" valign="top" bgcolor="#000080" width="853">
<p><br />PS:&gt; Measure-Command { Get-CimInstance -ClassName CIM_DataFile -Namespace root/cimv2 } <br />Days : 0 <br />Hours : 0 <br />Minutes : 38 <br />Seconds : 27 </p>
</td>
</tr>
</tbody>
</table>
<h3>&nbsp;</h3>
<h3>How performance can be improved</h3>
<p>Here are few alternatives that can improve performance of your PowerShell script if it includes <strong>CIM_DataFile </strong>or<strong> Win32_Directory </strong>instance<strong> </strong>enumeration. These methods can be used on any other class with a large number of instances.</p>
<p>&nbsp;</p>
<h4>Alternative 1: Enumerating instances using a WQL query</h4>
<p>You can use a WQL query to narrow down enumeration to single instances. When you use WQL query, the Get-CimInstance cmdlet executes faster.</p>
<blockquote>
<p>For example, the following query returns result immediately:</p>
</blockquote>
<table style="width: 600px;" border="0" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="color: white;" valign="top" bgcolor="#000080" width="853">
<p><br />PS:&gt; # Build a WQL query, which will return C:\ directory <br />PS:&gt; $query = "Select * From Win32_Directory Where Name = 'C:'" <br />PS:&gt; # Get Win32_Directory instance using WQL query <br />PS:&gt; $instances = Get-CimInstance -Query $query -Namespace root/cimv2 <br />PS:&gt; $instances | Select Name <br />Name : c: </p>
</td>
</tr>
</tbody>
</table>
<blockquote>
<p>If WQL query uses the <strong>LIKE</strong> operator, expect the query to be as slow as Get-CimInstance without a WQL query.</p>
</blockquote>
<table style="width: 600px;" border="0" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="color: white;" valign="top" bgcolor="#000080" width="853">
<p><br />PS:&gt; # Build a WQL query, which will return all directories under C:\ <br />PS:&gt; $query = "Select * From Win32_Directory Where Name LIKE 'C:*'" <br />PS:&gt; # Get Win32_Directory instances matching the query filter <br />PS:&gt; Measure-Command { $instances = Get-CimInstance -Query $query -Namespace root/cimv2 } <br />Days : 0 <br />Hours : 0 <br />Minutes : 2 <br />Seconds : 34 </p>
</td>
</tr>
</tbody>
</table>
<h4>&nbsp;</h4>
<p>&nbsp;</p>
<h4>Alternative 2: Enumerating instances using Get-CimInstance with local instance</h4>
<p>This method can only be used when the instance key property value is known.</p>
<table style="width: 600px;" border="0" cellspacing="0" cellpadding="1">
<tbody>
<tr>
<td style="color: white;" valign="top" bgcolor="#000080" width="853">
<p><br />PS:&gt; # Get CIM_DataFile class <br />PS:&gt; $class = Get-CimClass -ClassName CIM_DataFile -Namespace root/cimv2 <br />PS:&gt; # Create hash table containing instance&rsquo;s key property and its value <br />PS:&gt; $keyPropertyHash = @{} <br />PS:&gt; $keyPropertyHash.Add('Name', 'C:\Temp\Test.txt') <br />PS:&gt; # Create a new CIM instance in memory for a CIM_DataFile class with the key property @{ 'Name'='C:\Temp\Test.txt' } <br />PS:&gt; $localInstance = New-CimInstance -CimClass $class -Property $keyPropertyHash &ndash;ClientOnly <br />PS:&gt; #Get Test.txt file instance using $localInstance as an input object <br />PS:&gt; $instance = Get-CimInstance &ndash;InputObject $localInstance <br />PS:&gt; $instance | fl Name <br />Name : c:\temp\test.txt </p>
</td>
</tr>
</tbody>
</table>
<h3>&nbsp;</h3>
<h3>Summary</h3>
<p>When you&rsquo;re enumerating instances in a class with large number of instances:</p>
<ul>
<li>Use WQL queries if enumeration can be scoped down.</li>
<li>Run Get-CimInstance with the local instance if the key property value is known.</li>
<li>Avoid using queries with the LIKE operator if possible.</li>
<li>If you need full enumeration, plan for the time overhead that&rsquo;s added to your script.</li>
</ul>
<h3>&nbsp;</h3>
<h3>Important links:</h3>
<p>Link to related post:</p>
<p><a href="https://blogs.msdn.com/b/wmi/archive/2014/03/28/performing-management-tasks-using-cim-cmdlets-4-files-and-folders.aspx">Files and Folders</a></p>
<p>&nbsp;</p>
<p>Thanks,</p>
<p>Milena Natanov [MSFT]</p>
<p>Standards-Based Management</p>]]></content:encoded>
    </item>
    <item>
      <title>Performing management tasks using CIM Cmdlets [4] – Files and Folders</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/performing-management-tasks-using-cim-cmdlets-4-files-and-folders</link>
      <pubDate>Fri, 28 Mar 2014 15:05:35 GMT</pubDate>
      <dc:creator><![CDATA[Milena Natanov]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2014/03/28/performing-management-tasks-using-cim-cmdlets-4-files-and-folders/</guid>
      <description><![CDATA[&#160;  As a part of the ongoing blog series Performing Management tasks using CIM Cmdlets we are...]]></description>
      <content:encoded><![CDATA[<h3>&#160;</h3>  <p>As a part of the ongoing blog series<b> <a href="https://blogs.msdn.com/b/wmi/archive/2014/01/09/performing-management-tasks-using-cimcmdlets-processes.aspx">Performing Management tasks using CIM Cmdlets</a></b> we are sharing PowerShell snippets for a few computer management tasks.</p>  <p>In this post, we will be going over the PowerShell snippets for file and folder management. The corresponding Visual Basic samples are in the MSDN article, <a href="https://msdn.microsoft.com/library/aa394594(v=vs.85).aspx">WMI Tasks for Files and Folders</a>. </p>  <br />  <ul>   <li>Rename a file: </li> </ul>  <br />  <table cellspacing="0" cellpadding="1" width="600" border="0"><tbody>     <tr>       <td style="color: white" bgcolor="#000080" valign="top" width="853">         <p>PS:&gt; $fileName = 'C:\\Temp\\Test1.txt' </p>          <p>PS:&gt; $newFileName = 'C:\\Temp\\Test1_NewName.txt' </p>          <p>PS:&gt; $query = &quot;SELECT * FROM CIM_DataFile WHERE Name = '$fileName'&quot; </p>          <p>PS:&gt; # Get Instance of CIM_DataFile where file name is C:\\Temp\\Test1.txt</p>          <p>PS:&gt; $file = Get-CimInstance -Query $query -Namespace root/cimv2 </p>          <p>PS:&gt; # Change name of file Test1.txt to Test1_NewName.txt</p>          <p>PS:&gt; Invoke-CimMethod -InputObject $file -MethodName 'Rename' –Arguments            <br />@{FileName=$newFileName} </p>          <p>ReturnValue PSComputerName            <br />----------- -------------- 0</p>          <p></p>       </td>     </tr>   </tbody></table>  <p>&#160; </p>  <ul>   <li>Determine whether users have .MP3 files stored on their computer: </li> </ul>  <br />  <table cellspacing="0" cellpadding="1" width="600" border="0"><tbody>     <tr>       <td style="color: white" bgcolor="#000080" valign="top" width="851">         <p>PS:&gt; $query = &quot;SELECT * FROM CIM_DataFile WHERE Extension = 'mp3'&quot; </p>          <p>PS:&gt; # Get Instances of CIM_DataFile with Extension property set to mp3</p>          <p>PS:&gt; $mp3Files = Get-CimInstance -Query $query -Namespace root/cimv2</p>          <p>PS:&gt; $mp3Files | Select Name </p>          <p>Name            <br />----             <br />c:\temp\test1.mp3             <br />c:\temp\test2.mp3</p>          <p></p>       </td>     </tr>   </tbody></table>  <p>&#160;</p>  <ul>   <li>Create shared folders on a computer: </li> </ul>  <br />  <table cellspacing="0" cellpadding="1" width="600" border="0"><tbody>     <tr>       <td style="color: white" bgcolor="#000080" valign="top" width="853">         <p>PS:&gt; # Create new share under C:\Temp called TestShare</p>          <p>PS:&gt; Invoke-CimMethod -ClassName Win32_Share -Namespace root/cimv2 –MethodName            <br />'Create' -Arguments @{Path='C:\Temp'; Name='TestShare'; Type=[uint32]'0';             <br />MaximumAllowed=[uint32]'25'; Description='Public share for team'}</p>          <p>ReturnValue PSComputerName            <br />----------- --------------             <br />0 </p>          <p></p>       </td>     </tr>   </tbody></table>  <p>&#160;</p>  <p>We will be covering other computer management scenarios in our future posts. If you have any questions, please feel free to send them to us, or post them in the Comments section.</p>  <p>&#160;</p>  <p><b></b></p>  <h5>Important links:</h5>  <p>The complete list of tasks we are covering in this series is in the MSDN article, <a href="https://msdn.microsoft.com/library/aa394585(v=vs.85).aspx">WMI Tasks for Scripts and Applications</a>. </p>  <p>Links to previous posts:</p>  <p><a href="https://blogs.msdn.com/b/wmi/archive/2014/01/09/performing-management-tasks-using-cimcmdlets-processes.aspx">Processes</a> </p>  <p><a href="https://blogs.msdn.com/b/wmi/archive/2014/01/15/performing-management-tasks-using-cimcmdlets-2-computer-hardware.aspx">Computer Hardware</a></p>  <p><a href="https://blogs.msdn.com/b/wmi/archive/2014/01/16/performing-management-tasks-using-cimcmdlets-3-operating-system.aspx">Operating System</a></p>  <p>&#160;</p>  <p>Thanks,</p>  <p>Milena Natanov [MSFT]</p>  <p>Standards-Based Management</p>]]></content:encoded>
    </item>
    <item>
      <title>Performing Management tasks using Cimcmdlets [3] – Operating System</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/performing-management-tasks-using-cimcmdlets-3-operating-system</link>
      <pubDate>Thu, 16 Jan 2014 14:17:00 GMT</pubDate>
      <dc:creator><![CDATA[Vaibhav Chugh]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2014/01/16/performing-management-tasks-using-cimcmdlets-3-operating-system/</guid>
      <description><![CDATA[&nbsp;
As a part of the ongoing blog series &ldquo;Performing Management tasks using...]]></description>
      <content:encoded><![CDATA[<p>&nbsp;</p>
<p>As a part of the ongoing blog series <strong>&ldquo;Performing Management tasks using Cimcmdlets&rdquo;</strong> we are sharing PowerShell snippets for a few Computer Management tasks.</p>
<p>In this post we will be going over the PS snippets for Operating System Management. The corresponding Visual Basic samples are at: <a href="https://msdn.microsoft.com/en-us/library/aa394596(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa394596(v=vs.85).aspx</a></p>
<p>1. Determine if a service pack has been installed on a computer:</p>
<table style="width: 616px; height: 92px;" border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="599">
<p><span style="color: #ffffff;">PS:&gt; # Get Instance of Win32_OperatingSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Look for ServicePackMajorVersion and ServicePackMinorVersion properties</span></p>
<p><span style="color: #ffffff;">PS:&gt; Get-CimInstance &ndash;ClassName Win32_OperatingSystem &ndash;Namespace root/cimv2 | Select&nbsp;ServicePackMajorVersion, ServicePackMinorVersion</span></p>
</td>
</tr>
</tbody>
</table>
<p>2. Determine when the operating system was installed on a computer:</p>
<table style="width: 648px; height: 93px;" border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;">PS:&gt; # Get Instance of Win32_OperatingSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Look for InstallDate property</span></p>
<p><span style="color: #ffffff;">PS:&gt; Get-CimInstance &ndash;ClassName Win32_OperatingSystem &ndash;Namespace root/cimv2 | Select&nbsp; InstallDate </span></p>
</td>
</tr>
</tbody>
</table>
<p>3. Determine which version of the Windows operating system is installed on a computer:</p>
<table style="width: 614px; height: 90px;" border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;">PS:&gt; # Get Instance of Win32_OperatingSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Look for Caption and Version properties</span></p>
<p><span style="color: #ffffff;">PS:&gt; $os = Get-CimInstance &ndash;ClassName Win32_OperatingSystem &ndash;Namespace root/cimv2 | Select&nbsp;Caption, Version</span></p>
</td>
</tr>
</tbody>
</table>
<p>4. Determine which folder is the Windows folder (%Windir%) on a computer:</p>
<table style="width: 611px; height: 86px;" border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;">PS:&gt; # Get Instance of Win32_OperatingSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Look for WindowsDirectory property</span></p>
<p><span style="color: #ffffff;">PS:&gt; $os = Get-CimInstance &ndash;ClassName Win32_OperatingSystem &ndash;Namespace root/cimv2 | Select&nbsp;WindowsDirectory</span></p>
</td>
</tr>
</tbody>
</table>
<p>5. Determine what hotfixes have been installed on a computer:</p>
<table style="width: 645px; height: 90px;" border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;">PS:&gt; # Get Instance of Win32_ QuickFixEngineering</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Look for HotFixID property</span></p>
<p><span style="color: #ffffff;">PS:&gt; Get-CimInstance &ndash;ClassName Win32_QuickFixEngineering &ndash;Namespace root/cimv2 | Select&nbsp;HotFixID</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>We will be covering other computer management scenarios in our future posts. If you have any questions please feel free to send them to us.</p>
<p><strong>Important links:</strong></p>
<ul>
<li>The complete list of tasks we will be covering in this series is at: <a href="https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx</a></li>
<li>Link to previous post(s):</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://blogs.msdn.com/b/wmi/archive/2014/01/09/performing-management-tasks-using-cimcmdlets-processes.aspx">Processes</a></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://blogs.msdn.com/b/wmi/archive/2014/01/15/performing-management-tasks-using-cimcmdlets-2-computer-hardware.aspx">Computer Hardware</a></p>
<p>&nbsp;</p>
<p>Thanks</p>
<p>Vaibhav Chugh [MSFT]</p>
<p>Standards Based Management</p>]]></content:encoded>
    </item>
    <item>
      <title>Performing Management tasks using Cimcmdlets [2] – Computer Hardware</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/performing-management-tasks-using-cimcmdlets-2-computer-hardware</link>
      <pubDate>Wed, 15 Jan 2014 11:42:00 GMT</pubDate>
      <dc:creator><![CDATA[Vaibhav Chugh]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2014/01/15/performing-management-tasks-using-cimcmdlets-2-computer-hardware/</guid>
      <description><![CDATA[As part of this blog series we are sharing PowerShell snippets for a few Computer Management tasks....]]></description>
      <content:encoded><![CDATA[<p>As part of this blog series we are sharing PowerShell snippets for a few Computer Management tasks. In this post we will be going over the samples for Computer Hardware management.</p>
<p>The Visual Basic samples for Computer Hardware Management are at: <a href="https://msdn.microsoft.com/en-us/library/aa394587(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa394587(v=vs.85).aspx</a></p>
<p>The corresponding PowerShell samples are below:</p>
<p>1. Determine how much free memory a computer has:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="599">
<p><span style="color: #ffffff;">PS:&gt; # Get Instance of Win32_OperatingSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; $os = Get-CimInstance &ndash;ClassName Win32_OperatingSystem &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Look for FreePhysicalMemory property</span></p>
<p><span style="color: #ffffff;">PS:&gt; $os | Select&nbsp;FreePhysicalMemory</span></p>
</td>
</tr>
</tbody>
</table>
<p>2. Determine whether a computer has a DVD drive:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Look for instances of Win32_CDROMDrive</span></p>
<p><span style="color: #ffffff;">$insts = Get-CimInstance &ndash;ClassName Win32_CDROMDrive &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;"># Loop through them and print DeviceID, Description and Name</span></p>
<p><span style="color: #ffffff;">foreach($inst in $insts)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$inst | Select&nbsp;Name, DeviceID, Description</span></p>
<p><span style="color: #ffffff;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p>3. Determine how much RAM is installed in a computer:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;">PS:&gt; # Get instance of Win32_ComputerSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; $inst = Get-CimInstance &ndash;ClassName Win32_ComputerSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Print Name of the System and the Total Physical Memory</span></p>
<p><span style="color: #ffffff;">PS:&gt; $inst | Select&nbsp;Name, TotalPhysicalMemory</span></p>
</td>
</tr>
</tbody>
</table>
<p>4. Determine if a computer has more than one processor:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;">PS:&gt; # Get instance of Win32_ComputerSystem</span></p>
<p><span style="color: #ffffff;">PS:&gt; $inst = Get-CimInstance &ndash;ClassName Win32_ComputerSystem &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">PS:&gt; # Print Name of the system and Number of Processors</span></p>
<p><span style="color: #ffffff;">PS:&gt; $inst | Select&nbsp;Name, NumberOfProcessors</span></p>
</td>
</tr>
</tbody>
</table>
<p>5. Determine whether a computer has a PCMCIA slot:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Use the Win32_PCMCIAController class and check the value of the Count property.</span></p>
<p><span style="color: #ffffff;"># If Count is 0, then the computer has no PCMCIA slots.</span></p>
<p><span style="color: #ffffff;">$insts = Get-CimInstance &ndash;ClassName Win32_PCMCIAController &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">if($insts -ne $null)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$count = $insts.Count</span></p>
<p><span style="color: #ffffff;">if($count -eq $null)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$count = 1</span></p>
<p><span style="color: #ffffff;">}</span></p>
<p><span style="color: #ffffff;">Write-Host "Number of PCMCIA slots: $count"</span></p>
<p><span style="color: #ffffff;">}</span></p>
<p><span style="color: #ffffff;">else</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">Write-Host "Number of PCMCIA slots: 0"</span></p>
<p><span style="color: #ffffff;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p>6. Identify devices that are not working (those marked with an exclamation point icon in Device Manager)?</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="599">
<p><span style="color: #ffffff;"># Use the Win32_PnPEntity class</span></p>
<p><span style="color: #ffffff;"># Use the following clause in your WQL query. WHERE ConfigManagerErrorCode &lt;&gt; 0</span></p>
<p><span style="color: #ffffff;">$query = "Select * from Win32_PnPEntity WHERE ConfigManagerErrorCode &lt;&gt; 0"</span></p>
<p><span style="color: #ffffff;">$insts = Get-CimInstance -Query $query</span></p>
<p><span style="color: #ffffff;"># Loop through all such devices and print their information.</span></p>
<p><span style="color: #ffffff;">foreach($inst in $insts)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$inst | Format-Table -Property @("ClassGuid", "Description", "DeviceID", "Manufacturer", "Name", "PNPDeviceID", "Service")</span></p>
<p>}</p>
</td>
</tr>
</tbody>
</table>
<p>7. Determine the properties of the mouse used on computer:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Use the Win32_PointingDevice class.</span></p>
<p><span style="color: #ffffff;"># This returns the properties of all pointing devices, not just mouse devices.</span></p>
<p><span style="color: #ffffff;">$insts = Get-CimInstance &ndash;ClassName Win32_PointingDevice</span></p>
<p><span style="color: #ffffff;"># Loop though instances of Win32_PointingDevice and print the properties.</span></p>
<p><span style="color: #ffffff;">foreach($inst in $insts)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$inst | Format-Table &ndash;Property @(&ldquo;Description", &ldquo;DeviceID", &ldquo;DeviceInterface", &ldquo;DoubleSpeedThreshold", &ldquo;Handedness", &ldquo;HardwareType", &ldquo;InfFileName", &ldquo;InfSection", &ldquo;Manufacturer", &ldquo;Name", &ldquo;NumberOfButtons", &ldquo;PNPDeviceID", &ldquo;PointingType", &ldquo;QuadSpeedThreshold", &ldquo;Resolution", &ldquo;SampleRate", &ldquo;Synch")</span></p>
<p><span style="color: #ffffff;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p>8. Determine the speed of a processor installed in a computer:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Use the Win32_Processor class and check the value of the MaxClockSpeed property.</span></p>
<p><span style="color: #ffffff;">$insts = Get-CimInstance &ndash;ClassName Win32_Processor &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">foreach($inst in $insts)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$inst | Select&nbsp;ProcessorId, MaxClockSpeed</span></p>
<p><span style="color: #ffffff;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p>9. Determine whether a computer is a tower, a mini-tower, a laptop, and so on:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Use the Win32_SystemEnclosure class and check the value of the ChassisType property.</span></p>
<p><span style="color: #ffffff;">$colChassis = Get-CimInstance &ndash;ClassName Win32_SystemEnclosure &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;"># Loop though the collection of chassis</span></p>
<p><span style="color: #ffffff;">foreach($chassis in $colChassis)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;"># Look though the Chassis Types</span></p>
<p><span style="color: #ffffff;">foreach($item in $chassis.ChassisTypes)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">Write-Host "Chassis Type: $item"</span></p>
<p><span style="color: #ffffff;">}</span></p>
<p><span style="color: #ffffff;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p>10. Get the serial number and asset tag of a computer:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Use the Win32_SystemEnclosure class, and the properties SerialNumber and SMBIOSAssetTag.</span></p>
<p><span style="color: #ffffff;">$sytemEnclosures = Get-CimInstance &ndash;ClassName Win32_SystemEnclosure</span></p>
<p><span style="color: #ffffff;">$sytemEnclosureCollection = @()</span></p>
<p><span style="color: #ffffff;">$sytemEnclosureCollection += $sytemEnclosures</span></p>
<p><span style="color: #ffffff;">foreach($systemEnclosure in $sytemEnclosureCollection)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$systemEnclosure | Select&nbsp;PartNumber, SerialNumber, SMBIOSAssetTag</span></p>
<p><span style="color: #ffffff;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p>11. Determine what kind of device is plugged into a USB port:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Use the Win32_USBHub class and check the Description property.</span></p>
<p><span style="color: #ffffff;"># This property may have a value such as "Mass Storage Device" or "Printing Support".</span></p>
<p><span style="color: #ffffff;">$items = Get-CimInstance &ndash;ClassName Win32_USBHub &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">foreach($item in $items)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$item | Select&nbsp;DeviceID, PNPDeviceID, Description</span></p>
<p><span style="color: #ffffff;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p>12. Determine how many tape drives are installed on a computer:</p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="navy">
<tbody>
<tr>
<td valign="top" width="623">
<p><span style="color: #ffffff;"># Use the class Win32_TapeDrive class and then count the number of instances received.</span></p>
<p><span style="color: #ffffff;"># If Count = 0, then no tape drives are installed on the computer.</span></p>
<p><span style="color: #ffffff;">$insts = Get-CimInstance &ndash;ClassName Win32_TapeDrive</span></p>
<p><span style="color: #ffffff;">$count = 0</span></p>
<p><span style="color: #ffffff;">if($insts -ne $null)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$count = $insts.Count</span></p>
<p><span style="color: #ffffff;">if($count -eq $null)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">$count = 1</span></p>
<p><span style="color: #ffffff;">}</span></p>
<p><span style="color: #ffffff;">}</span></p>
<p><span style="color: #ffffff;">Write-Host "Number of tape drives = $count"</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>We will be covering other computer management scenarios in our future posts. If you have any questions please feel free to send them to us.</p>
<p><strong>Important links:</strong></p>
<ul>
<li>The complete list of tasks we will be covering in this series is at: <a href="https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx</a></li>
<li>Link to previous post(s):</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://blogs.msdn.com/b/wmi/archive/2014/01/09/performing-management-tasks-using-cimcmdlets-processes.aspx">Processes</a></p>
<p>&nbsp;</p>
<p>Thanks</p>
<p>Vaibhav Chugh [MSFT]</p>
<p>Standards Based Management</p>]]></content:encoded>
    </item>
    <item>
      <title>Performing Management tasks using Cimcmdlets - Processes</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/performing-management-tasks-using-cimcmdlets-processes</link>
      <pubDate>Thu, 09 Jan 2014 12:56:00 GMT</pubDate>
      <dc:creator><![CDATA[Vaibhav Chugh]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2014/01/09/performing-management-tasks-using-cimcmdlets-processes/</guid>
      <description><![CDATA[WMI provides a standardized system management infrastructure that can be leveraged by a number of...]]></description>
      <content:encoded><![CDATA[<p style="text-align: justify;">WMI provides a standardized system management infrastructure that can be leveraged by a number of different clients. WMI providers and the classes exposed by the providers help in various management tasks.</p>
<p style="text-align: justify;">Our MSDN documentation lists a <a href="https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx">bunch</a> of management scenarios and the corresponding Visual Basic samples, but it is much easier for an IT administrator to perform the same operations using PowerShell.</p>
<p style="text-align: justify;">Customers have been requesting samples that will help them perform management tasks using PowerShell &ndash; therefore, in this series of blog posts we will be covering the PowerShell implementation of scenarios that are listed at the following MSDN page:&nbsp;<a title="https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx" href="https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx</a></p>
<p style="text-align: justify;">In this post we will be going over the scenarios specific to "Process Management" listed at :&nbsp;<a title="https://msdn.microsoft.com/en-us/library/aa394599(v=vs.85).aspx" href="https://msdn.microsoft.com/en-us/library/aa394599(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa394599(v=vs.85).aspx</a></p>
<p>&nbsp;</p>
<p>Here are the corresponding PowerShell snippets:</p>
<p><strong>1. Run an application in a hidden window:</strong></p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="#000080">
<tbody>
<tr>
<td valign="top" width="638">
<p><span style="color: #ffffff;">PS:&gt; $processStartupClass = Get-CimClass -ClassName Win32_ProcessStartup -Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">$processStartupInfo = New-CimInstance -cimclass $processStartupClass -Property @{ShowWindow =0} &ndash;Local</span><span style="background-color: #ffffff;">&nbsp;</span></p>
<p><span style="color: #ffffff;">PS:&gt; $processClass = Get-CimClass -ClassName Win32_Process -Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">PS:&gt; Invoke-CimMethod -CimClass $processClass -MethodName Create -Arguments @{commandline="notepad.exe"; ProcessStartupInformation = [CimInstance]$processStartupInfo}</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>2. Determine which scripts are running on the local computer:</strong></p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="#000080">
<tbody>
<tr>
<td valign="top" width="638">
<p>&nbsp;</p>
<p><span style="color: #ffffff;">PS:&gt; $query = "SELECT * FROM Win32_Process WHERE Name = 'cscript.exe' OR Name = 'wscript.exe'"</span></p>
<p><span style="color: #ffffff;">PS:&gt; $insts = Get-CimInstance -Query $query -Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">PS:&gt; $insts | Select&nbsp;Name, commandline</span></p>
<p>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>3. Find out the account name under which a process is running:</strong></p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="#000080">
<tbody>
<tr>
<td valign="top" width="614">
<p><span style="color: #ffffff;">PS:&gt; $query = "Select * from Win32_Process"</span></p>
<p><span style="color: #ffffff;">PS:&gt; $insts = Get-CimInstance -Query $query -Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">PS:&gt; # OR</span></p>
<p><span style="color: #ffffff;">PS:&gt; $insts = Get-CimInstance &ndash;ClassName Win32_Process &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">PS:&gt; $insts | %{</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write-host&nbsp;&nbsp; $_.CimInstanceProperties["Name"]</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$owner = Invoke-CimMethod -InputObject $_ -MethodName GetOwner</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;$owner | Select&nbsp;Domain, User, PSComputerName</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>4. Change the priority of a running process:</strong></p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="#000080">
<tbody>
<tr>
<td valign="top" width="638">
<p><span style="color: #ffffff;">PS:&gt; $query = "Select * from Win32_Process Where Name = 'Notepad.exe'"</span></p>
<p><span style="color: #ffffff;">PS:&gt; $insts = Get-CimInstance -Query $query -Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">PS:&gt; $aboveNormal = 32768</span></p>
<p><span style="color: #ffffff;">PS:&gt; $insts | %{</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp; Invoke-CimMethod -InputObject $_ -MethodName SetPriority -Arguments @{Priority = [Uint32]$aboveNormal}</span></p>
<p><span style="color: #ffffff;">}</span><span style="background-color: #ffffff;">&nbsp;</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>5. Terminate a process using a script:</strong></p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="#000080">
<tbody>
<tr>
<td valign="top" width="638">
<p><span style="color: #ffffff;">PS:&gt; $query = "Select * from Win32_Process Where Name = 'Notepad.exe'"</span></p>
<p><span style="color: #ffffff;">PS:&gt; Invoke-CimMethod -Query $query -MethodName Terminate</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>6. Determine how much processor time and memory each process is using:</strong></p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="#000080">
<tbody>
<tr>
<td valign="top" width="638">
<p><span style="color: #ffffff;">$query = "Select * from win32_process"</span></p>
<p><span style="color: #ffffff;">$procs = Get-CimInstance -Query $query</span></p>
<p><span style="color: #ffffff;"># OR</span></p>
<p><span style="color: #ffffff;">$procs = Get-CimInstance &ndash;ClassName Win32_Process &ndash;Namespace root/cimv2</span></p>
<p>&nbsp;</p>
<p><span style="color: #ffffff;">foreach($proc in $procs)</span></p>
<p><span style="color: #ffffff;">{</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp; $result = New-Object PSObject -Property @{</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; processorTime = ($proc.KernalModeTime + $proc.UserModeTime) / 10000000</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name = $proc.Name</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProcessID = $proc.ProcessId</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WorkingSetSize = $proc.WorkingSetSize</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PageFileUsage = $proc.PageFileUsage</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PageFaults = $proc.PageFaults</span></p>
<p><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p><span style="color: #ffffff;">$result | Format-Table -Property @("Name", "ProcessID", "WorkingSetSize", "PageFileUsage", "PageFaults", "ProcessorTime")</span></p>
<p><span style="color: #ffffff;">}</span></p>
<p>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>7. Determine what applications are running on a remote computer:</strong></p>
<table border="1" cellspacing="0" cellpadding="0" bgcolor="#000080">
<tbody>
<tr>
<td valign="top" width="638">
<p><span style="color: #ffffff;">$cimSession = New-CimSession remoteMachine &ndash;Credential $psCreds</span></p>
<p><span style="color: #ffffff;">$query = "Select * from Win32_Process"</span></p>
<p><span style="color: #ffffff;">$procs = Get-CimInstance -Query $query -CimSession $cimSession</span></p>
<p><span style="color: #ffffff;"># OR</span></p>
<p><span style="color: #ffffff;">$procs = Get-CimInstance &ndash;ClassName Win32_Process &ndash;Namespace root/cimv2</span></p>
<p><span style="color: #ffffff;">$procs |&nbsp; Format-Table &ndash;Property @(&ldquo;Name", &ldquo;ProcessID", &ldquo;ThreadCount", &ldquo;PageFileUsage", &ldquo;PageFaults", &ldquo;WorkingSetSize")</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>As mentioned above, this blog series will cover various management scenarios. The next post will be about Computer Hardware Management scenarios listed at:&nbsp;<a title="https://msdn.microsoft.com/en-us/library/aa394587(v=vs.85).aspx" href="https://msdn.microsoft.com/en-us/library/aa394587(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa394587(v=vs.85).aspx</a></p>
<p>&nbsp;</p>
<p>Thanks</p>
<p>Vaibhav Chugh [MSFT]</p>
<p>Standards Based Management</p>]]></content:encoded>
    </item>
    <item>
      <title>Implementing MI Provider (6) - Build, Register, and Debug</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/implementing-mi-provider-6-build-register-and-debug</link>
      <pubDate>Sat, 28 Dec 2013 16:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Haowei Qin [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2013/12/28/implementing-mi-provider-6-build-register-and-debug/</guid>
      <description><![CDATA[This blog discusses how to build, register and debug MI provider.
Build
To build MI provider, open...]]></description>
      <content:encoded><![CDATA[<p>This blog discusses how to build, register and debug MI provider.</p>
<p><strong style="font-size: medium;">Build</strong></p>
<p>To build MI provider, open visual studio 2012, create an empty Visual C++ project named &ldquo;process&rdquo;, set type to DLL, and add all generated files into the project.</p>
<ul>
<li>Open project property dialog box, navigate to linker page, click input option, Set Module Definition File to &ldquo;Provider.DEF&rdquo;. This will ensure DLL exports the set of APIS defined in provider.DEF file. NOTE, make sure the LIBRARY section of Provider.DEF file was set to process.DLL.</li>
<li>Select your target platform, if you want the provider to run on X64 platform, please create &ldquo;X64&rdquo; platform through &ldquo;Configuration Manager &hellip;&rdquo; button, otherwise keep the default option is &ldquo;Win32&rdquo;, which means target platform is X86.</li>
<li>Optionally, go to &ldquo;C/C++&rdquo; -&gt; &ldquo;code generation&rdquo; page, select &ldquo;Multi-threaded Debug (/MTd)&rdquo; or &ldquo;Multi-threaded (/MT)&rdquo; for runtime library to avoid the issue that target test machine is missing the runtime DLL requested by your provider DLL.</li>
</ul>
<p>Refer to <a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for the sample project, open the solution file within&nbsp;Visual studio 2012, which integrates windows 8 SDK installation directory, by build all projects, you will be able to get all of the MI provider's binaries, for example process.DLL.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>Register</strong></span></p>
<p><strong>(1) Tool</strong></p>
<p>Register-CimProvider.exe is the tool used to register MI provider, shipped with windows 8, which can be found under %system32% folder. Following diagram shows the process of the registration.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/4784.register.bmp" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/4784.register.bmp"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/4784.register.bmp" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/4784.register.bmp" alt="" border="0" /></a></p>
<p>On windows 8, MI provider is managed by WMI service. Register-CimProvider.exe tool helps to register MI providers into the system (WMI). The tool creates mof and mfl files on the fly based on the schema definition from the DLL as described above, and then compile the mof/mfl files into WMI repository. The tool registers the providers' DLL as a COM server as well.</p>
<p>To register process.DLL, copy the compiled process.DLL to a Windows 8 or Windows Server 2012 machine, and invoke the following command line from elevated commandline prompt (cmd.exe):</p>
<pre class="scroll"><code class="cplusplus">Register-CimProvider.exe -Namespace Root/Standardcimv2/sample -ProviderName process -Path process.dll -verbose -ForceUpdate</code></pre>
<p>Upon that completes, process.dll should be successfully registered into system. By default, the provider is registered as a coupled provider, i.e, it runs in a Wmiprvse.exe process. And default hosting model value is NetworkServiceHost, which means the host process is running under NETWORK SERVICE account. process.mof will also be generated under current directory, which contains the detail registration schema of the provider.</p>
<p><strong>(2) Provider Hosting Model</strong></p>
<p><span>On windows 8, MI Provider's hosting model follows the same specification of WMI provider hosting model and security. Please refer following link for the details.</span></p>
<p><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa392783(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/aa392783(v=vs.85).aspx</a></p>
<p>&nbsp;</p>
<p>MI provider can be hosted as coupled provider and decoupled provider. As mentioned above, coupled provider will be hosted in wmiprvse.exe running under specific account which could be specified by -HostingModel argument, while a decoupled provider is running under any customized arbitrary process. WMI service controlled the lifecycle of a coupled provider, i.e., loading/unloading the provider time; while the lifecycle of a decoupled provider is completely controlled by its hosting process. MI API also provides a convenient API to host arbitrary MI provider within current process.</p>
<p><strong>(3) Host Decoupled MI Provider</strong></p>
<p>MI_Application_NewHostedProvider is the API to host provider as a decoupled provider under current process. Following is the pseudo code snippet of hosting a MI provider as a decoupled provider.&nbsp;Code snippet of hosting decoupled MI provider, (please refer to&nbsp;<a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;dcuphost project for the complete implementation)<span>&nbsp;</span></p>
<pre class="scroll"><code class="cplusplus"> // load provider DLL<br /> hProvider = LoadLibraryExW(&ldquo;process.DLL&rdquo;, NULL, 0);<br /> // query MI_Main function from provider DLL<br /> mi_main = (MI_MainFunction)GetProcAddress(hProvider, MI_MAIN_FUNCNAME);<br /> // initialize MI_Application object<br /> result = MI_Application_Initialize(0, NULL, NULL, &amp;application);<br /> // host the provider as decoupled provider<br /> result = MI_Application_NewHostedProvider(&amp;application,<br /> pArgument-&gt;lpNamespace,<br /> pArgument-&gt;lpProviderName,<br /> mi_main,<br /> NULL,<br /> &amp;hostedProvider);<br /> </code></pre>
<div>
<div>
<div>
<p><span>Note that before hosting a MI provider as decoupled provider, it should be registered to the system as a decoupled provider firstly. Take process.dll for example, below is the command line to register it as a decoupled one,</span></p>
<pre class="scroll"><code class="cplusplus">Register-CimProvider.exe -Namespace Root/StandardCimV2/dcupsample -ProviderName process -Path C:\temp\provider.dll -Decoupled O:BAG:BAD:(A;;0x1;;;BA)(A;;0x1;;;NS) -Impersonation True</code></pre>
<p>&nbsp;</p>
</div>
</div>
</div>
<p><span style="font-size: medium;"><strong>Test/Validate</strong></span></p>
<p>To validate the MI provider is functioning or not, there are couple of approaches listed as of following, see&nbsp;<a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for the sample code.</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="139">
<p class="paragraph"><span style="font-family: 'courier new', courier;"><strong>Methodology</strong></span></p>
</td>
<td valign="top" width="355">
<p class="paragraph"><span style="font-family: 'courier new', courier;"><strong>Description</strong></span></p>
</td>
</tr>
<tr>
<td valign="top" width="139">
<p class="paragraph"><span style="font-family: 'courier new', courier;">Wbemtest.exe</span></p>
</td>
<td valign="top" width="355">
<p class="paragraph"><span style="font-family: 'courier new', courier;">Send request to provider via this UI tool.</span></p>
</td>
</tr>
<tr>
<td valign="top" width="139">
<p class="paragraph"><span style="font-family: 'courier new', courier;">Cim Cmdlets</span></p>
</td>
<td valign="top" width="355">
<p class="paragraph"><span style="font-family: 'courier new', courier;">A set of new cmdlets shipped with windows 8</span></p>
</td>
</tr>
<tr>
<td valign="top" width="139">
<p class="paragraph"><span style="font-family: 'courier new', courier;">Cim based cmdlets</span></p>
</td>
<td valign="top" width="355">
<p class="paragraph"><span style="font-family: 'courier new', courier;">Create cdxml to define a set of cim-based cmdlets to access the provider</span></p>
</td>
</tr>
<tr>
<td valign="top" width="139">
<p class="paragraph"><span style="font-family: 'courier new', courier;">Application</span></p>
</td>
<td valign="top" width="355">
<p class="paragraph"><span style="font-family: 'courier new', courier;">Using MI C API or MI.net API to build an application to verify the provider</span></p>
</td>
</tr>
</tbody>
</table>
<div>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>Un-register</strong></span></p>
</div>
<p>How to un-register the MI provider completely from system? Unfortunately, Register-CimProvider.exe tool has no option to un-register a MI provider from system. It providers an option to generate uninstall mof and (or) mfl file during the registration time. The option name is <em>GenerateUnregistration</em>.</p>
<p>Take process provider for example, if you run following command line, processUninstall.mof and process.mof will be generated under current directory.</p>
<pre class="scroll"><code class="cplusplus">Register-CimProvider.exe -Namespace Root/Standardcimv2/sample -ProviderName process -Path process.dll -verbose &ndash;ForceUpdate -GenerateUnregistration<br /> </code></pre>
<p><span>processUninstall.mof contains instructions of unregistering the registered provider from system. It will delete registered non-abstract classes, related provider registration instances, and __Win32Porvider instance from system.</span></p>
<pre class="scroll"><code class="cplusplus"> #pragma classflags ("forceupdate")<br /> #pragma namespace ( "\\\\.\\Root\\Standardcimv2\\sample")<br /> <br /> #pragma deleteclass("MSFT_WindowsProcess",nofail)<br /> #pragma deleteclass("MSFT_WindowsServiceProcess",nofail)<br /> #pragma deleteinstance("__MethodProviderRegistration.Provider=\"\\\\\\\\.\\\\Root\\\\Standardcimv2\\\\sample:__Win32Provider.Name=\\\"process\\\"\"", nofail)<br /> #pragma deleteinstance("__InstanceProviderRegistration.Provider=\"\\\\\\\\.\\\\Root\\\\Standardcimv2\\\\sample:__Win32Provider.Name=\\\"process\\\"\"", nofail)<br /> #pragma deleteinstance("__Win32Provider.Name=\"process\"", nofail)<br /></code></pre>
<table border="0">
<tbody>
<tr>
<td>
<p align="left"><em>Notes regarding un-register MI provider,</em></p>
<p align="left"><em></em>Abstract classes registered by MI provider are not generated in Uninstall.mof. Because abstract classes might be referred by other providers under the same namespace, detecting that would cause complexity. As a MI provider developer, you can choose to delete all classes defined in the MI provider by adding deleteclass instructions for all classes into Uninstall.mof, as long as it can be guaranteed that there is no other provider be affected under the same namespace.</p>
<p align="left">Registering MI provider will also create one registry key into the system. Process provider has the following registry key and value created,</p>
<div>
<pre class="scroll"><code class="cplusplus"> Windows Registry Editor Version 5.00<br /> <br /> [HKEY_CLASSES_ROOT\CLSID\{EDCB2856-2E63-4F57-B3A1-F03CC7D9FEE3}]<br /> @="process"<br /> <br /> [HKEY_CLASSES_ROOT\CLSID\{EDCB2856-2E63-4F57-B3A1-F03CC7D9FEE3}\InprocServer32]<br /> @="F:\\sdksrc\\book\\x64\\Debug\\process.dll"<br /> "ThreadingModel"="Free"<br /> </code></pre>
</div>
<div><span>To delete the registry key from system, run following command line,</span></div>
<div>
<pre class="scroll"><code class="cplusplus">reg delete HKEY_CLASSES_ROOT\CLSID\{EDCB2856-2E63-4F57- B3A1-F03CC7D9FEE3} /f<br /><br /></code></pre>
</div>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>Debug</strong></span></p>
<p>MI provider could be hosted in wmiprvse.exe process, or hosted as decoupled provider. Decoupled provider is relatively easy to debug since the host process has to start in order to host decoupled provider. By attaching to host process, you can debug the provider. This section focuses on debugging coupled provider, all break points and techniques are applicable to decoupled provider as well.</p>
<p>Normal debugging tools include visual studio and windbg. Following content introduces both techniques.</p>
<p>To debug a coupled provider, you need to</p>
<p>(1) Launch the provider into host process</p>
<p>(2) Attach to the host process</p>
<p>(3) set breakpoints and debug.</p>
<p>To launch MI provider, you may send an operation request to the MI provider (via powershell/cim cmdlets for example), the provider will be loaded into host process.</p>
<p>To attach to host process, you can run &ldquo;tasklist &ndash;m &lt;&gt;.DLL&rdquo; to tell which process is loading the provider. And use either windbg or visual studio 2012 attach to the process.</p>
<p>And then set breakpoints and you will be able to debug through. Following picture shows a snapshot of debugging EnumerateInstances method of MSFT_WindowsProcess class.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/7026.debug.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/7026.debug.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/7026.debug.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/7026.debug.png" alt="" border="0" /></a></p>
<p>&nbsp;</p>
<p><strong>Debug provider Load/Class Load function</strong></p>
<p>These two functions will be invoked once and only once, which were already called by the time attaching debugger to the host process. To debug these functions, debugger has to attach to host process before they get invoked. And following are the tricks,</p>
<p>(1) Register the provider as decoupled provider and start a host process to host the provider. This way you can attach the debugger tool to the host process to debug the provider load and class load function.</p>
<p>(2) Find another provider which shares the same host process with the target provider. Invoke another provider firstly will launch the host process. By attaching to the process, you will be able to set deferred breakpoints at Load and class Load function to debug.</p>
<p>For example, by default process.dll hosting model is NetworkServiceHost, which is the same with Cimwin32.dll. By invoking &ldquo;wmic os&rdquo; on any command line console, you will be able to see a wmiprvse.exe host process was launched running under NETWORKING SERVICE account. Now attach debugger to the process, and then let the process continue running. Then if invoke the process.dll provider by enumerate instances of MSFT_WindowsProcess class from powershell console, you will be able to see that process.dll is being launched in the same host process.</p>
<p>If you are not able to use trick 2, then try to use gflags.exe to set following debugger for image file &ldquo;wmiprvse.exe&rdquo;.</p>
<pre class="scroll"><code class="cplusplus">cdb.exe -server tcp:port=8080 -c "g"</code></pre>
<p>Then invoke the provider from powershell console, now the host process will be launched but was blocked into cdb.exe, use windbg.exe to connect to the remote debugging server, and then set interested breakpoints before hit &ldquo;g&rdquo;.</p>
<pre class="scroll"><code class="cplusplus">windbg.exe -remote tcp:server=&lt;server&gt;,port=8080</code></pre>
<p>Now you are able to debug Load and class Load functions.</p>
<p>Warning, For trick (2), you might block other host process from being launched, since cdb won&rsquo;t be able to create debugger server on the same tcp port more than once.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Happy Holidays!&nbsp;I hope "Implementing MI Provider" blogs helps. Fell free to comment, ask questions, or email <a href="mailto:haoweiqin@outlook.com">haoweiqin@outlook.com</a> for deep discussions regarding CIM, WMI, etc.</p>
<p>&nbsp;</p>
<p>Haowei Qin</p>
<p>Senior SDE</p>
<p>Standards Based Management</p>]]></content:encoded>
    </item>
    <item>
      <title>Implementing MI Provider (5) - Implement</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/implementing-mi-provider-5-implement</link>
      <pubDate>Sat, 28 Dec 2013 13:54:00 GMT</pubDate>
      <dc:creator><![CDATA[Haowei Qin [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2013/12/28/implementing-mi-provider-5-implement/</guid>
      <description><![CDATA[As discussed in&nbsp;Implementing MI Provider (4) - Generate Code...]]></description>
      <content:encoded><![CDATA[<p><span>As discussed in&nbsp;</span><a href="https://blogs.msdn.com/b/wmi/archive/2013/12/28/implementing-mi-provider-4-generate-code-continute.aspx">Implementing MI Provider (4) - Generate Code (continute)</a>,&nbsp;<span>Convert-MofToProvider.exe tool generates &lt;class name&gt;.c file for each target class, which contains stub functions to place the business logic of each operation, such as enumerate/get/delete/modify/new/&lt;extrinsic methods&gt;.</span></p>
<p><span>This blog discusses how to implement stub functions of normal (instance) classes, while association and indication class will be discussed separately in future. Let's first </span>introduce a set of frequently used MI APIs (when implementing MI provider) and then discuss how to implement the business logic of each generated stub function using those APIs.</p>
<p><span style="font-size: medium;"><strong>MI Context API</strong></span></p>
<p>The name of provider APIs are suffixed by MI_Context, which means the operation performed by the API was against the MI_Context object, while MI_Context defined as below, the MI_ContextFT structure definition could be found in mi.h from <a href="https://msdn.microsoft.com/en-us/windows/desktop/hh852363.aspx">windows 8 SDK</a>.</p>
<pre class="scroll"><code class="cplusplus"> typedef struct _MI_Context MI_Context;<br /> struct _MI_Context<br /> {<br /> /* Function table */<br /> const MI_ContextFT* ft;<br /> <br /> /* Reserved for internal use */<br /> ptrdiff_t reserved[3];<br /> };<br /> </code></pre>
<p>All MI_Context_* APIs are just a wrapper function that calls into one function inside MI_ContextFT structure.</p>
<p><strong>MI_Context_PostInstance</strong> is used to post a MI_Instance back to server. Usually a MI_Instance could be constructed by calling generated constructor API defined in a class header file. Normally, provider calls into this API to delivery prepared instances. For example, client send an enumeration request to omi server, then the provider generates N number of instances, and should call this API N times to post them back to server.</p>
<p><strong>MI_Context_PostError</strong> is used to post an error code with error message back to server.</p>
<p><strong>MI_Context_PostCimError</strong> is used to post a CimError instance back to server.</p>
<p><strong>MI_Context_PostResult</strong> is used to post the final operation result back to server.</p>
<table border="0">
<tbody>
<tr>
<td>
<div>
<p class="NoteWarning"><em><span style="font-family: 'courier new', courier;"><strong>NOTE:</strong> All Post APIs listed above are posting data to server, while server will deliver the data to client.</span></em></p>
<p class="NoteWarning"><em><span style="font-family: 'courier new', courier;">Any operation might post arbitrary number of instances back to server, however if without any specific clarification, all provider stub functions should call one of the following APIs once and only once (One exception is indication class's stub function EnableIndications, which may be covered by future blog).</span></em></p>
<p class="NoteWarning"><span style="font-family: 'courier new', courier;">&nbsp; MI_Context_PostError</span></p>
<p class="NoteWarning"><span style="font-family: 'courier new', courier;">&nbsp; MI_Context_PostCimError</span></p>
<p class="NoteWarning"><span style="font-family: 'courier new', courier;">&nbsp; MI_Context_PostResult</span></p>
</div>
</td>
</tr>
</tbody>
</table>
<p><strong>MI_Context_GetLocalSession</strong> gets local MI_Session object, which can be used to communicate back to the local CIMOM server for local operations, for example a provider need to query instances of another class on the local machine. The provider must *<strong>NOT</strong>* call MI_Session_Close on the local session object since the life cycle of the session object is managed by the host process.</p>
<p>&nbsp;</p>
<p><strong><span style="font-size: medium;">MI Powershell&nbsp;Semantics API</span></strong></p>
<p>Powershell Semantics APIs are designed to enable MI provider to interact with Powershell Console efficiently, such as MI_Context_PromptUser, be used by MI provider to send a prompt message to the client application (powershell for example) to confirm whether to continue the operation or not.</p>
<pre class="scroll"><code class="cplusplus"> MI_Context_PromptUser<br /> <br /> MI_Context_ShouldContinue<br /> <br /> MI_Context_ShouldProcess<br /> <br /> MI_Context_WriteCimError<br /> <br /> MI_Context_WriteError<br /> <br /> MI_Context_WriteProgress<br /> <br /> MI_Context_WriteMessage<br /> <br /> MI_Context_WriteVerbose<br /> <br /> MI_Context_WriteWarning<br /> <br /> MI_Context_WriteDebug</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>MI Client API</strong></span></p>
<p>A MI provider may need MI client API&nbsp;to perform specific operation to a different CIM class, such as querying instances of another CIM class or invoking an extrinsic method of another CIM class. Following are several frequently used client APIs, for a complete list of APIs, please refer to&nbsp;<a href="https://msdn.microsoft.com/en-us/windows/desktop/hh852363.aspx">windows 8 SDK</a>&nbsp;mi.h</p>
<p><strong>MI_Application_Initialize</strong> is used to initialize and create a MI_Application object.</p>
<p><strong>MI_Application_Close</strong> is used to close a MI_Application object, which will cancel all sessions and operations related to this application object.</p>
<p><strong>MI_Application_NewSession</strong> creates a new MI_Session object, which is used to kick off any operation towards the CIMOM server.</p>
<p><strong>MI_Session_Close</strong> closes the session, all operations have to be closed before session close finished.</p>
<p><strong>MI_Session_EnumerateInstances</strong> start an operation to enumerate instances of a target class under specific namespace from target server, which will return a MI_Operation object.</p>
<p><strong>MI_Operation_GetInstance</strong> retrieves MI_Instance from a started MI_Operation object synchronously.</p>
<p><strong>MI_Operation_Close</strong> closes the operation.</p>
<p>&nbsp;</p>
<p>Taking MSFT_WindowsProcess class example, remaining of this blog explains the general process of implementing enumerate instance, get instance, modify instance, delete instance, create instance, and extrinsic method.</p>
<p><strong><span style="font-size: small;">(1) Implement EnumerateInstances</span></strong></p>
<p>Generally speaking, there are six steps to implement enumerate instance operation for a class,</p>
<p>1) Firstly construct an instance of the target class by invoking &lt;class name&gt;_Construct API,</p>
<p>2) Set properties value of the instance. One <strong><em>important</em></strong> note is that all key properties of the instance must be set, and the combination of the key properties value should be unique, which identifies the instance uniquely.</p>
<p>3) Post the instances back by invoking &lt;class_name&gt;_Post API.</p>
<p>4) Destruct the constructed instances by calling &lt;class name&gt;_Destruct API.</p>
<p>5) Post final result to client by calling one of the post API. Call <strong>MI_Context_PostResult</strong> if succeed.</p>
<p>6) If there is any failure happened during above step which is considered blocking the current operation, provider should call MI_Context_PostError or MI_Context_PostCimError API to notify the client the final result.</p>
<p>Sometime, it may take time to complete the enumerating operation if there are quite a few instances to be posted back to client, and it makes sense to use ps-semantic API <strong><em>MI_Context_WriteProgress</em></strong> to notify client the current percentage of the operation.</p>
<p>Following diagram is the implementation diagram of MSFT_WindowsProcess_EnumerateInstances, see example code as well. Refer to&nbsp;<a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for complete implementation.</p>
<table border="0">
<tbody>
<tr>
<td><em><em><span><strong>NOTE:</strong>&nbsp;</span></em>For any MI_Instance constructed successfully by calling generated API &lt;class name&gt;_Construct, it should be destructed always once and only once by calling &lt;class name&gt;_Destruct.<br />For any MI_Instance created by MI_Context_NewInstance or generated API such as MSFT_WindowsProcess_Clone, it should be deleted by calling MI_Instance_Delete once and only once.</em></td>
</tr>
</tbody>
</table>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/7220.enum.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/7220.enum.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/7220.enum.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/7220.enum.png" alt="" border="0" /></a>&nbsp;</p>
<p>&nbsp;</p>
<pre class="scroll"><code class="cplusplus">void MI_CALL MSFT_WindowsProcess_EnumerateInstances(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_opt_ const MI_PropertySet* propertySet,<br /> _In_ MI_Boolean keysOnly,<br /> _In_opt_ const MI_Filter* filter)<br /> {<br /> MI_Result result = MI_RESULT_OK;<br /> <br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(propertySet);<br /> MI_UNREFERENCED_PARAMETER(filter);<br /> <br /> result = EnumerateProcesses(context, keysOnly);<br /> if (result == MI_RESULT_ACCESS_DENIED)<br /> {<br /> MI_Context_PostError(context,<br /> result,<br /> MI_RESULT_TYPE_MI,<br /> MI_T("Access denied. Please try to run client process with elevated priviledge."));<br /> }<br /> else if (result != MI_RESULT_OK)<br /> {<br /> MI_Context_PostError(context,<br /> result,<br /> MI_RESULT_TYPE_MI,<br /> MI_T(""));<br /> }<br /> else<br /> {<br /> MI_Context_PostResult(context, result);<br /> }<br /> }<br /> </code></pre>
<p><strong><span style="font-size: small;">(2) Implement GetInstance</span></strong></p>
<p>Get instance operation requires that all key properties of a MI_instance are sent to MI provider. There are several steps to implement get instance operation for a class,</p>
<p align="left">1) Firstly check the key properties value of the given instance is valid or not.</p>
<p>2) If it is valid, then construct an instance of the target class by invoking &lt;class name&gt;_Construct API,</p>
<p>3) Set properties' value of the instance. One <strong>important</strong> note is that all key properties of the instance must be set, which are equal to the input instance, and the combination of the key properties value should be unique, which identifies the instance uniquely.</p>
<p>4) Post the instances back by invoking &lt;class_name&gt;_Post API.</p>
<p>5) Destruct the constructed instance by calling &lt;class name&gt;_Destruct API.</p>
<p>6) Post final result to client by calling MI_Context_PostResult API.</p>
<p>7) If there is any failure happened during above step which is considered blocking the current operation, provider should call MI_Context_PostError or MI_Context_PostCimError API to notify the client the final result.</p>
<p>Refer to&nbsp;<a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for complete implementation of MSFT_WindowsProcess_GetInstance.</p>
<table border="0">
<tbody>
<tr>
<td><strong><em>NOTE:</em></strong>&nbsp;<em>If a MI provider does not support Get instance operation, i.e., keep generated code &lt;class name&gt;_GetInstance unchanged (i.e., post MI_RESULT_NOT_SUPPORTED via one of the post API), then the get instance request will be redirected to &lt;class name&gt;_EnumerateInstance function, and returned instances from EnumerateInstances function will be filtered based on the key properties value of the incoming requested instance, and then CIMOM server post back result full instance back to client. But this behavior is inefficient and might cause performance issue in case the class has too many instances.</em></td>
</tr>
</tbody>
</table>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/5584.get.bmp" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/5584.get.bmp"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/5584.get.bmp" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/5584.get.bmp" alt="" border="0" /></a></p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><strong>(3) Implement CreateInstance</strong></span></p>
<p>Not all classes support CreateInstance operation. The confusing part of the intrinsic create method is that it is hard for client user to figure out which properties value are mandatory to create an instance of a target class, and the supported format of each properties value, especially for key properties, it kind of different for client user to specify a valid key value to create a new instance, sometime, the key properties value might be generated by MI provider automatically. So commonly, defining an extrinsic method to create instance makes more sense, the method could define a set of input parameters and might the format of each parameter through parameter qualifiers. One example is Create method of MSFT_WindowsProcess class. However, if a MI provider does support intrinsic CreateInstance operation, following are the steps to implement it,</p>
<p align="left">1) Firstly check the properties&rsquo; value of the given instance is valid or not.</p>
<p>2) If it is valid, then construct an instance of the target class by invoking &lt;class name&gt;_Construct API,</p>
<p>3) Set all of the properties&rsquo; value of the instance. Some properties&rsquo; value might come from input instance; other might be calculated by the provider. One <strong><em>important</em></strong> note is that all key properties of the instance must be set, which are equal to the input instance, and the combination of the key properties value should be unique, which identifies the instance uniquely.</p>
<p>4) Post the newly created instance back by invoking &lt;class_name&gt;_Post API. This step is <strong><em>mandatory</em></strong> due to client relies on this to get the key values of the newly created instance.</p>
<p>5) Destruct the constructed instance by calling &lt;class name&gt;_Destruct API.</p>
<p>6) Post final result to client by calling MI_Context_PostResult API.</p>
<p>7) If there is any failure happened during above step which is considered blocking the current operation, provider should call MI_Context_PostError or MI_Context_PostCimError API to notify the client the final result.</p>
<p>Refer to&nbsp;<a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for complete implementation of MSFT_WindowsProcess_CreateInstance.</p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><strong>(4) Implement ModifyInstance</strong></span></p>
<p>ModifyInstance operation faces the similar issue with CreateInstance due to it is hard for client user to figure out which property could be modified and which property could not. Someone might argue that Read and Write qualifiers are the flag to tell which property could be modified, but in reality, not all of the class schema definition follows Read/Write qualifiers strictly. If schema does define Read/Write qualifier appropriately, powershell console as a client does prevent modifying the value of Read only properties.</p>
<p>For ModifyInstance operation, it is also challenging to implement. Provider developer needs to figure out the set of properties to be modified, unfortunately there is no straight forward approach to tell the exactly list of properties to be modified, the <strong><em>PropertySet</em></strong> parameter of following method is always set to NULL in windows 8.</p>
<pre class="scroll"><code class="cplusplus">void MI_CALL MSFT_WindowsProcess_ModifyInstance(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_ const MSFT_WindowsProcess* modifiedInstance,<br /> _In_opt_ const MI_PropertySet* propertySet)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(propertySet);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> </code></pre>
<pre class="scroll">There is one workaround of the problem,</pre>
<ul>
<li>The provider could query the latest value of the instance.</li>
<li>Comparing the instance latest value with given instance to be modified, for any property that has a different value, it might need modification.</li>
<li>One <strong>important</strong> note is that if the property value is NULL, then it needs another technique to tell should the property be modified or not.</li>
</ul>
<p>The following utility method could tell whether a specific property was explicitly modified by client application or not.</p>
<pre class="scroll"><code class="cplusplus">MI_Result MI_CALL MI_Instance_IsElementModified(<br /> _In_ const MI_Instance* self,<br /> _In_z_ const MI_Char* name,<br /> _Out_opt_ MI_Boolean* modified)<br /> {<br /> MI_Uint32 flags = 0;<br /> MI_Result r;<br /> if (!modified)<br /> {<br /> return MI_RESULT_INVALID_PARAMETER;<br /> }<br /> r = MI_Instance_GetElement(self, name, NULL, NULL, &amp;flags, NULL);<br /> if (r == MI_RESULT_OK)<br /> {<br /> if ((flags &amp; MI_FLAG_NOT_MODIFIED) == 0)<br /> {<br /> *modified = MI_TRUE;<br /> }<br /> else<br /> {<br /> *modified = MI_FALSE;<br /> }<br /> }<br /> return r;<br /> }<br /> </code></pre>
<table border="0">
<tbody>
<tr>
<td><em><strong>NOTE</strong>: MI_FLAG_NOT_MODIFIED is only applicable to top level property, which was modified by MI_Instance_SetElementAt or MI_Instance_SetElement APIs or equivalent MI.net APIs. Since a MI Instance could have embedded instance property, if a sub property value of an embedded instance property was modified, since there is no MI_Instance_SetElementAt or MI_Instance_SetElement API call to notify the parent instance of the change of the embedded property, then above utility method won&rsquo;t work as expected for this property.</em></td>
</tr>
</tbody>
</table>
<p>Given the above limitations, it might make more sense to define a specific extrinsic method to modify a specific property of an instance. One example is SetPriority method of MSFT_WindowsProcess class. However, some classes may still need to implement intrinsic ModifyInstance method following below steps,</p>
<p align="left">1) Firstly check the key properties value of the given instance is valid or not.</p>
<p>2) If it is valid, before modifying the instance properties&rsquo; value, it might make sense to request confirmation from client application by calling MI_Context_PromptUser or &hellip;&hellip; to confirm that user really wants the modification.</p>
<p>3) If get positive answer from client user, then modify all of the requested non-key properties value of the instance by figuring out which properties are requested to be modified based on above techniques. How to modify the instance value is really depends on the provider&rsquo;s business logic, it could modify the registry key; could store the value into file or database; could modify the value in memory cache, etc. There is NO need to post any instance back.</p>
<p>4) Post final result to client by calling MI_Context_PostResult API.</p>
<p>5) If there is any failure happened during above step which is considered blocking the current operation, provider should call MI_Context_PostError or MI_Context_PostCimError API to notify the client the final result.</p>
<p>Refer to&nbsp;<a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for complete implementation of MSFT_WindowsProcess_ModifyInstance.&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><strong>(5) Implement DeleteInstance</strong></span>&nbsp;</p>
<p>DeleteInstance may have different meaning to different class, for MSFT_WindowsProcess class, it means kill the process. To implement delete instance,</p>
<p align="left">1) Firstly check the key properties value of the given instance is valid or not.</p>
<p>2) If it is valid, then delete the instance. For MSFT_WindowsProcess class, it terminates the process corresponding to the given MI Instance.</p>
<p>3) Post final result to client by calling MI_Context_PostResult API.</p>
<p>4) If there is any failure happened during above step which is considered blocking the current operation, provider should call MI_Context_PostError or MI_Context_PostCimError API to notify the client the final result.</p>
<p>Refer to&nbsp;<a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for complete implementation of MSFT_WindowsProcess_DeleteInstance.&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: small;"><strong>(6) Implement Extrinsic Method</strong></span></p>
<p>Extrinsic methods include instance method and static method. The difference between static and instance method is that static method has [static] qualifier defined; while instance method does not have. For static method, the parameter [instanceName] is always set to NULL, while instance method has a valid instanceName parameter to tell provider on which instance should the method be invoked.</p>
<pre class="scroll"><code class="cplusplus"> _In_ const MSFT_WindowsProcess* instanceName,</code></pre>
<p>For any method, there is a structure defined for it, used to store all input and output parameters' value, and return value as well. There are several steps to implement method invoking operation for a class,</p>
<p align="left">1) For instance method, firstly check the key properties value of the given instance is valid or not. If valid then continue,</p>
<p>2) Construct an instance of the target method by invoking &lt;class name&gt;_&lt;method name&gt;_Construct API,</p>
<p>3) Implement the method logic base on the input parameters and setting all of the output parameters and return value of the output instance. One <strong><em>important</em></strong> note is that &hellip;.</p>
<p>4) Post the instances back by invoking &lt;class_name&gt;_&lt;method name&gt;_Post API.</p>
<p>5) Destruct the constructed instance by calling &lt;class name&gt;_&lt;method name&gt;_Destruct API.</p>
<p>6) Post final result to client by calling MI_Context_PostResult API.</p>
<p>7) If there is any failure happened during above step which is considered blocking the current operation, provider should call MI_Context_PostError or MI_Context_PostCimError API to notify the client the final result.</p>
<p>Please look at <a href="https://code.msdn.microsoft.com/Management-Infrastructure-79fb414f">MI API sample</a>&nbsp;for an example of extrinsic method implementation: MSFT_WindowsProcess_Invoke_SetPriority.</p>
<p>&nbsp;</p>
<p>Happy Holidays! <span>Next&nbsp;blog will&nbsp;discuss how to build, register and debug MI provider.</span></p>
<p>&nbsp;</p>
<p>Haowei Qin</p>
<p>Senior SDE</p>
<p>Standards Based Management</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Implementing MI Provider (4) - Generate Code (continute)</title>
      <link>https://docs.microsoft.com/archive/blogs/wmi/implementing-mi-provider-4-generate-code-continute</link>
      <pubDate>Sat, 28 Dec 2013 12:57:00 GMT</pubDate>
      <dc:creator><![CDATA[Haowei Qin [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/wmi/2013/12/28/implementing-mi-provider-4-generate-code-continute/</guid>
      <description><![CDATA[As described in&nbsp;Implementing MI Provider (3), Convert-MofToProvider.exe tool generates a set of...]]></description>
      <content:encoded><![CDATA[<p>As described in&nbsp;<a href="https://blogs.msdn.com/b/wmi/archive/2013/05/11/implementing-mi-provider-3-generate-provider-skeleton.aspx">Implementing MI Provider (3)</a>, Convert-MofToProvider.exe tool generates a set of code files, including schema.c, module.c, WMIAdapter.c, Provider.DEF, &lt;class name&gt;.h, and &lt;class name&gt;.c. There is one header file for each target class and all of it's ancestor class(es) if have. And one c file for each target class (specified by -ClassList parameter). Header files also get genrated for classes specified by -<span>ExtraClass parameter.</span></p>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>&lt;Class name&gt;.h file(s)</strong></span></p>
<p align="left">Those header files are named with pattern like &lt;class name&gt;.h, which defines the type of &lt;class name&gt; class and a set of helper functions to manipulate the instance of that type. Take&nbsp;MSFT_WindowsProcess.h for example, first of all, it defines the structure of MSFT_WindowsProcess, represents the run-time type of windows process instance defined by MSFT_WindowsProcess schema.</p>
<pre class="scroll"><code class="cplusplus">typedef struct _MSFT_WindowsProcess /* extends CIM_Process */<br /> {<br /> MI_Instance __instance;<br /> /* CIM_ManagedElement properties */<br /> MI_ConstStringField InstanceID;<br /> MI_ConstStringField Caption;<br /> MI_ConstStringField Description;<br /> MI_ConstStringField ElementName;<br /> /* CIM_ManagedSystemElement properties */<br /> MI_ConstDatetimeField InstallDate;<br /> MI_ConstStringField Name;<br /> MI_ConstUint16AField OperationalStatus;<br /> MI_ConstStringAField StatusDescriptions;<br /> MI_ConstStringField Status;<br /> MI_ConstUint16Field HealthState;<br /> MI_ConstUint16Field CommunicationStatus;<br /> MI_ConstUint16Field DetailedStatus;<br /> MI_ConstUint16Field OperatingStatus;<br /> MI_ConstUint16Field PrimaryStatus;<br /> /* CIM_LogicalElement properties */<br /> /* CIM_EnabledLogicalElement properties */<br /> MI_ConstUint16Field EnabledState;<br /> MI_ConstStringField OtherEnabledState;<br /> MI_ConstUint16Field RequestedState;<br /> MI_ConstUint16Field EnabledDefault;<br /> MI_ConstDatetimeField TimeOfLastStateChange;<br /> MI_ConstUint16AField AvailableRequestedStates;<br /> MI_ConstUint16Field TransitioningToState;<br /> /* CIM_Process properties */<br /> /*KEY*/ MI_ConstStringField CSCreationClassName;<br /> /*KEY*/ MI_ConstStringField CSName;<br /> /*KEY*/ MI_ConstStringField OSCreationClassName;<br /> /*KEY*/ MI_ConstStringField OSName;<br /> /*KEY*/ MI_ConstStringField CreationClassName;<br /> /*KEY*/ MI_ConstStringField Handle;<br /> MI_ConstUint32Field Priority;<br /> MI_ConstUint16Field ExecutionState;<br /> MI_ConstStringField OtherExecutionDescription;<br /> MI_ConstDatetimeField CreationDate;<br /> MI_ConstDatetimeField TerminationDate;<br /> MI_ConstUint64Field KernelModeTime;<br /> MI_ConstUint64Field UserModeTime;<br /> MI_ConstUint64Field WorkingSetSize;<br /> /* MSFT_WindowsProcess properties */<br /> MI_ConstStringField CommandLine;<br /> }<br /> MSFT_WindowsProcess;</code></pre>
<p align="left">Then, the header file defines a set of functions to manipulate the instance of MSFT_WindowsProcess, following helper funtions set and clear CommandLine property value of the instance.</p>
<pre class="scroll"><code class="cplusplus">MI_INLINE MI_Result MI_CALL MSFT_WindowsProcess_Set_CommandLine(<br /> _Inout_ MSFT_WindowsProcess* self,<br /> _In_z_ const MI_Char* str)<br /> {<br /> return self-&gt;__instance.ft-&gt;SetElementAt(<br /> (MI_Instance*)&amp;self-&gt;__instance,<br /> 35,<br /> (MI_Value*)&amp;str,<br /> MI_STRING,<br /> 0);<br /> }<br /> <br /> MI_INLINE MI_Result MI_CALL MSFT_WindowsProcess_SetPtr_CommandLine(<br /> _Inout_ MSFT_WindowsProcess* self,<br /> _In_z_ const MI_Char* str)<br /> {<br /> return self-&gt;__instance.ft-&gt;SetElementAt(<br /> (MI_Instance*)&amp;self-&gt;__instance,<br /> 35,<br /> (MI_Value*)&amp;str,<br /> MI_STRING,<br /> MI_FLAG_BORROW);<br /> }<br /> <br /> MI_INLINE MI_Result MI_CALL MSFT_WindowsProcess_Clear_CommandLine(<br /> _Inout_ MSFT_WindowsProcess* self)<br /> {<br /> return self-&gt;__instance.ft-&gt;ClearElementAt(<br /> (MI_Instance*)&amp;self-&gt;__instance,<br /> 35);<br /> }<br /><br /></code></pre>
<p align="left">&nbsp;</p>
<p align="left"><span style="font-size: medium;"><strong>&lt;Class name&gt;.c file(s)</strong></span></p>
<p align="left">Based on the type of target class, Convert-MofToProvider.exe generates different stub functions in c file. As mentioned, there are three type of classes, normal class, association class, and indication class.</p>
<p align="left">For&nbsp;<span>MSFT_WindowsProcess class, following are the generated stub functions,</span></p>
<pre class="scroll"><code class="cplusplus">#include &lt;MI.h&gt;<br />#include "MSFT_WindowsProcess.h"<br /> <br /> void MI_CALL MSFT_WindowsProcess_Load(<br /> _Outptr_result_maybenull_ MSFT_WindowsProcess_Self** self,<br /> _In_opt_ MI_Module_Self* selfModule,<br /> _In_ MI_Context* context)<br /> {<br /> MI_UNREFERENCED_PARAMETER(selfModule);<br /> <br /> *self = NULL;<br /> MI_Context_PostResult(context, MI_RESULT_OK);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_Unload(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_OK);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_EnumerateInstances(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_opt_ const MI_PropertySet* propertySet,<br /> _In_ MI_Boolean keysOnly,<br /> _In_opt_ const MI_Filter* filter)<br /> {<br /> MI_Result result = MI_RESULT_OK;<br /> <br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(propertySet);<br /> MI_UNREFERENCED_PARAMETER(filter);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_GetInstance(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_ const MSFT_WindowsProcess* instanceName,<br /> _In_opt_ const MI_PropertySet* propertySet)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(instanceName);<br /> MI_UNREFERENCED_PARAMETER(propertySet);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_CreateInstance(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_ const MSFT_WindowsProcess* newInstance)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(newInstance);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_ModifyInstance(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_ const MSFT_WindowsProcess* modifiedInstance,<br /> _In_opt_ const MI_PropertySet* propertySet)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(propertySet);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_DeleteInstance(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_ const MSFT_WindowsProcess* instanceName)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_Invoke_RequestStateChange(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_opt_z_ const MI_Char* methodName,<br /> _In_ const MSFT_WindowsProcess* instanceName,<br /> _In_opt_ const MSFT_WindowsProcess_RequestStateChange* in)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(methodName);<br /> MI_UNREFERENCED_PARAMETER(instanceName);<br /> MI_UNREFERENCED_PARAMETER(in);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_Invoke_SetPriority(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_opt_z_ const MI_Char* methodName,<br /> _In_ const MSFT_WindowsProcess* instanceName,<br /> _In_opt_ const MSFT_WindowsProcess_SetPriority* in)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(methodName);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> <br /> void MI_CALL MSFT_WindowsProcess_Invoke_Create(<br /> _In_opt_ MSFT_WindowsProcess_Self* self,<br /> _In_ MI_Context* context,<br /> _In_opt_z_ const MI_Char* nameSpace,<br /> _In_opt_z_ const MI_Char* className,<br /> _In_opt_z_ const MI_Char* methodName,<br /> _In_ const MSFT_WindowsProcess* instanceName,<br /> _In_opt_ const MSFT_WindowsProcess_Create* in)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(nameSpace);<br /> MI_UNREFERENCED_PARAMETER(className);<br /> MI_UNREFERENCED_PARAMETER(methodName);<br /> MI_UNREFERENCED_PARAMETER(instanceName);<br /> MI_UNREFERENCED_PARAMETER(in);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_NOT_SUPPORTED);<br /> }<br /> </code></pre>
<p>There are two categories of the generated methods insides one c file, intrinsic methods and extrinsic methods. Intrinsic methods are standard operations while extrinsic methods are methods defined within the class's schema (mof file).</p>
<div align="center">
<table border="1" cellspacing="0" cellpadding="0">
<thead>
<tr>
<td valign="top" width="247">
<p class="CellHeading">Intrinsic Methods</p>
</td>
<td valign="top" width="247">
<p class="CellHeading">Extrinsic methods</p>
</td>
</tr>
</thead>
<tbody>
<tr>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_EnumerateInstances</p>
</td>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_Invoke_SetPriority</p>
</td>
</tr>
<tr>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_GetInstance</p>
</td>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_Invoke_RequestStateChange</p>
</td>
</tr>
<tr>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_ModifyInstance</p>
</td>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_Invoke_Create</p>
</td>
</tr>
<tr>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_CreateInstance</p>
</td>
<td valign="top" width="247">
<p class="CellBody">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="247">
<p class="CellBody">MSFT_WindowsProcess_DeleteInstance</p>
</td>
<td valign="top" width="247">
<p class="CellBody">&nbsp;</p>
</td>
</tr>
</tbody>
</table>
</div>
<p>For each extrinsic method definition, there is also a type generated in the corresponding header file, for example, structure MSFT_WindowsProcess_Create was defined for Create method of MSFT_WindowsProcess class in MSFT_WindowsProcess.h file. Through this type, provider may access values of input parameters from client (who invoke the method) and output values of parameters to client.</p>
<p>For each class, there are two functions always generated within &lt;class name&gt;.c file, called load/unload functions. <strong>&lt;class name&gt;_Load</strong> function is invoked by CIMOM server to initialize the class before invoking any method, the class may initialize any resources which could live across class loading time and are used to during operations of the class. <strong>&lt;class name&gt;_Unload</strong> function is invoked by server to finalize the class, the class should finalize all resources initialized within load function.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>Module.c&nbsp;</strong></span></p>
<p>Module.c file defines and implements entry function (MI_Main) of the MI provider. As shown below, there are three functions defined, <strong>Load</strong>, <strong>Unload</strong>, <strong>MI_Main</strong>.</p>
<p><strong>Load</strong> function is used to initialize the provider wide resources, live during provider's life cycle. For example, inside Load function, a provider may initialize a critical section, which was used to protect shared data structures accessed by multiple threads simultaneously.</p>
<p><strong>Unload</strong> function is used to finalize the provider resources. For example, the provider could delete the critical section inside Unload function.</p>
<p><strong>MI_Main</strong> function exchanges information between the provider and its host. Usually provider manager calls MI_Main function of a MI provider to get the MI_Module information of a provider, which contains the flags, charsize, version, generator version, all supported schema, and load unload function pointer. Meanwhile, provider manager tells the provider server information by input parameter MI_Server. Provider could call MI_Server_GetVersion and MI_Server_GetSystemName to read current CIMOM server version and system name.</p>
<pre class="scroll"><code class="cplusplus"> #include &lt;MI.h&gt;<br /> <br /> MI_EXTERN_C MI_SchemaDecl schemaDecl;<br /> <br /> void MI_CALL Load(_Outptr_result_maybenull_ MI_Module_Self** self, _In_ struct _MI_Context* context)<br /> {<br /> *self = NULL;<br /> MI_Context_PostResult(context, MI_RESULT_OK);<br /> }<br /> <br /> void MI_CALL Unload(_In_opt_ MI_Module_Self* self, _In_ struct _MI_Context* context)<br /> {<br /> MI_UNREFERENCED_PARAMETER(self);<br /> MI_UNREFERENCED_PARAMETER(context);<br /> <br /> MI_Context_PostResult(context, MI_RESULT_OK);<br /> }<br /> <br /> MI_EXTERN_C MI_EXPORT MI_Module* MI_MAIN_CALL MI_Main(_In_ MI_Server* server)<br /> {<br /> /* WARNING: THIS FUNCTION AUTOMATICALLY GENERATED. PLEASE DO NOT EDIT. */<br /> static MI_Module module;<br /> MI_EXTERN_C MI_Server* __mi_server;<br /> __mi_server = server;<br /> module.flags |= MI_MODULE_FLAG_DESCRIPTIONS;<br /> module.flags |= MI_MODULE_FLAG_VALUES;<br /> module.flags |= MI_MODULE_FLAG_BOOLEANS;<br /> module.charSize = sizeof(MI_Char);<br /> module.version = MI_VERSION;<br /> module.generatorVersion = MI_MAKE_VERSION(1,0,0);<br /> module.schemaDecl = &amp;schemaDecl;<br /> module.Load = Load;<br /> module.Unload = Unload;<br /> return &amp;module;<br /> }</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>Schema.c</strong></span></p>
<p>schema.c file contains the schema of all related classes, and the schema of each class is represented by a set of embedded structures. Schema.c file defines two MI server functions as well. Schema file could be viewed as a binary format of the schema (mof) file. This file must *<strong>NOT</strong>* be modified, otherwise could break provider&rsquo;s functionality. To change the schema, modify the original MOF (in this case sample.mof) and re-generate the code.</p>
<p>To explain the structure of the schema file, a set of snippets are copied below.</p>
<p>(1) <strong>schemaDecl</strong> is of type MI_SchemaDecl, which defines the schema structure of the provider, which contains all qualifiers declarations and all classes declarations.</p>
<pre class="scroll"><code class="cplusplus"> MI_SchemaDecl <strong>schemaDecl</strong> =<br /> {<br /> qualifierDecls, /* qualifierDecls */<br /> MI_COUNT(qualifierDecls), /* numQualifierDecls */<br /> <strong>classes</strong>, /* classDecls */<br /> MI_COUNT(classes), /* classDecls */<br /> };<br /> </code></pre>
<p>(2) <strong>classes</strong>&nbsp;property is an array of MI_ClassDecl objects, which contains a list of all classes schema, which was named with &lt;class name&gt;_rtti. For example, MSFT_WindowsProcess_rtti is the schema of MSFT_WindowsProcess class.</p>
<pre class="scroll"><code class="cplusplus"> static MI_ClassDecl MI_CONST* MI_CONST classes[] =<br /> {<br /> &amp;CIM_ConcreteJob_rtti,<br /> &amp;CIM_EnabledLogicalElement_rtti,<br /> &amp;CIM_Error_rtti,<br /> &amp;CIM_Job_rtti,<br /> &amp;CIM_LogicalElement_rtti,<br /> &amp;CIM_ManagedElement_rtti,<br /> &amp;CIM_ManagedSystemElement_rtti,<br /> &amp;CIM_Process_rtti,<br /> &amp;CIM_Service_rtti,<br /> &amp;CIM_ServiceProcess_rtti,<br /> &amp;<strong>MSFT_WindowsProcess_rtti</strong>,<br /> &amp;MSFT_WindowsServiceProcess_rtti,<br /> };<br /> </code></pre>
<p>(3)&nbsp;<span><strong>MSFT_WindowsProcess_rtti</strong> defines as following, which contains a set of qualifiers, a set of properties, a set of methods, a set of generated stub functions, and other information of the class.</span></p>
<pre class="scroll"><code class="cplusplus"> /* class MSFT_WindowsProcess */<br /> MI_CONST MI_ClassDecl MSFT_WindowsProcess_rtti =<br /> {<br /> MI_FLAG_CLASS, /* flags */<br /> 0x006D7313, /* code */<br /> MI_T("MSFT_WindowsProcess"), /* name */<br /> <strong>MSFT_WindowsProcess_quals</strong>, /* qualifiers */<br /> MI_COUNT(MSFT_WindowsProcess_quals), /* numQualifiers */<br /> <strong>MSFT_WindowsProcess_props</strong>, /* properties */<br /> MI_COUNT(MSFT_WindowsProcess_props), /* numProperties */<br /> sizeof(MSFT_WindowsProcess), /* size */<br /> MI_T("CIM_Process"), /* superClass */<br /> &amp;CIM_Process_rtti, /* superClassDecl */<br /> <strong>MSFT_WindowsProcess_meths</strong>, /* methods */<br /> MI_COUNT(MSFT_WindowsProcess_meths), /* numMethods */<br /> &amp;schemaDecl, /* schema */<br /> &amp;<strong>MSFT_WindowsProcess_funcs</strong>, /* functions */<br /> NULL /* owningClass */<br /> };<br /> </code></pre>
<p><span>(4)&nbsp;</span><strong>MSFT_WindowsProcess_quals</strong> is an array of class qualifiers, and MSFT_WindowsProcess_ClassVersion_qual defines one of the qualifier as below.</p>
<pre class="scroll"><code class="cplusplus"> static MI_CONST MI_Char* MSFT_WindowsProcess_ClassVersion_qual_value = MI_T("1.0.0");<br /> <br /> static MI_CONST MI_Qualifier MSFT_WindowsProcess_ClassVersion_qual =<br /> {<br /> MI_T("ClassVersion"),<br /> MI_STRING,<br /> MI_FLAG_ENABLEOVERRIDE|MI_FLAG_RESTRICTED,<br /> &amp;MSFT_WindowsProcess_ClassVersion_qual_value<br /> };<br /> <br /> static MI_Qualifier MI_CONST* MI_CONST MSFT_WindowsProcess_quals[] =<br /> {<br /> &amp;MSFT_WindowsProcess_UMLPackagePath_qual,<br /> &amp;MSFT_WindowsProcess_Description_qual,<br /> &amp;MSFT_WindowsProcess_ClassVersion_qual,<br /> };<br /> </code></pre>
<p><span>(5)&nbsp;</span><strong>MSFT_WindowsProcess_props</strong> defines the array of all its properties, including the properties inherited from ancestor classes. One example of the property is MSFT_WindowsProcess_CommandLine_prop.</p>
<pre class="scroll"><code class="cplusplus"> static MI_PropertyDecl MI_CONST* MI_CONST MSFT_WindowsProcess_props[] =<br /> {<br /> &amp;CIM_ManagedElement_InstanceID_prop,<br /> &amp;CIM_ManagedElement_Caption_prop,<br /> &amp;CIM_ManagedElement_Description_prop,<br /> &amp;CIM_ManagedElement_ElementName_prop,<br /> &amp;CIM_ManagedSystemElement_InstallDate_prop,<br /> &amp;CIM_Process_Name_prop,<br /> &amp;CIM_ManagedSystemElement_OperationalStatus_prop,<br /> &amp;CIM_ManagedSystemElement_StatusDescriptions_prop,<br /> &amp;CIM_ManagedSystemElement_Status_prop,<br /> &amp;CIM_ManagedSystemElement_HealthState_prop,<br /> &amp;CIM_ManagedSystemElement_CommunicationStatus_prop,<br /> &amp;CIM_ManagedSystemElement_DetailedStatus_prop,<br /> &amp;CIM_ManagedSystemElement_OperatingStatus_prop,<br /> &amp;CIM_ManagedSystemElement_PrimaryStatus_prop,<br /> &amp;CIM_EnabledLogicalElement_EnabledState_prop,<br /> &amp;CIM_EnabledLogicalElement_OtherEnabledState_prop,<br /> &amp;CIM_EnabledLogicalElement_RequestedState_prop,<br /> &amp;CIM_EnabledLogicalElement_EnabledDefault_prop,<br /> &amp;CIM_EnabledLogicalElement_TimeOfLastStateChange_prop,<br /> &amp;CIM_EnabledLogicalElement_AvailableRequestedStates_prop,<br /> &amp;CIM_EnabledLogicalElement_TransitioningToState_prop,<br /> &amp;CIM_Process_CSCreationClassName_prop,<br /> &amp;CIM_Process_CSName_prop,<br /> &amp;CIM_Process_OSCreationClassName_prop,<br /> &amp;CIM_Process_OSName_prop,<br /> &amp;CIM_Process_CreationClassName_prop,<br /> &amp;CIM_Process_Handle_prop,<br /> &amp;CIM_Process_Priority_prop,<br /> &amp;CIM_Process_ExecutionState_prop,<br /> &amp;CIM_Process_OtherExecutionDescription_prop,<br /> &amp;CIM_Process_CreationDate_prop,<br /> &amp;CIM_Process_TerminationDate_prop,<br /> &amp;CIM_Process_KernelModeTime_prop,<br /> &amp;CIM_Process_UserModeTime_prop,<br /> &amp;CIM_Process_WorkingSetSize_prop,<br /> &amp;MSFT_WindowsProcess_CommandLine_prop,<br /> };<br /> &hellip;&hellip;<br /> /* property MSFT_WindowsProcess.CommandLine */<br /> static MI_CONST MI_PropertyDecl MSFT_WindowsProcess_CommandLine_prop =<br /> {<br /> MI_FLAG_PROPERTY|MI_FLAG_READONLY, /* flags */<br /> 0x0063650B, /* code */<br /> MI_T("CommandLine"), /* name */<br /> NULL, /* qualifiers */<br /> 0, /* numQualifiers */<br /> MI_STRING, /* type */<br /> NULL, /* className */<br /> 0, /* subscript */<br /> offsetof(MSFT_WindowsProcess, CommandLine), /* offset */<br /> MI_T("MSFT_WindowsProcess"), /* origin */<br /> MI_T("MSFT_WindowsProcess"), /* propagator */<br /> NULL,<br /> };<br /> </code></pre>
<p><span>(6)&nbsp;</span><strong>MSFT_WindowsProcess_meths</strong> defines an array of the schema of all extrinsic methods, while MSFT_WindowsProcess_funcs defines an array of function pointers, which are intrinsic methods.</p>
<p><span>Due to an extrinsic method might contain a set of input and output parameters, and a set off qualifiers for the method itself as well as all parameters, such that it requires a MI_MethodDecl structure to store all related information. Intrinsic methods do not have qualifiers and it has a fix set of parameters, such that is represented by a function pointer.</span></p>
<pre class="scroll"><code class="cplusplus">/* method MSFT_WindowsProcess.Create() */<br /> MI_CONST MI_MethodDecl MSFT_WindowsProcess_Create_rtti =<br /> {<br /> MI_FLAG_METHOD|MI_FLAG_STATIC, /* flags */<br /> 0x00636506, /* code */<br /> MI_T("Create"), /* name */<br /> MSFT_WindowsProcess_Create_quals, /* qualifiers */<br /> MI_COUNT(MSFT_WindowsProcess_Create_quals), /* numQualifiers */<br /> MSFT_WindowsProcess_Create_params, /* parameters */<br /> MI_COUNT(MSFT_WindowsProcess_Create_params), /* numParameters */<br /> sizeof(MSFT_WindowsProcess_Create), /* size */<br /> MI_UINT32, /* returnType */<br /> MI_T("MSFT_WindowsProcess"), /* origin */<br /> MI_T("MSFT_WindowsProcess"), /* propagator */<br /> &amp;schemaDecl, /* schema */<br /> (MI_ProviderFT_Invoke)MSFT_WindowsProcess_Invoke_Create, /* method */<br /> };<br /> <br /> static MI_MethodDecl MI_CONST* MI_CONST MSFT_WindowsProcess_meths[] =<br /> {<br /> &amp;MSFT_WindowsProcess_RequestStateChange_rtti,<br /> &amp;MSFT_WindowsProcess_SetPriority_rtti,<br /> &amp;MSFT_WindowsProcess_Create_rtti,<br /> };<br /> &hellip;&hellip;<br /> <br /> static MI_CONST MI_ProviderFT MSFT_WindowsProcess_funcs =<br /> {<br /> (MI_ProviderFT_Load)MSFT_WindowsProcess_Load,<br /> (MI_ProviderFT_Unload)MSFT_WindowsProcess_Unload,<br /> (MI_ProviderFT_GetInstance)MSFT_WindowsProcess_GetInstance,<br /> (MI_ProviderFT_EnumerateInstances)MSFT_WindowsProcess_EnumerateInstances,<br /> (MI_ProviderFT_CreateInstance)MSFT_WindowsProcess_CreateInstance,<br /> (MI_ProviderFT_ModifyInstance)MSFT_WindowsProcess_ModifyInstance,<br /> (MI_ProviderFT_DeleteInstance)MSFT_WindowsProcess_DeleteInstance,<br /> (MI_ProviderFT_AssociatorInstances)NULL,<br /> (MI_ProviderFT_ReferenceInstances)NULL,<br /> (MI_ProviderFT_EnableIndications)NULL,<br /> (MI_ProviderFT_DisableIndications)NULL,<br /> (MI_ProviderFT_Subscribe)NULL,<br /> (MI_ProviderFT_Unsubscribe)NULL,<br /> (MI_ProviderFT_Invoke)NULL,<br /> };<br /> <br /> typedef void (MI_CALL *MI_ProviderFT_EnumerateInstances)(<br /> _In_opt_ void* self,<br /> _In_ MI_Context* context,<br /> _In_z_ const MI_Char* nameSpace,<br /> _In_z_ const MI_Char* className,<br /> _In_opt_ const MI_PropertySet* propertySet,<br /> MI_Boolean keysOnly,<br /> _In_opt_ const MI_Filter* filter);<br /> </code></pre>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>WMIAdapter.c</strong></span></p>
<p>In order to host MI provider(s) within WMI, an adapter layer is necessary since WMI host process only supports COM based provider interface. WMIAdapter.c is a file to enable the MI provider running with WMI service. This file must *<strong>NOT</strong>* be modified.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;"><strong>Provider.DEF</strong></span></p>
<p>Provider.DEF defines list of exported APIs from the provider DLL. Usually, this file name was specified in visual studio project linker options &lsquo;/DEF:"Provider.DEF"&rsquo; (see following picture), in order to tell the linker to export a set of functions from target DLL.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/4062.pic.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/4062.pic.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/53/21/4062.pic.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-53-21/4062.pic.png" alt="" border="0" /></a></span></p>
<p><span><br /></span></p>
<p>&nbsp;</p>
<p>Happy holidays! Next&nbsp;blog will&nbsp;discuss how to implement instance (normal) class.</p>
<p>&nbsp;</p>
<p>Haowei Qin</p>
<p>Senior SDE</p>
<p>Standards Based Management</p>]]></content:encoded>
    </item>
  </channel>
</rss>