<?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>Keith Babinec's Development Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/kebab/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/kebab/feed.xml</link>
    <description>Discussing helpful tips for development in C# and PowerShell</description>
    <lastBuildDate>Tue, 16 Apr 2019 06:20:03 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Passing arrays, key value pairs, and other collections to SQL stored procedures using table valued parameters.</title>
      <link>https://docs.microsoft.com/archive/blogs/kebab/passing-arrays-key-value-pairs-and-other-collections-to-sql-stored-procedures-using-table-valued-parameters</link>
      <pubDate>Wed, 16 Jul 2014 14:21:00 GMT</pubDate>
      <dc:creator><![CDATA[Keith Babinec]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kebab/2014/07/16/passing-arrays-key-value-pairs-and-other-collections-to-sql-stored-procedures-using-table-valued-parameters/</guid>
      <description><![CDATA[Overview
MS SQL server doesn&rsquo;t support arrays or other collection data types, so we...]]></description>
      <content:encoded><![CDATA[<h1>Overview</h1>
<p>MS SQL server doesn&rsquo;t support arrays or other collection data types, so we can&rsquo;t directly send in these types as parameters to stored procedures from client applications. But fortunately, SQL does allow us to send in DataTable objects in MS SQL Server 2008 and later. The solution here is to simply convert our collection types into a DataTable object and then pass the DataTable into the stored procedure. This should work for any type that you can restructure into a table format.</p>
<p>Have an array of&nbsp;string or int? This can be converted into a table with one column with one row for each item in the array. Have a dictionary or other key-value pair collection? This becomes a table with two columns. Have a collection of class objects with multiple properties? Make a column for each class property and a row for each collection item.</p>
<p>Using table valued parameters makes it possible to send in a collection of items from your client application to the SQL server in a single roundtrip, without using XML or string parsing. This is helpful in several scenarios. For example, it is easier to delete a large number of records via stored procedure if you can call the delete procedure one time with a collection of record IDs instead of the same stored procedure over and over (one ID at a time). It also makes processing easier when you have other collections, such as key-value pairs that need to be passed into a stored procedure.</p>
<p><em><strong>Note</strong></em>: <em>At the time of this writing, table valued parameters are not supported for use&nbsp;in Linq to SQL. Hopefully this support is added in the future.</em></p>
<h1>Step 1: Business objects</h1>
<p>The first task is to address the business objects in the client. In the sample application I have defined a very simple class with two properties.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: green;">//&nbsp;code&nbsp;sample&nbsp;1</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Defines&nbsp;a&nbsp;single&nbsp;item&nbsp;object.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: blue;">class</span>&nbsp;<span style="color: #2b91af;">Item</span>
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Gets&nbsp;or&nbsp;sets&nbsp;the&nbsp;ID&nbsp;of&nbsp;the&nbsp;item.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;Guid&nbsp;ID&nbsp;{&nbsp;<span style="color: blue;">get</span>;&nbsp;<span style="color: blue;">set</span>;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Gets&nbsp;or&nbsp;sets&nbsp;the&nbsp;Name&nbsp;of&nbsp;the&nbsp;item.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">string</span>&nbsp;Name&nbsp;{&nbsp;<span style="color: blue;">get</span>;&nbsp;<span style="color: blue;">set</span>;&nbsp;}
}</pre>
<p>If we add conversion methods to the collection type, we can easily construct the required DataTable objects on demand. The first example extension returns a DataTable with the ID and Name properties of the business objects. The second example extension returns a DataTable with the ID of the each&nbsp;business object.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: green;">//&nbsp;code&nbsp;sample&nbsp;2</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Defines&nbsp;a&nbsp;collection&nbsp;of&nbsp;item&nbsp;objects.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: blue;">class</span>&nbsp;<span style="color: #2b91af;">Items</span>&nbsp;:&nbsp;<span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">Item</span>&gt;
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Returns&nbsp;the&nbsp;items&nbsp;as&nbsp;a&nbsp;DataTable.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;&lt;c&gt;</span><span style="color: green;">DataTable</span><span style="color: gray;">&lt;/c&gt;&lt;/returns&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: #2b91af;">DataTable</span>&nbsp;GetItemsAsDataTable()
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;construct&nbsp;the&nbsp;empty&nbsp;DataTable&nbsp;object&nbsp;with&nbsp;columns.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">DataTable</span>&nbsp;table&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">DataTable</span>();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.Columns.Add(<span style="color: #a31515;">"ID"</span>,&nbsp;<span style="color: blue;">typeof</span>(Guid));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.Columns.Add(<span style="color: #a31515;">"Name"</span>,&nbsp;<span style="color: blue;">typeof</span>(<span style="color: blue;">string</span>));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;add&nbsp;a&nbsp;single&nbsp;row&nbsp;for&nbsp;each&nbsp;item&nbsp;in&nbsp;the&nbsp;collection.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: blue;">var</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;<span style="color: blue;">this</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.Rows.Add(item.ID,&nbsp;item.Name);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;table;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Returns&nbsp;only&nbsp;the&nbsp;item&nbsp;IDs&nbsp;as&nbsp;a&nbsp;DataTable.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;&lt;c&gt;</span><span style="color: green;">DataTable</span><span style="color: gray;">&lt;/c&gt;&lt;/returns&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: #2b91af;">DataTable</span>&nbsp;GetItemIDsAsDataTable()
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;construct&nbsp;the&nbsp;empty&nbsp;DataTable&nbsp;object&nbsp;with&nbsp;columns.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">DataTable</span>&nbsp;table&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">DataTable</span>();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.Columns.Add(<span style="color: #a31515;">"ID"</span>,&nbsp;<span style="color: blue;">typeof</span>(Guid));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;add&nbsp;a&nbsp;single&nbsp;row&nbsp;for&nbsp;each&nbsp;item&nbsp;in&nbsp;the&nbsp;collection.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: blue;">var</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;<span style="color: blue;">this</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table.Rows.Add(item.ID);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;table;
&nbsp;&nbsp;&nbsp;&nbsp;}
}</pre>
<h1>Step 2: SQL database prep</h1>
<p>On the SQL server side we need to prepare the database to accept our table-valued parameters by defining them ahead of time. We&nbsp;then need to ensure that new or existing stored procedures are in place to accept these new table parameters.</p>
<p>For demo purposes I&rsquo;m assuming that we need to create a database from scratch. Sample 3&nbsp;(below) creates the following required objects:</p>
<p>&bull;&nbsp;A new table to store our business object (Item)<br />&bull;&nbsp;A user defined Table type to store Guids (IDs)<br />&bull;&nbsp;A user defined Table type to store Guids (IDs) and Strings (Names) <br />&bull;&nbsp;A stored procedure to remove items, using the table valued parameter.<br />&bull;&nbsp;A stored procedure to add items, using the table valued parameter.</p>
<p><em><strong>Note</strong>: that when a stored procedure uses a table-valued parameter, it must be passed as read-only. It cannot be modified inside the stored procedure. If it needs to be modified, then insert the rows into another table variable.</em></p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: green;">--&nbsp;code&nbsp;sample&nbsp;3</span>
<span style="color: blue;">create</span>&nbsp;<span style="color: blue;">table</span>&nbsp;dbo<span style="color: gray;">.</span>ItemsTable
<span style="color: gray;">(</span>
	[ID]	<span style="color: blue;">uniqueidentifier</span>&nbsp;<span style="color: blue;">primary</span>&nbsp;<span style="color: blue;">key</span>&nbsp;<span style="color: gray;">not</span>&nbsp;<span style="color: gray;">null,</span>
	[Name]	<span style="color: blue;">nvarchar</span><span style="color: gray;">(</span>255<span style="color: gray;">)</span>&nbsp;<span style="color: gray;">not</span>&nbsp;<span style="color: gray;">null</span>
<span style="color: gray;">)</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">create</span>&nbsp;<span style="color: blue;">type</span>&nbsp;dbo<span style="color: gray;">.</span>IDsAndNamesTable&nbsp;<span style="color: blue;">as</span>&nbsp;<span style="color: blue;">table</span>
<span style="color: gray;">(</span>
	[ID]	<span style="color: blue;">uniqueidentifier</span><span style="color: gray;">,</span>
	[Name]	<span style="color: blue;">nvarchar</span><span style="color: gray;">(</span>255<span style="color: gray;">)</span>
<span style="color: gray;">)</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">create</span>&nbsp;<span style="color: blue;">type</span>&nbsp;dbo<span style="color: gray;">.</span>IDsTable&nbsp;<span style="color: blue;">as</span>&nbsp;<span style="color: blue;">table</span>
<span style="color: gray;">(</span>
	[ID]	<span style="color: blue;">uniqueidentifier</span>
<span style="color: gray;">)</span>
<span style="color: blue;">go</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">create</span>&nbsp;<span style="color: blue;">procedure</span>&nbsp;dbo<span style="color: gray;">.</span>AddItems
<span style="color: gray;">(</span>
	@Items	[IDsAndNamesTable]&nbsp;<span style="color: blue;">readonly</span>
<span style="color: gray;">)</span>
<span style="color: blue;">as</span>
<span style="color: blue;">begin</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">	<span style="color: blue;">insert</span>&nbsp;<span style="color: blue;">into</span>&nbsp;dbo<span style="color: gray;">.</span>ItemsTable<span style="color: blue;">&nbsp;</span><span style="color: gray;">(</span>&nbsp;[ID]<span style="color: gray;">,</span>&nbsp;[Name]&nbsp;<span style="color: gray;">)</span>
	<span style="color: blue;">select</span>&nbsp;[ID]<span style="color: gray;">,</span>&nbsp;[Name]&nbsp;<span style="color: blue;">from</span>&nbsp;@Items&nbsp;
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">end</span>
<span style="color: blue;">go</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">create</span>&nbsp;<span style="color: blue;">procedure</span>&nbsp;dbo<span style="color: gray;">.</span>RemoveItems
<span style="color: gray;">(</span>
	@IDs	[IDsTable]&nbsp;<span style="color: blue;">readonly</span>
<span style="color: gray;">)</span>
<span style="color: blue;">as</span>
<span style="color: blue;">begin</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">	<span style="color: blue;">delete</span>&nbsp;<span style="color: blue;">from</span>&nbsp;dbo<span style="color: gray;">.</span>ItemsTable
	<span style="color: blue;">where</span>&nbsp;[ID]&nbsp;<span style="color: gray;">in</span><span style="color: blue;">&nbsp;</span><span style="color: gray;">(</span>&nbsp;<span style="color: blue;">select</span>&nbsp;[ID]&nbsp;<span style="color: blue;">from</span>&nbsp;@IDs&nbsp;<span style="color: gray;">)</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">end</span>
<span style="color: blue;">go</span></pre>
<h1>Step 3: Stored procedure execution</h1>
<p>Once the business objects and the database are prepared, we can add client side code to call the stored procedures. To demonstrate calling the stored procedures and passing in the DataTables, I have added the following code to the sample application.</p>
<p><em><strong>Note:</strong> The SqlDbType on the parameter is SqlDbType.Structured to indicate a user defined table type. </em></p>
<p>Also, at this location we convert the client collection type into a DataTable via the&nbsp;methods written earlier.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: green;">//&nbsp;code&nbsp;sample&nbsp;4</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Adds&nbsp;items&nbsp;to&nbsp;the&nbsp;database.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"items"</span><span style="color: gray;">&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;items&nbsp;to&nbsp;add.</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">void</span>&nbsp;AddItemsToDatabase(<span style="color: #2b91af;">Items</span>&nbsp;items)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;construct&nbsp;sql&nbsp;connection&nbsp;and&nbsp;sql&nbsp;command&nbsp;objects.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">SqlConnection</span>&nbsp;sqlcon&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SqlConnection</span>(<span style="color: #a31515;">"&lt;insert&nbsp;connection&nbsp;string&nbsp;here&gt;"</span>))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">SqlCommand</span>&nbsp;cmd&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SqlCommand</span>(<span style="color: #a31515;">"AddItems"</span>,&nbsp;sqlcon))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;add&nbsp;the&nbsp;table-valued-parameter.&nbsp;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.CommandType&nbsp;=&nbsp;<span style="color: #2b91af;">CommandType</span>.StoredProcedure;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.Parameters.Add(<span style="color: #a31515;">"@Items"</span>,&nbsp;<span style="color: #2b91af;">SqlDbType</span>.Structured).Value&nbsp;=&nbsp;items.GetItemsAsDataTable();
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;execute</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sqlcon.Open();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.ExecuteNonQuery();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Removes&nbsp;items&nbsp;from&nbsp;the&nbsp;database.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"items"</span><span style="color: gray;">&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;items&nbsp;to&nbsp;remove.</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">void</span>&nbsp;RemoveItemsFromDatabase(<span style="color: #2b91af;">Items</span>&nbsp;items)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;construct&nbsp;sql&nbsp;connection&nbsp;and&nbsp;sql&nbsp;command&nbsp;objects.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">SqlConnection</span>&nbsp;sqlcon&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SqlConnection</span>(<span style="color: #a31515;">"&lt;insert&nbsp;connection&nbsp;string&nbsp;here&gt;"</span>))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">SqlCommand</span>&nbsp;cmd&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SqlCommand</span>(<span style="color: #a31515;">"RemoveItems"</span>,&nbsp;sqlcon))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;add&nbsp;the&nbsp;table-valued-parameter.&nbsp;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.CommandType&nbsp;=&nbsp;<span style="color: #2b91af;">CommandType</span>.StoredProcedure;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.Parameters.Add(<span style="color: #a31515;">"@IDs"</span>,&nbsp;<span style="color: #2b91af;">SqlDbType</span>.Structured).Value&nbsp;=&nbsp;items.GetItemIDsAsDataTable();
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;execute</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sqlcon.Open();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.ExecuteNonQuery();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}</pre>
<p>Now it&rsquo;s time for a test run. In the main method I have decided to call the AddItems stored procedure just by passing in a collection:</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: green;">// code&nbsp;sample&nbsp;5</span>
<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">void</span>&nbsp;Main(<span style="color: blue;">string</span>[]&nbsp;args)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;add&nbsp;these&nbsp;new&nbsp;items</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Items</span>&nbsp;items&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Items</span>();
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"EE612E96-1577-4C43-978D-1ACF6BE8A22D"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Orange"</span>&nbsp;});
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"55D000B9-51E7-43FD-9540-D24ACA711231"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Yellow"</span>&nbsp;});
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"89DAB4DD-35D2-4BFA-8735-9C6DCFC4110E"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Green"</span>&nbsp;});
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"F4E0965E-8501-4FFB-A1B7-1D08B6EF3DBC"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Red"</span>&nbsp;});
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"40F3DFAA-65CD-45EC-814F-3E59E46C95E2"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Blue"</span>&nbsp;});
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"A453B8C3-E9AF-447E-B847-FC7FA6D822AD"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Grey"</span>&nbsp;});
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;AddItemsToDatabase(items);
}</pre>
<p>As expected, it inserted all the items:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/7633.tvp-add.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/7633.tvp_2D00_add.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/7633.tvp-add.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/482x257/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/7633.tvp_2D00_add.PNG" alt="" border="0" /></a></p>
<p>I slightly re-arranged the main method to remove some of the existing items:</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: green;">//&nbsp;code&nbsp;sample&nbsp;6</span>
<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">void</span>&nbsp;Main(<span style="color: blue;">string</span>[]&nbsp;args)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;remove&nbsp;these&nbsp;existing&nbsp;items</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Items</span>&nbsp;items&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Items</span>();
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"F4E0965E-8501-4FFB-A1B7-1D08B6EF3DBC"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Red"</span>&nbsp;});
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"40F3DFAA-65CD-45EC-814F-3E59E46C95E2"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Blue"</span>&nbsp;});
&nbsp;&nbsp;&nbsp;&nbsp;items.Add(<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Item</span>()&nbsp;{&nbsp;ID&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;Guid(<span style="color: #a31515;">"A453B8C3-E9AF-447E-B847-FC7FA6D822AD"</span>),&nbsp;Name&nbsp;=&nbsp;<span style="color: #a31515;">"Grey"</span>&nbsp;});
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;RemoveItemsFromDatabase(items);
}</pre>
<p>After execution we can see our items were removed correctly:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/4336.tvp-remove.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/4336.tvp_2D00_remove.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/4336.tvp-remove.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/488x229/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/4336.tvp_2D00_remove.PNG" alt="" border="0" /></a></p>
<h1>Conclusion</h1>
<p>Table valued parameters allow you to pass tables full of data directly to a stored procedure. Using methods like the ones defined in&nbsp;code sample 2 will allow you to easily generate DataTables on demand from your client application. Since the custom DataTables can be defined according to your own specifications, there is no technical requirement to limit them to just one or two columns like the samples above. You can leverage them to fit whatever objects or columns that need to be passed in.<br /><em><br /></em><em></em></p>]]></content:encoded>
    </item>
    <item>
      <title>Sending messages and commands to a Hyper-V Virtual Machine Guest OS using the KVP Exchange</title>
      <link>https://docs.microsoft.com/archive/blogs/kebab/sending-messages-and-commands-to-a-hyper-v-virtual-machine-guest-os-using-the-kvp-exchange</link>
      <pubDate>Tue, 24 Jun 2014 16:09:00 GMT</pubDate>
      <dc:creator><![CDATA[Keith Babinec]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kebab/2014/06/24/sending-messages-and-commands-to-a-hyper-v-virtual-machine-guest-os-using-the-kvp-exchange/</guid>
      <description><![CDATA[Part 1: Overview
Hyper-V virtual machines regularly need to communicate bits of information back to...]]></description>
      <content:encoded><![CDATA[<h1>Part 1: Overview</h1>
<p>Hyper-V virtual machines regularly need to communicate bits of information back to the Hyper-V hosts. Items like the current IP address, Operating System version, guest integration components version, etc. Sometimes the Hyper-V host also needs to send messages to the VM Guest OS (like issuing a Shutdown command).</p>
<p>Hyper-V has built in a communication channel to send these commands back and forth, and fortunately we can leverage this system to send our own messages. This communication channel occurs over the KVP (key-value-pair) Data Exchange. The channel is accessed on the Hyper-V Host side via WMI, and is accessed on the Hyper-V guest OS side via the Windows Registry. Detailed access via C# is discussed in sections 2 and 3 of this post. If you want PowerShell code for that, a quick web search should find some samples.<br /><br />This blog post covers the message send process through Hyper-V. It does not cover how to design your own messages, or the how to build a sender/listener service&nbsp;on either side. Those parts should be fairly straightforward once you understand how the sending process works.</p>
<h4>How can I use this?</h4>
<p>Sending messages to VMs via the Hyper-V KVP is a great way to command and control VMs you own that may not be on the same Network or Domain as the Hyper-V hosts or the rest of your infrastructure. Or for VMs that simply have no networking configured at all, but still need to communicate back to a central application.</p>
<h4>What would a message look like?</h4>
<p>The general idea is that you can format a message however you want (for example serialized XML), break it into chunks over KVP items, and write the message KVP items into the KVP store. You would write code for the other side that then reads the message chunks and deserializes it.</p>
<h4>What are the limitations?</h4>
<p>Sending messages certainly has limitations. I have never seen a documented message size limit for an individual message, but Hyper-V, WMI, and the Registry all have their own limitations for storing data in these locations that may vary by OS.</p>
<p>An individual KVP item has a key name, and a key value. In my own crude testing procedures, I was able to write a few hundred KVP items into the store. I observed that exceeding too many KVP items in the store, or too many characters in a key value would both lead to the Hyper-V integration services complaining. If this occurs, the VM may fall into a failed state which can be fixed by removing the message items. I recommend keeping message key values under 1024 characters.</p>
<p>Another requirement is that the data exchange service must be enabled on the Hyper-V VM for this to work. This is enabled by default in Hyper-V, but some environments may have it shut off for security reasons.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/2364.guest-data-exchange.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/2364.guest_2D00_data_2D00_exchange.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/2364.guest-data-exchange.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/448x333/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/2364.guest_2D00_data_2D00_exchange.PNG" alt="" border="0" /></a></p>
<h1>Part 2: Inside the Hyper-V Host Server</h1>
<h3>Part 2A: Prerequisites</h3>
<p>The sample code below uses WMI. Add a project reference to System.Management.dll, and then add a using statement for it. All of the sample code below uses the WMI root\virtualization\v2 namespace. This namespace was introduced in Windows 8 / Server 2012. If you are using Windows 7 / Server 2008 R2, you will need to use the root\virtualization namespace instead. For more information, <a title="read this" href="https://blogs.msdn.com/b/virtual_pc_guy/archive/2012/05/30/the-v2-wmi-namespace-in-hyper-v-on-windows-8.aspx">read this</a>.</p>
<h3>Part 2B: Sending messages to VMs</h3>
<p>To send a message from the Host to the VM Guest, you need to add KVP items to the store via the <a title="AddKvpItems" href="https://msdn.microsoft.com/en-us/library/cc160704(v=vs.85).aspx">AddKvpItems</a> method on the <a title="Msvm_VirtualSystemManagementService" href="https://msdn.microsoft.com/en-us/library/cc136940(v=vs.85).aspx">Msvm_VirtualSystemManagementService</a> WMI class.<br />Unfortunately the sample code on MSDN for this method is for adding a single KVP item. Sending large messages usually involves sending multiple KVP items at once, so here is a modified sample that sends in a collection of Key-Value pairs.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Adds&nbsp;KVP&nbsp;Exchange&nbsp;Data&nbsp;items</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"HyperVServerName"</span><span style="color: gray;">&gt;</span><span style="color: green;">The&nbsp;Hyper-V&nbsp;Server&nbsp;hostname</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineName"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;name&nbsp;as&nbsp;shown&nbsp;in&nbsp;Hyper-V&nbsp;manager</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineID"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;unique&nbsp;ID&nbsp;as&nbsp;known&nbsp;by&nbsp;Hyper-V</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"ItemsToAdd"</span><span style="color: gray;">&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;key-value&nbsp;pair&nbsp;items&nbsp;to&nbsp;add</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">void</span>&nbsp;AddKVPItems(<span style="color: blue;">string</span>&nbsp;HyperVServerName,&nbsp;<span style="color: blue;">string</span>&nbsp;VirtualMachineName,&nbsp;Guid&nbsp;VirtualMachineID,&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;ItemsToAdd)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;check&nbsp;all&nbsp;required&nbsp;parameters</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(HyperVServerName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"HyperVServerName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(VirtualMachineName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"VirtualMachineName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(VirtualMachineID&nbsp;==&nbsp;Guid.Empty)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"VirtualMachineID&nbsp;cannot&nbsp;be&nbsp;empty"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(ItemsToAdd&nbsp;==&nbsp;<span style="color: blue;">null</span>&nbsp;||&nbsp;ItemsToAdd.Count&nbsp;==&nbsp;0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"ItemsToAdd&nbsp;cannot&nbsp;be&nbsp;null&nbsp;or&nbsp;empty"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;AddKvpItems()&nbsp;WMI&nbsp;Method&nbsp;does&nbsp;not&nbsp;allow&nbsp;more&nbsp;than&nbsp;128&nbsp;items&nbsp;in&nbsp;a&nbsp;single&nbsp;call.&nbsp;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Very&nbsp;large&nbsp;messages&nbsp;will&nbsp;need&nbsp;to&nbsp;be&nbsp;broken&nbsp;down&nbsp;into&nbsp;message&nbsp;groups&nbsp;of&nbsp;128&nbsp;or&nbsp;less.</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(ItemsToAdd.Count&nbsp;&gt;&nbsp;128)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"ItemsToAdd&nbsp;cannot&nbsp;contain&nbsp;more&nbsp;than&nbsp;128&nbsp;items"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;new&nbsp;scope&nbsp;object&nbsp;for&nbsp;the&nbsp;remote&nbsp;Hyper-V&nbsp;Host</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementScope</span>&nbsp;scope&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementScope</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">@"\\{0}\root\virtualization\v2"</span>,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;find&nbsp;the&nbsp;Hyper-V&nbsp;Host&nbsp;Management&nbsp;object&nbsp;instance&nbsp;in&nbsp;the&nbsp;remote&nbsp;WMI</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementPath</span>&nbsp;wmiPath&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementPath</span>(<span style="color: #a31515;">"Msvm_VirtualSystemManagementService"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementClass</span>&nbsp;serviceClass&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementClass</span>(scope,&nbsp;wmiPath,&nbsp;<span style="color: blue;">null</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;hostInstance&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;serviceClass.GetInstances())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostInstance&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(hostInstance&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Hyper-V&nbsp;Host&nbsp;({0})&nbsp;Management&nbsp;Object&nbsp;Instance&nbsp;was&nbsp;not&nbsp;found&nbsp;in&nbsp;WMI."</span>,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;find&nbsp;the&nbsp;Hyper-V&nbsp;Machine&nbsp;object&nbsp;instance&nbsp;in&nbsp;the&nbsp;remote&nbsp;WMI</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;it&nbsp;must&nbsp;match&nbsp;both&nbsp;the&nbsp;display&nbsp;name&nbsp;and&nbsp;the&nbsp;ID</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">SelectQuery</span>&nbsp;vmQuery&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SelectQuery</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"SELECT&nbsp;*&nbsp;FROM&nbsp;Msvm_ComputerSystem&nbsp;WHERE&nbsp;ElementName&nbsp;=&nbsp;'{0}'&nbsp;AND&nbsp;Name&nbsp;=&nbsp;'{1}'"</span>,&nbsp;<br />						VirtualMachineName,&nbsp;VirtualMachineID));
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>&nbsp;vmSearcher&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>(scope,&nbsp;vmQuery);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;vmInstance&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;vmSearcher.Get())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vmInstance&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(vmInstance&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Virtual&nbsp;Machine&nbsp;({0},&nbsp;{1})&nbsp;WMI&nbsp;instance&nbsp;was&nbsp;not&nbsp;found&nbsp;on&nbsp;the&nbsp;Hyper-V&nbsp;Host&nbsp;{2}."</span>,&nbsp;<br />					VirtualMachineID,&nbsp;VirtualMachineName,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;prepare&nbsp;objects&nbsp;for&nbsp;method&nbsp;execution.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;get&nbsp;the&nbsp;method&nbsp;parameters&nbsp;for&nbsp;AddKvpItems()</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;populate&nbsp;the&nbsp;kvpItems&nbsp;array&nbsp;with&nbsp;new&nbsp;instances&nbsp;of&nbsp;Msvm_KvpExchangeDataItem</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementClass</span>&nbsp;kvpClass&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementClass</span>(scope,&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementPath</span>(<span style="color: #a31515;">"Msvm_KvpExchangeDataItem"</span>),&nbsp;<span style="color: blue;">null</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementBaseObject</span>&nbsp;kvpParams&nbsp;=&nbsp;hostInstance.GetMethodParameters(<span style="color: #a31515;">"AddKvpItems"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>[]&nbsp;kvpItems&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: blue;">string</span>[ItemsToAdd.Count];
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">int</span>&nbsp;arrayCounter&nbsp;=&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(KeyValuePair&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;kvpItem&nbsp;<span style="color: blue;">in</span>&nbsp;ItemsToAdd)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;a&nbsp;new&nbsp;instance&nbsp;of&nbsp;a&nbsp;KVP&nbsp;Exchange&nbsp;data&nbsp;item</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;for&nbsp;each&nbsp;item&nbsp;that&nbsp;needs&nbsp;to&nbsp;be&nbsp;added</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;kvpInstance&nbsp;=&nbsp;kvpClass.CreateInstance();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpInstance.Properties[<span style="color: #a31515;">"Name"</span>].Value&nbsp;=&nbsp;kvpItem.Key;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpInstance.Properties[<span style="color: #a31515;">"Data"</span>].Value&nbsp;=&nbsp;kvpItem.Value;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpInstance.Properties[<span style="color: #a31515;">"Source"</span>].Value&nbsp;=&nbsp;0;
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;save&nbsp;this&nbsp;new&nbsp;instance&nbsp;back&nbsp;to&nbsp;the&nbsp;items&nbsp;array</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;text&nbsp;must&nbsp;be&nbsp;formatted&nbsp;first</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpItems[arrayCounter]&nbsp;=&nbsp;kvpInstance.GetText(<span style="color: #2b91af;">TextFormat</span>.CimDtd20);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arrayCounter++;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;finalize&nbsp;parameters&nbsp;and&nbsp;invoke&nbsp;the&nbsp;WMI&nbsp;method</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;kvpParams[<span style="color: #a31515;">"TargetSystem"</span>]&nbsp;=&nbsp;vmInstance.Path.Path;
&nbsp;&nbsp;&nbsp;&nbsp;kvpParams[<span style="color: #a31515;">"DataItems"</span>]&nbsp;=&nbsp;kvpItems;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementBaseObject</span>&nbsp;outParams&nbsp;=&nbsp;hostInstance.InvokeMethod(<span style="color: #a31515;">"AddKvpItems"</span>,&nbsp;kvpParams,&nbsp;<span style="color: blue;">null</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;((UInt32)outParams[<span style="color: #a31515;">"ReturnValue"</span>]&nbsp;==&nbsp;<span style="color: #2b91af;">WMIReturnCode</span>.Started)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;the&nbsp;Job&nbsp;has&nbsp;started,&nbsp;but&nbsp;not&nbsp;finished&nbsp;yet.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;grab&nbsp;an&nbsp;instance&nbsp;of&nbsp;the&nbsp;WMI&nbsp;Job&nbsp;object&nbsp;and&nbsp;wait&nbsp;until&nbsp;the&nbsp;Job&nbsp;is&nbsp;completed&nbsp;or&nbsp;failed.</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;Job&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementObject</span>(scope,&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementPath</span>((<span style="color: blue;">string</span>)outParams[<span style="color: #a31515;">"Job"</span>]),&nbsp;<span style="color: blue;">null</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(Job&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: #a31515;">"WMI&nbsp;Job&nbsp;has&nbsp;successfully&nbsp;started,&nbsp;but&nbsp;we&nbsp;were&nbsp;unable&nbsp;to&nbsp;locate&nbsp;the&nbsp;WMI&nbsp;Job&nbsp;object&nbsp;instance."</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(JobCompleted(Job)&nbsp;==&nbsp;<span style="color: blue;">false</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"WMI&nbsp;Job&nbsp;failed&nbsp;with&nbsp;error:&nbsp;{0},&nbsp;{1}"</span>,&nbsp;Job[<span style="color: #a31515;">"ErrorCode"</span>],&nbsp;Job[<span style="color: #a31515;">"ErrorDescription"</span>]));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">else</span>&nbsp;<span style="color: blue;">if</span>&nbsp;((UInt32)outParams[<span style="color: #a31515;">"ReturnValue"</span>]&nbsp;==&nbsp;<span style="color: #2b91af;">WMIReturnCode</span>.Completed)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Job&nbsp;has&nbsp;completed&nbsp;successfully.</span>
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"WMI&nbsp;Job&nbsp;failed&nbsp;to&nbsp;start&nbsp;with&nbsp;error:&nbsp;{0}"</span>,&nbsp;outParams[<span style="color: #a31515;">"ReturnValue"</span>]));
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(kvpParams&nbsp;!=&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpParams.Dispose();
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(outParams&nbsp;!=&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outParams.Dispose();
&nbsp;&nbsp;&nbsp;&nbsp;}
}</pre>
<h3>Part 2C: Reading messages written by VMs</h3>
<p>To read a message written by a VM, we grab the instance of the Virtual Machine WMI object (<a title="Msvm_ComputerSystem" href="https://msdn.microsoft.com/en-us/library/hh850116(v=vs.85).aspx">Msvm_ComputerSystem</a>), and then use a related object query to pull the&nbsp;KVP items in the GuestInstrinsicExchangeItems property on <a title="Msvm_KvpExchangeComponent" href="https://msdn.microsoft.com/en-us/library/cc136848(v=vs.85).aspx">Msvm_KvpExchangeComponent</a>.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Gets&nbsp;KVP&nbsp;Exchange&nbsp;Data&nbsp;items&nbsp;that&nbsp;were&nbsp;added&nbsp;from&nbsp;inside&nbsp;a&nbsp;VM</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"HyperVServerName"</span><span style="color: gray;">&gt;</span><span style="color: green;">The&nbsp;Hyper-V&nbsp;Server&nbsp;hostname</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineName"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;name&nbsp;as&nbsp;shown&nbsp;in&nbsp;Hyper-V&nbsp;manager</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineID"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;unique&nbsp;ID&nbsp;as&nbsp;known&nbsp;by&nbsp;Hyper-V</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;KVP&nbsp;Exchange&nbsp;data&nbsp;items</span><span style="color: gray;">&lt;/returns&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;GetVMAddedKVPItems(<span style="color: blue;">string</span>&nbsp;HyperVServerName,&nbsp;<span style="color: blue;">string</span>&nbsp;VirtualMachineName,&nbsp;Guid&nbsp;VirtualMachineID)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;check&nbsp;all&nbsp;required&nbsp;parameters</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(HyperVServerName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"HyperVServerName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(VirtualMachineName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"VirtualMachineName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(VirtualMachineID&nbsp;==&nbsp;Guid.Empty)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"VirtualMachineID&nbsp;cannot&nbsp;be&nbsp;empty"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;new&nbsp;scope&nbsp;object&nbsp;for&nbsp;the&nbsp;remote&nbsp;Hyper-V&nbsp;Host</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementScope</span>&nbsp;scope&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementScope</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">@"\\{0}\root\virtualization\v2"</span>,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;find&nbsp;the&nbsp;Hyper-V&nbsp;Machine&nbsp;object&nbsp;instance&nbsp;in&nbsp;the&nbsp;remote&nbsp;WMI</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;it&nbsp;must&nbsp;match&nbsp;both&nbsp;the&nbsp;display&nbsp;name&nbsp;and&nbsp;the&nbsp;ID</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">SelectQuery</span>&nbsp;vmQuery&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SelectQuery</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"SELECT&nbsp;*&nbsp;FROM&nbsp;Msvm_ComputerSystem&nbsp;WHERE&nbsp;ElementName&nbsp;=&nbsp;'{0}'&nbsp;AND&nbsp;Name&nbsp;=&nbsp;'{1}'"</span>,&nbsp;<br />						VirtualMachineName,&nbsp;VirtualMachineID));
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>&nbsp;vmSearcher&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>(scope,&nbsp;vmQuery);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;vmInstance&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;vmSearcher.Get())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vmInstance&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(vmInstance&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Virtual&nbsp;Machine&nbsp;({0},&nbsp;{1})&nbsp;WMI&nbsp;instance&nbsp;was&nbsp;not&nbsp;found&nbsp;on&nbsp;the&nbsp;Hyper-V&nbsp;Host&nbsp;{2}."</span>,&nbsp;<br />					VirtualMachineID,&nbsp;VirtualMachineName,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;kvp&nbsp;exchange&nbsp;data&nbsp;items&nbsp;are&nbsp;found&nbsp;via&nbsp;the&nbsp;related&nbsp;object&nbsp;query</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">RelatedObjectQuery</span>&nbsp;kvpQuery&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">RelatedObjectQuery</span>(<span style="color: #a31515;">"Associators&nbsp;of&nbsp;{"</span>&nbsp;+&nbsp;vmInstance.ToString()&nbsp;+&nbsp;<br />					<span style="color: #a31515;">"}&nbsp;Where&nbsp;AssocClass=Msvm_SystemDevice&nbsp;ResultClass=Msvm_KvpExchangeComponent"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>&nbsp;kvpSearcher&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>(scope,&nbsp;kvpQuery);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;kvpCollectionInstance&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;kvpSearcher.Get())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpCollectionInstance&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(kvpCollectionInstance&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Virtual&nbsp;Machine&nbsp;({0},&nbsp;{1})&nbsp;KVPExchangeComponent&nbsp;items&nbsp;were&nbsp;not&nbsp;found."</span>,&nbsp;<br />					VirtualMachineID,&nbsp;VirtualMachineName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;translate&nbsp;the&nbsp;raw&nbsp;KVP&nbsp;Items&nbsp;into&nbsp;a&nbsp;results&nbsp;collection&nbsp;and&nbsp;return</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>[]&nbsp;kvp&nbsp;=&nbsp;kvpCollectionInstance.Properties[<span style="color: #a31515;">"GuestIntrinsicExchangeItems"</span>].Value&nbsp;<span style="color: blue;">as</span>&nbsp;<span style="color: blue;">string</span>[];
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;TranslateKVPDataItems(kvp);
}</pre>
<h3>Part 2D: Reading messages written by Host</h3>
<p>To read a message written by the Hyper-V Host, we grab the instance of the Virtual Machine WMI object (<a title="Msvm_ComputerSystem" href="https://msdn.microsoft.com/en-us/library/hh850116(v=vs.85).aspx">Msvm_ComputerSystem</a>), and then use a related object query to pull the KVP items in the HostExchangeItems property on <a title="Msvm_KvpExchangeComponentSettingData" href="https://msdn.microsoft.com/en-us/library/cc136849(v=vs.85).aspx">Msvm_KvpExchangeComponentSettingData</a>. Note this is not the same class as used in step 2C.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Gets&nbsp;KVP&nbsp;Exchange&nbsp;Data&nbsp;items&nbsp;that&nbsp;were&nbsp;added&nbsp;from&nbsp;the&nbsp;Hyper-V&nbsp;Host</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"HyperVServerName"</span><span style="color: gray;">&gt;</span><span style="color: green;">The&nbsp;Hyper-V&nbsp;Server&nbsp;hostname</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineName"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;name&nbsp;as&nbsp;shown&nbsp;in&nbsp;Hyper-V&nbsp;manager</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineID"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;unique&nbsp;ID&nbsp;as&nbsp;known&nbsp;by&nbsp;Hyper-V</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;KVP&nbsp;Exchange&nbsp;data&nbsp;items</span><span style="color: gray;">&lt;/returns&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;GetHostAddedKVPItems(<span style="color: blue;">string</span>&nbsp;HyperVServerName,&nbsp;<span style="color: blue;">string</span>&nbsp;VirtualMachineName,&nbsp;Guid&nbsp;VirtualMachineID)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;check&nbsp;all&nbsp;required&nbsp;parameters</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(HyperVServerName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"HyperVServerName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(VirtualMachineName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"VirtualMachineName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(VirtualMachineID&nbsp;==&nbsp;Guid.Empty)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"VirtualMachineID&nbsp;cannot&nbsp;be&nbsp;empty"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;new&nbsp;scope&nbsp;object&nbsp;for&nbsp;the&nbsp;remote&nbsp;Hyper-V&nbsp;Host</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementScope</span>&nbsp;scope&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementScope</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">@"\\{0}\root\virtualization\v2"</span>,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;find&nbsp;the&nbsp;Hyper-V&nbsp;Machine&nbsp;object&nbsp;instance&nbsp;in&nbsp;the&nbsp;remote&nbsp;WMI</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;it&nbsp;must&nbsp;match&nbsp;both&nbsp;the&nbsp;display&nbsp;name&nbsp;and&nbsp;the&nbsp;ID</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">SelectQuery</span>&nbsp;vmQuery&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SelectQuery</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"SELECT&nbsp;*&nbsp;FROM&nbsp;Msvm_ComputerSystem&nbsp;WHERE&nbsp;ElementName&nbsp;=&nbsp;'{0}'&nbsp;AND&nbsp;Name&nbsp;=&nbsp;'{1}'"</span>,&nbsp;<br />						VirtualMachineName,&nbsp;VirtualMachineID));
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>&nbsp;vmSearcher&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>(scope,&nbsp;vmQuery);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;vmInstance&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;vmSearcher.Get())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vmInstance&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(vmInstance&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Virtual&nbsp;Machine&nbsp;({0},&nbsp;{1})&nbsp;WMI&nbsp;instance&nbsp;was&nbsp;not&nbsp;found&nbsp;on&nbsp;the&nbsp;Hyper-V&nbsp;Host&nbsp;{2}."</span>,&nbsp;<br />					VirtualMachineID,&nbsp;VirtualMachineName,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;find&nbsp;the&nbsp;related&nbsp;KVP&nbsp;Component</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;kvpExchangeComponent&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;vmInstance.GetRelated(<span style="color: #a31515;">"Msvm_KvpExchangeComponent"</span>))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpExchangeComponent&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">break</span>;&nbsp;<span style="color: green;">//&nbsp;grab&nbsp;the&nbsp;first&nbsp;item&nbsp;and&nbsp;break</span>
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(kvpExchangeComponent&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Virtual&nbsp;Machine&nbsp;({0},&nbsp;{1})&nbsp;KVPExchangeComponent&nbsp;Host&nbsp;item&nbsp;was&nbsp;not&nbsp;found."</span>,&nbsp;<br />				VirtualMachineID,&nbsp;VirtualMachineName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;kvpExchangeComponentSettingData&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;kvpExchangeComponent.GetRelated(<span style="color: #a31515;">"Msvm_KvpExchangeComponentSettingData"</span>))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpExchangeComponentSettingData&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">break</span>;&nbsp;<span style="color: green;">//&nbsp;grab&nbsp;the&nbsp;first&nbsp;item&nbsp;and&nbsp;break</span>
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(kvpExchangeComponentSettingData&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Virtual&nbsp;Machine&nbsp;({0},&nbsp;{1})&nbsp;KVPExchangeComponentSettingData&nbsp;Host&nbsp;item&nbsp;was&nbsp;not&nbsp;found."</span>,&nbsp;<br />					VirtualMachineID,&nbsp;VirtualMachineName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;translate&nbsp;the&nbsp;raw&nbsp;KVP&nbsp;Items&nbsp;into&nbsp;a&nbsp;results&nbsp;collection&nbsp;and&nbsp;return</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>[]&nbsp;xmlItems&nbsp;=&nbsp;kvpExchangeComponentSettingData.Properties[<span style="color: #a31515;">"HostExchangeItems"</span>].Value&nbsp;<span style="color: blue;">as</span>&nbsp;<span style="color: blue;">string</span>[];
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;TranslateKVPDataItems(xmlItems);
}</pre>
<h3>Part 2E: Removing messages</h3>
<p>To remove messages from the KVP Store via WMI on the Host, we need to call the <a title="RemoveKvpItems" href="https://msdn.microsoft.com/en-us/library/cc160710(v=vs.85).aspx">RemoveKvpItems</a> method on the <a title="Msvm_VirtualSystemManagementService" href="https://msdn.microsoft.com/en-us/library/cc136940(v=vs.85).aspx">Msvm_VirtualSystemManagementService</a> WMI class.<br />Just like <a title="AddKvpItems" href="https://msdn.microsoft.com/en-us/library/cc160704(v=vs.85).aspx">AddKvpItems</a>, the sample code on MSDN is only for removing a single KVP item. The following is a modified example for removing a group of items.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Removes&nbsp;KVP&nbsp;Exchange&nbsp;Data&nbsp;items</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"HyperVServerName"</span><span style="color: gray;">&gt;</span><span style="color: green;">The&nbsp;Hyper-V&nbsp;Server&nbsp;hostname</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineName"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;name&nbsp;as&nbsp;shown&nbsp;in&nbsp;Hyper-V&nbsp;manager</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"VirtualMachineID"</span><span style="color: gray;">&gt;</span><span style="color: green;">Virtual&nbsp;Machine&nbsp;unique&nbsp;ID&nbsp;as&nbsp;known&nbsp;by&nbsp;Hyper-V</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"ItemsToRemove"</span><span style="color: gray;">&gt;</span><span style="color: green;">Array&nbsp;of&nbsp;item&nbsp;key&nbsp;names&nbsp;to&nbsp;remove</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">void</span>&nbsp;RemoveKVPItems(<span style="color: blue;">string</span>&nbsp;HyperVServerName,&nbsp;<span style="color: blue;">string</span>&nbsp;VirtualMachineName,&nbsp;Guid&nbsp;VirtualMachineID,&nbsp;<span style="color: blue;">string</span>[]&nbsp;ItemsToRemove)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;check&nbsp;all&nbsp;required&nbsp;parameters</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(HyperVServerName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"HyperVServerName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(VirtualMachineName))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"VirtualMachineName"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(VirtualMachineID&nbsp;==&nbsp;Guid.Empty)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"VirtualMachineID&nbsp;cannot&nbsp;be&nbsp;empty"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(ItemsToRemove&nbsp;==&nbsp;<span style="color: blue;">null</span>&nbsp;||&nbsp;ItemsToRemove.Length&nbsp;==&nbsp;0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"ItemsToRemove&nbsp;cannot&nbsp;be&nbsp;null&nbsp;or&nbsp;empty"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;RemoveKvpItems()&nbsp;WMI&nbsp;Method&nbsp;does&nbsp;not&nbsp;allow&nbsp;more&nbsp;than&nbsp;128&nbsp;items&nbsp;in&nbsp;a&nbsp;single&nbsp;call.&nbsp;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Very&nbsp;large&nbsp;messages&nbsp;will&nbsp;need&nbsp;to&nbsp;be&nbsp;broken&nbsp;down&nbsp;into&nbsp;message&nbsp;groups&nbsp;of&nbsp;128&nbsp;or&nbsp;less.</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(ItemsToRemove.Length&nbsp;&gt;&nbsp;128)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentException</span>(<span style="color: #a31515;">"ItemsToRemove&nbsp;cannot&nbsp;contain&nbsp;more&nbsp;than&nbsp;128&nbsp;items"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;new&nbsp;scope&nbsp;object&nbsp;for&nbsp;the&nbsp;remote&nbsp;Hyper-V&nbsp;Host</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementScope</span>&nbsp;scope&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementScope</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">@"\\{0}\root\virtualization\v2"</span>,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;find&nbsp;the&nbsp;Hyper-V&nbsp;Host&nbsp;Management&nbsp;object&nbsp;instance&nbsp;in&nbsp;the&nbsp;remote&nbsp;WMI</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementPath</span>&nbsp;wmiPath&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementPath</span>(<span style="color: #a31515;">"Msvm_VirtualSystemManagementService"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementClass</span>&nbsp;serviceClass&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementClass</span>(scope,&nbsp;wmiPath,&nbsp;<span style="color: blue;">null</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;hostInstance&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;serviceClass.GetInstances())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostInstance&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(hostInstance&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Hyper-V&nbsp;Host&nbsp;({0})&nbsp;Management&nbsp;Object&nbsp;Instance&nbsp;was&nbsp;not&nbsp;found&nbsp;in&nbsp;WMI."</span>,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;find&nbsp;the&nbsp;Hyper-V&nbsp;Machine&nbsp;object&nbsp;instance&nbsp;in&nbsp;the&nbsp;remote&nbsp;WMI</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;it&nbsp;must&nbsp;match&nbsp;both&nbsp;the&nbsp;display&nbsp;name&nbsp;and&nbsp;the&nbsp;ID</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">SelectQuery</span>&nbsp;vmQuery&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">SelectQuery</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"SELECT&nbsp;*&nbsp;FROM&nbsp;Msvm_ComputerSystem&nbsp;WHERE&nbsp;ElementName&nbsp;=&nbsp;'{0}'&nbsp;AND&nbsp;Name&nbsp;=&nbsp;'{1}'"</span>,&nbsp;<br />						VirtualMachineName,&nbsp;VirtualMachineID));
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>&nbsp;vmSearcher&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementObjectSearcher</span>(scope,&nbsp;vmQuery);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;vmInstance&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">ManagementObject</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;vmSearcher.Get())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vmInstance&nbsp;=&nbsp;item;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(vmInstance&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Virtual&nbsp;Machine&nbsp;({0},&nbsp;{1})&nbsp;WMI&nbsp;instance&nbsp;was&nbsp;not&nbsp;found&nbsp;on&nbsp;the&nbsp;Hyper-V&nbsp;Host&nbsp;{2}."</span>,&nbsp;<br />				VirtualMachineID,&nbsp;VirtualMachineName,&nbsp;HyperVServerName));
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;prepare&nbsp;objects&nbsp;for&nbsp;method&nbsp;execution</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;get&nbsp;the&nbsp;method&nbsp;parameters&nbsp;for&nbsp;RemoveKvpItems()</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;populate&nbsp;the&nbsp;kvpItems&nbsp;array&nbsp;with&nbsp;new&nbsp;instances&nbsp;of&nbsp;Msvm_KvpExchangeDataItem</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementClass</span>&nbsp;kvpClass&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementClass</span>(scope,&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementPath</span>(<span style="color: #a31515;">"Msvm_KvpExchangeDataItem"</span>),&nbsp;<span style="color: blue;">null</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementBaseObject</span>&nbsp;kvpParams&nbsp;=&nbsp;hostInstance.GetMethodParameters(<span style="color: #a31515;">"RemoveKvpItems"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>[]&nbsp;kvpItems&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: blue;">string</span>[ItemsToRemove.Length];
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">for</span>&nbsp;(<span style="color: blue;">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;ItemsToRemove.Length;&nbsp;i++)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;a&nbsp;new&nbsp;instance&nbsp;of&nbsp;a&nbsp;KVP&nbsp;Exchange&nbsp;data&nbsp;item</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;for&nbsp;each&nbsp;item&nbsp;that&nbsp;needs&nbsp;to&nbsp;be&nbsp;removed</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;kvpInstance&nbsp;=&nbsp;kvpClass.CreateInstance();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpInstance.Properties[<span style="color: #a31515;">"Name"</span>].Value&nbsp;=&nbsp;ItemsToRemove[i];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpInstance.Properties[<span style="color: #a31515;">"Data"</span>].Value&nbsp;=&nbsp;<span style="color: blue;">string</span>.Empty;&nbsp;<span style="color: green;">//&nbsp;pass&nbsp;string&nbsp;empty,&nbsp;since&nbsp;only&nbsp;the&nbsp;Item&nbsp;Name&nbsp;needs&nbsp;to&nbsp;match</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpInstance.Properties[<span style="color: #a31515;">"Source"</span>].Value&nbsp;=&nbsp;0;
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;save&nbsp;this&nbsp;new&nbsp;instance&nbsp;back&nbsp;to&nbsp;the&nbsp;items&nbsp;array</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;text&nbsp;must&nbsp;be&nbsp;formatted&nbsp;first</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpItems[i]&nbsp;=&nbsp;kvpInstance.GetText(<span style="color: #2b91af;">TextFormat</span>.CimDtd20);
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;finalize&nbsp;parameters&nbsp;and&nbsp;invoke&nbsp;the&nbsp;WMI&nbsp;method</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;kvpParams[<span style="color: #a31515;">"TargetSystem"</span>]&nbsp;=&nbsp;vmInstance.Path.Path;
&nbsp;&nbsp;&nbsp;&nbsp;kvpParams[<span style="color: #a31515;">"DataItems"</span>]&nbsp;=&nbsp;kvpItems;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementBaseObject</span>&nbsp;outParams&nbsp;=&nbsp;hostInstance.InvokeMethod(<span style="color: #a31515;">"RemoveKvpItems"</span>,&nbsp;kvpParams,&nbsp;<span style="color: blue;">null</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;((UInt32)outParams[<span style="color: #a31515;">"ReturnValue"</span>]&nbsp;==&nbsp;<span style="color: #2b91af;">WMIReturnCode</span>.Started)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;the&nbsp;Job&nbsp;has&nbsp;started,&nbsp;but&nbsp;not&nbsp;finished&nbsp;yet.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;grab&nbsp;an&nbsp;instance&nbsp;of&nbsp;the&nbsp;WMI&nbsp;Job&nbsp;object&nbsp;and&nbsp;wait&nbsp;until&nbsp;the&nbsp;Job&nbsp;is&nbsp;completed&nbsp;or&nbsp;failed.</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">ManagementObject</span>&nbsp;Job&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementObject</span>(scope,&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ManagementPath</span>((<span style="color: blue;">string</span>)outParams[<span style="color: #a31515;">"Job"</span>]),&nbsp;<span style="color: blue;">null</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(Job&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: #a31515;">"WMI&nbsp;Job&nbsp;has&nbsp;successfully&nbsp;started,&nbsp;but&nbsp;we&nbsp;were&nbsp;unable&nbsp;to&nbsp;locate&nbsp;the&nbsp;WMI&nbsp;Job&nbsp;object&nbsp;instance."</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(JobCompleted(Job)&nbsp;==&nbsp;<span style="color: blue;">false</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"WMI&nbsp;Job&nbsp;failed&nbsp;with&nbsp;error:&nbsp;{0},&nbsp;{1}"</span>,&nbsp;Job[<span style="color: #a31515;">"ErrorCode"</span>],&nbsp;Job[<span style="color: #a31515;">"ErrorDescription"</span>]));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">else</span>&nbsp;<span style="color: blue;">if</span>&nbsp;((UInt32)outParams[<span style="color: #a31515;">"ReturnValue"</span>]&nbsp;==&nbsp;<span style="color: #2b91af;">WMIReturnCode</span>.Completed)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Job&nbsp;has&nbsp;completed&nbsp;successfully.</span>
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"WMI&nbsp;Job&nbsp;failed&nbsp;to&nbsp;start&nbsp;with&nbsp;error:&nbsp;{0}"</span>,&nbsp;outParams[<span style="color: #a31515;">"ReturnValue"</span>]));
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(kvpParams&nbsp;!=&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kvpParams.Dispose();
&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(outParams&nbsp;!=&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outParams.Dispose();
&nbsp;&nbsp;&nbsp;&nbsp;}
}</pre>
<h3>Part 2F: Helper classes</h3>
<p>The code samples above use the following helper classes.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Translates&nbsp;raw&nbsp;KVP&nbsp;Exchange&nbsp;Data&nbsp;item&nbsp;XML&nbsp;nodes&nbsp;into&nbsp;a&nbsp;results&nbsp;collection</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;remarks&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;The&nbsp;kvp&nbsp;data&nbsp;items&nbsp;returned&nbsp;from&nbsp;WMI&nbsp;are&nbsp;a&nbsp;blob&nbsp;of&nbsp;XML&nbsp;that&nbsp;can&nbsp;be&nbsp;translated&nbsp;into&nbsp;a&nbsp;collection&nbsp;of&nbsp;usable&nbsp;key-value&nbsp;pairs.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/remarks&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"kvpXmlNodes"</span><span style="color: gray;">&gt;</span><span style="color: green;">Array&nbsp;of&nbsp;KVP&nbsp;Exchange&nbsp;Data&nbsp;items</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;key-value&nbsp;pair&nbsp;items</span><span style="color: gray;">&lt;/returns&gt;</span>
<span style="color: blue;">private</span>&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;TranslateKVPDataItems(<span style="color: blue;">string</span>[]&nbsp;kvpXmlNodes)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(kvpXmlNodes&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"kvpXmlNodes"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;KVPItems&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;();
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: blue;">string</span>&nbsp;xmlString&nbsp;<span style="color: blue;">in</span>&nbsp;kvpXmlNodes)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;each&nbsp;string&nbsp;contains&nbsp;an&nbsp;XML&nbsp;document&nbsp;with&nbsp;XmlElements</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;load&nbsp;the&nbsp;XML&nbsp;string&nbsp;into&nbsp;a&nbsp;Document&nbsp;object&nbsp;for&nbsp;processing</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">XmlDocument</span>&nbsp;d&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">XmlDocument</span>();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d.LoadXml(xmlString);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>&nbsp;Name&nbsp;=&nbsp;<span style="color: blue;">null</span>;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>&nbsp;Value&nbsp;=&nbsp;<span style="color: blue;">null</span>;
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">XmlElement</span>&nbsp;property&nbsp;<span style="color: blue;">in</span>&nbsp;d.SelectNodes(<span style="color: #a31515;">"/INSTANCE/PROPERTY"</span>))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(property.InnerText)&nbsp;==&nbsp;<span style="color: blue;">false</span>)
&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;<span style="color: green;">//&nbsp;this&nbsp;element&nbsp;has&nbsp;data&nbsp;in&nbsp;it&nbsp;(InnerText&nbsp;not&nbsp;null)</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;look&nbsp;at&nbsp;the&nbsp;attributes&nbsp;for&nbsp;this&nbsp;element&nbsp;to&nbsp;find&nbsp;out&nbsp;if&nbsp;this&nbsp;is&nbsp;the&nbsp;Name&nbsp;or&nbsp;the&nbsp;Value&nbsp;portion&nbsp;of&nbsp;the&nbsp;KVP&nbsp;item</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">XmlAttribute</span>&nbsp;attrib&nbsp;<span style="color: blue;">in</span>&nbsp;property.Attributes)
&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;<span style="color: blue;">if</span>&nbsp;(attrib.Value&nbsp;==&nbsp;<span style="color: #a31515;">"Name"</span>)
&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;Name&nbsp;=&nbsp;property.InnerText;
&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;<span style="color: blue;">if</span>&nbsp;(attrib.Value&nbsp;==&nbsp;<span style="color: #a31515;">"Data"</span>)
&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;Value&nbsp;=&nbsp;property.InnerText;
&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;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(<span style="color: blue;">string</span>.IsNullOrEmpty(Name)&nbsp;==&nbsp;<span style="color: blue;">false</span>&nbsp;&amp;&amp;&nbsp;<span style="color: blue;">string</span>.IsNullOrEmpty(Value)&nbsp;==&nbsp;<span style="color: blue;">false</span>&nbsp;&amp;&amp;&nbsp;KVPItems.ContainsKey(Name)&nbsp;==&nbsp;<span style="color: blue;">false</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Found&nbsp;a&nbsp;KVP&nbsp;item&nbsp;that&nbsp;has&nbsp;Name&nbsp;and&nbsp;Value&nbsp;fields&nbsp;populated</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Also&nbsp;it&nbsp;does&nbsp;not&nbsp;already&nbsp;exist&nbsp;in&nbsp;the&nbsp;results&nbsp;collection</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KVPItems.Add(Name,&nbsp;Value);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;KVPItems;
}
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Waits&nbsp;until&nbsp;a&nbsp;WMI&nbsp;Job&nbsp;is&nbsp;completed</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"Job"</span><span style="color: gray;">&gt;</span><span style="color: green;">WMI&nbsp;Job&nbsp;object</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;</span><span style="color: green;">True&nbsp;if&nbsp;Job&nbsp;success,&nbsp;False&nbsp;if&nbsp;Job&nbsp;failure</span><span style="color: gray;">&lt;/returns&gt;</span>
<span style="color: blue;">private</span>&nbsp;<span style="color: blue;">bool</span>&nbsp;JobCompleted(<span style="color: #2b91af;">ManagementObject</span>&nbsp;Job)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Capture&nbsp;latest&nbsp;Job&nbsp;status</span>
&nbsp;&nbsp;&nbsp;&nbsp;Job.Get();
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;Is&nbsp;the&nbsp;job&nbsp;still&nbsp;in&nbsp;progress&nbsp;or&nbsp;starting?</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;If&nbsp;yes,&nbsp;then&nbsp;sleep&nbsp;and&nbsp;check&nbsp;job&nbsp;status&nbsp;again&nbsp;until&nbsp;completed.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">while</span>&nbsp;((UInt16)Job[<span style="color: #a31515;">"JobState"</span>]&nbsp;==&nbsp;<span style="color: #2b91af;">WMIJobState</span>.Starting&nbsp;||&nbsp;(UInt16)Job[<span style="color: #a31515;">"JobState"</span>]&nbsp;==&nbsp;<span style="color: #2b91af;">WMIJobState</span>.Running)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Threading.<span style="color: #2b91af;">Thread</span>.Sleep(500);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Job.Get();
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;return&nbsp;the&nbsp;success/failure&nbsp;of&nbsp;the&nbsp;job</span>
&nbsp;&nbsp;&nbsp;&nbsp;UInt16&nbsp;jobState&nbsp;=&nbsp;(UInt16)Job[<span style="color: #a31515;">"JobState"</span>];
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(jobState&nbsp;!=&nbsp;<span style="color: #2b91af;">WMIJobState</span>.Completed)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;<span style="color: blue;">false</span>;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;<span style="color: blue;">true</span>;
&nbsp;&nbsp;&nbsp;&nbsp;}
}
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;WMI&nbsp;Job&nbsp;State&nbsp;class&nbsp;enumeration</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">class</span>&nbsp;<span style="color: #2b91af;">WMIJobState</span>
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;New&nbsp;=&nbsp;2;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Starting&nbsp;=&nbsp;3;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Running&nbsp;=&nbsp;4;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Suspended&nbsp;=&nbsp;5;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;ShuttingDown&nbsp;=&nbsp;6;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Completed&nbsp;=&nbsp;7;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Terminated&nbsp;=&nbsp;8;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Killed&nbsp;=&nbsp;9;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Exception&nbsp;=&nbsp;10;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt16&nbsp;Service&nbsp;=&nbsp;11;
}
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;WMI&nbsp;Method&nbsp;Invoke&nbsp;return&nbsp;code&nbsp;class&nbsp;enumeration</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">class</span>&nbsp;<span style="color: #2b91af;">WMIReturnCode</span>
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;Completed&nbsp;=&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;Started&nbsp;=&nbsp;4096;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;Failed&nbsp;=&nbsp;32768;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;AccessDenied&nbsp;=&nbsp;32769;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;NotSupported&nbsp;=&nbsp;32770;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;Unknown&nbsp;=&nbsp;32771;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;Timeout&nbsp;=&nbsp;32772;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;InvalidParameter&nbsp;=&nbsp;32773;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;SystemInUse&nbsp;=&nbsp;32774;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;InvalidState&nbsp;=&nbsp;32775;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;IncorrectDataType&nbsp;=&nbsp;32776;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;SystemNotAvailable&nbsp;=&nbsp;32777;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">const</span>&nbsp;UInt32&nbsp;OutofMemory&nbsp;=&nbsp;32778;
}</pre>
<h1>Part 3: Inside the Guest VM Operating System</h1>
<h3>Part 3A: Sending</h3>
<p>Writing messages back to the host is as simple as writing to the registry. Inside the Hyper-V Guest OS, the registry key &ldquo;HKLM\SOFTWARE\Microsoft\Virtual Machine\Auto&rdquo; stores the messages to be read by the Hyper-V Host. Write the keys and values as new string value entries.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/0602.guest-auto.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/0602.guest_2D00_auto.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/0602.guest-auto.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x588/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/0602.guest_2D00_auto.png" alt="" border="0" /></a></p>
<p>You can see that this location already hosts several key/values that Hyper-V uses internally to communicate OS information back to the Host. This registry key location should always exist on Hyper-V guest operating systems, assuming that they have integration services components installed.</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Registry&nbsp;key&nbsp;location&nbsp;for&nbsp;the&nbsp;Guest&nbsp;outgoing&nbsp;KVP&nbsp;Items.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: blue;">private</span>&nbsp;<span style="color: blue;">const</span>&nbsp;<span style="color: blue;">string</span>&nbsp;KVPOutgoingRegistryKey&nbsp;=&nbsp;<span style="color: #a31515;">@"SOFTWARE\Microsoft\Virtual&nbsp;Machine\Auto"</span>;
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Writes&nbsp;outgoing&nbsp;KVP&nbsp;messages&nbsp;to&nbsp;the&nbsp;registry.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"ItemsToAdd"</span><span style="color: gray;">&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;items&nbsp;to&nbsp;add</span><span style="color: gray;">&lt;/param&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">void</span>&nbsp;SendGuestKVPItems(<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;ItemsToAdd)
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(ItemsToAdd&nbsp;==&nbsp;<span style="color: blue;">null</span>&nbsp;||&nbsp;ItemsToAdd.Count&nbsp;==&nbsp;0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">ArgumentNullException</span>(<span style="color: #a31515;">"ItemsToAdd"</span>);
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: blue;">var</span>&nbsp;item&nbsp;<span style="color: blue;">in</span>&nbsp;ItemsToAdd)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;write&nbsp;the&nbsp;value&nbsp;to&nbsp;the&nbsp;registry</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Registry</span>.SetValue(<span style="color: #a31515;">"HKEY_LOCAL_MACHINE\\"</span>&nbsp;+&nbsp;KVPOutgoingRegistryKey,&nbsp;item.Key,&nbsp;item.Value);
&nbsp;&nbsp;&nbsp;&nbsp;}
}</pre>
<h3>Part 3B: Receiving</h3>
<p>Reading messages sent from the Host to the VM is similar to step 3A in that it involves the registry. We just open and read the registry key &ldquo;HKLM\SOFTWARE\Microsoft\Virtual Machine\External&rdquo;. Inside this location will be any key-value pair items that were written from the Host and floated down to the VM. Simply read the message items, and reconstruct the message or instruction in your desired format.</p>
<p>Unless you have been sending messages, this key is usually empty:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/6457.guest-external.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/6457.guest_2D00_external.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/6457.guest-external.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x554/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/6457.guest_2D00_external.PNG" alt="" border="0" /></a></p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Registry&nbsp;key&nbsp;location&nbsp;for&nbsp;the&nbsp;Guest&nbsp;incoming&nbsp;KVP&nbsp;Items.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: blue;">private</span>&nbsp;<span style="color: blue;">const</span>&nbsp;<span style="color: blue;">string</span>&nbsp;KVPIncomingRegistryKey&nbsp;=&nbsp;<span style="color: #a31515;">@"SOFTWARE\Microsoft\Virtual&nbsp;Machine\External"</span>;
</pre>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;Reads&nbsp;the&nbsp;Host&nbsp;KVP&nbsp;Data&nbsp;Exchanges&nbsp;items.</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;</span><span style="color: green;">Collection&nbsp;of&nbsp;key/value&nbsp;pairs.</span><span style="color: gray;">&lt;/returns&gt;</span>
<span style="color: blue;">public</span>&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;ReadHostKVPItems()
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;&nbsp;KvpItems&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Dictionary</span>&lt;<span style="color: blue;">string</span>,&nbsp;<span style="color: blue;">string</span>&gt;();
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">RegistryKey</span>&nbsp;HostKey&nbsp;=&nbsp;<span style="color: #2b91af;">Registry</span>.LocalMachine.OpenSubKey(KVPIncomingRegistryKey))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(HostKey&nbsp;==&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;this&nbsp;would&nbsp;indicate&nbsp;the&nbsp;host&nbsp;registry&nbsp;key&nbsp;doesn't&nbsp;exist.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;the&nbsp;only&nbsp;time&nbsp;this&nbsp;should&nbsp;happen&nbsp;is&nbsp;on&nbsp;a&nbsp;machine&nbsp;that&nbsp;isn't&nbsp;a&nbsp;hyper-v&nbsp;VM</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;or&nbsp;we&nbsp;don't&nbsp;have&nbsp;access&nbsp;to&nbsp;open&nbsp;the&nbsp;key.</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">throw</span>&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">Exception</span>(<span style="color: #a31515;">"Host&nbsp;KVP&nbsp;Registry&nbsp;key&nbsp;not&nbsp;found."</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;read&nbsp;the&nbsp;key&nbsp;value&nbsp;names</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>[]&nbsp;ValueNames&nbsp;=&nbsp;HostKey.GetValueNames();
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(ValueNames.Length&nbsp;==&nbsp;0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;KvpItems;&nbsp;<span style="color: green;">//&nbsp;no&nbsp;items&nbsp;found!</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: blue;">string</span>&nbsp;keyValueName&nbsp;<span style="color: blue;">in</span>&nbsp;ValueNames)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;capture&nbsp;the&nbsp;value&nbsp;as&nbsp;a&nbsp;string</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;returns&nbsp;string&nbsp;empty&nbsp;if&nbsp;the&nbsp;key&nbsp;value&nbsp;is&nbsp;null.</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">string</span>&nbsp;keyValue&nbsp;=&nbsp;<span style="color: #2b91af;">Registry</span>.GetValue(<span style="color: #a31515;">"HKEY_LOCAL_MACHINE\\"</span>&nbsp;+&nbsp;KVPIncomingRegistryKey,&nbsp;keyValueName,&nbsp;<span style="color: blue;">string</span>.Empty)&nbsp;<span style="color: blue;">as</span>&nbsp;<span style="color: blue;">string</span>;
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;add&nbsp;to&nbsp;the&nbsp;collection.</span>
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KvpItems.Add(keyValueName,&nbsp;keyValue);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;KvpItems;
}</pre>]]></content:encoded>
    </item>
    <item>
      <title>Executing PowerShell scripts from C#</title>
      <link>https://docs.microsoft.com/archive/blogs/kebab/executing-powershell-scripts-from-c</link>
      <pubDate>Mon, 28 Apr 2014 08:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Keith Babinec]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kebab/2014/04/28/executing-powershell-scripts-from-c/</guid>
      <description><![CDATA[In today&rsquo;s post, I will demonstrate the basics of how to execute PowerShell scripts and code...]]></description>
      <content:encoded><![CDATA[<p><span style="font-family: arial,helvetica,sans-serif; font-size: small;">In today&rsquo;s post, I will demonstrate the basics of how to execute PowerShell scripts and code from within a C#/.NET applications. I will walk through how to setup your project prerequisites, populate the pipeline with script code and parameters, perform synchronous and asynchronous execution, capture output, and leverage shared namespaces.<br /><br /><em><strong>Update 8/7/2014</strong></em>: <a title="Here" href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/0601.PowerShellExecutionSample.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/0601.PowerShellExecutionSample.zip">Here</a> is the downloadable solution file.<br /><em><strong>Update 11/5/2014</strong></em>: Added a section on execution policy behavior.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><strong>Prerequisites:</strong></span><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><br />First, ensure that PowerShell 2.0 or later is installed on the system you are developing on. The features used below will not be supported on PowerShell 1.0. Next, start by making a new console application (targeting .NET 4.0) in Visual Studio.</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/6354.references.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/6354.references.png"><img style="border: 0px currentColor;" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/6354.references.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/6354.references.png" alt="" width="335" height="256" /></a></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: small;">In the solution explorer, add a project reference to the <em><strong>System.Management.Automation</strong></em> assembly<em><strong>*</strong></em>. On my machine (PowerShell 3.0), it was located at <em><strong>C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0</strong></em>. Then, add <em><strong>using</strong></em> statements for the above referenced assembly, along with <em><strong>System.Collections.Objectmodel</strong></em>, which is used later for execution output.</span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><em><strong>Note</strong></em>: <em>You will need to install the Windows SDK in order to obtain the <strong>System.Management.Automation</strong> assembly file.<br /><strong>Note</strong>: You do not have to distribute the <strong>System.Management.Automation</strong> assembly file with your application binaries&nbsp;- it is located in the GAC on machines with Windows PowerShell installed and should resolve automatically.</em></span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/1070.usingPS.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/1070.usingPS.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/1070.usingPS.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/398x325/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/1070.usingPS.png" alt="" border="0" /></a></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><strong>Prepare the Pipeline for execution:</strong></span></p>
<p><span style="font-family: arial,helvetica,sans-serif; font-size: small;">The first step is to create a new instance of the <em><strong>PowerShell</strong></em> class. The static method <em><strong>PowerShell.Create()</strong></em> creates an empty PowerShell pipeline for us to use for execution. The PowerShell class implements <em><strong>IDisposable</strong></em>, so remember to wrap it up in a using block.</span></p>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">PowerShell</span>&nbsp;PowerShellInstance&nbsp;=&nbsp;<span style="color: #2b91af;">PowerShell</span>.Create())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Next, we can add scripts or commands to execute. Call the <em><strong>AddScript()</strong></em> and <em><strong>AddCommand()</strong></em> methods to add this content to the execution pipeline. If your script has parameters, adding them is easy with the <em><strong>AddParameter()</strong></em> method. <em><strong>AddParameter()</strong></em> accepts a string parameter name, and object for the parameter value. Feel free to pass in full object instances/types if you want. The scripts and pipeline handle it just fine. No need to limit yourself with only passing in string values.</span></p>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">The string contents supplied to <em><strong>AddScript()</strong></em> can come from anywhere. Good choices may be text loaded from files on disk or embedded resources, or user input. For the purposes of this tutorial, I&rsquo;m just hard-coding some example script text.</span></p>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">PowerShell</span>&nbsp;PowerShellInstance&nbsp;=&nbsp;<span style="color: #2b91af;">PowerShell</span>.Create())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;use&nbsp;"AddScript"&nbsp;to&nbsp;add&nbsp;the&nbsp;contents&nbsp;of&nbsp;a&nbsp;script&nbsp;file&nbsp;to&nbsp;the&nbsp;end&nbsp;of&nbsp;the&nbsp;execution&nbsp;pipeline.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;use&nbsp;"AddCommand"&nbsp;to&nbsp;add&nbsp;individual&nbsp;commands/cmdlets&nbsp;to&nbsp;the&nbsp;end&nbsp;of&nbsp;the&nbsp;execution&nbsp;pipeline.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PowerShellInstance.AddScript(<span style="color: #a31515;">"param($param1)&nbsp;$d&nbsp;=&nbsp;get-date;&nbsp;$s&nbsp;=&nbsp;'test&nbsp;string&nbsp;value';&nbsp;"</span>&nbsp;+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a31515;">"$d;&nbsp;$s;&nbsp;$param1;&nbsp;get-service"</span>);<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;use&nbsp;"AddParameter"&nbsp;to&nbsp;add&nbsp;a&nbsp;single&nbsp;parameter&nbsp;to&nbsp;the&nbsp;last&nbsp;command/script&nbsp;on&nbsp;the&nbsp;pipeline.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PowerShellInstance.AddParameter(<span style="color: #a31515;">"param1"</span>,&nbsp;<span style="color: #a31515;">"parameter&nbsp;1&nbsp;value!"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<p style="background: white; color: black; font-family: Consolas;"><br /><strong><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Script/Command Execution:</span></strong></p>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">So far, we have a PowerShell pipeline populated with script code and parameters. There are two ways we can call PowerShell to execute it: synchronously and asynchronously.</span></p>
<p style="background: white; color: black; font-family: Consolas;"><strong><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Synchronous execution:</span></strong></p>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">For synchronous execution, we call <em><strong>PowerShell.Invoke()</strong></em>. The caller waits until the script or commands have finished executing completely before returning from the call to <em><strong>Invoke()</strong></em>. If you don&rsquo;t care about the items in the output stream, the simplest execution looks like this:</span></p>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;invoke&nbsp;execution&nbsp;on&nbsp;the&nbsp;pipeline&nbsp;(ignore&nbsp;output)</span>
&nbsp;&nbsp;&nbsp;&nbsp;PowerShellInstance.Invoke();</pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">For situations where you don&rsquo;t need to see or monitor the output or results of execution, this may be acceptable. But, in other scenarios you probably need to peek at the results or perform additional processing with the output that comes back from PowerShell. Let&rsquo;s see what that code looks like:</span></p>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;invoke&nbsp;execution&nbsp;on&nbsp;the&nbsp;pipeline&nbsp;(collecting&nbsp;output)</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Collection</span>&lt;<span style="color: #2b91af;">PSObject</span>&gt;&nbsp;PSOutput&nbsp;=&nbsp;PowerShellInstance.Invoke();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;loop&nbsp;through&nbsp;each&nbsp;output&nbsp;object&nbsp;item</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">PSObject</span>&nbsp;outputItem&nbsp;<span style="color: blue;">in</span>&nbsp;PSOutput)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;if&nbsp;null&nbsp;object&nbsp;was&nbsp;dumped&nbsp;to&nbsp;the&nbsp;pipeline&nbsp;during&nbsp;the&nbsp;script&nbsp;then&nbsp;a&nbsp;null</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;object&nbsp;may&nbsp;be&nbsp;present&nbsp;here.&nbsp;check&nbsp;for&nbsp;null&nbsp;to&nbsp;prevent&nbsp;potential&nbsp;NRE.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(outputItem&nbsp;!=&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//TODO:&nbsp;do&nbsp;something&nbsp;with&nbsp;the&nbsp;output&nbsp;item&nbsp;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;outputItem.BaseOBject</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">The return object from <em><strong>Invoke()</strong></em> is a collection of <em><strong><a title="PSObject" href="https://msdn.microsoft.com/en-us/library/system.management.automation.psobject_members(v=vs.85).aspx">PSObject</a></strong></em> instances that were written to the output stream during execution. <em><strong>PSObject</strong></em> is a wrapper class that adds PowerShell specific functionality around whatever the base object is. Inside the <em><strong>PSObject</strong></em> is a member called <em><strong>BaseObject</strong></em>, which contains an object reference to the base type you are working with. If nothing was written to the output stream, then the collection of <em><strong>PSObjects</strong></em>&nbsp;will be empty. </span><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Besides the standard output stream, there are also dedicated streams for warnings, errors, debug, progress, and verbose logging. If any cmdlets leverage those streams, or you call them directly (<em><strong>write-error</strong></em>, <em><strong>write-debug</strong></em>, etc.), then those items will appear in the streams collections.</span><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">After invoking the script, you can check each of these stream collections to see if items were written to them.</span></p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: green;">&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;invoke&nbsp;execution&nbsp;on&nbsp;the&nbsp;pipeline&nbsp;(collecting&nbsp;output)</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Collection</span>&lt;<span style="color: #2b91af;">PSObject</span>&gt;&nbsp;PSOutput&nbsp;=&nbsp;PowerShellInstance.Invoke();<br />
 &nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;check&nbsp;the&nbsp;other&nbsp;output&nbsp;streams&nbsp;(for&nbsp;example,&nbsp;the&nbsp;error&nbsp;stream)</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(PowerShellInstance.Streams.Error.Count&nbsp;&gt;&nbsp;0)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;error&nbsp;records&nbsp;were&nbsp;written&nbsp;to&nbsp;the&nbsp;error&nbsp;stream.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;do&nbsp;something&nbsp;with&nbsp;the&nbsp;items&nbsp;found.</span>
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">In my sample script supplied above, I am writing a few manually-created objects to the output stream and calling the <em><strong>get-service</strong></em> cmdlet, which also writes its output to the stream since I didn&rsquo;t save the output in a variable.</span><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">As a test, I write the type name and <em><strong>ToString()</strong></em> on all of the base objects that came back from the sample script. As you can see, accessing the base object allows you to view or manipulate the object directly as needed. The base types that come back from execution are usually standard .NET types you may already be familiar with, just wrapped up in a <em><strong>PSObject</strong></em>.</span></p>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;loop&nbsp;through&nbsp;each&nbsp;output&nbsp;object&nbsp;item</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">PSObject</span>&nbsp;outputItem&nbsp;<span style="color: blue;">in</span>&nbsp;PSOutput)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;if&nbsp;null&nbsp;object&nbsp;was&nbsp;dumped&nbsp;to&nbsp;the&nbsp;pipeline&nbsp;during&nbsp;the&nbsp;script&nbsp;then&nbsp;a&nbsp;null</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;object&nbsp;may&nbsp;be&nbsp;present&nbsp;here.&nbsp;check&nbsp;for&nbsp;null&nbsp;to&nbsp;prevent&nbsp;potential&nbsp;NRE.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if</span>&nbsp;(outputItem&nbsp;!=&nbsp;<span style="color: blue;">null</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//TODO:&nbsp;do&nbsp;something&nbsp;with&nbsp;the&nbsp;output&nbsp;item&nbsp;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(outputItem.BaseObject.GetType().FullName);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(outputItem.BaseObject.ToString()&nbsp;+&nbsp;<span style="color: #a31515;">"\n"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<pre style="background: white; color: black; font-family: Consolas;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/2742.cmdout1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/2742.cmdout1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/2742.cmdout1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/351x270/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/2742.cmdout1.png" alt="" border="0" /></a> </pre>
<pre style="background: white; color: black; font-family: Consolas;"><strong><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Asynchronous execution:</span></strong></pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">For asynchronous execution, we call <em><strong>PowerShell.BeginInvoke()</strong></em>. <em><strong>BeginInvoke()</strong></em> immediately returns to the caller and the script execution begins in the background so you can perform other work. Unlike the synchronous <em><strong>Invoke()</strong></em> method, the return type of <em><strong>BeginInvoke()</strong></em> is not a collection of <em><strong>PSObject</strong></em> instances from the output stream. The output isn&rsquo;t ready yet. The caller is given an <em><strong>IAsyncResult</strong></em> object to monitor the status of the execution pipeline. Let&rsquo;s start with a really simple example:</span></p>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">PowerShell</span>&nbsp;PowerShellInstance&nbsp;=&nbsp;<span style="color: #2b91af;">PowerShell</span>.Create())
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;this&nbsp;script&nbsp;has&nbsp;a&nbsp;sleep&nbsp;in&nbsp;it&nbsp;to&nbsp;simulate&nbsp;a&nbsp;long&nbsp;running&nbsp;script</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PowerShellInstance.AddScript(<span style="color: #a31515;">"start-sleep&nbsp;-s&nbsp;7;&nbsp;get-service"</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;begin&nbsp;invoke&nbsp;execution&nbsp;on&nbsp;the&nbsp;pipeline</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">IAsyncResult</span>&nbsp;result&nbsp;=&nbsp;PowerShellInstance.BeginInvoke();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;do&nbsp;something&nbsp;else&nbsp;until&nbsp;execution&nbsp;has&nbsp;completed.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;this&nbsp;could&nbsp;be&nbsp;sleep/wait,&nbsp;or&nbsp;perhaps&nbsp;some&nbsp;other&nbsp;work</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">while</span>&nbsp;(result.IsCompleted&nbsp;==&nbsp;<span style="color: blue;">false</span>)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Waiting&nbsp;for&nbsp;pipeline&nbsp;to&nbsp;finish..."</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Thread</span>.Sleep(1000);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;might&nbsp;want&nbsp;to&nbsp;place&nbsp;a&nbsp;timeout&nbsp;here...</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Finished!"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;"><em><strong>Note:</strong> If you wrap the PowerShell instance in a <strong>using</strong> block like the sample above and do not wait for execution to complete, the pipeline will close itself, and will abort script execution, when it reaches the closing brace of the <strong>using</strong> block. You can avoid this by waiting for completion of the pipeline, or by removing the <strong>using</strong> block and manually calling <strong>Dispose()</strong> on the instance at a later time.</em></span><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">In this first asynchronous example, we ignored the output stream. Again, this is only useful if you don&rsquo;t care about your script results. Fortunately, the <em><strong>BeginInvoke()</strong></em> method has a few overloads that allow us to extend the functionality. Let&rsquo;s improve the example by adding output collection and event handling for data hitting the pipeline.</span><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">First, we will create a new instance of <em><strong>PSDataCollection&lt;PSObject&gt;</strong></em>. This collection is a thread-safe buffer that will store output stream objects as they hit the pipeline. Next, we will subscribe to the <em><strong>DataAdded</strong></em> event on this collection. This event will fire every time an object is written to the output stream. To use this new output buffer, pass it as a parameter to <em><strong>BeginInvoke()</strong></em>.</span><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">I added some other functionality and comments to the next code block. First, notice that you can check the <a title="state of the pipeline" href="https://msdn.microsoft.com/en-us/library/system.management.automation.psinvocationstateinfo_members(v=vs.85).aspx">state of the pipeline</a> to see its status. The <em><strong>State</strong></em> will equal <em><strong>Completed</strong></em> when your script is done. If <em><strong>State</strong></em> is <em><strong>Failed</strong></em>, it is likely caused by an unhandled exception that occurred in the script, also known as a <a title="terminating error" href="https://blogs.msdn.com/b/kebab/archive/2013/06/09/an-introduction-to-error-handling-in-powershell.aspx">terminating error</a>. Second, if your scripts utilize <em><strong>write-error</strong></em>, <em><strong>write-debug</strong></em>, <em><strong>write-progress</strong></em>, etc. (all thread-safe collections), you can review these during or after execution to check for items logged there. I have subscribed to the <em><strong>DataAdded</strong></em> event on the <em><strong>Error</strong></em> stream as well to be notified in real time.</span></p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: gray;">&nbsp;&nbsp;&nbsp;&nbsp;///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Sample&nbsp;execution&nbsp;scenario&nbsp;2:&nbsp;Asynchronous</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;remarks&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Executes&nbsp;a&nbsp;PowerShell&nbsp;script&nbsp;asynchronously&nbsp;with&nbsp;script&nbsp;output&nbsp;and&nbsp;event&nbsp;handling.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/remarks&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">void</span>&nbsp;ExecuteAsynchronously()
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">PowerShell</span>&nbsp;PowerShellInstance&nbsp;=&nbsp;<span style="color: #2b91af;">PowerShell</span>.Create())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;this&nbsp;script&nbsp;has&nbsp;a&nbsp;sleep&nbsp;in&nbsp;it&nbsp;to&nbsp;simulate&nbsp;a&nbsp;long&nbsp;running&nbsp;script</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PowerShellInstance.AddScript(<span style="color: #a31515;">"$s1&nbsp;=&nbsp;'test1';&nbsp;$s2&nbsp;=&nbsp;'test2';&nbsp;$s1;&nbsp;write-error&nbsp;'some&nbsp;error';start-sleep&nbsp;-s&nbsp;7;&nbsp;$s2"</span>);
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;prepare&nbsp;a&nbsp;new&nbsp;collection&nbsp;to&nbsp;store&nbsp;output&nbsp;stream&nbsp;objects</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">PSDataCollection</span>&lt;<span style="color: #2b91af;">PSObject</span>&gt;&nbsp;outputCollection&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;<span style="color: #2b91af;">PSDataCollection</span>&lt;<span style="color: #2b91af;">PSObject</span>&gt;();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outputCollection.DataAdded&nbsp;+=&nbsp;outputCollection_DataAdded;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;the&nbsp;streams&nbsp;(Error,&nbsp;Debug,&nbsp;Progress,&nbsp;etc)&nbsp;are&nbsp;available&nbsp;on&nbsp;the&nbsp;PowerShell&nbsp;instance.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;we&nbsp;can&nbsp;review&nbsp;them&nbsp;during&nbsp;or&nbsp;after&nbsp;execution.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;we&nbsp;can&nbsp;also&nbsp;be&nbsp;notified&nbsp;when&nbsp;a&nbsp;new&nbsp;item&nbsp;is&nbsp;written&nbsp;to&nbsp;the&nbsp;stream&nbsp;(like&nbsp;this):</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PowerShellInstance.Streams.Error.DataAdded&nbsp;+=&nbsp;Error_DataAdded;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;begin&nbsp;invoke&nbsp;execution&nbsp;on&nbsp;the&nbsp;pipeline</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;use&nbsp;this&nbsp;overload&nbsp;to&nbsp;specify&nbsp;an&nbsp;output&nbsp;stream&nbsp;buffer</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">IAsyncResult</span>&nbsp;result&nbsp;=&nbsp;PowerShellInstance.BeginInvoke&lt;<span style="color: #2b91af;">PSObject</span>,&nbsp;<span style="color: #2b91af;">PSObject</span>&gt;(<span style="color: blue;">null</span>,&nbsp;outputCollection);
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;do&nbsp;something&nbsp;else&nbsp;until&nbsp;execution&nbsp;has&nbsp;completed.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;this&nbsp;could&nbsp;be&nbsp;sleep/wait,&nbsp;or&nbsp;perhaps&nbsp;some&nbsp;other&nbsp;work</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">while</span>&nbsp;(result.IsCompleted&nbsp;==&nbsp;<span style="color: blue;">false</span>)
&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;<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Waiting&nbsp;for&nbsp;pipeline&nbsp;to&nbsp;finish..."</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Thread</span>.Sleep(1000);
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;might&nbsp;want&nbsp;to&nbsp;place&nbsp;a&nbsp;timeout&nbsp;here...</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Execution&nbsp;has&nbsp;stopped.&nbsp;The&nbsp;pipeline&nbsp;state:&nbsp;"</span>&nbsp;+&nbsp;PowerShellInstance.InvocationStateInfo.State);
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">PSObject</span>&nbsp;outputItem&nbsp;<span style="color: blue;">in</span>&nbsp;outputCollection)
&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;<span style="color: green;">//TODO:&nbsp;handle/process&nbsp;the&nbsp;output&nbsp;items&nbsp;if&nbsp;required</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(outputItem.BaseObject.ToString());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Event&nbsp;handler&nbsp;for&nbsp;when&nbsp;data&nbsp;is&nbsp;added&nbsp;to&nbsp;the&nbsp;output&nbsp;stream.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"sender"</span><span style="color: gray;">&gt;</span><span style="color: green;">Contains&nbsp;the&nbsp;complete&nbsp;PSDataCollection&nbsp;of&nbsp;all&nbsp;output&nbsp;items.</span><span style="color: gray;">&lt;/param&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"e"</span><span style="color: gray;">&gt;</span><span style="color: green;">Contains&nbsp;the&nbsp;index&nbsp;ID&nbsp;of&nbsp;the&nbsp;added&nbsp;collection&nbsp;item&nbsp;and&nbsp;the&nbsp;ID&nbsp;of&nbsp;the&nbsp;PowerShell&nbsp;instance&nbsp;this&nbsp;event&nbsp;belongs&nbsp;to.</span><span style="color: gray;">&lt;/param&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">void</span>&nbsp;outputCollection_DataAdded(<span style="color: blue;">object</span>&nbsp;sender,&nbsp;<span style="color: #2b91af;">DataAddedEventArgs</span>&nbsp;e)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;do&nbsp;something&nbsp;when&nbsp;an&nbsp;object&nbsp;is&nbsp;written&nbsp;to&nbsp;the&nbsp;output&nbsp;stream</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Object&nbsp;added&nbsp;to&nbsp;output."</span>);
&nbsp;&nbsp;&nbsp;&nbsp;}
<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Event&nbsp;handler&nbsp;for&nbsp;when&nbsp;Data&nbsp;is&nbsp;added&nbsp;to&nbsp;the&nbsp;Error&nbsp;stream.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"sender"</span><span style="color: gray;">&gt;</span><span style="color: green;">Contains&nbsp;the&nbsp;complete&nbsp;PSDataCollection&nbsp;of&nbsp;all&nbsp;error&nbsp;output&nbsp;items.</span><span style="color: gray;">&lt;/param&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;param&nbsp;name=</span><span style="color: gray;">"e"</span><span style="color: gray;">&gt;</span><span style="color: green;">Contains&nbsp;the&nbsp;index&nbsp;ID&nbsp;of&nbsp;the&nbsp;added&nbsp;collection&nbsp;item&nbsp;and&nbsp;the&nbsp;ID&nbsp;of&nbsp;the&nbsp;PowerShell&nbsp;instance&nbsp;this&nbsp;event&nbsp;belongs&nbsp;to.</span><span style="color: gray;">&lt;/param&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">void</span>&nbsp;Error_DataAdded(<span style="color: blue;">object</span>&nbsp;sender,&nbsp;<span style="color: #2b91af;">DataAddedEventArgs</span>&nbsp;e)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;do&nbsp;something&nbsp;when&nbsp;an&nbsp;error&nbsp;is&nbsp;written&nbsp;to&nbsp;the&nbsp;error&nbsp;stream</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"An&nbsp;error&nbsp;was&nbsp;written&nbsp;to&nbsp;the&nbsp;Error&nbsp;stream!"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
<pre style="background: white; color: black; font-family: Consolas;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/8507.cmdout2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/8507.cmdout2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/8507.cmdout2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/539x257/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/8507.cmdout2.png" alt="" border="0" /></a> </pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">As you can see above, the complete asynchronous model allows for some pretty interesting scenarios with long-running scripts. We can listen for events like data being added to the output stream. We can monitor the progress stream to see how much longer a task may take and provide feedback to the UI. We can listen for new errors being written to the error stream and react accordingly, instead of waiting until all execution has completed.</span></p>
<p style="background: white; color: black; font-family: Consolas;"><strong><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Execution Policy:</span></strong></p>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">When you invoke cmdlets through the PowerShell class in C#, the execution policy behavior is subject to the policy restrictions of the machine. This behavior is the same is if you opened up a PowerShell prompt on the machine. You can issue commands just fine, but invoking another script might get blocked if your execution policy is undefined or restricted in some way. An easy way to get around this is to set the execution policy for&nbsp;the scope of the application process. Simply run <em><strong>Set-ExecutionPolicy</strong></em> and specify the scope to be <em><strong>Process</strong></em>. This should allow you to invoke secondary&nbsp;scripts&nbsp;without altering the&nbsp;machine/user policies. For more information about policies and their order of precedence, <a title="see here" href="https://technet.microsoft.com/en-us/library/hh847748.aspx">see here</a>.</span></p>
<p><strong><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Shared Namespace:</span></strong><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">To wrap up our discussion, I&rsquo;d like to share a potentially useful feature that can expand some of the functionality for your scripts. When you use the PowerShell class to invoke a script, that script has access to the classes inside the caller&rsquo;s namespace, if they were declared public. </span><br /><br /><span style="font-family: arial,helvetica,sans-serif; font-size: small;">In the example code below, we make a public class with a single public property, and a public static class with a single public method. Both of these items exist in the same namespace as the PowerShell executor code. The script we execute creates a new instance of the class, sets the property, and writes it to the pipeline. The static class and method are then called directly from inside the script, saving the results to a string which is then written to the pipeline as well.</span></p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">namespace</span>&nbsp;PowerShellExecutionSample
{
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Test&nbsp;class&nbsp;object&nbsp;to&nbsp;instantiate&nbsp;from&nbsp;inside&nbsp;PowerShell&nbsp;script.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">class</span>&nbsp;<span style="color: #2b91af;">TestObject</span>
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Gets&nbsp;or&nbsp;sets&nbsp;the&nbsp;Name&nbsp;property</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">string</span>&nbsp;Name&nbsp;{&nbsp;<span style="color: blue;">get</span>;&nbsp;<span style="color: blue;">set</span>;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Test&nbsp;static&nbsp;class&nbsp;to&nbsp;invoke&nbsp;from&nbsp;inside&nbsp;PowerShell&nbsp;script.</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">class</span>&nbsp;<span style="color: #2b91af;">TestStaticClass</span>
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Sample&nbsp;static&nbsp;method&nbsp;to&nbsp;call&nbsp;from&nbsp;insider&nbsp;PowerShell&nbsp;script.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;returns&gt;</span><span style="color: green;">String&nbsp;message</span><span style="color: gray;">&lt;/returns&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">static</span>&nbsp;<span style="color: blue;">string</span>&nbsp;TestStaticMethod()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return</span>&nbsp;<span style="color: #a31515;">"Hello,&nbsp;you&nbsp;have&nbsp;called&nbsp;the&nbsp;test&nbsp;static&nbsp;method."</span>;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Provides&nbsp;PowerShell&nbsp;script&nbsp;execution&nbsp;examples</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">class</span>&nbsp;<span style="color: #2b91af;">PowerShellExecutor</span>
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Sample&nbsp;execution&nbsp;scenario&nbsp;3:&nbsp;Namespace&nbsp;test</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/summary&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;remarks&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;Executes&nbsp;a&nbsp;PowerShell&nbsp;script&nbsp;synchronously&nbsp;and&nbsp;utilizes&nbsp;classes&nbsp;in&nbsp;the&nbsp;callers&nbsp;namespace.</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: gray;">///</span><span style="color: green;">&nbsp;</span><span style="color: gray;">&lt;/remarks&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public</span>&nbsp;<span style="color: blue;">void</span>&nbsp;ExecuteSynchronouslyNamespaceTest()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">using</span>&nbsp;(<span style="color: #2b91af;">PowerShell</span>&nbsp;PowerShellInstance&nbsp;=&nbsp;<span style="color: #2b91af;">PowerShell</span>.Create())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</pre>
<pre style="background: white; color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;add&nbsp;a&nbsp;script&nbsp;that&nbsp;creates&nbsp;a&nbsp;new&nbsp;instance&nbsp;of&nbsp;an&nbsp;object&nbsp;from&nbsp;the&nbsp;caller's&nbsp;namespace</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PowerShellInstance.AddScript(<span style="color: #a31515;">"$t&nbsp;=&nbsp;new-object&nbsp;PowerShellExecutionSample.TestObject;"</span>&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;<span style="color: #a31515;">"$t.Name&nbsp;=&nbsp;'created&nbsp;from&nbsp;inside&nbsp;PowerShell&nbsp;script';&nbsp;$t;"</span>&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;<span style="color: #a31515;">"$message&nbsp;=&nbsp;[PowerShellExecutionSample.TestStaticClass]::TestStaticMethod();&nbsp;$message"</span>);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;invoke&nbsp;execution&nbsp;on&nbsp;the&nbsp;pipeline&nbsp;(collecting&nbsp;output)</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">Collection</span>&lt;<span style="color: #2b91af;">PSObject</span>&gt;&nbsp;PSOutput&nbsp;=&nbsp;PowerShellInstance.Invoke();
<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;loop&nbsp;through&nbsp;each&nbsp;output&nbsp;object&nbsp;item</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach</span>&nbsp;(<span style="color: #2b91af;">PSObject</span>&nbsp;outputItem&nbsp;<span style="color: blue;">in</span>&nbsp;PSOutput)
&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;<span style="color: blue;">if</span>&nbsp;(outputItem&nbsp;!=&nbsp;<span style="color: blue;">null</span>)
&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;<span style="color: #2b91af;">Console</span>.WriteLine(outputItem.BaseObject.GetType().FullName);
<br />&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 style="color: blue;">if</span>&nbsp;(outputItem.BaseObject&nbsp;<span style="color: blue;">is</span>&nbsp;<span style="color: #2b91af;">TestObject</span>)
&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;<span style="color: #2b91af;">TestObject</span>&nbsp;testObj&nbsp;=&nbsp;outputItem.BaseObject&nbsp;<span style="color: blue;">as</span>&nbsp;<span style="color: #2b91af;">TestObject</span>;
&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;<span style="color: #2b91af;">Console</span>.WriteLine(testObj.Name);
&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;<span style="color: blue;">else</span>
&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;<span style="color: #2b91af;">Console</span>.WriteLine(outputItem.BaseObject.ToString());
&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}&nbsp;</pre>
<pre style="background: white; color: black; font-family: Consolas;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/3286.cmdout3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/3286.cmdout3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/59/78/3286.cmdout3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/471x149/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-78/3286.cmdout3.png" alt="" border="0" /></a> </pre>
<p style="background: white; color: black; font-family: Consolas;"><span style="font-family: arial,helvetica,sans-serif; font-size: small;">As we can see from the console output, the public static class and non-static class were both available from inside the script for use. The ability to leverage public members from the caller&rsquo;s namespace allows you to create some interesting scenarios calling C# code directly from your PowerShell scripts.</span></p>]]></content:encoded>
    </item>
    <item>
      <title>Collecting Name and Integer values from enum types in PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/kebab/collecting-name-and-integer-values-from-enum-types-in-powershell</link>
      <pubDate>Sun, 09 Jun 2013 19:34:00 GMT</pubDate>
      <dc:creator><![CDATA[Keith Babinec]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kebab/2013/06/09/collecting-name-and-integer-values-from-enum-types-in-powershell/</guid>
      <description><![CDATA[Introduction:
We encounter enum types&nbsp;frequently when using PowerShell cmdlets. For anyone who...]]></description>
      <content:encoded><![CDATA[<p><strong>Introduction:</strong></p>
<p>We encounter <a href="https://msdn.microsoft.com/en-us/library/1zt1ybx4.aspx">enum types</a>&nbsp;frequently when using PowerShell cmdlets. For anyone who isn&rsquo;t familiar, an <strong><em>enum </em></strong>is an <span style="text-decoration: underline;">enumeration of named constants</span>; essentially, a static list of options or choices. A good example of this is when you run <strong><em>Get-VM</em></strong> in Hyper-V to examine a Virtual Machine. The <strong><em>State</em></strong> property of the Virtual Machine object displays whether the VM is <strong><em>Running</em></strong>, <strong><em>Stopped</em></strong>, <strong><em>Saved</em></strong>, etc.</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; $virtualmachine = get-vm -ComputerName TestServer -name TestVM</li>
<li>PS C:\&gt; $virtualmachine | fl Name, State</li>
<li>&nbsp;</li>
<li>Name&nbsp;&nbsp;: TestVM</li>
<li>State : Running</li>
</ol></div>
</div>
<p><strong><em><br /></em></strong>Instead of storing this data in a text/string field, this object is stored as an <span style="text-decoration: underline;">enum</span> type. This means there are limited and defined possible choices this value can be &ndash; and it will never fall outside of these possible values. This becomes really helpful in scripts for the consumer of the cmdlet to make logic decisions based on the value (such as the leveraging the&nbsp;<strong><em>switch</em></strong> statement).</p>
<p><strong>How do we know the property is an enum type?</strong></p>
<p>Utilize the <strong><em>GetType()</em></strong> method found on any object inside PowerShell (or, the .NET Framework). In the example below we have run <strong><em>GetType() </em></strong>against both the <strong><em>Name</em></strong> and <strong><em>State</em></strong> properties of the VM object. As seen in the output the base type for <strong><em>State</em></strong> is <strong><em>System.Enum</em></strong>. This means we have an enum type.</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; $virtualmachine.Name.GetType()</li>
<li>&nbsp;</li>
<li>IsPublic IsSerial Name&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;BaseType</li>
<li>-------- -------- ----&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;--------</li>
<li>True&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;True&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&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;System.Object</li>
<li>&nbsp;</li>
<li>PS C:\&gt; $virtualmachine.State.GetType()</li>
<li>&nbsp;</li>
<li>IsPublic IsSerial Name&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;BaseType</li>
<li>-------- -------- ----&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;--------</li>
<li>True&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;True&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VMState&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;<span style="background-color: #ffff00;">System.Enum</span></li>
</ol></div>
</div>
<p><strong><br />How do we find the other possible enumeration values?</strong></p>
<p>If the VM is currently in <strong><em>Running</em></strong> state, what other possible states exist? This is a very common question that arises when working with enums. The answer is usually found in the cmdlet documentation, but this is not always the case. Follow these steps to retrieve the answer on your own:</p>
<p>First, locate the full name of the enumeration type. Extract the <strong><em>FullName </em></strong>property from the enum, as depicted below.</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; $virtualmachine.State.GetType().FullName</li>
<li>Microsoft.HyperV.PowerShell.VMState</li>
</ol></div>
</div>
<p><strong><em><br /></em></strong>Second, call the <strong><em>GetValues()</em></strong> static method on the <strong><em>enum </em></strong>type. Be sure to enclose the full type name inside square brackets. Example with desired output is below.</p>
<p>Note 1: If you attempt to use <strong><em>GetValues()</em></strong> on the partial type name (<strong><em>VMState</em></strong>) instead of the full type name (<strong><em>Microsoft.HyperV.PowerShell.VMState</em></strong>), PowerShell is likely going to complain that it can&rsquo;t find the type. Ensure you use the full type name.</p>
<p>Note 2: A newer PSv3 only method to accomplish this same task is to call <strong><em>[Microsoft.HyperV.PowerShell.VMState].GetEnumValues(). </em></strong></p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; [enum]::GetValues([Microsoft.HyperV.PowerShell.VMState])</li>
<li>Other</li>
<li>Running</li>
<li>Off</li>
<li>Stopping</li>
<li>Saved</li>
<li>Paused</li>
<li>Starting</li>
<li>Reset</li>
<li>Saving</li>
<li>Pausing</li>
<li>Resuming</li>
<li>RunningCritical</li>
<li>OffCritical</li>
<li>StoppingCritical</li>
<li>SavedCritical</li>
<li>PausedCritical</li>
<li>StartingCritical</li>
<li>ResetCritical</li>
<li>SavingCritical</li>
<li>PausingCritical</li>
<li>ResumingCritical</li>
</ol></div>
</div>
<p><strong><em><br /></em></strong><strong>Capturing enumeration Integer values:</strong></p>
<p>To take it one step further, you can also find the associated integer values of the enumeration. This can be useful in certain programming scenarios.</p>
<p>Here is a one-liner to accomplish that. All we do is cast the enumeration value to <strong><em>int</em></strong> and print it to the screen along with the text value.</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; foreach ($v in [enum]::GetValues([Microsoft.HyperV.PowerShell.VMState])) { write-host ([int]$v): $v }</li>
<li>1 : Other</li>
<li>2 : Running</li>
<li>3 : Off</li>
<li>4 : Stopping</li>
<li>6 : Saved</li>
<li>9 : Paused</li>
<li>10 : Starting</li>
<li>11 : Reset</li>
<li>32773 : Saving</li>
<li>32776 : Pausing</li>
<li>32777 : Resuming</li>
<li>32778 : RunningCritical</li>
<li>32779 : OffCritical</li>
<li>32780 : StoppingCritical</li>
<li>32781 : SavedCritical</li>
<li>32782 : PausedCritical</li>
<li>32783 : StartingCritical</li>
<li>32784 : ResetCritical</li>
<li>32785 : SavingCritical</li>
<li>32786 : PausingCritical</li>
<li>32787 : ResumingCritical</li>
</ol></div>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>An Introduction to Error Handling in PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/kebab/an-introduction-to-error-handling-in-powershell</link>
      <pubDate>Sun, 09 Jun 2013 18:14:00 GMT</pubDate>
      <dc:creator><![CDATA[Keith Babinec]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/kebab/2013/06/09/an-introduction-to-error-handling-in-powershell/</guid>
      <description><![CDATA[Today&rsquo;s post (and this blog's inaugural post!) is An Introduction to Error Handling in...]]></description>
      <content:encoded><![CDATA[<p>Today&rsquo;s post (and this blog's inaugural post!) is <span style="text-decoration: underline;">An Introduction to Error Handling in PowerShell</span>. We will discuss error types, the <em><strong>$error</strong></em> variable, error action preferences, try/catch blocks, and <em><strong>$lastexitcode</strong></em>.</p>
<p>The first requirement is to understand the types of errors that can occur during execution.</p>
<p><strong>Terminating vs. Non-Terminating Errors:</strong></p>
<ul>
<li><strong>Terminating Error</strong>: A serious error during execution that halts the command (or script execution) completely. Examples can include non-existent cmdlets, syntax errors that would prevent a cmdlet from running, or other fatal errors.</li>
<li><strong>Non-Terminating Error</strong>: A non-serious error that allows execution to continue despite the failure. Examples include operational errors such file not found, permissions problems, etc.</li>
</ul>
<p><strong><em>Update 12/13/2013:</em></strong> <em>Writing a cmdlet? For further information regarding how a cmdlet should determine when to throw a terminating error or non-terminating error, MSDN has a nice&nbsp;<a title="explanation here" href="https://msdn.microsoft.com/en-us/library/ms714414(v=vs.85).aspx">explanation&nbsp;here</a>.</em></p>
<p><em><strong>Update 12/13/2013</strong>: Want to know if an error you encountered is terminating or non-terminating? Check to see if&nbsp;the error behavior&nbsp;is affected by changing the&nbsp;$ErrorActionPreference. According to the MSDN <a title="documentation here" href="https://technet.microsoft.com/en-us/library/hh847796.aspx">documentation here</a>, "Neither $ErrorActionPreference nor the ErrorAction common parameter affect how Windows PowerShell responds to terminating errors (those that stop cmdlet processing).". </em></p>
<p>&nbsp;</p>
<p><strong>The $error variable:</strong></p>
<p>When either type of error occurs during execution, it is logged to a global variable called <strong><em>$error</em></strong>. This variable is a collection of PowerShell Error Objects with the most recent error at index 0. On a freshly initialized PowerShell instance (no errors have occurred yet) the <strong><em>$error </em></strong>variable is ready and waiting as an empty collection:&nbsp;</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto; max-height: 300px;"><ol style="background: #ffffff; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; $error.GetType()</li>
<li>&nbsp;</li>
<li>IsPublic IsSerial Name&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;BaseType</li>
<li>-------- -------- ----&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;--------</li>
<li>True&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;True&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ArrayList&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;System.Object</li>
<li>&nbsp;</li>
<li>PS C:\&gt; $error.Count</li>
<li>0</li>
</ol></div>
</div>
<p>&nbsp;<br />In the next snippet I have executed a cmdlet that doesn&rsquo;t exist, throwing an error. If we grab the count on <strong><em>$error</em></strong>, you will notice it has increased to one item. Dumping that object to the pipeline by accessing <strong><em>$error[0] </em></strong>just prints the error we already saw, right back at us.</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; ThisCmdlet-DoesNotExist</li>
<li><span style="color: #ff0000;">The term 'ThisCmdlet-DoesNotExist' is not recognized as the name of a cmdlet, f</span></li>
<li><span style="color: #ff0000;">unction, script file, or operable program. Check the spelling of the name, or i</span></li>
<li><span style="color: #ff0000;">f a path was included, verify that the path is correct and try again.</span></li>
<li><span style="color: #ff0000;">At line:1 char:24</span></li>
<li><span style="color: #ff0000;">+ ThisCmdlet-DoesNotExist &lt;&lt;&lt;&lt;</span></li>
<li><span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;+ CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: ObjectNotFound: (ThisCmdlet-DoesNotExist:String)</span></li>
<li><span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;[], CommandNotFoundException</span></li>
<li><span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;+ FullyQualifiedErrorId : CommandNotFoundException</span></li>
<li>&nbsp;</li>
<li>PS C:\&gt; $error.Count</li>
<li>1</li>
<li>PS C:\&gt; $error[0]</li>
<li>The term 'ThisCmdlet-DoesNotExist' is not recognized as the name of a cmdlet, f</li>
<li>unction, script file, or operable program. Check the spelling of the name, or i</li>
<li>f a path was included, verify that the path is correct and try again.</li>
<li>At line:1 char:24</li>
<li>+ ThisCmdlet-DoesNotExist &lt;&lt;&lt;&lt;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;+ CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: ObjectNotFound: (ThisCmdlet-DoesNotExist:String)</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;[], CommandNotFoundException</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;+ FullyQualifiedErrorId : CommandNotFoundException</li>
</ol></div>
</div>
<p>&nbsp;<br />There is more available to us than just what is immediately visible. The ErrorRecord is a rich object that contains many useful properties to explore. Try piping the error to <strong><em>get-member</em></strong> (aliased by <strong><em>gm</em></strong>) to see what options we have available to us:</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; $error[0] | gm</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;TypeName: System.Management.Automation.ErrorRecord</li>
<li>&nbsp;</li>
<li>Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MemberType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Definition</li>
<li>----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;----------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;----------</li>
<li>Equals&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool Equals(System.Object obj)</li>
<li>GetHashCode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int GetHashCode()</li>
<li>GetObjectData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Void GetObjectData(System.Runtim...</li>
<li>GetType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type GetType()</li>
<li>ToString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string ToString()</li>
<li>CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Management.Automation.ErrorCateg...</li>
<li>ErrorDetails&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Management.Automation.ErrorDetai...</li>
<li>Exception&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Exception Exception {get;}</li>
<li>FullyQualifiedErrorId Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.String FullyQualifiedErrorId {get;}</li>
<li>InvocationInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Management.Automation.Invocation...</li>
<li>PipelineIterationInfo Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Collections.ObjectModel.ReadOnly...</li>
<li>TargetObject&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Object TargetObject {get;}</li>
<li>PSMessageDetails&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScriptProperty System.Object PSMessageDetails {get=&amp; {...</li>
</ol></div>
</div>
<p><br />For details on what each property member provides, visit <a href="https://msdn.microsoft.com/en-us/library/system.management.automation.errorrecord_members(v=vs.85).aspx">the ErrorRecord MSDN documentation</a>. A couple important highlights:</p>
<ul>
<li><strong><em>$error[0].InvocationInfo</em></strong> provides details about the context which the command was executed, if available.</li>
<li><strong><em>$error[0].Exception</em></strong> contains the original exception object as it was thrown to PowerShell. If we explore that object (also piped to get-member) we can see important items to pull up like stack trace, source, HResult, InnerException, etc.</li>
</ul>
<p>Diving into the exception object itself (<strong><em>$error[0].Exception</em></strong>) can provide very important diagnostic details not immediately visible on the top level error record. This is especially useful in troubleshooting third party cmdlets!</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; $error[0].Exception</li>
<li>The term 'ThisCmdlet-DoesNotExist' is not recognized as the name of a cmdlet, f</li>
<li>unction, script file, or operable program. Check the spelling of the name, or i</li>
<li>f a path was included, verify that the path is correct and try again.</li>
<li>&nbsp;</li>
<li>PS C:\&gt; $error[0].Exception | gm</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;TypeName: System.Management.Automation.CommandNotFoundException</li>
<li>&nbsp;</li>
<li>Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MemberType Definition</li>
<li>----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;---------- ----------</li>
<li>Equals&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool Equals(System.Object obj)</li>
<li>GetBaseException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Exception GetBaseException()</li>
<li>GetHashCode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int GetHashCode()</li>
<li>GetObjectData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Void GetObjectData(System.Runt...</li>
<li>GetType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type GetType()</li>
<li>ToString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string ToString()</li>
<li>CommandName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.String CommandName {get;set;}</li>
<li>Data&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.Collections.IDictionary Data {...</li>
<li>ErrorRecord&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.Management.Automation.ErrorRec...</li>
<li>HelpLink&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.String HelpLink {get;set;}</li>
<li>InnerException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.Exception InnerException {get;}</li>
<li>Message&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.String Message {get;}</li>
<li>Source&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.String Source {get;set;}</li>
<li>StackTrace&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.String StackTrace {get;}</li>
<li>TargetSite&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Property&nbsp;&nbsp;&nbsp;System.Reflection.MethodBase TargetSi...</li>
<li>WasThrownFromThrowStatement Property&nbsp;&nbsp;&nbsp;System.Boolean WasThrownFromThrowStat...</li>
<li>&nbsp;</li>
<li>PS C:\&gt; $error[0].Exception.StackTrace</li>
<li>&nbsp;&nbsp;&nbsp;at System.Management.Automation.CommandDiscovery.LookupCommandInfo(String co</li>
<li>mmandName, CommandOrigin commandOrigin)</li>
<li>&nbsp;&nbsp;&nbsp;at System.Management.Automation.CommandDiscovery.LookupCommandProcessor(Stri</li>
<li>ng commandName, CommandOrigin commandOrigin, Nullable`1 useLocalScope)</li>
<li>&nbsp;&nbsp;&nbsp;at System.Management.Automation.ExecutionContext.CreateCommand(String comman</li>
<li>d)</li>
<li>&nbsp;&nbsp;&nbsp;at System.Management.Automation.CommandNode.CreateCommandProcessor(Int32&amp; in</li>
<li>dex, ExecutionContext context)</li>
<li>&nbsp;&nbsp;&nbsp;at System.Management.Automation.CommandNode.AddToPipeline(PipelineProcessor</li>
<li>pipeline, ExecutionContext context)</li>
<li>&nbsp;&nbsp;&nbsp;at System.Management.Automation.PipelineNode.Execute(Array input, Pipe outpu</li>
<li>tPipe, ArrayList&amp; resultList, ExecutionContext context)</li>
<li>&nbsp;&nbsp;&nbsp;at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTree</li>
<li>Node statement, Array input, Pipe outputPipe, ArrayList&amp; resultList, ExecutionC</li>
<li>ontext context)</li>
</ol></div>
</div>
<p><strong><br />Error Action Preference: </strong></p>
<p>PowerShell halts execution on terminating errors, as mentioned before. For non-terminating errors we have the option to tell PowerShell how to handle these situations. This is where the error action preference comes in. Error Action Preference allows us to specify the desired behavior for a non-terminating error; it can be scoped at the command level or all the way up to the script level.</p>
<p>Available choices for error action preference:</p>
<ul>
<li><strong><em>SilentlyContinue</em></strong> &ndash; error messages are suppressed and execution continues.</li>
<li><strong><em>Stop</em></strong> &ndash; forces execution to stop, behaving like a terminating error.</li>
<li><strong><em>Continue</em></strong> - the default option. Errors will display and execution will continue.</li>
<li><strong><em>Inquire</em></strong> &ndash; prompt the user for input to see if we should proceed.</li>
<li><strong><em>Ignore</em></strong> &ndash; (new in v3) &ndash; the error is ignored and not logged to the error stream. Has very restricted usage scenarios.</li>
</ul>
<p>Example: Set the preference at the script scope to <strong><em>Stop</em></strong>, place the following near the top of the script file:</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 5px;" start="1">
<li>$ErrorActionPreference = "Stop"</li>
</ol></div>
</div>
<p><br />Example: Set the preference at the cmdlet level to <strong><em>Inquire</em></strong>, add error action switch (or alias <strong><em>EA</em></strong>):&nbsp;</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 5px;" start="1">
<li>get-childitem "G:\FakeFolder" -ErrorAction "Inquire"</li>
<li>get-childitem "G:\FakeFolder" -ea "Inquire"</li>
</ol></div>
</div>
<p><strong><br />Try/Catch/Finally Blocks:</strong></p>
<p>The <strong><em>Try</em></strong>, <strong><em>Catch</em></strong>, and <strong><em>Finally </em></strong>statements allow us to control script flow when we encounter errors. The statements behave similar to the statements of the same name found in C# and other languages.</p>
<p>The&nbsp;behavior of try/catch is to catch terminating errors (exceptions). This means Non-terminating (operational) errors inside a try block will not trigger a <strong><em>Catch*</em></strong>. If you would like to catch all possible errors (terminating and non-terminating) &ndash; then simply set the error action preference to <strong><em>Stop</em></strong>. Remember that <strong><em>Stop</em></strong> error action forces a non-terminating error to behave like a terminating error, which means it can then be trapped in a catch block. Here is an example:</p>
<p><em><strong>*Update 12/13/2013</strong>: In&nbsp;almost all cases, non-terminating errors will not trigger a catch. However I did&nbsp;recently observe&nbsp;a situation where a non-terminating error did trigger a catch block. It wasn't from a cmdlet, but an exception generated from directly calling a method on a .net object. So keep&nbsp;in mind that behavior might be possible.</em></p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>try</li>
<li>{</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;#</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Add dangerous code here that might produce exceptions.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Place as many code statements as needed here.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Non-terminating errors must have error action preference set to Stop to be caught.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;#&gt;</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;write-host "Attempting dangerous operation"</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;$content = get-content -Path "C:\SomeFolder\This_File_Might_Not_Exist.txt" -ErrorAction Stop</li>
<li>}</li>
<li>catch</li>
<li>{</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;#</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;You can have multiple catch blocks (for different exceptions), or one single catch.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The last error record is available inside the catch block under the $_ variable.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Code inside this block is used for error handling. Examples include logging an error,</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sending an email, writing to the event log, performing a recovery action, etc.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;In this example I'm just printing the exception type and message to the screen.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;#&gt;</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;write-host "Caught an exception:" -ForegroundColor Red</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;write-host "Exception Type: $($_.Exception.GetType().FullName)" -ForegroundColor Red</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;write-host "Exception Message: $($_.Exception.Message)" -ForegroundColor Red</li>
<li>}</li>
<li>finally</li>
<li>{</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;#</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Any statements in this block will always run even if errors are caught.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This statement block is optional. Normally used for cleanup and</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;releasing resources that must happen even under error situations.</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;#&gt;</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;write-host "Finally block reached"</li>
<li>}</li>
</ol></div>
</div>
<p>&nbsp;<br />You can also have <strong><em>Catch</em></strong> blocks that will only trap specific exceptions. The reason for doing this is so you can add different handlers for each possible failure condition that you may encounter. Some exceptions you may just want to log and exit, but others you may have a recovery action for. Here is a <strong><em>Catch</em></strong> statement that would trap a specific Exception type. The Exception type is displayed in brackets after the catch statement:</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 5px;" start="1">
<li>catch [System.Management.Automation.ItemNotFoundException]</li>
<li>{</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# catching specific exceptions allows you to have</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;# custom actions for different types of errors</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;write-host "Caught an ItemNotFoundException" -ForegroundColor Red</li>
<li>}</li>
</ol></div>
</div>
<p>&nbsp;<br />You might be wondering how I found the type name for the previous exception. The possible exceptions for cmdlets are not usually documented, so you may need to find them on your own. When an exception occurs you can look up the error in the <strong><em>$error </em></strong>collection, or while inside a catch block under the <strong><em>$_ </em></strong>variable. Call the <strong><em>GetType()</em></strong> method on the base exception to extract the <strong><em>FullName </em></strong>property. Like shown here:</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; $error[0].Exception.GetType().FullName</li>
<li>System.Management.Automation.ItemNotFoundException</li>
</ol></div>
</div>
<p><strong><br />Handling Errors from non-PowerShell processes:</strong></p>
<p>What happens when your script needs to run an external process from PowerShell and you want to know if it succeeded? An example would be a cmdline tool such as robocopy.exe. It&rsquo;s an external application that returns an exit code upon completion. But since it is an external process, its errors will not be caught in your <strong><em>try</em></strong>/<strong><em>catch</em></strong> blocks.</p>
<p>To trap this exit code utilize the <strong><em>$LastExitCode</em></strong> PowerShell variable.</p>
<p>When the launched process exits, PowerShell will write the exit code directly to <strong><em>$LastExitCode</em></strong>. In most cases an exit code of 0 means success, and 1 or greater indicates a failure. Check the external tool's documentation to verify of course.</p>
<p>Here it is seen in action:</p>
<div style="border: 1px solid #000080; color: #000000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background: #dddddd; overflow: auto;"><ol style="background: #ffffff; margin: 0px 0px 0px 2.5em; padding: 0px 0px 0px 5px;" start="1">
<li>PS C:\&gt; robocopy.exe "C:\DirectoryDoesNotExist" "C:\NewDestination" "*.*" /R:0</li>
<li>&nbsp;</li>
<li>-------------------------------------------------------------------------------</li>
<li>&nbsp;&nbsp;&nbsp;ROBOCOPY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;::&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Robust File Copy for Windows</li>
<li>&nbsp;</li>
<li>-------------------------------------------------------------------------------</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;Started : Sun Jun 09 18:42:09 2013</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;Source : C:\DirectoryDoesNotExist\\par&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dest : C:\NewDestination\\par</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;Files : *.*</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;Options : *.* /COPY:DAT /R:0 /W:30</li>
<li>&nbsp;</li>
<li>------------------------------------------------------------------------------</li>
<li>&nbsp;</li>
<li>2013/06/09 18:42:09 ERROR 2 (0x00000002) Accessing Source Directory C:\Directory</li>
<li>DoesNotExist\\par The system cannot find the file specified.</li>
<li>PS C:\&gt; $lastexitcode</li>
<li>16</li>
</ol></div>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
  </channel>
</rss>