powershell_blog.xml
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Windows PowerShell Blog</title><link>http://blogs.msdn.com/b/powershell/</link><description>Automating the world one-liner at a time...</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>WMI cheat sheet for PS users</title><link>http://blogs.msdn.com/b/powershell/archive/2012/10/28/wmi-cheat-sheet-for-ps-users.aspx</link><pubDate>Sun, 28 Oct 2012 21:10:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10363470</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10363470</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/10/28/wmi-cheat-sheet-for-ps-users.aspx#comments</comments><description><p>Hi,</p> <p>We got multiple requests to publish the cheat sheet for CIM Cmdlets that was distributed in Tech Ed NA&nbsp;this year. Responding to popular demand, this document is attached as PDF . This is a great resource put together by WMI team for people who want to get started with CIM cmdlets.</p> <p>Standard disclaimer :-). Cheat sheet is just for a quick start to get people started&nbsp;- real documentation is here <a href="http://technet.microsoft.com/en-us/library/jj553783.aspx">http://technet.microsoft.com/en-us/library/jj553783.aspx</a>.</p> <p>&nbsp;</p> <p>Thanks</p> <p>Osama Sajid</p> <p>Program Manager</p> <p>&nbsp;</p> <p>&nbsp;</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10363470" width="1" height="1"></description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-36-34-70/WMI-CheatSheet-for-PS.pdf" length="289863" type="application/pdf" /><category domain="http://blogs.msdn.com/b/powershell/archive/tags/WMI/">WMI</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/CIM/">CIM</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/CimCmdlets/">CimCmdlets</category></item><item><title>Joining Multiple Tables, Grouping and Evaluating Totals</title><link>http://blogs.msdn.com/b/powershell/archive/2012/10/04/joining-multiple-tables-grouping-and-evaluating-totals.aspx</link><pubDate>Thu, 04 Oct 2012 00:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10355722</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10355722</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/10/04/joining-multiple-tables-grouping-and-evaluating-totals.aspx#comments</comments><description><div class="WordSection1"> <p class="MsoNormal"><b>Joining Multiple Tables, Grouping And Evaluating Totals</b></p> <p class="MsoNormal">This is a continuation to the <a href="http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx">Join-Object</a> blog post considering multiple joins and SQL style grouping and total evaluation.</p> <p class="MsoNormal"><b>Problem:</b></p> <p class="MsoNormal">In the <a href="http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx">Join-Object</a> blog we&rsquo;ve seen that relational data naturally organizes in multiple tables.&nbsp;Once we have those tables, we frequently want to see&nbsp;the information back together, so we need something like <a href="http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx">Join-Object</a>. Sometimes we also need to group the information and evaluate totals inside the groups. For instance, what are the total sales for each customer?</p> <p class="MsoNormal">How can we use <a href="http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx">Join-Object</a><span class="MsoHyperlink"> </span>in multiple tables and group information from the tables to report totals?</p> <p class="MsoNormal"><b>Joining multiple tables:</b></p> <p class="MsoNormal">Consider the following tables describing sales at a fruit stand:</p> <div align="center"> <table class="MsoTableGrid" style="border: currentColor; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td width="271" valign="top" style="padding: 0in 5.4pt; width: 203.4pt;" colspan="3"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: normal;"><b>Customers</b></p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Id</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Name</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Phone</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">1</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">John Smith</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">(206)555-8899</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">2</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Mark Stone</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">(425)999-8811</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">3</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Ruth Moore</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">(425)888-3355</p> </td> </tr> </tbody> </table> </div> <p class="MsoNormal">&nbsp;</p> <div align="center"> <table class="MsoTableGrid" style="border: currentColor; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td width="271" valign="top" style="padding: 0in 5.4pt; width: 203.4pt;" colspan="3"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;"><b>Products</b></p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Id</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Name</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Price</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">1</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Apple</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">10</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">2</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Orange</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">12</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">3</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Kiwi</p> </td> <td width="114" valign="top" style="padding: 0in 5.4pt; width: 85.5pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">15</p> </td> </tr> </tbody> </table> </div> <p class="MsoNormal"><span style="line-height: 115%; font-size: 7pt;">&nbsp;</span></p> <table align="center" class="MsoTableGrid" style="border: currentColor; margin-right: 6.75pt; margin-left: 6.75pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td width="319" valign="top" style="padding: 0in 5.4pt; width: 239.4pt;" colspan="3"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;"><b>Orders</b></p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Id</p> </td> <td width="174" valign="top" style="padding: 0in 5.4pt; width: 130.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Date</p> </td> <td width="102" valign="top" style="padding: 0in 5.4pt; width: 76.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">CustomerId</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">1</p> </td> <td width="174" valign="top" style="padding: 0in 5.4pt; width: 130.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/6/2012 9:12:44 AM</p> </td> <td width="102" valign="top" style="padding: 0in 5.4pt; width: 76.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">1</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">2</p> </td> <td width="174" valign="top" style="padding: 0in 5.4pt; width: 130.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/7/2012 6:12:10 PM</p> </td> <td width="102" valign="top" style="padding: 0in 5.4pt; width: 76.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">1</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">3</p> </td> <td width="174" valign="top" style="padding: 0in 5.4pt; width: 130.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/5/2012 12:05:03 PM</p> </td> <td width="102" valign="top" style="padding: 0in 5.4pt; width: 76.5pt; text-align: center;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">2</p> </td> </tr> </tbody> </table> <p class="MsoNormal">&nbsp;</p> <table align="center" class="MsoTableGrid" style="border: currentColor; margin-right: 6.75pt; margin-left: 6.75pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td width="259" valign="top" style="padding: 0in 5.4pt; width: 2.7in;" colspan="4"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;"><b>OrderItems</b></p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p align="center" class="MsoNormal" style="text-align: center; line-height: 115%; margin-bottom: 10pt;">Id</p> </td> <td width="72" valign="top" style="padding: 0in 5.4pt; width: 0.75in;"> <p align="center" class="MsoNormal" style="text-align: center; line-height: 115%; margin-bottom: 10pt;">Quantity</p> </td> <td width="78" valign="top" style="padding: 0in 5.4pt; width: 58.5pt;"> <p align="center" class="MsoNormal" style="text-align: center; line-height: 115%; margin-bottom: 10pt;">ProductId</p> </td> <td width="66" valign="top" style="padding: 0in 5.4pt; width: 49.5pt;"> <p align="center" class="MsoNormal" style="text-align: center; line-height: 115%; margin-bottom: 10pt;">OrderId</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> <td width="72" valign="top" style="padding: 0in 5.4pt; width: 0.75in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">2</p> </td> <td width="78" valign="top" style="padding: 0in 5.4pt; width: 58.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">3</p> </td> <td width="66" valign="top" style="padding: 0in 5.4pt; width: 49.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">2</p> </td> <td width="72" valign="top" style="padding: 0in 5.4pt; width: 0.75in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> <td width="78" valign="top" style="padding: 0in 5.4pt; width: 58.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">2</p> </td> <td width="66" valign="top" style="padding: 0in 5.4pt; width: 49.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">3</p> </td> <td width="72" valign="top" style="padding: 0in 5.4pt; width: 0.75in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">4</p> </td> <td width="78" valign="top" style="padding: 0in 5.4pt; width: 58.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">5</p> </td> <td width="66" valign="top" style="padding: 0in 5.4pt; width: 49.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">4</p> </td> <td width="72" valign="top" style="padding: 0in 5.4pt; width: 0.75in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">5</p> </td> <td width="78" valign="top" style="padding: 0in 5.4pt; width: 58.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> <td width="66" valign="top" style="padding: 0in 5.4pt; width: 49.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">2</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">5</p> </td> <td width="72" valign="top" style="padding: 0in 5.4pt; width: 0.75in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">4</p> </td> <td width="78" valign="top" style="padding: 0in 5.4pt; width: 58.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">2</p> </td> <td width="66" valign="top" style="padding: 0in 5.4pt; width: 49.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">2</p> </td> </tr> <tr> <td width="43" valign="top" style="padding: 0in 5.4pt; width: 0.45in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">6</p> </td> <td width="72" valign="top" style="padding: 0in 5.4pt; width: 0.75in;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> <td width="78" valign="top" style="padding: 0in 5.4pt; width: 58.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">1</p> </td> <td width="66" valign="top" style="padding: 0in 5.4pt; width: 49.5pt;"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;">3</p> </td> </tr> </tbody> </table> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal">As we saw in the <a href="http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx">Join-Object</a> blog, we need this many tables to deal with the simple conceptual problem of selling fruit!</p> <p class="MsoNormal" style="text-align: justify;">One might question the need for the OrderItems table. An order item is a line in the receipt for an order that lists a product and its quantity. Since there can be many items per order, it needs its own table as mentioned in the <a href="http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx">Join-Object</a> blog.</p> <p class="MsoNormal" style="text-align: justify;">As we can see from the data, we have 3 customers, 3 products, 3 orders, and 6 order items. The three first order items are for the Order with Id 1.</p> <p class="MsoNormal" style="text-align: justify;">Good data design forces us to split the tables, but after this is done, we frequently need to see the data together.</p> <p class="MsoNormal" style="text-align: justify;">For example, suppose I want a report with all basic receipt information, including customer name, order date, all products bought, their quantity, and price. Here is the SQL statement that produces the report:</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">SELECT&nbsp;&nbsp;&nbsp;&nbsp; Customer.Name, [Order].Date, OrderItem.Quantity,</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Product.Name AS [Product Name], Product.Price</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">FROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OrderItem INNER JOIN Product ON OrderItem.ProductId = Product.id INNER JOIN</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Customer INNER JOIN&nbsp; [Order] ON Customer.id = [Order].CustomerId ON OrderItem.OrderId = [Order].id</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">&nbsp;</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">Here is the result:</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">&nbsp;</p> <div align="center"> <table class="MsoTableGrid" style="border: currentColor; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td width="559" valign="top" style="padding: 0in 5.4pt; width: 419.4pt;" colspan="5"> <p align="center" class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: center; line-height: 115%;"><b>Joining All Tables</b></p> </td> </tr> <tr> <td width="115" valign="top" style="padding: 0in 5.4pt; width: 1.2in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Name</p> </td> <td width="156" valign="top" style="padding: 0in 5.4pt; width: 117pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Date</p> </td> <td width="112" valign="top" style="padding: 0in 5.4pt; width: 83.85pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Quantity</p> </td> <td width="128" valign="top" style="padding: 0in 5.4pt; width: 95.75pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Product Name</p> </td> <td width="49" valign="top" style="padding: 0in 5.4pt; width: 36.4pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Price</p> </td> </tr> <tr> <td width="115" valign="top" style="padding: 0in 5.4pt; width: 1.2in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">John Smith</p> </td> <td width="156" valign="top" style="padding: 0in 5.4pt; width: 117pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/6/2012 9:12:44 AM</p> </td> <td width="112" valign="top" style="padding: 0in 5.4pt; width: 83.85pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">2</p> </td> <td width="128" valign="top" style="padding: 0in 5.4pt; width: 95.75pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Apple</p> </td> <td width="49" valign="top" style="padding: 0in 5.4pt; width: 36.4pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">10</p> </td> </tr> <tr> <td width="115" valign="top" style="padding: 0in 5.4pt; width: 1.2in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">John Smith</p> </td> <td width="156" valign="top" style="padding: 0in 5.4pt; width: 117pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/6/2012 9:12:44 AM</p> </td> <td width="112" valign="top" style="padding: 0in 5.4pt; width: 83.85pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">1</p> </td> <td width="128" valign="top" style="padding: 0in 5.4pt; width: 95.75pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Orange</p> </td> <td width="49" valign="top" style="padding: 0in 5.4pt; width: 36.4pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">12</p> </td> </tr> <tr> <td width="115" valign="top" style="padding: 0in 5.4pt; width: 1.2in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">John Smith</p> </td> <td width="156" valign="top" style="padding: 0in 5.4pt; width: 117pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/6/2012 9:12:44 AM</p> </td> <td width="112" valign="top" style="padding: 0in 5.4pt; width: 83.85pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">4</p> </td> <td width="128" valign="top" style="padding: 0in 5.4pt; width: 95.75pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Kiwi</p> </td> <td width="49" valign="top" style="padding: 0in 5.4pt; width: 36.4pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">5</p> </td> </tr> <tr> <td width="115" valign="top" style="padding: 0in 5.4pt; width: 1.2in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">John Smith</p> </td> <td width="156" valign="top" style="padding: 0in 5.4pt; width: 117pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/7/2012 6:12:10 PM</p> </td> <td width="112" valign="top" style="padding: 0in 5.4pt; width: 83.85pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">5</p> </td> <td width="128" valign="top" style="padding: 0in 5.4pt; width: 95.75pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Apple</p> </td> <td width="49" valign="top" style="padding: 0in 5.4pt; width: 36.4pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">10</p> </td> </tr> <tr> <td width="115" valign="top" style="padding: 0in 5.4pt; width: 1.2in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">John Smith</p> </td> <td width="156" valign="top" style="padding: 0in 5.4pt; width: 117pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/7/2012 6:12:10 PM</p> </td> <td width="112" valign="top" style="padding: 0in 5.4pt; width: 83.85pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">4</p> </td> <td width="128" valign="top" style="padding: 0in 5.4pt; width: 95.75pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Orange</p> </td> <td width="49" valign="top" style="padding: 0in 5.4pt; width: 36.4pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">12</p> </td> </tr> <tr> <td width="115" valign="top" style="padding: 0in 5.4pt; width: 1.2in;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Mark Stone</p> </td> <td width="156" valign="top" style="padding: 0in 5.4pt; width: 117pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">6/5/2012 12:00:00 AM</p> </td> <td width="112" valign="top" style="padding: 0in 5.4pt; width: 83.85pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">1</p> </td> <td width="128" valign="top" style="padding: 0in 5.4pt; width: 95.75pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">Apple</p> </td> <td width="49" valign="top" style="padding: 0in 5.4pt; width: 36.4pt;"> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal;">10</p> </td> </tr> </tbody> </table> </div> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;"><b>A little explanation of the SQL statement</b></p> <p class="MsoNormal" style="text-align: justify;">The&nbsp; &ldquo;AS [Product Name]&rdquo; segment sets the column name in the output. Both product name and customer name are called &ldquo;Name&rdquo; in their own tables, so we need to differentiate them in the output.</p> <p class="MsoNormal" style="text-align: justify;">The brackets around &ldquo;[Order]&rdquo; differentiate it from the SQL "Order" keyword.</p> <p class="MsoNormal" style="text-align: justify;">The Inner Join shows only the items present in both tables.</p> <p class="MsoNormal" style="text-align: justify;">All 4 tables are &ldquo;inner joined&rdquo; in the statement.</p> <p class="MsoNormal" style="text-align: justify;"><b>&nbsp;</b></p> <p class="MsoNormal" style="text-align: justify;"><b>Putting the data in Windows PowerShell</b></p> <p class="MsoNormal" style="text-align: justify;">From here on, we will use Windows PowerShell to manipulate this data, so let&rsquo;s start by putting this data in PowerShell.</p> <p class="MsoNormal" style="text-align: justify;">The following script creates four CSV files and then imports them into four variables that contain our data.</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">@"</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">Id,Name,Phone</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">1,John Smith,(206)555-8899</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">2,Mark Stone,(425)999-8811</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">3,Ruth Moore,(425)888-3355</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"@</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">&gt;</span> <span style="color: blueviolet;">c:\temp\customers.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$customers</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 9pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 9pt;">import-csv</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: blueviolet;">c:\temp\customers.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">@"</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">Id,Name,Price</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">1,Apple,10</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">2,Orange,12</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">3,Kiwi,15</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"@</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">&gt;</span> <span style="color: blueviolet;">c:\temp\products.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$products</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 9pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 9pt;">import-csv</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: blueviolet;">c:\temp\products.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">@"</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">Id,Date,CustomerId</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">1,6/6/2012 9:12:44 AM,1</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">2,6/7/2012 6:12:10 PM,1</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">3,6/5/2012 12:05:03 PM,2</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"@</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">&gt;</span> <span style="color: blueviolet;">c:\temp\orders.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$orders</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 9pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 9pt;">import-csv</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: blueviolet;">c:\temp\orders.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">@"</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">Id,Quantity,ProductId,OrderId</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">1,2,1,1</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">2,1,2,1</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">3,4,3,1</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">4,5,1,2</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">5,4,2,2</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">6,1,1,3</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"@</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">&gt;</span> <span style="color: blueviolet;">c:\temp\orderItems.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$orderItems</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 9pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 9pt;">import-csv</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: blueviolet;">c:\temp\orderItems.csv</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"Customers "</span><span style="font-family: 'Lucida Console'; font-size: 9pt;">;<span style="color: orangered;">$customers</span> <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span> <span style="color: navy;">-AutoSize</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"`r`nProducts "</span><span style="font-family: 'Lucida Console'; font-size: 9pt;">;<span style="color: orangered;">$products</span> <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span> <span style="color: navy;">-AutoSize</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"`r`nOrders "</span><span style="font-family: 'Lucida Console'; font-size: 9pt;">;<span style="color: orangered;">$orders</span> <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span> <span style="color: navy;">-AutoSize</span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkred; font-family: 'Lucida Console'; font-size: 9pt;">"`r`nOrder Items "</span><span style="font-family: 'Lucida Console'; font-size: 9pt;">;<span style="color: orangered;">$orderItems</span> <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span> <span style="color: navy;">-AutoSize </span></span></p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal">Here is the output:</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Customers </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Id Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Phone </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">-- ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----- </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">1&nbsp; John Smith&nbsp; (206)555-8899</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">2&nbsp; Mark Stone&nbsp; (425)999-8811</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">3&nbsp; Ruth Moore&nbsp; (425)888-3355</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Products </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Id Name&nbsp;&nbsp;&nbsp; Price</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">-- ----&nbsp;&nbsp;&nbsp; -----</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">1&nbsp; Apple&nbsp;&nbsp; 10 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">2&nbsp; Orange&nbsp; 12 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">3&nbsp; Kiwi&nbsp;&nbsp;&nbsp; 15 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Orders </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Id Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CustomerId</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">-- ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">1&nbsp; 6/6/2012&nbsp; 9:12:44 AM 1 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">2&nbsp; 6/7/2012&nbsp; 6:12:10 PM 1 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">3&nbsp; 6/5/2012&nbsp; 12:05:03 PM 2 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Order Items </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Id Quantity ProductId OrderId</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">-- -------- --------- -------</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">1&nbsp; 2&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;1 &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 1 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">2&nbsp; 1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 1 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">3&nbsp; 4&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;1 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">4&nbsp; 5&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;1&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;2 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">5&nbsp; 4&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;2&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 2 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">6&nbsp; 1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;1&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;3 </span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; line-height: normal; background: #012456; text-autospace: none;"><span style="font-size: 9.0pt; font-family: 'Lucida Console'; color: whitesmoke;">&nbsp;</span></p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal">The equivalent joins in PowerShell with the help of <a href="http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx">Join-Object</a> are as follows:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 8pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># Joins the customer to his orders and places Name(from Customer),</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># Date(from Order) and Id (from Order)</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 8pt;">$customerOrders</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 8pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 8pt;">Join-Object</span><span style="font-family: 'Lucida Console'; font-size: 8pt;"> <span style="color: navy;">-Left</span> <span style="color: orangered;">$customers</span> <span style="color: navy;">-Right</span> <span style="color: orangered;">$orders</span> <span style="color: navy;">-LeftProperties</span> <span style="color: blueviolet;">Name</span> <span style="color: navy;">-RightProperties</span> <span style="color: blueviolet;">Date</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Id</span> <span style="color: navy;">-Where</span> {<span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">0</span><span style="color: darkgray;">].</span>Id <span style="color: darkgray;">-eq</span> <span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">1</span><span style="color: darkgray;">].</span>CustomerId}</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 8pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># Adds the OrderItems to the data already gathered. The output objects will</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># have Name(from Customer), Date(from Order), Quantity(from OrderItem) </span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># and ProductId (from OrderItem).</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 8pt;">$customerOrderItems</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 8pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 8pt;">Join-Object</span><span style="font-family: 'Lucida Console'; font-size: 8pt;"> <span style="color: navy;">-Left</span> <span style="color: orangered;">$customerOrders</span> <span style="color: navy;">-Right</span> <span style="color: orangered;">$orderItems</span> <span style="color: navy;">-LeftProperties</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Date</span> <span style="color: navy;">-RightProperties</span> <span style="color: blueviolet;">Quantity</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">ProductId</span> <span style="color: navy;">-Where</span> {<span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">0</span><span style="color: darkgray;">].</span>Id <span style="color: darkgray;">-eq</span> <span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">1</span><span style="color: darkgray;">].</span>OrderId}</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 8pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># Adds the Products to the data already gathered. The output objects will</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># have Name (from Customer), Date(from Order), Quantity (from OrderItem)</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># Product Name (from Product) and Price from Product</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># We use a Hashtable instead of simply "Name" for Product Name because</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># "Name" is already present in the output object for the customer name,</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># so we need to differentiate the Product name from that.</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># If you did not know the syntax for the Hashtable Expression, you will</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: darkgreen; font-family: 'Lucida Console'; font-size: 8pt;"># be interested in the fact it also works for Select-Object properties</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 8pt;">$customerProducts</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 8pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 8pt;">Join-Object</span><span style="font-family: 'Lucida Console'; font-size: 8pt;"> <span style="color: navy;">-Left</span> <span style="color: orangered;">$customerOrderItems</span> <span style="color: navy;">-Right</span> <span style="color: orangered;">$products</span> <span style="color: navy;">-LeftProperties</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Date</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Quantity</span> <span style="color: navy;">-RightProperties</span> @{Name<span style="color: darkgray;">=</span><span style="color: darkred;">"Product Name"</span>;Expression<span style="color: darkgray;">=</span>{<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Name}}<span style="color: darkgray;">,</span><span style="color: blueviolet;">Price</span> <span style="color: navy;">-Where</span> {<span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">0</span><span style="color: darkgray;">].</span>ProductId <span style="color: darkgray;">-eq</span> <span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">1</span><span style="color: darkgray;">].</span>Id}</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 8pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 8pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 8pt;">$customerProducts</span><span style="font-family: 'Lucida Console'; font-size: 8pt;"> <span style="color: darkgray;">|</span> <span style="color: blue;">format-table </span></span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: blue; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal">Here is the output:</p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Quantity Product Name Price</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -------- ------------ -----</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">John Smith 6/6/2012 9:12:44 AM&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Apple&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">John Smith 6/6/2012 9:12:44 AM&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Orange&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">John Smith 6/6/2012 9:12:44 AM&nbsp; 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Kiwi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 15&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">John Smith 6/7/2012 6:12:10 PM&nbsp; 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Apple&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">John Smith 6/7/2012 6:12:10 PM&nbsp; 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Orange&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Mark Stone 6/5/2012 12:05:03 PM 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Apple&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal">So, the following three lines of code &hellip;</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 8pt;">$customerOrders</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 8pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 8pt;">Join-Object</span><span style="font-family: 'Lucida Console'; font-size: 8pt;"> <span style="color: navy;">-Left</span> <span style="color: orangered;">$customers</span> <span style="color: navy;">-Right</span> <span style="color: orangered;">$orders</span> <span style="color: navy;">-LeftProperties</span> <span style="color: blueviolet;">Name</span> <span style="color: navy;">-RightProperties</span> <span style="color: blueviolet;">Date</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Id</span> <span style="color: navy;">-Where</span> {<span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">0</span><span style="color: darkgray;">].</span>Id <span style="color: darkgray;">-eq</span> <span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">1</span><span style="color: darkgray;">].</span>CustomerId}</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 8pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 8pt;">$customerOrderItems</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 8pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 8pt;">Join-Object</span><span style="font-family: 'Lucida Console'; font-size: 8pt;"> <span style="color: navy;">-Left</span> <span style="color: orangered;">$customerOrders</span> <span style="color: navy;">-Right</span> <span style="color: orangered;">$orderItems</span> <span style="color: navy;">-LeftProperties</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Date</span> <span style="color: navy;">-RightProperties</span> <span style="color: blueviolet;">Quantity</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">ProductId</span> <span style="color: navy;">-Where</span> {<span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">0</span><span style="color: darkgray;">].</span>Id <span style="color: darkgray;">-eq</span> <span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">1</span><span style="color: darkgray;">].</span>OrderId}</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 8pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 8pt;">$customerProducts</span><span style="color: darkgray; font-family: 'Lucida Console'; font-size: 8pt;">=</span><span style="color: blue; font-family: 'Lucida Console'; font-size: 8pt;">Join-Object</span><span style="font-family: 'Lucida Console'; font-size: 8pt;"> <span style="color: navy;">-Left</span> <span style="color: orangered;">$customerOrderItems</span> <span style="color: navy;">-Right</span> <span style="color: orangered;">$products</span> <span style="color: navy;">-LeftProperties</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Date</span><span style="color: darkgray;">,</span><span style="color: blueviolet;">Quantity</span> <span style="color: navy;">-RightProperties</span> @{Name<span style="color: darkgray;">=</span><span style="color: darkred;">"Product Name"</span>;Expression<span style="color: darkgray;">=</span>{<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Name}}<span style="color: darkgray;">,</span><span style="color: blueviolet;">Price</span> <span style="color: navy;">-Where</span> {<span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">0</span><span style="color: darkgray;">].</span>ProductId <span style="color: darkgray;">-eq</span> <span style="color: orangered;">$args</span><span style="color: darkgray;">[</span><span style="color: purple;">1</span><span style="color: darkgray;">].</span>Id}</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">&hellip; do the same job as the SQL statement:</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">&nbsp;</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">SELECT&nbsp;&nbsp;&nbsp;Customer.Name, [Order].Date, OrderItem.Quantity,</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Product.Name AS [Product Name], Product.Price</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">FROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OrderItem INNER JOIN Product ON OrderItem.ProductId = Product.id INNER JOIN</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Customer INNER JOIN&nbsp; [Order] ON Customer.id = [Order].CustomerId ON OrderItem.OrderId = [Order].id</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">&nbsp;</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: justify;">There are some advantages to the SQL statement:</p> <p class="MsoListParagraphCxSpFirst" style="margin: 0pt; padding: 0pt; text-align: justify; text-indent: -0.25in;"><span style="font-family: Symbol;">&middot;<span style="font: 7pt/normal 'Times New Roman'; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>It is a single statement that is somewhat shorter than the three statements&nbsp; in PowerShell.</p> <p class="MsoListParagraphCxSpLast" style="margin: 0pt; padding: 0pt; text-align: justify; text-indent: -0.25in;"><span style="font-family: Symbol;">&middot;<span style="font: 7pt/normal 'Times New Roman'; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>It has a better syntax for aliasing a property in the output (&ldquo;as ProductName&rdquo; as opposed to &ldquo;<span style="line-height: 115%; font-family: 'Lucida Console'; font-size: 9pt;">@{Name<span style="color: darkgray;">=</span><span style="color: darkred;">"Product Name"</span>;Expression<span style="color: darkgray;">=</span>{<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Name}}</span>&rdquo;).</p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">In my opinion, those are small advantages. Each one of the PowerShell join statements is easy to understand in isolation. The hashtable syntax used in the third command (to change a property name) is a bit long, but very common to PowerShell users, because&nbsp; it is useful for other cmdlets including Select-Object.</p> <p class="MsoNormal" style="text-align: justify;">I considered changing Join-Object to take all the lists and Where clauses in a single cmdlet call, but the need to pair each of two lists with a Where clause (and a Join type) makes the command a bit too cryptic for my taste. I prefer three statements that are easy to understand to one that is not. Performance-wise, there is no difference, because each Join has to be considered in isolation.</p> <p class="MsoNormal" style="text-align: justify;">Now that the data is joined, what about getting the total money spent by each customer, the total money spent in each product and the total money spent?</p> <p class="MsoNormal" style="text-align: justify;"><b>Total Money Spent by Each Customer</b></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;">Let&rsquo;s start with the whole command:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$customerProducts</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">|</span> <span style="color: blue;">Group-Object</span> <span style="color: blueviolet;">name</span> <span style="color: darkgray;">|</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">Select-Object</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span>@{Name<span style="color: darkgray;">=</span><span style="color: darkred;">'Total'</span>;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expression<span style="color: darkgray;">=</span>{<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Group <span style="color: darkgray;">|</span> <span style="color: blue;">ForEach-Object</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Begin</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">=</span><span style="color: purple;">0</span>;} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Process</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">+=[</span><span style="color: teal;">int</span><span style="color: darkgray;">]</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Price<span style="color: darkgray;">*</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Quantity} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-End</span> {<span style="color: orangered;">$total</span>}}} <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span>&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">It produces this output:</p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sum</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">John Smith 190</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">Mark Stone&nbsp; 10</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">The first line:</p> <p class="MsoNormal" style="text-align: justify;"><span style="color: orangered; line-height: 115%; font-family: 'Lucida Console'; font-size: 9pt;">$customerProducts</span><span style="line-height: 115%; font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">|</span> <span style="color: blue;">Group-Object</span> <span style="color: blueviolet;">name</span></span></p> <p class="MsoNormal" style="text-align: justify;">Produces two groups:</p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">Count Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Group&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">----- ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">&nbsp;&nbsp;&nbsp; 5 John Smith&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {@{Name=John Smith; Date=6/6/2012 9:12:44 AM;...</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: courier new,courier; font-size: 9pt;">&nbsp;&nbsp;&nbsp; 1 Mark Stone&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {@{Name=Mark Stone; Date=6/5/2012 12:05:03 PM;...&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">In order to better see what is in each group, we run:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">(<span style="color: orangered;">$customerProducts</span> <span style="color: darkgray;">|</span> <span style="color: blue;">Group-Object</span> <span style="color: blueviolet;">name</span>)<span style="color: darkgray;">[</span><span style="color: purple;">0</span><span style="color: darkgray;">].</span>Group </span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="text-align: justify;">Which produces:</p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : John Smith</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6/6/2012 9:12:44 AM</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Quantity&nbsp;&nbsp;&nbsp; : 2</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">ProductName : Apple</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Price&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;: 10</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : John Smith</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6/6/2012 9:12:44 AM</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Quantity&nbsp;&nbsp;&nbsp; : 1</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">ProductName : Orange</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Price&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 12</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : John Smith</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6/6/2012 9:12:44 AM</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Quantity&nbsp;&nbsp;&nbsp; : 4</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">ProductName : Kiwi</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Price&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 15</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : John Smith</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6/7/2012 6:12:10 PM</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Quantity&nbsp;&nbsp;&nbsp; : 5</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">ProductName : Apple</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Price&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 10</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : John Smith</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6/7/2012 6:12:10 PM</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Quantity&nbsp;&nbsp;&nbsp; : 4</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">ProductName : Orange</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Price&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 12 </span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">And:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">(<span style="color: orangered;">$customerProducts</span> <span style="color: darkgray;">|</span> <span style="color: blue;">Group-Object</span> <span style="color: blueviolet;">name</span>)<span style="color: darkgray;">[</span><span style="color: purple;">1</span><span style="color: darkgray;">].</span>Group </span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="text-align: justify;">Which produces:</p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Mark Stone</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6/5/2012 12:05:03 PM</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Quantity&nbsp;&nbsp;&nbsp; : 1</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">ProductName : Apple</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Price&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 10 </span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">So, inside the &ldquo;Group&rdquo; property of each object in the output of group-object is the Price and Quantity we want to multiply in order to get a total. If we wanted just the total quantity of fruit we could do:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$customerProducts</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">|</span> <span style="color: blue;">Group-Object</span> <span style="color: blueviolet;">name</span> <span style="color: darkgray;">|</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">Select-Object</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp; @{Name<span style="color: darkgray;">=</span><span style="color: darkred;">'Total'</span>;Expression<span style="color: darkgray;">=</span>{(<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Group <span style="color: darkgray;">|</span> <span style="color: blue;">Measure-Object</span> <span style="color: blueviolet;">Quantity</span> <span style="color: navy;">-Sum</span>)<span style="color: darkgray;">.</span>Sum}} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp; <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span>&nbsp; </span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal" style="text-align: justify;">With output:</p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Total</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">John Smith&nbsp;&nbsp;&nbsp; 16</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Mark Stone&nbsp;&nbsp;&nbsp;&nbsp; 1 </span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: blueviolet; font-family: 'Lucida Console';">Name</span> is the first column in the output. The second column is given by:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">@{Name<span style="color: darkgray;">=</span><span style="color: darkred;">'Total'</span>; Expression<span style="color: darkgray;">=</span>{(<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Group <span style="color: darkgray;">|</span> <span style="color: blue;">Measure-Object</span> <span style="color: blueviolet;">Quantity</span> <span style="color: navy;">-Sum</span>)<span style="color: darkgray;">.</span>Sum}}</span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">This hashtable is a syntax for select object which means a column with a Name = Total and a value which is the Expression. The Expression gets the value of the Group property and pipes to Measure-Object to sum the &lsquo;Quantity&rsquo; property of each member of the Group. Finally the Sum property of the Measure-Object result is retrieved. That property contains the actual sum.</p> <p class="MsoNormal" style="text-align: justify;">Since we want to get Price * Quantity and measure-object only supports plain properties we end up with the full command repeated here:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$customerProducts</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">|</span> <span style="color: blue;">Group-Object</span> <span style="color: blueviolet;">name</span> <span style="color: darkgray;">|</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">Select-Object</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span>@{Name<span style="color: darkgray;">=</span><span style="color: darkred;">'Total'</span>;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expression<span style="color: darkgray;">=</span>{<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Group <span style="color: darkgray;">|</span> <span style="color: blue;">ForEach-Object</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Begin</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">=</span><span style="color: purple;">0</span>;} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Process</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">+=[</span><span style="color: teal;">int</span><span style="color: darkgray;">]</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Price<span style="color: darkgray;">*</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Quantity} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-End</span> {<span style="color: orangered;">$total</span>}}} <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span>&nbsp;&nbsp; </span></p> <p class="MsoNormal" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">Instead of | measure-object we have a | ForEach-Object where we use &ndash;Begin, -Process and &ndash;End to evaluate the total. This could be easily modified to calculate anything else, including averages, standard deviations, etc.</p> <p class="MsoNormal"><span style="line-height: 115%; font-size: 4pt;">&nbsp;</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt; text-align: justify;">Note: The [int] cast in front of $_.Price is required because the price is a string out of our CSV file. This could be avoided by using Export-CliXml and Import-CliXml for our data, whioch would preserve the data type.</p> <p class="MsoListParagraph" style="text-align: justify;">&nbsp;</p> <p class="MsoNormal" style="text-align: justify;">Here is the corresponding SQL statement:</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">SELECT&nbsp;&nbsp;&nbsp;Customer.Name, <b>SUM(OrderItem.Quantity * Product.Price)</b> AS SUM</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">FROM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OrderItem INNER JOIN</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Product ON OrderItem.ProductId = Product.id INNER JOIN</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Customer INNER JOIN</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Order] ON Customer.id = [Order].CustomerId ON OrderItem.OrderId = [Order].id</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;"><b>GROUP BY Customer.Name</b></span></p> <p class="MsoNormal"><b>&nbsp;</b></p> <p class="MsoNormal" style="text-align: justify;">The SQL statement combines the joining, grouping and total evaluation(Price * Quantity) operations.</p> <p class="MsoNormal" style="text-align: justify;">The Powershell statement is only doing the grouping and total evaluation, since the $customerProducts variable has the result of the joins performed in the previous section of this blog post.</p> <p class="MsoNormal" style="text-align: justify;">The bold segments of the SQL statement are performing the grouping and the PowerShell statement.</p> <p class="MsoNormal" style="text-align: justify;">SQL is designed specifically for this kind of data, so it provides a shorter syntax overall, but I believe the PowerShell equivalent is simple enough to understand.</p> <p class="MsoNormal" style="text-align: justify;"><b>Total Money Spent in Each Product</b></p> <p class="MsoNormal" style="text-align: justify;">The only thing that changes from the previous section is that the property we&rsquo;re passing to Group-Object is &ldquo;ProductName&rdquo;:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$customerProducts</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">|</span> <span style="color: blue;">Group-Object</span> <span style="color: blueviolet;">ProductName</span> <span style="color: darkgray;">|</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp; <span style="color: blue;">Select-Object</span> <span style="color: blueviolet;">Name</span><span style="color: darkgray;">,</span>@{Name<span style="color: darkgray;">=</span><span style="color: darkred;">'Total'</span>;</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expression<span style="color: darkgray;">=</span>{<span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Group <span style="color: darkgray;">|</span> <span style="color: blue;">ForEach-Object</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Begin</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">=</span><span style="color: purple;">0</span>;} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Process</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">+=[</span><span style="color: teal;">int</span><span style="color: darkgray;">]</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Price<span style="color: darkgray;">*</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Quantity} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-End</span> {<span style="color: orangered;">$total</span>}}} <span style="color: darkgray;">|</span> <span style="color: blue;">format-table</span>&nbsp;&nbsp; </span></p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Name&nbsp;&nbsp; Sum</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">----&nbsp;&nbsp; ---</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Apple&nbsp;&nbsp; 80</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Orange&nbsp; 60</span></p> <p class="MsoNormal" style="background: #012456; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: whitesmoke; font-family: 'Lucida Console'; font-size: 9pt;">Kiwi&nbsp;&nbsp;&nbsp; 60 </span></p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal">The corresponding SQL is:</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">SELECT&nbsp;&nbsp;Product.Name, <b>SUM(OrderItem.Quantity * Product.Price)</b> AS Sum</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">FROM&nbsp;&nbsp;&nbsp;&nbsp;OrderItem INNER JOIN</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Product ON OrderItem.ProductId = Product.id</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;"><b>GROUP BY Product.Name</b></span></p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal"><b>Total Money Spent</b></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;">Here is the command that produces this total:</p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="color: orangered; font-family: 'Lucida Console'; font-size: 9pt;">$customerProducts</span><span style="font-family: 'Lucida Console'; font-size: 9pt;"> <span style="color: darkgray;">|</span> <span style="color: blue;">ForEach-Object</span> `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Begin</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">=</span><span style="color: purple;">0</span>;} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-Process</span> {<span style="color: orangered;">$total</span><span style="color: darkgray;">+=[</span><span style="color: teal;">int</span><span style="color: darkgray;">]</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Price<span style="color: darkgray;">*</span><span style="color: orangered;">$_</span><span style="color: darkgray;">.</span>Quantity} `</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;&nbsp;&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: navy;">-End</span> {<span style="color: orangered;">$total</span>}</span></p> <p class="MsoNormal" style="background: white; margin: 0pt; padding: 0pt; line-height: normal;"><span style="font-family: 'Lucida Console'; font-size: 9pt;">&nbsp;</span></p> <p class="MsoNormal">&nbsp;</p> <p class="MsoNormal">Here is the corresponding SQL:</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">SELECT&nbsp; <b>SUM(OrderItem.Quantity * Product.Price)</b> AS Sum</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">FROM&nbsp;&nbsp;&nbsp;&nbsp;OrderItem INNER JOIN</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;"><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Product ON OrderItem.ProductId = Product.id</span></p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">&nbsp;</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">&nbsp;</p> <p class="MsoNormal" style="margin: 0pt; padding: 0pt;">Lucio Silveira[MSFT]</p> </div><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10355722" width="1" height="1"></description></item><item><title>Windows Management Framework 3.0 Available for Download</title><link>http://blogs.msdn.com/b/powershell/archive/2012/09/17/windows-management-framework-3-0-available-for-download.aspx</link><pubDate>Mon, 17 Sep 2012 19:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10350225</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>14</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10350225</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/09/17/windows-management-framework-3-0-available-for-download.aspx#comments</comments><description><p>We hope that you&rsquo;ve been enjoying all of the great new Windows PowerShell 3.0 features in <a href="http://www.windows-server-launch.com/">Windows Server 2012</a>. We wanted to make sure that everyone knows the final release of Windows Management Framework 3.0 is also available for download from the <a href="http://go.microsoft.com/fwlink/?LinkId=251995">Microsoft Download Center</a>.</p> <p>Windows Management Framework 3.0 makes much of the same great management functionality from Windows Server 2012 available to earlier versions of Windows. Windows Management Framework 3.0 allows you to install Windows PowerShell 3.0 (including a new version of WMI and WinRM) on the following Operating Systems:</p> <ul> <li>Windows 7 Service Pack 1 (32-bit &amp; 64-bit)</li> <li>Windows Server 2008 R2 Service Pack 1 (64-bit only, includes Server Core)&nbsp;</li> <li>Windows Server 2008 Service Pack 2 (32-bit &amp; 64-bit)</li> </ul> <p>&nbsp;</p> <p>Note: You must uninstall any of the pre-release packages of Windows Management Framework prior to installing the final release.</p> <p>&nbsp;</p> <p>Travis Jones [MSFT] <br />Program Manager &ndash; Windows PowerShell <br />Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10350225" width="1" height="1"></description></item><item><title>Managing Hardware devices from PowerShell</title><link>http://blogs.msdn.com/b/powershell/archive/2012/09/10/managing-hardware-devices-from-powershell.aspx</link><pubDate>Mon, 10 Sep 2012 17:52:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10347897</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10347897</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/09/10/managing-hardware-devices-from-powershell.aspx#comments</comments><description><p>Steve did a very cool blog post last month about managing hardware that implements standard DMTF profiles (examples: Intel AMT , Broadcom TruManage )</p> <p><a href="http://blogs.msdn.com/b/wmi/archive/2012/08/08/standards-based-hardware-management-using-powershell.aspx">http://blogs.msdn.com/b/wmi/archive/2012/08/08/standards-based-hardware-management-using-powershell.aspx</a></p> <p>He has also published a PowerShell module on TechNet script center to help IT Pros. This module has been built on top of new CIM Cmdlets.</p> <p><a href="http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Out-of-Band-84009c12">http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Out-of-Band-84009c12</a></p> <p>&nbsp;</p> <p>Take a look, and send your feedback.</p> <p>Osama Sajid</p> <p>Program Manager, WMI</p> <p>&nbsp;</p> <p>&nbsp;</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10347897" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/WMI/">WMI</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/CIM/">CIM</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/DMTF/">DMTF</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Hardware+Management/">Hardware Management</category></item><item><title>Introduction to CIM Cmdlets</title><link>http://blogs.msdn.com/b/powershell/archive/2012/08/24/introduction-to-cim-cmdlets.aspx</link><pubDate>Fri, 24 Aug 2012 22:42:26 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10343415</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10343415</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/08/24/introduction-to-cim-cmdlets.aspx#comments</comments><description><p>PowerShell 3.0 shipping with Windows server 2012 and Windows 8 brings a new set of Cmdlets to manage any server or device that complies with CIM and WS-Man standards defined by DMTF. In this blog post we will explore these new Cmdlets and how can they help IT Pros in managing a datacenter.</p> <p>The list of new Cmdlets is given in the table below: <table border="1" cellspacing="0" cellpadding="0" width="668"><tbody> <tr> <td valign="top" width="205"> <p><b>Cmdlet</b></p> </td> <td valign="top" width="461"> <p><b>Purpose</b></p> </td> </tr> <tr> <td valign="top" width="205"> <p>Get-CimInstance</p> </td> <td valign="top" width="461"> <p>Gets instances of a class.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>New-CimInstance</p> </td> <td valign="top" width="461"> <p>Creates a new instance of a class.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Remove-CimInstance</p> </td> <td valign="top" width="461"> <p>Removes one of more instances of a class.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Set-CimInstance</p> </td> <td valign="top" width="461"> <p>Modifies one or more instances of a class.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Get-CimAssociatedInstance</p> </td> <td valign="top" width="461"> <p>Gets all the associated instances for a particular instance.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Invoke-CimMethod</p> </td> <td valign="top" width="461"> <p>Invokes instance or static method of a class.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Get-CimClass</p> </td> <td valign="top" width="461"> <p>Gets class schema of a CIM class.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Register-CimIndicationEvent</p> </td> <td valign="top" width="461"> <p>Helps subscribe to events.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>New-CimSession</p> </td> <td valign="top" width="461"> <p>Creates a CIM Session with local or a remote machine</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Get-CimSession</p> </td> <td valign="top" width="461"> <p>Gets a list of CIM Sessions that have been made.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>Remove-CimSession</p> </td> <td valign="top" width="461"> <p>Removes CimSessions that are there on a machine.</p> </td> </tr> <tr> <td valign="top" width="205"> <p>New-CimSessionOption</p> </td> <td valign="top" width="461"> <p>Creates a set of options that can be used while creating a CIM session.</p> </td> </tr> </tbody></table> </p> <p>&#160;</p> <h3>Basic terminology</h3> <p>If you are already familiar with terms like WMI, CIM, WinRM and WS-Man, you can skip this section.</p> <p><b>CIM</b>: Common Information Model (CIM) is the DMTF standard [DSP0004] for describing the structure and behavior of managed resources such as storage, network, or software components.</p> <p><b>WMI</b>: Windows Management Instrumentation (WMI) is a CIM server that implements the CIM standard on Windows. </p> <p><b>WS-Man</b>: WS-Management (WS-Man) protocol is a SOAP-based, firewall-friendly protocol for management clients to communicate with CIM servers.</p> <p><b>WinRM:</b> Windows Remote Management (WinRM) is the Microsoft implementation of the WS-Man protocol on Windows.</p> <p>&#160;</p> <h3>Why new Cmdlets</h3> <p>With Windows Server 2012, Windows has shifted its focus to become a Cloud OS. In a datacenter running a private or public cloud – there are always set of devices and servers from different vendors. We strongly believe that the only way to reduce the cost of running datacenters is through automation built on top of standards. There is less learning and less chances of error when IT Pros are able to automate heterogeneous environment using same set of tools that they have learned for Windows.</p> <p>This was not the case with previous versions of PowerShell. We had two set of Cmdlets to manage Windows and Non-Windows. WMI Cmdlets were primarily used to manage Windows and WsMan Cmdlets were targeted at non-Windows that implemented WsMan standard.</p> <p><b>WMI Cmdlets: </b></p> <blockquote> <p>- Pros: Provided better task abstraction compared to WsMan Cmdlets, output is a .NET object.</p> </blockquote> <blockquote> <p>- Cons: Use of non-standard DCOM protocol. Does not work for non-Windows. <b></b></p> </blockquote> <p><b>WinRM Cmdlets</b></p> <blockquote> <p>- Pros: Works with Windows and non-Windows using standard protocol.</p> </blockquote> <blockquote> <p>- Cons: Poor task abstraction. Output is XML , scaring most IT Pros away</p> </blockquote> <p>We heard from you that the major obstacle in PS scripting for WMI is lack of discoverability. We also heard that WMI Cmdlets don’t provide first class PS experience. There are issues with serializing a WMI object, there is no concept of session reuse and WMI object has weird looking property names (like __Server). Last but not least, there is poor formatting for most of the commonly used WMI classes. Someone said “When I run Get-WmiObject Win32_process, I feel like standing on bridge above freeway and lot of traffic zipping in front of my eyes”.</p> <h3>Key goals for new CIM Cmdlets</h3> <blockquote> <p>- <strong>Rich PowerShell experience</strong>. Make CIM a first class citizen of PS, addressing usability concerns and user feedback for WMI and WsMan Cmdlets. </p> </blockquote> <blockquote> <p>- <strong>Standard compliance</strong>. With so much focus on standards, our goal is to make PowerShell the best platform for managing Windows and Non-Windows. New CIM Cmdlets should be able to manage any CIM + WsMan compliant endpoint, including Windows.</p> </blockquote> <blockquote> <p>- <strong>Support for down-level machines</strong>. We understand that there are more down-level servers in a datacenter than there would be Windows Server 2012 for some time to come. We want to make sure same set of Cmdlets can be used to manage down-level Windows as well.</p> </blockquote> <p>In the subsequent sections we will talk about each of these goals in detail.</p> <p>&#160;</p> <h3><u>Goal 1 - Rich PowerShell experience</u> </h3> <h4><strong>1. Discovery of classes and namespaces.</strong></h4> <p>There is a famous joke about WMI, often attributed to Jeffrey Snover. “IT Pros love and hate WMI. They love it because there is so much they accomplish with WMI and PowerShell. They hate it because it is very difficult to discover what’s in there”</p> <p>To address this, we have done key improvements in new CIM Cmdlets</p> <ol> <li>Tab completion for classname and namespace parameters. </li> <li>Get-CimClass Cmdlet </li> </ol> <p> <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" bgcolor="#000066"><tbody> <tr> <td valign="top" width="638"> <p># Using tab completion for CIM cmdlet parameters ( Tab+Space in ISE shows a drop down)</p> <p>Get-CimInstance –Namespace &lt;Tab&gt; #Finding top-level namespaces</p> <p># Tab completion for class names</p> <p># If namespace is not specified, shows classes from default root/cimv2 namespace</p> <p>Get-CimInstance -ClassName *Bios&lt;Tab&gt;</p> <p>Get-CimInstance –Namespace root/Microsoft/Windows/smb –ClassName &lt;tab&gt;</p> <p># Note: Tab completion only works for local machine.</p> <p>#Using Get-CimClass for advanced class search</p> <p>#All classes in root/cimv2</p> <p>PS:&gt;Get-CimClass </p> <p>#Classes named like disk</p> <p>PS:&gt;Get-CimClass -ClassName *disk*</p> <p># The Cmdlet makes querying much easier (what would require scripting before)</p> <p># Get all classes starting with &quot;Win32&quot; that have method starting with &quot;Term&quot; </p> <p>PS:&gt;Get-CimClass Win32* -MethodName Term* </p> <p># Get classes starting with &quot;Win32&quot; that have a property named &quot;Handle&quot;</p> <p>PS:&gt;Get-CimClass Win32* -PropertyName Handle</p> <p># Get classes starting with &quot;Win32&quot; that have the &quot;Association&quot; qualifier</p> <p>PS:&gt;Get-CimClass Win32* -QualifierName Association</p> <p>#Find classes used for events</p> <p>PS:&gt; Get-CimClass -Namespace root/Microsoft/Windows/smb -class *Smb* -QualifierName Indication</p> </td> </tr> </tbody></table> </p> <p>Get-CimClass and tab completion described above only works for local machine. If you specify ComputerName or CimSession parameter, tab completion would not work. In order to make tab completion more efficient, PowerShell caches the list of namespaces and classnames.</p> <h4><strong>2. Getting Instances</strong></h4> <p>Getting/Enumerating instance of a class is the most commonly performed operation. We wanted the new Get-CimInstance Cmdlet to have better performance and even better user experience as compared to the old Get-WmiObject cmdlet. To achieve these goals we made the following design decisions:</p> <p>a. The Get-CimInstance cmdlet returns one or more instances of CimInstance. CimInstance is different from the object returned by Get-WmiObject. </p> <p>b. __Properties are no longer mixed with properties of an instance.</p> <p>c. Reduce memory and on-the-wire footprint by allowing retrieval of a subset of properties. </p> <p>d. Allow retrieval of key properties.</p> <p>e. Allow creation of in-memory instance to reduce round trips.</p> <p>f. Allow retrieval of specific instances using in-memory instances or actual instances.</p> <p>g. DateTime values are returned as objects of System.DateTime type. Old cmdlets treat them as strings.</p> <p>&#160;</p> <p> <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" bgcolor="#000066"><tbody> <tr> <td valign="top" width="638"> <p># Get-CimInstance was designed to be similar to the Get-WmiObject</p> <p># WMI Cmdlet : Get-WmiObject -class Win32_Process</p> <p># WsMan Cmdlet : get-wsmaninstance wmicimv2/win32_process -Enumerate</p> <p># The default value of -Namespace is root/cimv2, and the default value of -ComputerName is local computer </p> <p>PS:&gt; Get-CimInstance -Class Win32_Process</p> <p># Filtering using WQL</p> <p>PS:&gt; Get-CimInstance -Query &quot;SELECT * FROM Win32_Process WHERE Name Like 'power%'&quot; </p> <p># use the -Filter parameter with -classname</p> <p>PS:&gt; Get-CimInstance -Class Win32_Process -Filter &quot;Name Like 'power%'&quot; </p> <p>#Retrieving a subset of properties : To reduce memory and on-the-wire footprint</p> <p>PS:&gt; Get-CimInstance -Class Win32_Process -Property Name, Handle </p> <p>#Only get the key properties</p> <p>PS:&gt; Get-CimInstance -Class Win32_Process -KeyOnly</p> <p>########################## Looking into CimInstance #########################</p> <p>PS:&gt;&#160; $x, $y = Get-CimInstance Win32_Process</p> <p>PS:&gt;&#160; $x | gm</p> <p># The object contains the full CIM class derivation hierarchy</p> <p>PS:&gt; $x.pstypenames</p> <p># The object also has a reference to its class declaration</p> <p>PS:&gt; $x.CimClass | gm</p> <p># DateTime values are returned as strings</p> <p>PS:&gt; Get-WmiObject Win32_OperatingSystem | Select *Time*</p> <p># DateTime values are returned as System.DateTime</p> <p>PS:&gt; Get-CimInstance Win32_OperatingSystem | Select *Time*#</p> </td> </tr> </tbody></table> </p> <h4><strong>3. Working with associations</strong></h4> <p>Working with associations was not straight forward in the old WMI cmdlets. Customers wanted a way to find out associated instances of a particular instance. To resolve this issue we came up with a cmdlet called Get-CimAssociatedInstance. The following example shows some of the important features of this cmdlet.</p> <p> <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" bgcolor="#000066"><tbody> <tr> <td valign="top" width="638"> <p># Get instance of Win32_LogicalDisk class with DriveType =3 (hard drives)</p> <p>PS:&gt; $disk1, $diskn = Get-CimInstance -class Win32_LogicalDisk -Filter 'DriveType = 3'</p> <p>PS:&gt; $disk1</p> <p># Get the all instances associated with this disk</p> <p>PS:&gt; Get-CimAssociatedInstance -CimInstance $disk1</p> <p># Get instances of a specific type</p> <p>PS:&gt; Get-CimAssociatedInstance -CimInstance $disk1 -ResultClassName Win32_DiskPartition</p> <p># Finding associated instances through a specific CIM relationship </p> <p>PS:&gt; Get-CimAssociatedInstance -CimInstance $diskn -Association Win32_LogicalDiskRootDirectory</p> </td> </tr> </tbody></table> </p> <h4><strong>4. Working with methods</strong></h4> <p>A large number of tasks in WMI are achieved by invoking methods. The new Invoke-CimMethod makes two things really easy: </p> <blockquote> <p>a. Discovery of method and method parameters</p> </blockquote> <blockquote> <p>b. Execution of methods with parameters. Using feedback from our customers: <a href="https://connect.microsoft.com/PowerShell/feedback/details/624263/invoking-wmi-methods-with-invoke-wmimethod">Connect bug</a></p> </blockquote> <p>The following examples show how easy it is to discover and execute methods using Invoke-CimMethod: </p> <p> <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" width="725" bgcolor="#000066"><tbody> <tr> <td valign="top" width="723"> <p>PS:&gt; $class = Get-CimClass Win32_Process</p> <p>PS:&gt; $class.CimClassMethods</p> <p># Get the parameters of the Create method</p> <p>PS:&gt; $class.CimClassMethods[&quot;Create&quot;].Parameters</p> <p># Invoke the static Create method on the Win32_Process class to create an instance of the Notepad </p> <p># application. Notice that the method parameters are given in a hash table since CIM method arguments</p> <p># are unordered by definition. </p> <p>PS:&gt; Invoke-CimMethod -Class win32_process -MethodName Create -Argument @{CommandLine='notepad.exe';</p> <p>CurrentDirectory = &quot;c:\windows\system32&quot;}</p> <p># Get the owners of the running Notepad instances</p> <p>PS:&gt; $result = Invoke-CimMethod -Query 'SELECT * FROM Win32_Process WHERE name like &quot;notepad%&quot;' </p> <p>-MethodName GetOwner</p> <p># The result has the returned value and out parameters of the method</p> <p>PS:&gt; $result</p> </td> </tr> </tbody></table> </p> <h4><strong>5. CliXML serialization.</strong></h4> <p>CimInstance supports full fidelity serialization and deserialization. This is an important feature for those who wish to save state of an instance or result of a cmdlet and then want to use it later. The WMI cmdlets do not support full-fidelity serialization/deserialization. <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" bgcolor="#000066"><tbody> <tr> <td valign="top" width="638"> <p># CimInstances are serialized and deserialized with full fidelity</p> <p>PS:&gt; $x = Get-CimInstance Win32_Service </p> <p>PS:&gt; $x</p> <p>PS:&gt; $x[0].pstypenames</p> <p>PS:&gt; $x | Export-CliXml t1.xml</p> <p>PS:&gt; $y = Import-CliXml .\t1.xml</p> <p>PS:&gt; $y</p> <p>PS:&gt; $y[0].pstypenames</p> <p># The deserialized objects are identical to the ones obtained from the server</p> <p>PS:&gt; diff ($y) (Get-CimInstance win32_service )</p> </td> </tr> </tbody></table> </p> <h4><strong>6. Remote management</strong></h4> <p>Managing remote machines with the new cmdlets is also pretty simple and straight forward. The two parameters that can be used to manage remote machines are:</p> <blockquote> <p>a. ComputerName</p> </blockquote> <blockquote> <p>b. CimSession</p> </blockquote> <p>The following example will explain how these two parameters can be used to manage a remote machine. </p> <p> <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" width="729" bgcolor="#000066"><tbody> <tr> <td valign="top" width="727"> <p>PS:&gt; $props = @{v_Key = [UInt64] 8;}</p> <p># If ComputerName parameter is used, the cmdlets create an implicit session during the execution.</p> <p>PS:&gt; $inst = New-CimInstance -ClassName TestClass -Namespace root\test -Key v_Key -Property $props </p> <p>-ComputerName SecondWin8Server</p> <p># Create a session</p> <p>PS:&gt; $session = New-CimSession –ComputerName SecondWin8Server</p> <p># Use the session </p> <p>PS:&gt; $inst = New-CimInstance -ClassName TestClass -Namespace root\test -Key v_Key -Property $props </p> <p>–CimSession $session</p> </td> </tr> </tbody></table> </p> <p><strong>Tip:</strong> If a large number of remote operations are to be performed then session reuse is highly recommended. This can provide a significant performance gain.</p> <h4><strong>7. Easy migration from WMI cmdlets</strong></h4> <p>Last, but not the least, a very important aspect is to reduce learning. If you know how to use WMI cmdlets from PowerShell 2.0, you will find learning new CIM cmdlets easy. These cmdlets follow similar patterns as WMI cmdlets -including parameter names and alias. Let’s see how easy or difficult it is to move to new cmdlets <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" bgcolor="#000066"><tbody> <tr> <td valign="top" width="638"> <p><b># OLD: One liner to get ComputerSystem information</b></p> <p>PS:&gt; Get-WmiObject Win32_ComputerSystem</p> <p><b># NEW:</b></p> <p>PS:&gt; Get-CimInstance Win32_ComputerSystem</p> <p># ClassName is position and mandatory.</p> <p># Namespace default is root/cimv2 namespace</p> <p>#WMI Cmdlet – with classnames and Namespace</p> <p>PS:&gt; Get-WmiObject –ClassName Win32_Process –Namespace root/cimv2</p> <p>#CIM cmdlet follows the same pattern</p> <p>PS:&gt; Get-CimInstance –ClassName Win32_Process –Namespace root/cimv2</p> </td> </tr> </tbody></table> </p> <p>The table below shows the list of WMI cmdlets and their CIM equivalent: <table border="1" cellspacing="0" cellpadding="0"><tbody> <tr> <td valign="top" width="319"> <p><b>Old cmdlet</b></p> </td> <td valign="top" width="319"> <p><b>New Cmdlet</b></p> </td> </tr> <tr> <td valign="top" width="319"> <p>Get-WmiObject</p> </td> <td valign="top" width="319"> <p>Get-CimInstance</p> </td> </tr> <tr> <td valign="top" width="319"> <p>Get-WmiObject -list</p> </td> <td valign="top" width="319"> <p>Get-CimClass</p> </td> </tr> <tr> <td valign="top" width="319"> <p>Set-WmiInstance</p> </td> <td valign="top" width="319"> <p>Set-CimInstance</p> </td> </tr> <tr> <td valign="top" width="319"> <p>Set-WmiInstance –PutType CreateOnly</p> </td> <td valign="top" width="319"> <p>New-CimInstance</p> </td> </tr> <tr> <td valign="top" width="319"> <p>Remove-WmiObject</p> </td> <td valign="top" width="319"> <p>Remove-CimInstance </p> </td> </tr> <tr> <td valign="top" width="319"> <p>Invoke-WmiMethod</p> </td> <td valign="top" width="319"> <p>Invoke-CimMethod</p> </td> </tr> </tbody></table> </p> <p><b>Note: </b>In old cmdlets Set-WmiInstance was used to perform update and create operations. The new cmdlets clearly define the distinction between the two operations i.e. New-CimInstance is used to create an instance and Set-CimInstance is used to update an existing instance.</p> <p>You will also notice that in some places we have broken this rule – and script using WMI cmdlet can’t be simply changed to CIM cmdlet by changing the cmdlet name. e.g. <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" bgcolor="#000066"><tbody> <tr> <td valign="top" width="638"> <p><b># OLD:</b></p> <p>PS:&gt; Invoke-WMIMethod -class Win32_Process -Name create -ArgumentList 'calc.exe'</p> <p><b># NEW:</b></p> <p>PS:&gt;Invoke-CimMethod Win32_Process -MethodName create -Arguments @{CommandLine='calc.exe'}</p> <p>New Cmdlet takes a hash table or ordered dictionary as input not an Object.</p> </td> </tr> </tbody></table> </p> <p>The rule here is, if the WMI cmdlet experience is not ideal, we don’t want to carry it forward. It’s better to break a bad experience (like in the example given above)</p> <p>&#160;</p> <h3><u>Goal 2 - Standard Compliance</u></h3> <p>· CIM cmdlets are modeled on generic CIM operations</p> <p>· Work over WsMan for remote management, making it possible to manage any server or device that implements WsMan and CIM standard.</p> <p>· Removes the need to build custom agents and/or protocol to manage complex heterogeneous environments</p> <p>· CIM cmdlets will work seamlessly with the new Open Management Infrastructure. <a href="http://blogs.technet.com/b/windowsserver/archive/2012/06/28/open-management-infrastructure.aspx">http://blogs.technet.com/b/windowsserver/archive/2012/06/28/open-management-infrastructure.aspx</a></p> <p>The following example shows that CimCmdlets can be used to manage a non-windows device (i.e. an Intel AMT box): <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" bgcolor="#000066"><tbody> <tr> <td valign="top" width="638"> <p># Save credentials in an object</p> <p>PS:&gt; $cred = Get-Credential -UserName admin</p> <p># Create a session with Intel AMT machine.</p> <p>PS:&gt; $s = New-CimSession -ComputerName $serverAMT -Port 16992 -Authentication Digest -Credential $cred</p> <p># Use classname to get instances from an Intel AMT machine.</p> <p>PS:&gt; Get-CimInstance -class CIM_ComputerSystem -Namespace interop -CimSession $s</p> <p># Use resourceURI to get instances from an Intel AMT machine.</p> <p>PS:&gt; $resourceURI = “http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings”</p> <p>PS:&gt; Get-CimInstance -ResourceUri $resourceURI -Namespace interop -CimSession $s</p> </td> </tr> </tbody></table> </p> <h3><u></u></h3> <h3><u></u></h3> <h3><u>Goal 3 - Support for down-level OS or non-windows machines</u></h3> <p>CimCmdlets can be used to manage Windows 8, down-level windows machines and any machine that has a CIM standards compliant CIMOM. So, IT pros can now manage non-windows machines with PowerShell in the exact same fashion as they could manage a windows box.</p> <p>To manage these machines, a CimSession to the machine is required. Once a CimSession is created, the machine can be managed irrespective of the operating system. </p> <p>WinRM support on down-level windows machines is limited. The latest WMF-V1 release will enable the latest version of WinRM on the down-level machines; this will help our customers in making best use of these new cmdlets. </p> <p>If customers do not want to install WMF-V1 or do not wish to use WinRM then they can always use DCOM protocol to achieve the same results. </p> <p>&#160;</p> <p> <table style="color: #ffffff" border="1" cellspacing="0" cellpadding="0" width="824" bgcolor="#000066"><tbody> <tr> <td valign="top" width="822"> <p># If ComputerName is specified, WinRM protocol is used</p> <p>PS:&gt; $serverwin8 = New-CimSession –ComputerName &quot;ServerWin8&quot;</p> <p>PS:&gt; $serverwin2k8r2 = New-CimSession –ComputerName “Serverwin2k8r2 &quot;</p> <p># For a remote machine, if you wish to go over DCOM, you need to explicitly specify </p> <p>PS:&gt; $sOpt = New-CimSessionOption –Protocol DCOM</p> <p>PS:&gt; $sessionWin2k8r2Dcom = New-CimSession –ComputerName “Serverwin2k8r2 &quot; –SessionOption $sOpt</p> <p># User Experience remains same irrespective of the target machine.</p> <p>PS:&gt; $instanceServerWin8 = Get-CimInstance –CimSession $ serverwin8</p> <p>PS:&gt; $instanceServerWin2k8r2 = Get-CimInstance –CimSession $ serverwin2k8r2</p> <p>PS:&gt; $instanceServerWin2k8r2DCOM = Get-CimInstance –CimSession $ sessionWin2k8r2Dcom</p> <p>#Note: The results in $instanceServerWin2k8r2 and $instanceServerWin2k8r2DCOM are identical in all aspects. </p> <p># Only the protocol used to get them is different.</p> </td> </tr> </tbody></table> </p> <p>Our objective is to provide the best user experience to all the IT professionals. We would love to know what you think about these new cmdlets. Please give us your comments below.</p> <p>&#160;</p> <p>Vaibhav Chugh</p> <p>SDET, WMI</p> <p>Osama Sajid</p> <p>Program Manager, WMI</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10343415" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/WMI/">WMI</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/CIM/">CIM</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/MI+Client/">MI Client</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/CimInstance/">CimInstance</category></item><item><title>New-Workflow –MakeItEasy: Authoring Workflows using PowerShell Extended Syntax</title><link>http://blogs.msdn.com/b/powershell/archive/2012/07/21/new-workflow-makeiteasy-authoring-workflows-using-powershell-extended-syntax.aspx</link><pubDate>Sat, 21 Jul 2012 20:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10332271</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10332271</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/07/21/new-workflow-makeiteasy-authoring-workflows-using-powershell-extended-syntax.aspx#comments</comments><description><p>Some time back, in his <a href="http://blogs.technet.com/b/windowsserver/archive/2012/05/30/windows-server-2012-powershell-3-0-and-devops-part-2.aspx">blog post</a>, Jeffrey Snover introduced one of the new Windows PowerShell 3.0 feature &ndash; <strong>Windows PowerShell Workflow</strong>. In that post, you saw a glimpse of how to author workflows using PowerShell syntax. This post dives into more details of authoring workflows using PowerShell syntax and various extensions to it.</p> <h2>Why we chose to extend the PowerShell Language for Workflow Authoring</h2> <p>As Jeffrey mentioned in that blog post, Windows Workflow Foundation traditionally has been a developer-focused feature that requires Visual Studio and a lot of code to create a solution. To review the solution, another person has to understand XAML or they have to install Workflow Designer. Authoring workflows by using Windows PowerShell is much easier and overcomes the development hurdles. Additionally, you get the benefit of sharing the workflows by simply pasting them into an email or publishing them online.</p> <p>Another reason, as pointed out in <a href="http://blogs.msdn.com/b/powershell/archive/2012/03/17/when-windows-powershell-met-workflow.aspx">another blog post</a>, is our promise to the PowerShell community about learning once and reusing that knowledge over and over again:</p> <blockquote> <p><b><i>&ldquo; &hellip; We respect your investment in learning Windows PowerShell by reusing concepts over and over to make sure learning Windows PowerShell was the best thing you ever did. &hellip;&rdquo;</i></b><b><i></i></b></p> </blockquote> <p>While designing the workflow authoring experience, we kept this promise in mind. We also thought of ways to work with existing tools and, hence, came up with two approaches to workflow authoring:</p> <ol> <li><b>Script-based Workflow Authoring</b>: Leverage and extend the PowerShell language for workflows so IT Pros can reuse their existing PowerShell scripting skills.</li> <li><b>XAML-based Workflow Authoring:</b> Plug into the Visual Studio Workflow Designer experience so developers can easily get the management activities in their existing environment and continue leveraging their XAML and Visual Studio knowledge.</li> </ol> <p>This post will dive into details of the former approach for workflow authoring: PowerShell script-based workflows. In a later blog post, we will look into the XAML-based authoring experience.</p> <p>Although there are multiple ways to showcase the new script-based workflow experience, we will explain it by using a real-world example: <span style="text-decoration: underline;">Creating virtual machines on a Hyper-V capable host machine and joining those virtual machines to a domain.</span> This example is a good workflow sample because it has all the necessary workflow characteristics &ndash; long running task across multiple machines that require robustness due to machine reboots.</p> <p>The benefit of this approach is that by the end of this blog, you will have a real-world workflow sample that can easily be used in your environment. <img class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5661.wlEmoticon_2D00_smile_5F00_438CBD30.png" /></p> <h2>Workflow Extensions to the PowerShell Language</h2> <p>In next couple of sections, we will look at various extensions to the PowerShell language that expose and enable Windows Workflow Foundation concepts.</p> <h3>Workflow Keyword</h3> <p>The most important of extensions to the PowerShell language is the <b>workflow</b> keyword. To create a workflow, use the <b>workflow</b> keyword, followed by a name for the workflow and, then, followed by the body of the workflow, such as:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7536.Invoke_2D00_HelloWorld_5F00_2A59F1EC.png"><img width="255" height="51" title="Invoke-HelloWorld" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Invoke-HelloWorld" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8625.Invoke_2D00_HelloWorld_5F00_thumb_5F00_5128082C.png" border="0" /></a></p> <p>As you can see, if you know how to write a PowerShell function, you are 80% on the way to being able to write a workflow.</p> <p><i>Note: The behavior of a workflow is different than a function and it has a few more rules that we will delve into in another blog post soon.</i></p> <p>After knowing how easy it is to create a workflow, let&rsquo;s build our workflow for creating virtual machines (VM). We will name it <b>Install-VM</b> &ndash; using a verb-noun name just like those of any other PowerShell command. We will add parameters to our workflow that will specify virtual hard disk (VHD) location for VMs, default prefix for VM name and the number of VM to create.</p> <p><a name="DefinitionAndParam"></a><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2211.Install_2D00_VM_2D00_Param_5F00_39244B47.png"><img width="414" height="176" title="Install-VM-Param" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Install-VM-Param" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0181.Install_2D00_VM_2D00_Param_5F00_thumb_5F00_1FBC480D.png" border="0" /></a></p> <blockquote> <p><i>Note: As you might notice, in Windows PowerShell Workflow, you can specify default values for the parameters, just like you do in functions.</i></p> </blockquote> <p>In the example above, notice that Windows PowerShell ISE recognizes the workflow and its content and colorizes them appropriately, just like it does for any other PowerShell command.</p> <h3><a name="ParallelExecution"></a>Parallel Execution</h3> <p>The underlying Windows Workflow Foundation runtime supports running activities or commands in parallel. We expose this capability in Windows PowerShell Workflow through the <b>parallel</b> keyword, as well as <b>foreach-paralle</b>l, an enhancement to the ForEach statement. With parallel execution, you can significantly reduce the operation time across a set of machines.</p> <p>Additionally, to execute a collection of activities or commands in order (not in parallel) within a <b>parallel </b>block, use the <b>sequence </b>block, such as:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3480.Invoke_2D00_ParallelWorkflow_5F00_1CBF83AF.png"><img width="432" height="250" title="Invoke-ParallelWorkflow" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Invoke-ParallelWorkflow" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4073.Invoke_2D00_ParallelWorkflow_5F00_thumb_5F00_0E810ABF.png" border="0" /></a></p> <p>Now let&rsquo;s go back to our <a href="#DefinitionAndParam">previous Install-VM</a> workflow. We'll use a <b>foreach &ndash;parallel </b>block to add logic for creating VMs in parallel.</p> <p><i><a name="CreateVM"></a><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0312.Install_2D00_VM_2D00_ForeachParallel_5F00_48237A7A.png"><img width="547" height="310" title="Install-VM-ForeachParallel" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Install-VM-ForeachParallel" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8814.Install_2D00_VM_2D00_ForeachParallel_5F00_thumb_5F00_195DC1D8.png" border="0" /></a></i></p> <blockquote> <p><i>Note: In order to call <b>New-VM</b> and <b>New-VHD</b> commands, you need to install Hyper-V module.</i></p> </blockquote> <h3>Checkpoint Workflow Execution</h3> <p>Windows Workflow Foundation allows a workflow to persist or checkpoint all aspects of its state by using an explicit call to the <b>Persist</b> activity. The same feature is exposed through the <b>Checkpoint-Workflow</b> command in Windows PowerShell Workflow.. With the use of <b>Checkpoint-Workflow,</b> Window PowerShell Workflow checkpoints the workflow state and saves the workflow data to the persistence store. In case of unintended interruptions (machine reboot, process crash, network disruption, etc.), the workflow execution resumes from the last persistence point. Alternatively, to achieve similar results, you can add <b>-PSPersist $true</b> at the end of an activity or command.</p> <p>Now let&rsquo;s add a <b>Checkpoint-Workflow</b> call to our <a href="#CreateVM">previous Install-VM</a> workflow to save the workflow state.</p> <p><a name="SaveWorkflowState"></a><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3225.Install_2D00_VM_2D00_Checkpoint_5F00_6746C189.png"><img width="413" height="160" title="Install-VM-Checkpoint" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Install-VM-Checkpoint" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3301.Install_2D00_VM_2D00_Checkpoint_5F00_thumb_5F00_0E14D7CA.png" border="0" /></a><i></i></p> <blockquote> <p><i>Note: Just look at the <b>param</b> and <b>foreach &ndash;parallel</b> block above and you will notice another cool ISE feature: </i><i>collapsible regions.</i></p> </blockquote> <h3><a name="InlineScript"></a>InlineScript: Running Isolated Blocks of Windows PowerShell Script</h3> <p>By default, each command in a workflow is executed with no PowerShell state sharing. Variables created by one command are not visible to the next command. But, by using the <b>inlineScript</b> keyword it is possible to execute a collection of PowerShell commands as a single execution unit</p> <p><i><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2313.Invoke_2D00_InlineScript_5F00_4DDEBE4F.png"><img width="310" height="128" title="Invoke-InlineScript" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Invoke-InlineScript" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8664.Invoke_2D00_InlineScript_5F00_thumb_5F00_74ACD48F.png" border="0" /></a></i></p> <blockquote> <p><i>Note: As mentioned in section 5 of </i><a href="http://blogs.msdn.com/b/powershell/archive/2012/06/19/high-level-architecture-of-windows-powershell-workflow-part-2.aspx"><i>PowerShell Workflow architecture</i></a><i>, for reliability reasons, by default, <b>inlineScript</b> runs in a separate process</i><i></i></p> </blockquote> <h3><a name="UsingWithVariables"></a>Accessing Workflow Variables from Different Execution Scopes</h3> <p>Just like PowerShell remoting in PowerShell 3.0, Windows PowerShell Workflow supports the <b>$Using:&lt;variable name&gt; </b>scope modifier. This new scope modifier can access workflow variables into the context of an <a href="#InlineScript">inlineScript</a>.</p> <p>Unlike PowerShell, Windows Workflow Foundation does not support dynamic scoping of variables. This means that a variable that is defined in the parent scope cannot be redefined in a child scope. In Windows PowerShell Workflow, to change a workflow-scoped variable from any inner scope, use the <b>$workflow:&lt;variable name&gt; </b>scope modifier.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7674.Invoke_2D00_WithUsingandWorkflowScope_5F00_0689685D.png"><img width="600" height="285" title="Invoke-WithUsingandWorkflowScope" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Invoke-WithUsingandWorkflowScope" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3225.Invoke_2D00_WithUsingandWorkflowScope_5F00_thumb_5F00_7AF3AB1D.png" border="0" /></a></p> <p>Now, we will use our new <a href="#ParallelExecution">foreach -parallel</a>, <a href="#InlineScript">inlineScript</a> and <a href="#UsingWithVariables">$using</a> concepts, to update our <a href="#SaveWorkflowState">previous Install-VM</a><b> </b>workflow by adding logic for starting the VMs and getting their IP addresses in parallel.</p> <p><a name="StartVMandWaitForIP"></a><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4743.Install_2D00_VM_2D00_VMIPAddress_5F00_45B18082.png"><img width="579" height="565" title="Install-VM-VMIPAddress" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Install-VM-VMIPAddress" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1425.Install_2D00_VM_2D00_VMIPAddress_5F00_thumb_5F00_12E17A0E.png" border="0" /></a></p> <blockquote> <p><i>Note: All the commands in workflow have a <b>&ndash;DisplayName</b> common parameter to provide a custom or friendly name for the command. In the previous example, we used it on <b>inlineScript</b>.</i></p> </blockquote> <h3>Suspending a Workflow from within the workflow</h3> <p>Windows PowerShell Workflow has a <b>Suspend-Workflow</b> command that suspends the workflow during its execution. This command gives the workflow author complete control over the workflow suspension behavior independent of the workflow user. For example, a workflow can detect a problem that requires manual intervention, notify the operator of this condition, and then suspend operations until the operator corrects the situation and resumes the workflow.</p> <p>Let us update our <a href="#StartVMandWaitForIP">previous Install-VM</a><b> </b>workflow to send an email to a senior admin and suspend itself. Once the senior admin gets the email, he/she can resume the workflow manually.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5633.Install_2D00_VM_2D00_Suspend_5F00_725A3A5B.png"><img width="660" height="410" title="Install-VM-Suspend" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Install-VM-Suspend" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8053.Install_2D00_VM_2D00_Suspend_5F00_thumb_5F00_641BC16B.png" border="0" /></a></p> <p>Additionally, you can integrate the workflow execution with the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/hh880865(v=vs.85).aspx">Management Odata IIS Extension feature</a> of Windows Server 2012 to manage workflows from any Windows or non-Windows device that can understand HTTP requests. The PowerShell team demonstrated this feature at TechEd North America and TechEd Europe 2012. You can see a recording of this session <a href="http://channel9.msdn.com/Events/TechEd/NorthAmerica/2012/WSV414">here</a> (look at the 1:03:17 mark).</p> <h3>Workflow Calling Workflow</h3> <p>This feature of Windows PowerShell Workflow enables you to re-use workflows to create higher-level workflows, while leveraging your existing workflow investment, workflows from other users, and workflows from the PowerShell Community. To use this feature, the child workflow (e.g. <b>Join-Domain</b>) must be defined and imported into the PowerShell session in which the parent workflow is defined..</p> <p>Let&rsquo;s define a <b>Join-Domain</b> workflow that joins a machine to a domain. To complete the scenario, we will call <b>Join-Domain</b> from our <b>Install-VM </b>workflow.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5047.Join_2D00_Domain_5F00_38A092DA.png"><img width="673" height="230" title="Join-Domain" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Join-Domain" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6102.Join_2D00_Domain_5F00_thumb_5F00_6378F6EC.png" border="0" /></a></p> <p>Updated <b>Install-VM </b>workflow looks like as follows (and script is attached at the end of the blog post):</p> <p><i><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4718.Install_2D00_VM_2D00_WithJoin_2D00_Domain_5F00_182B60EA.png"><img width="692" height="660" title="Install-VM-WithJoin-Domain" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Install-VM-WithJoin-Domain" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1184.Install_2D00_VM_2D00_WithJoin_2D00_Domain_5F00_thumb_5F00_45404DB8.png" border="0" /></a></i></p> <blockquote> <p><i>NOTE: Notice that the param block of <b>Install-VM</b> has two additional parameters: $domainCred and $localCred. The <b>Join-Domain</b> workflow needs these values. </i></p> </blockquote> <p>Additionally, you can define nested functions or nested workflows inside the workflows as well, such as:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5635.Invoke_2D00_NestedCommand_5F00_7AFA92E7.png"><img width="393" height="270" title="Invoke-NestedCommand" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Invoke-NestedCommand" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4152.Invoke_2D00_NestedCommand_5F00_thumb_5F00_4FB5FBE0.png" border="0" /></a></p> <h3>Finding and Running Your Workflow</h3> <p>As explained by Mir Rosenberg in an <a href="http://blogs.msdn.com/b/powershell/archive/2012/03/17/when-windows-powershell-met-workflow.aspx">earlier blog post</a>, Windows PowerShell Workflows behave just like other Windows PowerShell commands. You can discover them by using <b>Get-Command:</b></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7382.Get_2D00_Command_5F00_287BB2AB.png"><img width="585" height="190" title="Get-Command" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Get-Command" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5314.Get_2D00_Command_5F00_thumb_5F00_410B4FFB.png" border="0" /></a></p> <p>You can run them interactively or use the <b>AsJob </b>common parameter of workflows to run any workflow as a background job.</p> <p><b><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7610.Invoke_2D00_Install_2D00_VM_5F00_182338EC.png"><img width="591" height="32" title="Invoke-Install-VM" style="margin: 0px 0px 0px 30px; border: 0px currentcolor; display: inline; background-image: none;" alt="Invoke-Install-VM" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3312.Invoke_2D00_Install_2D00_VM_5F00_thumb_5F00_3EF14F2C.png" border="0" /></a></b></p> <p><b><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7115.InvokeAsJob_2D00_Install_2D00_VM_5F00_13ACB825.png"><img width="706" height="42" title="InvokeAsJob-Install-VM" style="margin: 0px 0px 0px 30px; display: inline; background-image: none;" alt="InvokeAsJob-Install-VM" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0172.InvokeAsJob_2D00_Install_2D00_VM_5F00_thumb_5F00_3E851C37.png" border="0" /></a></b></p> <h3>Join-In</h3> <p>Now that you know how easy it is to author workflows using PowerShell syntax, please try your hand at creating couple of workflows for long-running multi-machine scenarios and tell us about your experience (and feature requests J ). As always, you can send feedback directly to us by using the <a href="http://connect.microsoft.com/powershell">Windows PowerShell Connect site</a>.</p> <p>While we create our next set of blog posts about Windows PowerShell Workflow, enjoy some additional resources about Windows PowerShell 3.0 and Windows PowerShell Workflow:</p> <ul> <li><a href="http://www.windowsitpro.com/blog/powershell-with-a-purpose-blog-36/windows-powershell/powershell-v3-workflow-flagship-feature-140712">PowerShell v3: Workflow is the Flagship Feature</a> (by Don Jones &ndash; PowerShell MVP)</li> <li><a href="http://halr9000.com/article/947">PowerShell Workflow, Defined</a> (by Hal Rottenberg &ndash; PowerShell MVP)</li> <li><a href="http://technet.microsoft.com/library/hh847767.aspx">PowerShell Workflow module</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.powershell.workflow(v=VS.85).aspx">PowerShell Workflow SDK documentation</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/hh852738(v=vs.85).aspx">Authoring a Workflow using PowerShell Activities</a></li> </ul> <p>Hemant Mahawar [MSFT] <br />Senior Program Manager <br />Windows PowerShell</p> <p>&nbsp;</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10332271" width="1" height="1"></description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-33-22-71/Install_2D00_VM.psm1" length="5138" type="application/octet-stream" /><category domain="http://blogs.msdn.com/b/powershell/archive/tags/LANGUAGE/">LANGUAGE</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/CMDLET/">CMDLET</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Get_2D00_Command/">Get-Command</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell/">PowerShell</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Functions/">Functions</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Workflow/">Workflow</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+Workflow/">PowerShell Workflow</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Getting+Started/">Getting Started</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Powershell+3-0/">Powershell 3.0</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>Windows PowerShell Web Access - Installation guide II</title><link>http://blogs.msdn.com/b/powershell/archive/2012/07/18/windows-powershell-web-access-install.aspx</link><pubDate>Wed, 18 Jul 2012 08:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10330330</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10330330</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/07/18/windows-powershell-web-access-install.aspx#comments</comments><description><p><span style="font-size: small; font-family: arial, helvetica, sans-serif;"><span face="Calibri">This blog is a continuation of the post on </span><a href="http://blogs.msdn.com/b/powershell/archive/2012/06/27/windows-powershell-web-access-basic-installation-guide.aspx"><span style="color: #0000ff;" face="Calibri" color="#0000ff">Basic installation guide for PowerShell Web Access</span></a><span face="Calibri">. In the basic installation blog, we configured IIS with the default values used by the Install-PswaWebApplication cmdlet. This is the simplest way to install and configure the feature. </span></span></p> <p><span style="font-family: arial, helvetica, sans-serif; font-size: small;" face="Calibri">&nbsp;</span></p> <p><span style="font-family: arial, helvetica, sans-serif; font-size: small;" face="Calibri">The video below illustrates two more ways to configure IIS &ndash;</span></p> <p style="padding-left: 30px;"><span style="font-size: small; font-family: arial, helvetica, sans-serif;"><b><span face="Calibri">1. Using Install-PswaWebApplication</span></b></span></p> <p style="padding-left: 30px;"><span style="font-family: arial, helvetica, sans-serif; font-size: small;" face="Calibri">&nbsp;&nbsp;&nbsp;&nbsp; In this case we specify values for &ndash;WebSiteName and &ndash;WebApplication parameters for the cmdlet</span></p> <p style="padding-left: 30px;"><span style="font-size: small; font-family: arial, helvetica, sans-serif;"><b><span face="Calibri">2. </span></b><b><span face="Calibri">Using the GUI equivalent</span></b></span></p> <p style="padding-left: 30px;"><span style="font-family: arial, helvetica, sans-serif; font-size: small;" face="Calibri">&nbsp;&nbsp;&nbsp;&nbsp; In this case, we use IIS Manager to configure the website and the web application pool. <b></b></span></p> <p><span style="font-family: arial, helvetica, sans-serif; font-size: small;" face="Calibri">&nbsp;</span></p> <p><span style="font-size: small; font-family: arial, helvetica, sans-serif;"><span face="Calibri">Detailed instructions on different ways to configure IIS can also be found in the </span><a href="http://technet.microsoft.com/en-us/library/hh831611.aspx#BKMK_config"><span style="color: #0000ff;" face="Calibri" color="#0000ff">Windows PowerShell Web Access help document</span></a><span face="Calibri">. </span></span></p> <p><span style="font-size: small; font-family: arial, helvetica, sans-serif;"><span face="Calibri">The video also briefly describes how the events are logged for </span><a href="http://blogs.msdn.com/b/powershell/archive/2012/03/07/introducing-windows-powershell-web-access-in-windows-server-8-beta.aspx"><span style="color: #0000ff;" face="Calibri" color="#0000ff">PowerShell Web Access</span></a><span face="Calibri">. Admins can use this information to troubleshoot login failures.</span></span></p> <script src="http://technet.microsoft.com/en-us/videoembed/installation-guide-it-for-windows-powershell-web-access" type="text/javascript"></script> <p></p> <p><span style="font-size: small; font-family: arial, helvetica, sans-serif;">&nbsp;</span></p> <p><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Kriti Jindal</span></p> <p><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Program Manager</span></p> <p><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Windows PowerShell Web Access</span></p> <p><span style="font-family: arial, helvetica, sans-serif; font-size: small;">Microsoft Corporation</span></p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10330330" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server/">Windows Server</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+Web+Access/">PowerShell Web Access</category></item><item><title>Join-Object</title><link>http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx</link><pubDate>Fri, 13 Jul 2012 22:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10329770</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10329770</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/07/13/join-object.aspx#comments</comments><description><h1><span style="color: #000080; font-family: arial,helvetica,sans-serif;">Problem:</span></h1> <p><span style="font-family: arial,helvetica,sans-serif;">How do I join two lists of objects into a single list? Or the equivalent: How do I join two CSV files into a single one?</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Note that joining makes sense only when the two lists or CSV files have something in common.</span></p> <p>&nbsp;</p> <h1><span style="color: #000080; font-family: arial,helvetica,sans-serif;">Why do we need Join?</span></h1> <p><span style="font-family: arial,helvetica,sans-serif;">If </span><span style="font-family: arial,helvetica,sans-serif;">you know why you need join would not enjoy a review of basic database concepts, </span><span style="font-family: arial,helvetica,sans-serif;">feel free to skip this section.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Say </span><span style="font-family: arial,helvetica,sans-serif;">you own a company and want to keep track of the time when your employees </span><span style="font-family: arial,helvetica,sans-serif;">arrive. A simplified table of employees could look like this:</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="107" colspan="2"> <p align="center"><span style="font-family: arial,helvetica,sans-serif;"><b>Employee</b></span></p> </td> </tr> <tr> <td width="30"> <p style="text-align: right;"><span style="font-family: arial,helvetica,sans-serif;"><b>Id</b></span></p> </td> <td width="75"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>Name</b></span></p> </td> </tr> <tr> <td width="30"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">1</span></p> </td> <td width="75"> <p><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> </tr> <tr> <td width="30"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">2</span></p> </td> <td width="75"> <p><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> </tr> <tr> <td width="30"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">3</span></p> </td> <td width="75"> <p><span style="font-family: arial,helvetica,sans-serif;">Hanna</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;<span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">The </span><span style="font-family: arial,helvetica,sans-serif;">id uniquely identifies an employee because two employees can have the same </span><span style="font-family: arial,helvetica,sans-serif;">name. A full table would have more employees. It would also have last name, </span><span style="font-family: arial,helvetica,sans-serif;">first name, the date the employee joined the company, and other columns.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The </span><span style="font-family: arial,helvetica,sans-serif;">Entrance table that contains each employee's arrival time might look like this:</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="332" colspan="2"> <p align="center"><span style="font-family: arial,helvetica,sans-serif;"><b>Entrance</b></span></p> </td> </tr> <tr> <td width="105"> <p style="text-align: right;"><span style="font-family: arial,helvetica,sans-serif;"><b>Employee&nbsp; Id</b></span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>When</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">1</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 08:05:01 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">1</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 07:59:12 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">1</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/14/2012 07:49:10 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">2</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 10:33:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">2</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 10:15:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">44</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">2/29/2012 01:00:00 AM</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">The &ldquo;When&rdquo; </span><span style="font-family: arial,helvetica,sans-serif;">column has both the date and the time. Types like DateTime are common for .Net </span><span style="font-family: arial,helvetica,sans-serif;">Objects and databases.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">We can </span><span style="font-family: arial,helvetica,sans-serif;">conclude the following from the data:</span></p> <ol> <li><span style="font-family: arial,helvetica,sans-serif;">John </span><span style="font-family: arial,helvetica,sans-serif;">(the employee with id 1) seems to arrive early; at around 8.</span></li> <li><span style="font-family: arial,helvetica,sans-serif;">Mark </span><span style="font-family: arial,helvetica,sans-serif;">(the employee with id 2) is not a morning person (I like him already).</span></li> <li><span style="font-family: arial,helvetica,sans-serif;">Mary </span><span style="font-family: arial,helvetica,sans-serif;">is more of a &ldquo;work from home&rdquo; kind of person. She has never entered the company </span><span style="font-family: arial,helvetica,sans-serif;">headquarters.</span></li> <li><span style="font-family: arial,helvetica,sans-serif;">What </span><span style="font-family: arial,helvetica,sans-serif;">about the Employee with id 44? There is no such employee in our table! And what </span><span style="font-family: arial,helvetica,sans-serif;">nefarious thing was he doing at 1:00 am on February 29? I wonder if he will be coming </span><span style="font-family: arial,helvetica,sans-serif;">back in 4 years&hellip; </span><span style="font-family: arial,helvetica,sans-serif;">Employee </span><span style="font-family: arial,helvetica,sans-serif;">44 seems to be a mistake. Maybe the data was entered incorrectly. In some </span><span style="font-family: arial,helvetica,sans-serif;">databases, you can use &ldquo;referential integrity&rdquo; to make sure that such mistakes </span><span style="font-family: arial,helvetica,sans-serif;">never make into your table data. Obviously, this system doesn't have a check </span><span style="font-family: arial,helvetica,sans-serif;">like that.</span></li> </ol> <p><span style="font-family: arial,helvetica,sans-serif;">Wait </span><span style="font-family: arial,helvetica,sans-serif;">a minute, why do we have two tables instead of one? </span></p> <p><span style="font-family: arial,helvetica,sans-serif;">A simple one-table solution </span><span style="font-family: arial,helvetica,sans-serif;">might look like this:</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="332" colspan="2"> <p align="center"><span style="font-family: arial,helvetica,sans-serif;"><b>Employee Entrance</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;"><b>Employee</b></span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>When</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 08:05:01 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 07:59:12 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/14/2012 07:49:10 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 10:33:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 10:15:00 AM</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">Before </span><span style="font-family: arial,helvetica,sans-serif;">throwing stones at this solution, I should say this could work for the simplest </span><span style="font-family: arial,helvetica,sans-serif;">of cases. As we are going to see below, it doesn&rsquo;t work if things get a bit </span><span style="font-family: arial,helvetica,sans-serif;">more complex, so it is not future-proof. Now, for more specific stones:</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">In </span><span style="font-family: arial,helvetica,sans-serif;">the table above, John&rsquo;s 3 entrances and Mark&rsquo;s 2 entrances are recorded, but I </span><span style="font-family: arial,helvetica,sans-serif;">omitted the Entrance for id 44 that we used to have, because he doesn&rsquo;t have a </span><span style="font-family: arial,helvetica,sans-serif;">name. If we consider that we can have 2 Johns working for the company, we will </span><span style="font-family: arial,helvetica,sans-serif;">need an ID, as seen below. We can also have more data for each employee, like </span><span style="font-family: arial,helvetica,sans-serif;">their Last Name:</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="504" colspan="4"> <p align="center"><span style="font-family: arial,helvetica,sans-serif;"><b>Employee Entrance</b></span></p> </td> </tr> <tr> <td width="41"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;"><b>Id</b></span></p> </td> <td width="112"> <p style="text-align: right;"><span style="font-family: arial,helvetica,sans-serif;"><b>First Name</b></span></p> </td> <td width="114"> <p style="text-align: right;"><span style="font-family: arial,helvetica,sans-serif;"><b>Last Name</b></span></p> </td> <td width="231" valign="top"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>When</b></span></p> </td> </tr> <tr> <td width="41"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">1</span></p> </td> <td width="112"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="114"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Smith</span></p> </td> <td width="231"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 08:05:01 AM</span></p> </td> </tr> <tr> <td width="41"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">1</span></p> </td> <td width="112"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="114"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Smith</span></p> </td> <td width="231"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 07:59:12 AM</span></p> </td> </tr> <tr> <td width="41"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">1</span></p> </td> <td width="112"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="114"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Smith</span></p> </td> <td width="231"> <p><span style="font-family: arial,helvetica,sans-serif;">6/14/2012 07:49:10 AM</span></p> </td> </tr> <tr> <td width="41"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">2</span></p> </td> <td width="112"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="114"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">West</span></p> </td> <td width="231"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 10:33:00 AM</span></p> </td> </tr> <tr> <td width="41"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">2</span></p> </td> <td width="112"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="114"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">West</span></p> </td> <td width="231"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 10:15:00 AM</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">This re</span><span style="font-family: arial,helvetica,sans-serif;">petition of first name and last name is one of the reasons we have two </span><span style="font-family: arial,helvetica,sans-serif;">tables. Having two tables allows us to have an Entrance Table, where we repeat </span><span style="font-family: arial,helvetica,sans-serif;">just the Employee Id, a small amount of data. This way, the tables can evolve </span><span style="font-family: arial,helvetica,sans-serif;">separately. If we start adding columns for Employees, like Address, Phone, </span><span style="font-family: arial,helvetica,sans-serif;">etc., nothing changes in the Entrance table.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">There </span><span style="font-family: arial,helvetica,sans-serif;">is one more fundamental reason to have two tables. Say we want to start keeping </span><span style="font-family: arial,helvetica,sans-serif;">track of employee payments. If the employees are in the same table as their entrance, </span><span style="font-family: arial,helvetica,sans-serif;">how do add the payments? It clearly does not fit in the same table, because </span><span style="font-family: arial,helvetica,sans-serif;">there would be multiple payments per employee and there are already multiple </span><span style="font-family: arial,helvetica,sans-serif;">employee entries for their entrances.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The </span><span style="font-family: arial,helvetica,sans-serif;">proper way to express the concept of one of Employee and multiple entrances is </span><span style="font-family: arial,helvetica,sans-serif;">to have two tables. Then, it is going to be simple to add columns to the </span><span style="font-family: arial,helvetica,sans-serif;">Employee table or add another table for their multiple payments. Another way to </span><span style="font-family: arial,helvetica,sans-serif;">say this is that a one-to-many relationship, like one employee to many payments, </span><span style="font-family: arial,helvetica,sans-serif;">or one employee to many entrances, needs a separate table. </span></p> <p><span style="font-family: arial,helvetica,sans-serif;"><span style="font-family: arial,helvetica,sans-serif;">It </span><span style="font-family: arial,helvetica,sans-serif;">turns out that problems we can easily describe conceptually can often require many </span><span style="font-family: arial,helvetica,sans-serif;">tables.</span></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">For </span><span style="font-family: arial,helvetica,sans-serif;">example, let&rsquo;s consider keeping track of sales at a fruit stand. That seems </span><span style="font-family: arial,helvetica,sans-serif;">simple enough conceptually, but let&rsquo;s see what is involved in this task. We </span><span style="font-family: arial,helvetica,sans-serif;">have customers, fruit (our product), and sales. Each sale receipt has one or </span><span style="font-family: arial,helvetica,sans-serif;">more lines, in which each line describes a product and its quantity. The tables </span><span style="font-family: arial,helvetica,sans-serif;">we have are:</span></p> <ol> <li>The customer table with name, delivery address, phone, etc.</li> <li>The product table with name, price, etc.</li> <li>The sales table with date and customer.</li> <li>The sale item table with the sale (id), product (id) and quantity.</li> </ol> <p>The information on a customer receipt would be gathered from all 4 tables and we would need to join this information from multiple tables.</p> <p><span style="font-family: arial,helvetica,sans-serif;">If </span><span style="font-family: arial,helvetica,sans-serif;">even simple conceptual problems require many tables, joining tables becomes a </span><span style="font-family: arial,helvetica,sans-serif;">fundamental need, which brings us to the next section.</span></p> <p>&nbsp;</p> <h1><span style="color: #000080; font-family: arial,helvetica,sans-serif;">The different types of Joins</span></h1> <p><span style="font-family: arial,helvetica,sans-serif;">Let&rsquo;s look </span><span style="font-family: arial,helvetica,sans-serif;">at our entrance data again.</span></p> <table style="width: 560px; height: 362px;" border="1"> <tbody> <tr> <td> <table style="margin-right: auto; margin-left: auto;" border="0" cellpadding="0"> <tbody> <tr> <td width="50" colspan="2"> <p align="center"><b>Employee</b></p> </td> </tr> <tr> <td width="30"> <p style="text-align: right;"><b>Id</b></p> </td> <td width="75" style="text-align: center;"> <p><b>Name</b></p> </td> </tr> <tr> <td width="30"> <p align="right">1</p> </td> <td width="75" style="text-align: center;"> <p>John</p> </td> </tr> <tr> <td width="30"> <p align="right">2</p> </td> <td width="75" style="text-align: center;"> <p>Mark</p> </td> </tr> <tr> <td width="30"> <p align="right">3</p> </td> <td width="75" style="text-align: center;"> <p>Hanna</p> </td> </tr> </tbody> </table> </td> <td> <table style="margin-right: auto; margin-left: auto;" border="0" cellpadding="0"> <tbody> <tr> <td width="332" colspan="2"> <p align="center"><b>Entrance</b></p> </td> </tr> <tr> <td width="105"> <p style="text-align: right;"><b>Employee&nbsp; Id</b></p> </td> <td width="225" style="text-align: center;"> <p><b>When</b></p> </td> </tr> <tr> <td width="105"> <p align="right">1</p> </td> <td width="225" style="text-align: center;"> <p>6/12/2012 08:05:01 AM</p> </td> </tr> <tr> <td width="105"> <p align="right">1</p> </td> <td width="225" style="text-align: center;"> <p>6/13/2012 07:59:12 AM</p> </td> </tr> <tr> <td width="105"> <p align="right">1</p> </td> <td width="225" style="text-align: center;"> <p>6/14/2012 07:49:10 AM</p> </td> </tr> <tr> <td width="105"> <p align="right">2</p> </td> <td width="225" style="text-align: center;"> <p>6/12/2012 10:33:00 AM</p> </td> </tr> <tr> <td width="105"> <p align="right">2</p> </td> <td width="225" style="text-align: center;"> <p>6/13/2012 10:15:00 AM</p> </td> </tr> <tr> <td width="105"> <p align="right">44</p> </td> <td width="225" style="text-align: center;"> <p>2/29/2012 01:00:00 AM</p> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <p><br /><span style="font-family: arial,helvetica,sans-serif;">Now that </span><span style="font-family: arial,helvetica,sans-serif;">the tables are separate and future-proof, we might want a view of the data that </span><span style="font-family: arial,helvetica,sans-serif;">joins the name and entrance date/time for each employee. This can be done in 4 different </span><span style="font-family: arial,helvetica,sans-serif;">ways:</span></p> <p><strong>&nbsp;<span style="font-family: arial,helvetica,sans-serif;">1) Only the Employees with Entrances and Entrances with an Employee (SQL </span><span style="font-family: arial,helvetica,sans-serif;">Inner Join)</span></strong></p> <p><span style="font-family: arial,helvetica,sans-serif;">This join shows all </span><span style="font-family: arial,helvetica,sans-serif;">the employee entrances except for the Entrance for Employee 44 that has no </span><span style="font-family: arial,helvetica,sans-serif;">corresponding Id. It also does not show a line for Hanna because there is no </span><span style="font-family: arial,helvetica,sans-serif;">entry for her in the Entrance table.</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;"><b>Name</b></span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>When</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 08:05:01 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 07:59:12 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/14/2012 07:49:10 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 10:33:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 10:15:00 AM</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">An example </span><span style="font-family: arial,helvetica,sans-serif;">of a SQL statement that would perform this join looks like this:</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">SELECT&nbsp;&nbsp; <b>Employee.Name</b>,</span><span style="font-family: arial,helvetica,sans-serif;"><b>Entrance.[When]</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">FROM&nbsp;&nbsp;&nbsp; <b>Employee</b></span><br /><span style="font-family: arial,helvetica,sans-serif;"><i>INNER JOIN</i> <b>Entrance</b> ON <b>Employee.id</b> =<b> Entrance.EmployeeId</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;"><i>Select</i> enumerates the columns, which are </span><span style="font-family: arial,helvetica,sans-serif;">Name from the Employee table, and When from the Entrance table. The square brackets </span><span style="font-family: arial,helvetica,sans-serif;">surrounding &ldquo;<b>[</b>When<b>]</b>&rdquo;&nbsp;</span><span style="font-family: arial,helvetica,sans-serif;">distinguish the &ldquo;When&rdquo;&nbsp; column </span><span style="font-family: arial,helvetica,sans-serif;">name from the "When" SQL command. This is required only for SQL </span><span style="font-family: arial,helvetica,sans-serif;">language keywords.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Employee is &ldquo;inner </span><span style="font-family: arial,helvetica,sans-serif;">joined&rdquo; to Entrance by the statement:&nbsp;Employee.id = Entrance.EmployeeId.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Inner Join is the </span><span style="font-family: arial,helvetica,sans-serif;">name SQL gives to this kind of join where an item appears in the result only if </span><span style="font-family: arial,helvetica,sans-serif;">the join statement (Employee.id = Entrance.EmployeeId) is true in <strong>both</strong> tables </span><span style="font-family: arial,helvetica,sans-serif;">being joined. Hanna has her ID of 3, but there is no 3 in the Entrance table to </span><span style="font-family: arial,helvetica,sans-serif;">make this statement true. Employee 44 has his Entrance but there is no ID in </span><span style="font-family: arial,helvetica,sans-serif;">the Employee table corresponding to 44 that would make the statement true.</span></p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"><b>2) All Employees (SQL Left Outer Join)</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">This join shows all employees, </span><span style="font-family: arial,helvetica,sans-serif;">including Hanna who has no corresponding entry in the Entrance table.</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;"><b>Name</b></span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>When</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 08:05:01 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 07:59:12 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/14/2012 07:49:10 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 10:33:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 10:15:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Hanna</span></p> </td> <td width="225"> <p>&nbsp;</p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">The SQL Statement looks like:</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">SELECT&nbsp;&nbsp; <b>Employee.Name</b>, </span><span style="font-family: arial,helvetica,sans-serif;"><b>Entrance.[When]</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">FROM&nbsp;&nbsp;&nbsp; <b>Employee</b></span><br /><span style="font-family: arial,helvetica,sans-serif;"><i>LEFT OUTER JOIN</i> <b>Entrance</b> ON <b>Employee.id = Entrance.EmployeeId</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The </span><span style="font-family: arial,helvetica,sans-serif;">only change in this second SQL statement is the use of &ldquo;LEFT OUTER JOIN&rdquo; </span><span style="font-family: arial,helvetica,sans-serif;">(instead of inner join).</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Left </span><span style="font-family: arial,helvetica,sans-serif;">refers to the fact that <strong>all</strong> elements of the left table in &ldquo;Employee LEFT OUTER </span><span style="font-family: arial,helvetica,sans-serif;">JOIN Entrance&rdquo; (which is Employee) will appear in the result. &ldquo;</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">OUTER </span><span style="font-family: arial,helvetica,sans-serif;">is in opposition to the INNER join and it allows Hanna to be listed even though </span><span style="font-family: arial,helvetica,sans-serif;">her Employee.id is not in any of the Entrance&rsquo;s EmployeeIds.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Note: </span><span style="font-family: arial,helvetica,sans-serif;">Some SQL variants will not use &ldquo;OUTER&rdquo;.</span></p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"><b>3) All Entrances (SQL Right Outer Join)</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">This </span><span style="font-family: arial,helvetica,sans-serif;">join has all of the Entrances, including the entry for Employee 44 even </span><span style="font-family: arial,helvetica,sans-serif;">though there is no corresponding employee Id for that in the Employee&rsquo;s table.</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;"><b>Name</b></span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>When</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 08:05:01 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 07:59:12 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/14/2012 07:49:10 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 10:33:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 10:15:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right">&nbsp;</p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">2/29/2012 01:00:00 AM</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;<span style="font-family: arial,helvetica,sans-serif;">The SQL Statement looks like:</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">SELECT&nbsp;&nbsp; <b>Employee.Name</b>, </span><span style="font-family: arial,helvetica,sans-serif;"><b>Entrance.[When]</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">FROM&nbsp;&nbsp;&nbsp; <b>Employee</b></span><br /><span style="font-family: arial,helvetica,sans-serif;"><i>RIGHT OUTER JOIN</i> <b>Entrance</b> ON <b>Employee.id = Entrance.EmployeeId</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The </span><span style="font-family: arial,helvetica,sans-serif;">only change to the previous join SQL statement is the use of &ldquo;RIGHT&rdquo; instead of </span><span style="font-family: arial,helvetica,sans-serif;">&ldquo;LEFT&rdquo;.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Right </span><span style="font-family: arial,helvetica,sans-serif;">refers to the fact that all elements of the left table in &ldquo;Employee RIGHT OUTER </span><span style="font-family: arial,helvetica,sans-serif;">JOIN Entrance&rdquo; (which is Entrance) will appear in the result. &ldquo;</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Note: </span><span style="font-family: arial,helvetica,sans-serif;">Some SQL variants will not use &ldquo;OUTER&rdquo;.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;"><b>&nbsp;</b></span><span style="font-family: arial,helvetica,sans-serif;"><b>&nbsp;</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;"><b>4) All Entrances and Employees (SQL Full Join)</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The </span><span style="font-family: arial,helvetica,sans-serif;">join below shows all employees and all entrances, including Employees with no </span><span style="font-family: arial,helvetica,sans-serif;">corresponding entrances (Hanna) or entrances with no corresponding employee </span><span style="font-family: arial,helvetica,sans-serif;">(the entrance for Employee 44).</span></p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;"><b>Name</b></span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>When</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 08:05:01 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 07:59:12 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">John</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/14/2012 07:49:10 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/12/2012 10:33:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Mark</span></p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">6/13/2012 10:15:00 AM</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">Hanna</span></p> </td> <td width="225"> <p>&nbsp;</p> </td> </tr> <tr> <td width="105"> <p align="right">&nbsp;</p> </td> <td width="225"> <p><span style="font-family: arial,helvetica,sans-serif;">2/29/2012 01:00:00 AM</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">The SQL Statement looks like:</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">SELECT&nbsp;&nbsp; <b>Employee.Name</b>, </span><span style="font-family: arial,helvetica,sans-serif;"><b>Entrance.[When]</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">FROM&nbsp;&nbsp;&nbsp; <b>Employee</b></span><br /><span style="font-family: arial,helvetica,sans-serif;"><i>FULL OUTER JOIN</i> <b>Entrance</b> ON <b>Employee.id = Entrance.EmployeeId</b></span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The </span><span style="font-family: arial,helvetica,sans-serif;">only change to the previous join the use of &ldquo;FULL&rdquo; instead of &ldquo;RIGHT&rdquo; or </span><span style="font-family: arial,helvetica,sans-serif;">&ldquo;LEFT&rdquo;.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Full </span><span style="font-family: arial,helvetica,sans-serif;">refers to the fact that all elements of both join sides (Employee and Entrance </span><span style="font-family: arial,helvetica,sans-serif;">specified in &ldquo;Employee FULL OUTER JOIN Entrance&rdquo;) will appear in the result. </span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Note: </span><span style="font-family: arial,helvetica,sans-serif;">Some SQL variants will not use &ldquo;OUTER&rdquo;.</span></p> <p>&nbsp;</p> <h1><span style="color: #000080; font-family: arial,helvetica,sans-serif;">Join in Windows PowerShell</span></h1> <p><span style="font-family: arial,helvetica,sans-serif;">There is no built-in </span><span style="font-family: arial,helvetica,sans-serif;">cmdlet for joining in Windows PowerShell, so the remainder of this post will be </span><span style="font-family: arial,helvetica,sans-serif;">about building a cmdlet called Join-Object that performs the four join </span><span style="font-family: arial,helvetica,sans-serif;">operations in lists of objects in memory. Those objects can come from different </span><span style="font-family: arial,helvetica,sans-serif;">places, including csv files.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">For example, lets create a couple </span><span style="font-family: arial,helvetica,sans-serif;">of CSV files that contain the sample data we have been using:</span></p> <p><span style="font-family: courier new,courier;">@"</span><br /><span style="font-family: courier new,courier;">Id,Name</span><br /><span style="font-family: courier new,courier;">1,John</span><br /><span style="font-family: courier new,courier;">2,Mark</span><br /><span style="font-family: courier new,courier;">3,Hanna</span><br /><span style="font-family: courier new,courier;">"@ &gt; c:\temp\employee.csv</span></p> <p><span style="font-family: courier new,courier;">@"</span><br /><span style="font-family: courier new,courier;">EmployeeId,When</span><br /><span style="font-family: courier new,courier;">1,6/12/2012 08:05:01 AM</span><br /><span style="font-family: courier new,courier;">1,6/13/2012 07:59:12 AM</span><br /><span style="font-family: courier new,courier;">1,6/14/2012 07:49:10 AM</span><br /><span style="font-family: courier new,courier;">2,6/12/2012 10:33:00 AM</span><br /><span style="font-family: courier new,courier;">2,6/13/2012 10:15:00 AM</span><br /><span style="font-family: courier new,courier;">44,2/29/2012 01:00:00 AM</span><br /><span style="font-family: courier new,courier;">"@ &gt; c:\temp\entrance.csv</span></p> <p><span style="font-family: courier new,courier;">$employee = Import-Csv c:\temp\employee.csv</span><br /><span style="font-family: courier new,courier;">$entrance = Import-Csv c:\temp\entrance.csv</span></p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">After running these commands, we </span><span style="font-family: arial,helvetica,sans-serif;">have:</span></p> <p><span style="font-family: courier new,courier;">PS C:\temp&gt; $employee</span></p> <p><span style="font-family: courier new,courier;">Id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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;&nbsp;&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><br /><span style="font-family: courier new,courier;">--&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hanna&nbsp;&nbsp;</span></p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">And:</span></p> <p><span style="font-family: courier new,courier;">PS C:\temp&gt; $entrance</span></p> <p>&nbsp;</p> <p><span style="font-family: courier new,courier;">EmployeeId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; When&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">----------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 08:05:01 AM</span><br /><span style="font-family: courier new,courier;">1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 07:59:12 AM</span><br /><span style="font-family: courier new,courier;">1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/14/2012 07:49:10 AM</span><br /><span style="font-family: courier new,courier;">2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 10:33:00 AM</span><br /><span style="font-family: courier new,courier;">2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 10:15:00 AM</span><br /><span style="font-family: courier new,courier;">44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2/29/2012 01:00:00 AM</span></p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">I chose CSV because you can find </span><span style="font-family: arial,helvetica,sans-serif;">data to be joined in CSV files and also because it&rsquo;s a compact way to show the sample </span><span style="font-family: arial,helvetica,sans-serif;">data.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Below are 4 calls to the Join-Object&nbsp;</span><span style="font-family: arial,helvetica,sans-serif;">that produce the equivalent of the 4 types of join.</span></p> <p>&nbsp;</p> <p><span style="font-family: courier new,courier;">PS C:\temp&gt; Join-Object -Left $employee -Right $entrance -Where {$args[0].Id -eq $args[1].EmployeeId} &ndash;LeftProperties "Name" &ndash;RightProperties "When" -Type OnlyIfInBoth</span></p> <p>&nbsp;</p> <p><span style="font-family: courier new,courier;">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; When&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 08:05:01 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 07:59:12 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/14/2012 07:49:10 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 10:33:00 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 10:15:00 AM&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;&nbsp;</p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">Join-Object&rsquo;s first </span><span style="font-family: arial,helvetica,sans-serif;">two parameters are the left and right lists of objects.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The &ldquo;Where&rdquo; </span><span style="font-family: arial,helvetica,sans-serif;">parameter is the join condition, and it uses $args[0] to represent an item from </span><span style="font-family: arial,helvetica,sans-serif;">the left list and $args[1] for an item in the right list.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The RightProperties </span><span style="font-family: arial,helvetica,sans-serif;">and LeftProperties parameters are the names of the properties to appear in the </span><span style="font-family: arial,helvetica,sans-serif;">output from the left list and right list.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">The Type parameter </span><span style="font-family: arial,helvetica,sans-serif;">is one of four names: AllInLeft, AllInRight, OnlyIfInBoth and AllInBoth. I </span><span style="font-family: arial,helvetica,sans-serif;">thought those four names were simpler to relate to their functionality than </span><span style="font-family: arial,helvetica,sans-serif;">SQL&rsquo;s <i>full</i>, <i>inner</i> and <i>outer</i> names, </span><span style="font-family: arial,helvetica,sans-serif;">but here is a mapped correspondence:</span></p> <p>&nbsp;&nbsp;</p> <div align="center"> <table style="float: left;" border="0" cellpadding="0"> <tbody> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;"><b>Join-Object</b></span></p> </td> <td width="129"> <p><span style="font-family: arial,helvetica,sans-serif;"><b>SQL</b></span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">AllInLeft</span></p> </td> <td width="129"> <p><span style="font-family: arial,helvetica,sans-serif;">Left Outer</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">AllIInRight</span></p> </td> <td width="129"> <p><span style="font-family: arial,helvetica,sans-serif;">Right Outer</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">OnlyIfInBoth</span></p> </td> <td width="129"> <p><span style="font-family: arial,helvetica,sans-serif;">Inner</span></p> </td> </tr> <tr> <td width="105"> <p align="right"><span style="font-family: arial,helvetica,sans-serif;">AllInBoth</span></p> </td> <td width="129"> <p><span style="font-family: arial,helvetica,sans-serif;">Full Outer</span></p> </td> </tr> </tbody> </table> </div> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">Here is an example of AllInLeft:&nbsp;&nbsp;</span></p> <p>&nbsp;</p> <p><span style="font-family: courier new,courier;">PS C:\temp&gt; Join-Object -Left $employee -Right $entrance -Where {$args[0].Id -eq $args[1].EmployeeId} -LeftProperties "Name" -RightProperties "When" -Type AllInLeft</span></p> <p>&nbsp;</p> <p><span style="font-family: courier new,courier;">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; When&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 08:05:01 AM&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 07:59:12 AM&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/14/2012 07:49:10 AM&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 10:33:00 AM&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 10:15:00 AM&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Hanna&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p> <p>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif;">Here is the output of AllInRight:</span></p> <p><span style="font-family: courier new,courier;">PS C:\temp&gt; Join-Object -Left $employee -Right $entrance -Where {$args[0].Id -eq $args[1].EmployeeId} -LeftProperties "Name" -RightProperties "When" -Type AllInRight&nbsp;</span></p> <p><span style="font-family: courier new,courier;">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; When&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 08:05:01 AM&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 07:59:12 AM&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/14/2012 07:49:10 AM&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 10:33:00 AM&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 10:15:00 AM&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2/29/2012 01:00:00 AM&nbsp;&nbsp;&nbsp;</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">And finally, the output of AllInBoth:</span></p> <p>&nbsp;</p> <p><span style="font-family: courier new,courier;">PS C:\temp&gt; Join-Object &ndash;Left $employee &ndash;Right $entrance &ndash;Where {$args[0].Id -eq $args[1].EmployeeId} &ndash;LeftProperties "Name" &ndash;RightProperties "When" -Type AllInBoth&nbsp;</span></p> <p><span style="font-family: courier new,courier;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; When&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 08:05:01 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 07:59:12 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">John&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/14/2012 07:49:10 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/12/2012 10:33:00 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Mark&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6/13/2012 10:15:00 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br /><span style="font-family: courier new,courier;">Hanna&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2/29/2012 01:00:00 AM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p> <h1><span style="color: #000080; font-family: arial,helvetica,sans-serif;">Conclusions</span></h1> <p><span style="font-family: arial,helvetica,sans-serif;">Join </span><span style="font-family: arial,helvetica,sans-serif;">is an essential tool for data centric problems because, usually, multiple </span><span style="font-family: arial,helvetica,sans-serif;">tables are necessary.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;">Data </span><span style="font-family: arial,helvetica,sans-serif;">centric problems are normally handled by database tools, but if you happen to </span><span style="font-family: arial,helvetica,sans-serif;">have CSV files with this kind of data, Join-Object might be useful.</span></p> <p><span style="font-family: arial,helvetica,sans-serif;"></span>&nbsp;</p> <p><span style="font-family: arial,helvetica,sans-serif; font-size: small;">Lucio Silveira [MSFT]</span></p> <h1>&nbsp;</h1> <h1><span style="color: #000080;">The Join-Object Script</span></h1> <p><span style="font-family: courier new,courier;">function AddItemProperties($item, $properties, $output)</span><br /><span style="font-family: courier new,courier;">{</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; if($item -ne $null)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach($property in $properties)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $propertyHash =$property -as [hashtable]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($propertyHash -ne $null)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $hashName=$propertyHash["name"] -as [string]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($hashName -eq $null)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw "there should be a string Name"&nbsp; </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $expression=$propertyHash["expression"] -as [scriptblock]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($expression -eq $null)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw "there should be a ScriptBlock Expression"&nbsp; </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $_=$item</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $expressionValue=&amp; $expression</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $output | add-member -MemberType "NoteProperty" -Name $hashName -Value $expressionValue</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # .psobject.Properties allows you to list the properties of any object, also known as "reflection"</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach($itemProperty in $item.psobject.Properties)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ($itemProperty.Name -like $property)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $output | add-member -MemberType "NoteProperty" -Name $itemProperty.Name -Value $itemProperty.Value</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">}</span></p> <p>&nbsp;&nbsp;&nbsp; <br /><span style="font-family: courier new,courier;">function WriteJoinObjectOutput($leftItem, $rightItem, $leftProperties, $rightProperties, $Type)</span><br /><span style="font-family: courier new,courier;">{</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; $output = new-object psobject</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; if($Type -eq "AllInRight")</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # This mix of rightItem with LeftProperties and vice versa is due to</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # the switch of Left and Right arguments for AllInRight</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AddItemProperties $rightItem $leftProperties $output</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AddItemProperties $leftItem $rightProperties $output</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; else</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AddItemProperties $leftItem $leftProperties $output</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AddItemProperties $rightItem $rightProperties $output</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; $output</span><br /><span style="font-family: courier new,courier;">}</span></p> <p><span style="font-family: courier new,courier;">&lt;#</span><br /><span style="font-family: courier new,courier;">.Synopsis</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp; Joins two lists of objects</span><br /><span style="font-family: courier new,courier;">.DESCRIPTION</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp; Joins two lists of objects</span><br /><span style="font-family: courier new,courier;">.EXAMPLE</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp; Join-Object $a $b "Id" ("Name","Salary")</span><br /><span style="font-family: courier new,courier;">#&gt;</span><br /><span style="font-family: courier new,courier;">function Join-Object</span><br /><span style="font-family: courier new,courier;">{</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; [CmdletBinding()]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; [OutputType([int])]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; Param</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; (</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # List to join with $Right</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$true,</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Position=0)]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [object[]]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $Left,</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # List to join with $Left</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$true,</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Position=1)]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [object[]]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $Right,</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Condition in which an item in the left matches an item in the right</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # typically something like: {$args[0].Id -eq $args[1].Id}</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$true,</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Position=2)]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [scriptblock]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $Where,</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Properties from $Left we want in the output.</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Each property can:</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # - Be a plain property name like "Name"</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # - Contain wildcards like "*"</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # - Be a hashtable like @{Name="Product Name";Expression={$_.Name}}. Name is the output property name</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp; and Expression is the property value. The same syntax is available in select-object and it is </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp; important for join-object because joined lists could have a property with the same name</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$true,</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Position=3)]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [object[]]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $LeftProperties,</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Properties from $Right we want in the output.</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Like LeftProperties, each can be a plain name, wildcard or hashtable. See the LeftProperties comments.</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$true,</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Position=4)]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [object[]]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $RightProperties,</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Type of join. </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp; AllInLeft will have all elements from Left at least once in the output, and might appear more than once</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # if the where clause is true for more than one element in right, Left elements with matches in Right are </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # preceded by elements with no matches. This is equivalent to an outer left join (or simply left join) </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # SQL statement.</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp; AllInRight is similar to AllInLeft.</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp; OnlyIfInBoth will cause all elements from Left to be placed in the output, only if there is at least one</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # match in Right. This is equivalent to a SQL inner join (or simply join) statement.</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp; AllInBoth will have all entries in right and left in the output. Specifically, it will have all entries</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # in right with at least one match in left, followed by all entries in Right with no matches in left, </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # followed by all entries in Left with no matches in Right.This is equivallent to a SQL full join.</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$false,</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Position=5)]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [ValidateSet("AllInLeft","OnlyIfInBoth","AllInBoth", "AllInRight")]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [string]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $Type="OnlyIfInBoth"</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; )</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; Begin</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # a list of the matches in right for each object in left</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $leftMatchesInRight = new-object System.Collections.ArrayList</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # the count for all matches&nbsp; </span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rightMatchesCount = New-Object "object[]" $Right.Count</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for($i=0;$i -lt $Right.Count;$i++)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rightMatchesCount[$i]=0</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; }</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; Process</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($Type -eq "AllInRight")</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # for AllInRight we just switch Left and Right</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $aux = $Left</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $Left = $Right</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $Right = $aux</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # go over items in $Left and produce the list of matches</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach($leftItem in $Left)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $leftItemMatchesInRight = new-object System.Collections.ArrayList</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $null = $leftMatchesInRight.Add($leftItemMatchesInRight)</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for($i=0; $i -lt $right.Count;$i++)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rightItem=$right[$i]</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($Type -eq "AllInRight")</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # For AllInRight, we want $args[0] to refer to the left and $args[1] to refer to right,</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # but since we switched left and right, we have to switch the where arguments</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $whereLeft = $rightItem</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $whereRight = $leftItem</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $whereLeft = $leftItem</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $whereRight = $rightItem</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(Invoke-Command -ScriptBlock $where -ArgumentList $whereLeft,$whereRight)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $null = $leftItemMatchesInRight.Add($rightItem)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rightMatchesCount[$i]++</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # go over the list of matches and produce output</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for($i=0; $i -lt $left.Count;$i++)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $leftItemMatchesInRight=$leftMatchesInRight[$i]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $leftItem=$left[$i]</span><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($leftItemMatchesInRight.Count -eq 0)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($Type -ne "OnlyIfInBoth")</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WriteJoinObjectOutput $leftItem&nbsp; $null&nbsp; $LeftProperties&nbsp; $RightProperties $Type</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach($leftItemMatchInRight in $leftItemMatchesInRight)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WriteJoinObjectOutput $leftItem $leftItemMatchInRight&nbsp; $LeftProperties&nbsp; $RightProperties $Type</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; }</span></p> <p><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; End</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #produce final output for members of right with no matches for the AllInBoth option</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($Type -eq "AllInBoth")</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for($i=0; $i -lt $right.Count;$i++)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rightMatchCount=$rightMatchesCount[$i]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($rightMatchCount -eq 0)</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $rightItem=$Right[$i]</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WriteJoinObjectOutput $null $rightItem $LeftProperties $RightProperties $Type</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">&nbsp;&nbsp;&nbsp; }</span><br /><span style="font-family: courier new,courier;">}</span></p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10329770" width="1" height="1"></description></item><item><title>Introducing Management OData Schema Designer</title><link>http://blogs.msdn.com/b/powershell/archive/2012/07/11/introducing-management-odata-schema-designer.aspx</link><pubDate>Tue, 10 Jul 2012 23:17:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10328585</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10328585</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/07/11/introducing-management-odata-schema-designer.aspx#comments</comments><description><p><font color="#000000" size="3"></font></p> <p class="MsoNormal" style="margin: 0in 0in 10pt;"><font color="#000000" size="2">We are excited to introduce the new </font><a href="http://archive.msdn.microsoft.com/mgmtODataWebServ/"><font size="2">Management OData Schema Designer tool</font></a><u><font color="#0000ff"></font></u><font color="#000000"><font size="2">.<o:p></o:p></font></font></p> <font size="2"></font> <p><font color="#000000"></font></p> <font size="2"></font> <p class="MsoNormal" style="margin: 0in 0in 10pt;"><font color="#000000" size="2">The tool’s goal is to accelerate evaluation /development on top of “Management OData IIS Extension” optional Windows Server 2012 feature. A very informative introduction about this feature can be found in the </font><a href="http://blogs.technet.com/b/windowsserver/archive/2012/03/30/standards-based-management-in-windows-server-8.aspx"><font size="2">Standards based management in Windows Server 8</font></a><span lang="EN" style="mso-ansi-language: en;"><u><font color="#0000ff"></font></u></span><font color="#000000"><font size="2"> <span lang="EN" style="mso-ansi-language: en;">by Jeffrey Snover and Wojtek Kozaczynski.</span><o:p></o:p></font></font></p> <font size="2"></font> <p><font color="#000000"></font></p> <font size="2"></font> <p class="MsoNormal" style="margin: 0in 0in 10pt;"><font color="#000000"><font size="2">The new tool has <o:p></o:p></font></font></p> <font size="2"></font> <ul> <li><font color="#000000"><font size="2">a user friendly schema creation experience (as a wizard) </font></font></li> <li><font color="#000000"><font size="2">custom Management OData endpoint deployment capabilities. </font></font></li> <li><font color="#000000"><font size="2">schema editing and validation capabilities</font></font></li> </ul> <font size="2"></font> <p><font color="#000000"></font></p> <font size="2"></font> <p class="MsoNormal" style="margin: 0in 0in 10pt;"><font color="#000000"><font size="2">There are 2 versions available:</font></font></p> <ul> <li> <div class="MsoNormal" style="margin: 0in 0in 10pt;"><font color="#000000"><font size="2">a stand-alone version of the tool: x86/x64 (targeted at ITPros)<o:p></o:p></font></font></div> </li> </ul> <blockquote> <p><font color="#000000"><font size="2"><i>Prerequisites</i>:&#160; </font><a href="http://www.microsoft.com/en-us/download/details.aspx?id=1366"><font size="2">Visual Studio Isolated Shell</font></a></font><span style="color: windowtext;"><u></u></span><font color="#000000"><font size="2"> <o:p></o:p></font></font></p> </blockquote> <font size="2"></font> <ul> <li><font color="#000000"><font size="2">a Visual Studio 2010 Ultimate/Pro plugin (the same functionality as the stand-alone tool)<o:p></o:p></font></font></li> </ul> <font size="2"></font> <p>&#160;</p> <font size="2"></font> <p><font color="#000000"></font></p> <font size="2"></font> <p class="MsoNormal" style="margin: 0in 0in 10pt;"><span style="color: rgb(8, 8, 8); line-height: 115%; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;; font-size: 8.5pt;"><font size="2" face="Segoe UI">Please use it and let us know if it is useful to you via the “Issue tracker”.</font></span></p> <p><font color="#000000" size="2"></font></p> <p><font color="#000000" size="2">Raluca Hera</font></p> <font color="#000000"></font> <p><font color="#000000" size="2">Program Manager, Windows Server Manageability</font></p> <font color="#000000"></font> <p><font color="#000000" size="2">Microsoft Corporation</font></p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10328585" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>OMI - Open Management Infrastructure to bring the power of PowerShell and standards to devices in your datacenter.</title><link>http://blogs.msdn.com/b/powershell/archive/2012/07/02/omi-open-management-infrastructure-to-bring-the-power-of-powershell-and-standards-to-devices-in-your-datacenter.aspx</link><pubDate>Mon, 02 Jul 2012 22:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10326305</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10326305</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/07/02/omi-open-management-infrastructure-to-bring-the-power-of-powershell-and-standards-to-devices-in-your-datacenter.aspx#comments</comments><description><p><span style="font-size: small;">PowerShell community,</span></p> <p><span style="font-size: small;">We are pleased to announce availability of OMI - a highly portable, small footprint, high performance CIM Object Manager. OMI stands for Open Management Infrastructure, and it is available from Open Group as an open source project. </span></p> <p><span style="font-size: small;">See this Windows Server blog post for full details. <a href="http://blogs.technet.com/b/windowsserver/archive/2012/06/28/open-management-infrastructure.aspx">http://blogs.technet.com/b/windowsserver/archive/2012/06/28/open-management-infrastructure.aspx</a></span><u5:p></u5:p></p> <p><span style="font-size: small;">OMI opens up management of hardware devices in a datacenter using&nbsp;what we call a &nbsp;"Datacenter Abstraction Layer" or DAL. Imagine configuring a set of &nbsp;hardware devices from different vendors&nbsp;(like&nbsp; network switches)&nbsp;using a set of PowerShell cmdlets - that's what DAL&nbsp;would bring to you. Basically, a<span style="font-size: small;"><span><span>ny</span> device or server &nbsp;that implements standard protocol and &nbsp;schema can be managed from standard compliant tools like <span>PowerShell</span>. A big blocker for IHVs to adopt was availability of a portable and high performance&nbsp;CIM+WsMan server that they can easily port to their devices. This gap has been filled by OMI. &nbsp;</span></span></span></p> <p><span style="font-size: small;">This is cool&nbsp; and we are so excited about it. Jeffrey Snover did a technology demonstration at TechEd Europe in which he used PowerShell to manage a </span><span style="font-size: small;">base-motherboard controller on a server, a Windows operating system, and an Arista switch running OMI. You can see recording of this session <span style="color: #0000ff;"><a href="http://channel9.msdn.com/Events/TechEd/Europe/2012/FDN04" target="_blank"><span style="color: #0000ff;">here</span></a>&nbsp;</span> (look at 51:15 mark)</span></p> <p><span style="font-size: small;"></span>&nbsp;</p> <p><span style="font-size: small;">Osama Sajid , Program Manager</span></p> <p><span style="font-size: small;">Standards Based Management Team</span></p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10326305" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Open+Management+Infrastructure/">Open Management Infrastructure</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/OMI/">OMI</category></item><item><title>Snippets in Windows PowerShell ISE 3.0</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/27/snippets-in-windows-powershell-ise-3-0.aspx</link><pubDate>Wed, 27 Jun 2012 15:40:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10324561</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10324561</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/27/snippets-in-windows-powershell-ise-3-0.aspx#comments</comments><description><p><em><font color="#a5a5a5"><sub></sub><sub></sub><sub></sub><sub></sub><sub></sub><sub></sub><sub></sub>This blog post applies to the Windows PowerShell Integrated Scripting Environment (ISE) in Windows 8 and Windows Server 2012.&#160; The ISE is also fully supported and available when Server 2012 is deployed using the <a href="http://blogs.technet.com/b/windowsserver/archive/2012/03/20/building-an-optimized-private-cloud-using-windows-server-8-server-core.aspx">Minimal Server Interface</a>.&#160; To start ISE, type <font style="background-color: rgb(255, 255, 255);"><font face="Lucida Console"><strong>ise</strong></font>&#160; </font>in a PowerShell console and press <font face="Lucida Console"><strong>Enter</strong></font></font></em></p> <p>Snippets provide a convenient way to paste arbitrary text into the ISE console and script editor, right where you need it.&#160; The idea is to provide improved productivity, discoverability, and usability:</p> <ul> <li>To save you from typing repetitive or long text (or hunting for the script to copy-and-paste from)</li> <li>To save you a trip to Get-Help (think about all the attributes on script cmdlets)</li> <li>Beginners may insert an if statement as a means of learning PowerShell syntax</li> </ul> <p>For those of you who are familiar with Visual Studio’s Snippets, the ISE version uses the same shortcut key, but it will surely feel like a “poor man’s version” :-), lacking the ability to tab between fields, among other things.</p> <p>You can list available Snippets by pressing <font face="Lucida Console"><strong>Ctrl</strong></font>+<strong><font face="Lucida Console">J</font></strong> or selecting “Start Snippets” from the “Edit” menu.&#160; Notice that a tooltip displays the actual text which will be inserted, as you move over the selections in the Snippets drop-down.&#160; Here’s what it looks like: </p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2727.image_5F00_083C0C0E.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6835.image_5F00_thumb_5F00_72E37807.png" width="425" height="234" /></a></p> <p>There are 3 types of snippets:</p> <ul> <li>Default snippets, which ship with PowerShell ISE 3.0</li> <li>User-defined snippets</li> <li>Module-based snippets</li> </ul> <em></em> <h3>Default Snippets </h3> <p>Consider these to be the “starter set” of snippets: PowerShell code that is either frequently used, or hard to discover.&#160; Press <font face="Lucida Console"><strong>Ctrl</strong></font>+<strong><font face="Lucida Console">J</font></strong> to start Snippets and look through the various default snippets.</p> <p>For those of who may have developed a specific coding style over the years, and feel very strongly about whether the curly braces belong on the same line or on the next line :-), you’ll be pleased to know that you can hide the default snippets, either through the Options dialog (at the bottom of the “General Settings” tab), or directly through the ISE object model at the command line:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1207.image_5F00_7137CD95.png"><img title="image" style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2604.image_5F00_thumb_5F00_27A87F98.png" width="321" height="17" /></a></p> <h3>User-Defined Snippets </h3> <p>You can create your own snippets and add them to the snippets drop-down list using the <font face="Lucida Console">New-IseSnippet</font> cmdlet.&#160; Here’s the cmdlet syntax, using one of my favorite new features: Show-Command:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8535.image_5F00_6B7F44A0.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4035.image_5F00_thumb_5F00_63F665E4.png" width="214" height="240" /></a> <br /><em>Note that you can also type New-IseSnippet anywhere in the ISE, and then press <font face="Lucida Console">Ctrl+F1</font> when the caret (you may be calling it “cursor”) is anywhere within the cmdlet string.</em></p> <p>Here’s an example: I often find myself wanting to show the definition (body) of a function.&#160; for that, I would have to type <font face="Lucida Console">Get-Command</font>, followed by the function name, wrap the whole thing in parentheses, and then append <font face="Lucida Console">.Definition</font>.&#160; A snippet comes in handy:</p> <p><font face="Lucida Console">New-IseSnippet -Title &quot;Show Definition&quot; -Description &quot;Shows command definition&quot; -Text &quot;(Get-Command ).Definition&quot; -CaretOffset 13</font></p> <p>This example adds a “Show Definition” snippet to the snippets list, and inserts the following text when selected:&#160;&#160; <font face="Lucida Console">(Get-Command ).Definition</font></p> <p>Notes: </p> <ul> <li>The caret is placed 13 characters after the start of the snippet text (ready for you to enter the command name).&#160; This is what the –CaretOffset parameter is for</li> <li>Example usage: <font face="Lucida Console">(Get-Command prompt).Definition </font></li> <li>To see all user-defined snippets, type: <font face="Lucida Console">Get-IseSnippet</font></li> <li>To remove a snippet, go to the folder which contains all user-defined snippets (available from <font face="Lucida Console">Get-IseSnippet</font>) and delete the corresponding snippet file.&#160; </li> </ul> <p>If you prefer to hand-craft your snippets instead of using the cmdlet, just create an XML file like the one below, and copy it to the snippets “home” folder, which you can get using one of the following methods: </p> <ul> <li><font face="Lucida Console">Join-Path (Split-Path $profile.CurrentUserCurrentHost) &quot;Snippets&quot;</font></li> <li>Type <font face="Lucida Console">Get-IseSnippet</font> and copy the displayed path &#160;&#160;&#160;&#160; </li> </ul> <p>Any snippets in the snippets home folder will be loaded automatically by the ISE when it starts.&#160; If you don’t want to place your snippets in the home folder, you can place them anywhere (C:\temp for example), but then you must load them explicitly in your ISE profile using: <font face="Lucida Console">Import-IseSnippet -Path 'C:\Temp'</font></p> <p>Snippets files have an extension of .snippets.ps1xml and have the following structure: </p> <blockquote><font face="Lucida Console"> <p>&lt;?xml version='1.0' encoding='utf-8' ?&gt; <br />&#160;&#160;&#160; &lt;Snippets&#160; xmlns='<a href="http://schemas.microsoft.com/PowerShell/Snippets'">http://schemas.microsoft.com/PowerShell/Snippets'</a>&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;Snippet Version='1.0.0'&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;Header&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;Title&gt;Show Definition&lt;/Title&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;Description&gt;Shows command definition&lt;/Description&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;Author&gt;&lt;/Author&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt; SnippetTypes&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt; SnippetType&gt;Expansion&lt;/SnippetType&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;/SnippetTypes&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;/Header&gt;</p> <p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;Code&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;Script Language='PowerShell' CaretOffset='13'&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;![CDATA[(Get-Command ).Definition]]&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;/Script&gt; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;/Code&gt;</p> <p>&#160;&#160;&#160; &lt;/Snippet&gt; <br />&lt; /Snippets&gt;</p> </font></blockquote> <p>Where: </p> <ul> <li>Title: The name which appears in the snippets drop-down list</li> <li>Description: The description which appears in the snippet tooltip</li> <li>Cdata: The tag which contains the actual snippet text</li> </ul> <h3>Module-Based Snippets</h3> <p>To load all module-based snippets (which only works for modules which have already been imported using <font face="Lucida Console">Import-Module</font>), use: <font face="Lucida Console">Import-IseSnippet -Module Xyz</font></p> <p>If you’re shipping a module with snippets, place your snippet files into a “Snippets” folder, directly under the module folder.</p> <p>&#160;</p> <p>I hope that this quick walk-through will encourage you to use snippets, create your own, and share them with the community.&#160; </p> <p>&#160;</p> <p>ref@ </p> <p>Refaat Issa</p> <p>Program Manager, Windows Server Manageability</p> <p>Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10324561" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+ISE/">PowerShell ISE</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>Basic installation guide for Windows PowerShell Web Access</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/27/windows-powershell-web-access-basic-installation-guide.aspx</link><pubDate>Tue, 26 Jun 2012 23:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10324286</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10324286</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/27/windows-powershell-web-access-basic-installation-guide.aspx#comments</comments><description><p><a title="Windows PowerShell Web Access" href="http://blogs.msdn.com/b/powershell/archive/2012/03/07/introducing-windows-powershell-web-access-in-windows-server-8-beta.aspx">Windows PowerShell Web Access</a> is a new feature in Windows Server 2012. It is an IIS application that provides a Windows PowerShell console in a web browser. The IIS application acts as a gateway between the web browser and the machines that you can connect to in your environment. These machines should have Windows PowerShell remoting enabled.</p> <p><br />The video&nbsp;below illustrates the three simple steps of setup and configuration &ndash;</p> <p><br /><strong>1.&nbsp;Feature installation</strong><br />In the video we use GUI to install the feature. We could also use the Windows PowerShell cmdlet equivalent for installation (run the cmd in an elevated PowerShell console) &ndash; <br /><span style="font-family: courier new,courier;">Install-WindowsFeature &ndash;Name WindowsPowerShellWebAccess &ndash;IncludeAllManagementTools</span></p> <p><strong>2.&nbsp;Web application setup in IIS</strong><br />After successful feature installation, IIS has to be configured to host the web application. The video illustrates automated setup for IIS using the cmdlet <span style="font-family: courier new,courier;">Install-PswaWebApplication <span style="font-family: arial,helvetica,sans-serif;">where</span></span>&nbsp;default values are used by the cmdlet to setup the web application and the website.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/7140.IIS-setup-with-PSWA.png"><img style="margin-right: auto; margin-left: auto; display: block;" border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/7140.IIS-setup-with-PSWA.png" /></a></p> <p>If you don&rsquo;t wish to use the default values, you can specify values for <span style="font-family: courier new,courier;">&ndash;WebApplicationName</span> and <span style="font-family: courier new,courier;">&ndash;WebsiteName</span> parameters for the cmdlet. You can also configure IIS manually. More details on different ways to configure IIS are available in <a title="Windows PowerShell Web Access help document" href="http://technet.microsoft.com/en-us/library/hh831611#BKMK_config">Windows PowerShell Web Access help document</a>.</p> <p><strong>3.&nbsp;Configuring authorization rules</strong> <br />The authorization rules act as a white list and help manage access control to the gateway and the remote machine. Without the authorization rules, no user will be able to use PSWA&rsquo;s website to login and manage a remote machine.</p> <p>In the video, we create one authorization rule for the administrator to login to the pswagateway machine. As specified by the rule, the administrator will only be able to connect to the default PowerShell endpoint, i.e. Microsoft.PowerShell on the machine pswagateway. The login will fail if the administrator tries to connect to some other machine or some other PowerShell endpoint on pswagateway.</p> <p>There may be other local or built-in users on pswagateway machine who have access rights to manage the machine using other remote connection software such as Remote Desktop services etc. But, they cannot connect to pswagateway via <a title="PowerShell Web Access " href="http://blogs.msdn.com/b/powershell/archive/2012/03/07/introducing-windows-powershell-web-access-in-windows-server-8-beta.aspx">PowerShell Web Access</a> because no authorization rule is created for them. Therefore, authorization rules provide an additional layer of security on top of the existing access control rights on the machine.</p> <p>More details on authorization rules can be found in <a title="Windows PowerShell Web Access help document" href="http://technet.microsoft.com/en-us/library/hh831611.aspx#BKMK_auth">Windows PowerShell Web Access help document</a>. Also, stay tuned for a blog post on authorization rules.<br />&nbsp;</p> <p>In all, <a title="Windows PowerShell Web Access " href="http://blogs.msdn.com/b/powershell/archive/2012/03/07/introducing-windows-powershell-web-access-in-windows-server-8-beta.aspx">Windows PowerShell Web Access</a> provides a secure way to access a remote PowerShell console in a web browser. This provides mobility and ease of access. Since the web console is accessible via a website, users can now connect to their remote machines from various mobile devices such as tablets, phones etc.</p> <p>&nbsp;</p> <p>Kriti Jindal<br />&nbsp;<br />Program Manager<br />&nbsp;<br />Windows PowerShell Web Access<br />&nbsp;<br />Microsoft Corporation</p> <p>&nbsp;</p> <p>Click <a title="here" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/5023.Video01_2D00_basic_2D00_pswa_2D00_install.wmv">here</a> to download the video.<br />&nbsp;</p><p align="center" id="video_10324286"><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/5023.Video01_2D00_basic_2D00_pswa_2D00_install.wmv"><img src="http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/7875.server_2D00_manager.png" border = "0" width="700" height="625"></a><br /><a href = "http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/5023.Video01_2D00_basic_2D00_pswa_2D00_install.wmv">View Video</a><br />Format: wmv<br />Duration: 06:29</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10324286" width="1" height="1"></description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/5023.Video01_2D00_basic_2D00_pswa_2D00_install.wmv" length="0" type="video/x-ms-wmv" /><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+Web+Access/">PowerShell Web Access</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>Improving the FileSystem Provider through Community feedback</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/21/improving-the-filesystem-provider-through-community-feedback.aspx</link><pubDate>Thu, 21 Jun 2012 21:53:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10322746</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10322746</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/21/improving-the-filesystem-provider-through-community-feedback.aspx#comments</comments><description><p>One of the things we love about the Windows PowerShell community is that folks are not shy. It turns out that having a vocal community is a great way to build and evangelize a product like ours. Of course, the Unix guys had this all figured out a long time ago.</p> <p>Positive comments are good and all, but it&rsquo;s difficult to really improve without being told where we came short. One of the ways we take feedback from the community for Windows PowerShell is through our public <a href="http://connect.microsoft.com/powershell">Microsoft Connect</a> site. On that site anyone with a Live ID can log a bug or suggestion against Windows PowerShell. Items then get voted up or down by the community according to popularity.</p> <p>We don&rsquo;t get to implement every suggestion and fix every bug, but it&rsquo;s a great way for us to understand what people are looking for and how important it is to them. With Windows PowerShell 3.0 we fixed over 200 items that were filed on Connect. This post will quickly touch on a few improvements to the FileSystem Provider based on this community feedback.</p> <p><b></b>&nbsp;</p> <p><b>Support for Credentials</b></p> <p>PowerShell MVP Joel Bennett filed <a href="https://connect.microsoft.com/PowerShell/feedback/details/334084/filesystem-provider-should-support-credentials">a suggestion</a> a few years ago asking that we support credentials with the FileSystem Provider. That suggestion was recently our 4<sup>th</sup> most voted item with 82 votes. The scenario is quite basic: You want to access a network file share, and that share requires a different set of credentials than the ones you are currently logged on with.</p> <p>I&rsquo;m happy to say that support for credentials on the FileSystem provider is available in Windows PowerShell 3.0! To use alternate credentials, simply use the Credential parameter on the New-PSDrive cmdlet</p> <p><span style="font-family: terminal,monaco;">PS &gt; New-PSDrive -Name J -PSProvider FileSystem -Root \\server001\sharename -Credential mydomain\travisj</span></p> <p><span style="font-family: terminal,monaco;">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Used (GB)&nbsp;&nbsp;&nbsp;&nbsp; Free (GB) Provider&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="font-family: terminal,monaco;">----&nbsp;&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 /></span><span style="font-family: terminal,monaco;">J&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileSystem&nbsp;&nbsp;&nbsp; <a href="file://\\server001\sharename">\\server001\sharename</a></span></p> <p>You can use all of the regular provider cmdlets like Get-ChildItem, Set-Location and Copy-Item against this new PSDrive just as you would normally &ndash; no need to specify the credentials over and over.</p> <p>It gets better! By specifying the Persist switch parameter to the New-PSDrive cmdlet, the PSDrive will stay mounted across sessions. That line would look like:</p> <p><span style="font-family: terminal,monaco;">PS &gt; New-PSDrive -Name J -PSProvider FileSystem -Root \\server001\sharename -Credential mydomain\travisj -Persist</span></p> <p><b></b>&nbsp;</p> <p><b>Moving items across drives</b></p> <p>While we&rsquo;re on the subject of the provider cmdlets, I want to mention that <a href="https://connect.microsoft.com/PowerShell/feedback/details/161675/move-item-cmdlet-cant-move-items-between-different-psdrives">Move-Item can now move items across PSDrives</a>. Using the PSDrive created above, we can move items from the network share (that was even mounted using a different set of credentials) to a location on the local file system. This one-liner will copy all XML files from the network share to a temporary directory on my computer.</p> <p><span style="font-family: terminal,monaco;">Move-Item -Path J:\*.xml -Destination C:\temp</span></p> <p><b></b>&nbsp;</p> <p><b>LiteralPath Parameter</b></p> <p>Finally, we know that users have <a href="https://connect.microsoft.com/PowerShell/feedback/details/211307/-item-cmdlets-ignore-items-containing">experienced difficulty</a> working with files that contain characters like &lsquo;[&lsquo; or &lsquo;]&rsquo;. To help with this in Windows PowerShell 2.0, we added the LiteralPath parameter to some of the provider cmdlets. With Windows PowerShell 3.0, we have now added<br />LiteralPath to the Rename-Item cmdlet (the last of the provider cmdlets) and in many other places. LiteralPath is now available on 49 different cmdlets in Windows PowerShell 3.0!</p> <p>&nbsp;</p> <p>Now that you&rsquo;ve read this post, head on over to our <a href="http://connect.microsoft.com/powershell">Connect</a> site and file a suggestion or bug for us. Or vote someone else&rsquo;s up.</p> <p>&nbsp;</p> <p>Travis Jones [MSFT]<br />Program Manager - Windows PowerShell<br />Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10322746" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/MVP/">MVP</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Community/">Community</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title> Running show-command to discover cmdlets </title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/21/running-show-command-to-discover-cmdlets.aspx</link><pubDate>Thu, 21 Jun 2012 02:49:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10322439</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10322439</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/21/running-show-command-to-discover-cmdlets.aspx#comments</comments><description><h1><span style="font-size: large;" size="4"><span style="color: #4f81bd;" color="#4f81bd"><span style="font-family: Cambria;" face="Cambria"><span style="font-size: large;" size="4"><span style="color: #4f81bd;" color="#4f81bd"><span style="font-family: Cambria;" face="Cambria"><em><span style="color: #a5a5a5;" color="#a5a5a5">This blog post applies to the Windows PowerShell&nbsp;Version 3.0.&nbsp;</span></em></span></span></span></span></span></span><span style="font-size: large;" size="4"><span style="color: #4f81bd;" color="#4f81bd"><span style="font-family: Cambria;" face="Cambria"><span style="font-size: large;" size="4"><span style="color: #4f81bd;" color="#4f81bd"><span style="font-family: Cambria;" face="Cambria"><em><span style="color: #a5a5a5;" color="#a5a5a5"><span style="font-family: Lucida Console;" face="Lucida Console"><strong></strong></span></span></em></span></span></span></span></span></span></h1> <h2><span style="font-size: large;" size="4"><span style="color: #4f81bd;" color="#4f81bd"><span style="font-family: Cambria;" face="Cambria">Problem: How can I find out what cmdlets are available for a given task?&nbsp;</span></span></span></h2> <h2><span style="font-size: large;" size="4"><span style="color: #4f81bd;" color="#4f81bd"><span style="font-family: Cambria;" face="Cambria">Finding cmdlets in the traditional way</span></span></span></h2> <p><strong><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri" size="3">&nbsp;</span><span style="font-family: Calibri;" face="Calibri"><span size="3">If you know the basics of get-command, feel free to skip this section.</span></span></span></strong></p> <p><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri"><span size="3">If you are searching for a cmdlet to add a printer, you could star with something like:</span></span></span></p> <p><span style="font-family: Calibri;" face="Calibri"><span style="font-size: small;" size="3"></span></span></p> <p><span style="font-family: courier new,courier;">PS C:\Users\mspuser&gt; get-command *printer*</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">CommandType&nbsp;&nbsp;&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ModuleName</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">-----------&nbsp;&nbsp;&nbsp; ----&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Add-Printer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Add-PrinterDriver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Add-PrinterPort&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get-Printer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get-PrinterDriver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;Get-PrinterPort&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get-PrinterProperty&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Remove-Printer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Remove-PrinterDriver&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Remove-PrinterPort&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rename-Printer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set-Printer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set-PrinterProperty&nbsp;&nbsp;&nbsp; PrintManagement</span></p> <p><span style="font-family: courier new,courier; font-size: small;" size="3">Cmdlet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Out-Printer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Microsoft.PowerShell.Utility</span></p> <p><span style="font-family: Calibri; font-size: small;" face="Calibri" size="3">&nbsp;</span></p> <p><span style="font-size: medium;" size="3"><span style="font-family: Calibri;" face="Calibri">Notice the choice of the noun &ldquo;printer&rdquo;, as opposed to the verb &ldquo;add&rdquo;. &ldquo;Add&rdquo; could be adding anything, so reducing the scope to &ldquo;printer&rdquo; allows for a more precise initial search.</span></span></p> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">For this simple case of adding a printer, it is very possible that the first guess would be &ldquo;add-printer&rdquo;, but the verb is not always as simple to guess. Also, it is nice to look around and see what other printer related cmdlets are available. Chances are one task leads to another and we will need another cmdlet soon like get-printer to see that the printer we added is there.</span></span></p> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">The first * in *printer* allows finding cmdlets with any verb or noun prefix. By &ldquo;noun prefix&rdquo; I mean the cmdlet developers could have called them <b>System</b>Printers, <b>PS</b>Printers, or other name. The second * allows for any noun suffix like &ldquo;Driver&rdquo; and &ldquo;Property&rdquo; in the list above. </span></span></p> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">After looking at the list, we might conclude that we are not interested in &ldquo;PrinterDriver&rdquo; or &ldquo;PrinterPort&rdquo; so that the second * made our search less precise. We can issue the command again without the second * for less results but, for the generic case of searching for any other noun, using both * will guarantee we will not miss anything.</span></span></p> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">After you found the cmdlet, you can explorer it a bit further with one of the following: </span></span></p> <p><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri"><span size="3">&nbsp;&nbsp;&nbsp;&nbsp; get-help add-printer</span></span><span style="font-family: Calibri;" face="Calibri"><span size="3">&nbsp;&nbsp; </span></span></span></p> <p><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri"><span size="3">&nbsp;&nbsp;&nbsp;&nbsp; get-command add-printer</span></span><span style="font-family: Calibri;" face="Calibri" size="3">&nbsp;</span></span></p> <h2><span style="font-size: large;" size="4"><span style="color: #4f81bd;" color="#4f81bd"><span style="font-family: Cambria;" face="Cambria">Finding cmdlets with show-cmdlet</span></span></span></h2> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">We saw in <a title="Running show-command for a cmdlet" href="http://blogs.msdn.com/b/powershell/archive/2012/04/13/running-show-command-for-a-cmdlet.aspx">Running show-command for a cmdlet</a>, how to use show-command for a specific cmdlet. If you run just &ldquo;show-command&rdquo; this is what you get:</span></span></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/5554.a.png"><img width="419" height="633" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/5554.a.png" border="0" /></a></p> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">Note:</span></span></p> <ul> <li><span style="font-family: Calibri; font-size: medium;" face="Calibri">&nbsp;<span size="3">A &ldquo;Module&rdquo; is a set of cmdlets for a given domain. In this window you can see cmdlets from all modules, but you might filter the results to a specific module, in the &ldquo;Modules&rdquo; drop down.</span></span></li> </ul> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3"></span>&nbsp;</span></p> <p><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">If then you type &ldquo;printer&rdquo; under Name, you have:</span></span></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/1616.a.png"><img width="421" height="673" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/1616.a.png" border="0" /></a></p> <p><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri" size="3">&nbsp;</span><span style="font-family: Calibri;" face="Calibri"><span size="3">Notice that *printer* is implicit. If the cmdlet contains printer, you will see it.</span></span></span></p> <p><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri" size="3">&nbsp;</span><span style="font-family: Calibri;" face="Calibri"><span size="3">If you had typed printers, you would see the same list, because the search results also include the singular form of what you typed.</span></span></span></p> <p align="left"><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri" size="3">&nbsp;</span><span style="font-family: Calibri;" face="Calibri"><span size="3">When you click the Add-Printer cmdlet you get the window on the left below, and after you click &ldquo;Show-Details&rdquo; you get the window on the right:</span></span></span></p> <p align="left"><span style="font-family: Calibri;" face="Calibri"><span style="font-size: small;" size="3"></span></span>&nbsp;<a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/1667.a.png"><img width="625" height="479" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74/1667.a.png" border="0" /></a></p> <p align="left"><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">Show-command allows for a simpler way to find a cmdlet and then to get more details about it such as parameters and help (question mark button). It is a simpler route from thinking about a task to finding out how to accomplish it.</span></span></p> <p><span style="font-size: medium;"><span style="font-family: Calibri;" face="Calibri" size="3">&nbsp;</span><span style="font-family: Calibri;" face="Calibri"><span size="3">Notes: </span></span></span></p> <ul> <li><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">The &ldquo;Add-Printer&rdquo; section of the window is the same we would see if we had typed &ldquo;show-command add-printer&rdquo; and that part is explored a bit more in <a title="Running show-command for a cmdlet" href="http://blogs.msdn.com/b/powershell/archive/2012/04/13/running-show-command-for-a-cmdlet.aspx">Running show-command for a cmdlet</a>.</span></span></li> <li><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">The same window as the one displayed for &ldquo;show-command&rdquo; is also embedded in &ldquo;PowerShell ISE&rdquo; by default and can be seen in the &ldquo;View - Show Command Add-on&rdquo; menu when not present. To start ISE, type <span style="color: #808080;">ise</span>&nbsp;in a PowerShell console and press Enter.</span></span></li> <li><span style="font-family: Calibri; font-size: medium;" face="Calibri"><span size="3">If the cmdlet module is already imported, you will not see the &ldquo;Show Details&rdquo; button. </span></span></li> <li><span style="font-size: medium;" size="3"><span style="font-family: Calibri;" face="Calibri">For a cmdlet belonging to a module that was not yet imported, we had 2 alternatives: starting to load the module as soon as Add-Printer is selected, or using the intermediary &ldquo;Show Details&rdquo; text you see on the left. We decided for the intermediate step to give the user a chance to understand a module is going to be imported and explicitly choose to do that. We were not comfortable with the idea of selecting list items with mouse or keyboard resulting in modules being loaded implicitly.</span></span></li> </ul> <p><span style="font-size: medium;" size="3"><span style="font-family: Calibri;" face="Calibri"></span></span>&nbsp;</p> <p><span style="font-size: medium;" size="3"><span style="font-family: Calibri;" face="Calibri">Lucio Silveira [MSFT]</span></span></p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10322439" width="1" height="1"></description></item><item><title>High Level Architecture of Windows PowerShell Workflow (Part 2)</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/19/high-level-architecture-of-windows-powershell-workflow-part-2.aspx</link><pubDate>Tue, 19 Jun 2012 22:09:12 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10321960</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10321960</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/19/high-level-architecture-of-windows-powershell-workflow-part-2.aspx#comments</comments><description><p align="justify"><font size="3">This is the second part of our post on the high level architecture of Windows PowerShell Workflow. </font><a href="http://blogs.msdn.com/b/powershell/archive/2012/06/15/high-level-architecture-of-windows-powershell-workflow-part-1.aspx"><font size="3">Part 1 of this blog post</font></a><font size="3"> provided an overview of the architecture and its various components. This post will go into more detail on the various subcomponents and provide some insight into the internals of Windows PowerShell Workflow. The component diagram for the PowerShell Workflow Executive is repeated (from part 1) for reference</font></p> <font size="3"></font> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2671.image_5F00_0EE8E64F.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0537.image_5F00_thumb_5F00_0116A054.png" width="712" height="373" /></a></p> <font size="3"></font> <p><font size="3">Each of the components in the diagram is discussed in detail below.</font></p> <font size="3"></font> <h1>1. Workflow Compilation, Caching and Validation</h1> <font size="3"></font> <p align="justify"><a href="http://msdn.microsoft.com/en-us/netframework/aa663328.aspx"><font size="3">Windows Workflow Foundation</font></a><font size="3"> deals with and understands Activity objects. An executable workflow is simply a collection of activity objects. Each step in the workflow corresponds to an activity in the collection. The activity objects in a workflow can be programmatically constructed or constructed from their eXtensible Application Markup Language (XAML) definition. In Windows PowerShell workflow, we use the XAML definition of an activity. .</font></p> <font size="3"></font> <h2>1.1 Compilation and Caching<font size="3"></font></h2> <p align="justify"><font size="3">The interaction begins when a user imports a XAML file into a Windows PowerShell session -- either a console session or the PowerShell Workflow Configuration. XAML files are treated like modules in PowerShell, so they are imported by using the <font size="4" face="Courier New">Import-Module</font> cmdlet. </font></p> <font size="3"></font> <p><font size="3">Here is what happens when a XAML file is imported:</font></p> <font size="3"></font> <p align="justify"><font size="3">1. The XAML file contents (and any dependencies) are read and compiled into an executable workflow using the <font size="4" face="Courier New">ActivityXamlServices</font> class.</font></p> <font size="3"></font> <p align="justify"><font size="3">2. The Activity object, the XAML definition, and any dependency information are stored in a process-wide cache. </font></p> <p align="justify"><i><font size="3">We do this because compiling a XAML definition into an executable workflow is a lengthy operation that we don't want to repeat. </font></i></p> <p align="justify"><font size="3">3. The parameters of the workflow are extracted and a PowerShell function is synthesized that has the same name as the XAML file that contained the workflow definition. The function has the same parameters as the workflow and all common workflow parameters that PowerShell provides. This synthesized function references the workflow that was compiled in step #1 and stored in the process-wide cache. </font></p> <p align="justify"><i><font size="3">When the user executes the workflow, this PowerShell function is actually executed.</font></i></p> <p align="justify"><font size="3">4. When multiple clients connect to the workflow session configuration, all of these connections will be directed to the same process (<i>all of the information about session configurations warrants a blog post in itself</i>). In this case each of the sessions will contain a synthesized function but all of these functions will refer to the same entry in the cache.</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7484.image_5F00_2131AD11.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8055.image_5F00_thumb_5F00_6F3A0C86.png" width="705" height="115" /></a></p> <font size="3"></font> <p align="justify"><font size="3">After a XAML file is imported, you can use <font size="4" face="Courier New">Get-Command</font> to look at the corresponding command. Note that its command type is &quot;workflow,&quot; even though the underlying implementation is a function. </font></p> <font size="3"></font> <h3><font size="3">1.1.1 PowerShell Script to Workflow Conversion</font></h3> <font size="3"></font> <p align="justify"><font size="3">When you author a workflow in PowerShell (using the <font size="4" face="Courier New">workflow</font> keyword, as detailed in Part 1), the PowerShell parser converts it into an intermediate representation referred to in developer terms as an Abstract Syntax Tree (AST). The AST is then converted to a XAML document in memory. This XAML document goes through the same compilation and caching steps detailed above. It is possible to examine this XAML definition by using the <font size="4" face="Courier New">Get-Command</font> cmdlet. For example, consider the following workflow:</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7450.image_5F00_6167C68B.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1682.image_5F00_thumb_5F00_2F702601.png" width="378" height="113" /></a></p> <font size="3"></font> <p><font size="3"></font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2262.image_5F00_3A99B04B.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0118.image_5F00_thumb_5F00_6FA63F7B.png" width="715" height="105" /></a></p> <p><font size="3">The converted XAML is available in the XamlDefinition property of each workflow.</font></p> <font size="3"></font> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4426.image_5F00_61D3F980.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1205.image_5F00_thumb_5F00_42251FB8.png" width="715" height="342" /></a></p> <font size="3"></font> <p align="justify"><font size="3">Note that the <font size="4" face="Courier New">Get-WMIObject</font> cmdlet is converted into the <font size="4" face="Courier New">GetWmiObject</font> activity. There is also some additional transformation – like <font size="4" face="Courier New">'3:5:Get-BiosUsingScript'</font> – which is used to preserve the position information in the script. This is used when writing error messages that actually reference the position of a statement in the PowerShell script, rather than the converted XAML document.</font></p> <font size="3"></font> <p align="justify"><font size="3">In XAML and PowerShell workflows, the synthesized function is available in the <font size="4" face="Courier New">ScriptBlock</font> property of the workflow.</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7462.image_5F00_174CBBA6.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8032.image_5F00_thumb_5F00_097A75AB.png" width="720" height="40" /></a></p> <h2>1.2 Validation</h2> <font size="3"></font> <p align="justify"><font size="3">Validation is the process of verifying that all activities in the workflow are allowed. For performance reasons, the workflow is validated when it is executed, rather than at compile time. PowerShell allows you to define workflow sandboxes where you specify which activities can be part of a workflow in a given session configuration. If the workflow includes activities that are not allowed, validation fails and workflow execution will not progress.</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8055.image_5F00_7BA82FAF.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7077.image_5F00_thumb_5F00_30B4BEE0.png" width="724" height="82" /></a></p> <font size="3"></font> <p align="justify"><font size="3"><font size="4" face="Courier New">PSDefaultActivities</font> indicate that all PowerShell activities are allowed in the session configuration. Here is an example of validation failure.</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1614.image_5F00_37D3FB58.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5808.image_5F00_thumb_5F00_6318925F.png" width="735" height="232" /></a></p> <p align="justify"><font size="3">Since the “<font size="4" face="Courier New">TestWorkflow</font>” custom session configuration was defined as a sandbox that allows only the <font size="4" face="Courier New">Get-Process</font> activity, the Get-Bios workflow fails because it uses the <font size="4" face="Courier New">Get-WmiObject</font> activity.</font></p> <font size="3"></font> <h1>2. Workflow Jobs Infrastructure</h1> <font size="3"></font> <p align="justify"><font size="3">As specified in </font><a href="http://blogs.msdn.com/b/powershell/archive/2012/06/15/high-level-architecture-of-windows-powershell-workflow-part-1.aspx"><font size="3">Part 1 of this blog post</font></a><font size="3">, in PowerShell, a workflow is always executed as a PowerShell job. The job infrastructure is not unique to PowerShell workflows but is an infrastructure provided by PowerShell that different modules can plug into. The PowerShell Workflow job infrastructure consists of the following four main components:</font></p> <font size="3"></font> <p><font size="3">1. The PowerShell workflow job implementation (the <font size="4" face="Courier New">PSWorkflowJob</font> object).</font></p> <font size="3"></font> <p><font size="3">2. A job manager that maintains the list of all workflow jobs and queries/filters them.</font></p> <font size="3"></font> <p align="justify"><font size="3">3. A workflow <font size="4" face="Courier New">JobSourceAdapter</font>, which is the interface between the PowerShell job cmdlets and the workflow job manager.</font></p> <font size="3"></font> <p align="justify"><font size="3">4. Workflow Job Throttle Manager –ensures that no more than a specified maximum number of jobs are running at any point in time</font></p> <font size="3"></font> <p align="justify"><font size="3">Since workflow jobs are built on the common job infrastructure, the PowerShell job cmdlets are used to manage the workflow jobs and they interact with the workflow job source adapter.</font></p> <font size="3"></font> <h2>2.1 Creation of Workflow Jobs</h2> <font size="3"></font> <p align="justify"><font size="3">When the user runs the workflow from the command line, the <font size="4" face="Courier New">ScriptBlock</font> associated with the synthesized function is executed. Here is what happens:</font></p> <font size="3"></font> <p align="justify"><font size="3">1. The Activity object for the specified workflow is obtained from the process-wide cache and it is validated as specified in the validation section (1.2).</font></p> <font size="3"></font> <p align="justify"><font size="3">2. If validation succeeds, a workflow job is created for the specified workflow. When the user specifies multiple computers (by using the <font size="4" face="Courier New">PSComputerName</font> parameter), a child workflow job is created under the parent job for each computer that is targeted. This way, all workflow job instances created by user in a particular invocation are managed together. (<i>Here is where the caching comes in handy. Since the same definition is used, a lot of time is saved by compiling only once. Caching of compiled workflows is one of the first performance improvements we made</i>). </font></p> <font size="3"></font> <p align="justify"><font size="3">3. The workflow job is submitted to the job throttle manager which invokes the job when it is permitted to do so under the current throttling policies.</font></p> <font size="3"></font> <p align="justify"><font size="3">4. If the user invoked the workflow by using the <font size="4" face="Courier New">AsJob</font> parameter, the parent job object is written to the pipeline. If the user did not specify the <font size="4" face="Courier New">AsJob</font> parameter, the synthesized function mimics synchronous behavior for the workflow.</font></p> <font size="3"></font> <h1>3. Activities</h1> <font size="3"></font> <p align="justify"><font size="3">Each workflow job instantiates a </font><a href="http://msdn.microsoft.com/en-us/library/system.activities.workflowapplication.aspx"><font size="4" face="Courier New">WorkflowApplication</font></a><font size="3"> using its compiled workflow definition it retrieved from the process-wide cache. As mentioned in </font><a href="http://blogs.msdn.com/b/powershell/archive/2012/06/15/high-level-architecture-of-windows-powershell-workflow-part-1.aspx"><font size="3">Part 1</font></a><font size="3">, <font size="4" face="Courier New">WorkflowApplication</font> provides a host for a single workflow instance. Since a workflow is a series of activities, the workflow engine is responsible for coordinating the execution of these activities. </font></p> <font size="3"></font> <p align="justify"><font size="3">PowerShell workflows can contain different kinds of activities. These can be broadly divided into three categories:</font></p> <font size="3"></font> <p align="justify"><font size="3">1. Activities supplied by Windows Workflow Foundation such as the flow control activities (while loops, if statements, etc)</font></p> <font size="3"></font> <p align="justify"><font size="3">2. Activities that represent PowerShell commands. This includes all the built-in activities supplied by PowerShell.</font></p> <font size="3"></font> <p align="justify"><font size="3">3. Special activities – like <font size="4" face="Courier New">Pipeline, PowerShellValue, GetPSWorkflowData</font> and <font size="4" face="Courier New">SetPSWorkflowData</font>. These are primarily “helper” activities and they are mostly used when a workflow authored in the PowerShell language is translated into a XAML. <i>We will provide details about these activities in an upcoming blog post about workflow authoring.</i></font></p> <font size="3"></font> <p align="justify"><font size="3"><font size="4" face="Courier New">PSActivity</font> is the base for all PowerShell activities. Deriving from this base class, there are a number of subclasses that encapsulate differences in remoting behavior exposed by some commands. For example, some commands like the WMI and CIM cmdlets are capable of handling remoting on their own. The activities wrapping these cmdlets derive from a special subclass that coordinates their execution. Other activities such as <font size="4" face="Courier New">Write-Output</font> are never executed remotely. The majority of activities, however, should be executed remotely but are not themselves capable of remote execution. These activities derive from <font size="4" face="Courier New">PSRemotingActivity</font>. Any activity derived from <font size="4" face="Courier New">PSRemotingActivity</font> gets default remoting support using PowerShell remoting. Since Workflows are meant for multi-machine management, it is important that an activity is able to perform a task on a remote computer. </font></p> <font size="3"></font> <p align="justify"><font size="3">We wanted to make it really easy for developers to develop activities. Developers just concentrate on developing cmdlets for use in PowerShell. A set of APIs can then be used to generate activities from these cmdlets. These activities now have remoting capabilities and can be used in workflows to target different computers. </font></p> <font size="3"></font> <h2>3.1 Determining Command Execution Type</h2> <font size="3"></font> <p><font size="3">As mentioned in Part 1, the command associated with an activity can be run in one of the following ways:</font></p> <font size="3"></font> <p><font size="3">1. In process – command runs within the hosting process</font></p> <font size="3"></font> <p><font size="3">2. Out-of-process - command is run in a separate PowerShell process</font></p> <font size="3"></font> <p><font size="3">3. Remotely - command is run on a remote machine</font></p> <font size="3"></font> <p><font size="3">How the command is run is determined as follows:</font></p> <font size="3"></font> <p align="justify"><font size="3">1. All CIM and WMI activities always run in-process (<i>these are first-class citizens and have special handling within PowerShell)</i> to provide maximal performance and scalability.</font></p> <font size="3"></font> <p align="justify"><font size="3">2. If the session configuration allows the activity to be run in-process, the command is executed within the host process</font></p> <font size="3"></font> <p align="justify"><font size="3">3. If the session configuration specifies that the activity needs to run out of process, the Activity Controller runs it in a separate process </font></p> <font size="3"></font> <p align="justify"><font size="3">4. If <font size="4" face="Courier New">PSComputerName</font> parameter is used, the command is executed remotely against the specified computer.</font></p> <font size="3"></font> <h2>3.2 Activity Execution</h2> <font size="3"></font> <p align="justify"><font size="3">1. WMI and CIM activities are special in that they always run in-process and PowerShell directly talks to the underlying infrastructure to execute these commands – either locally or remotely.</font></p> <font size="3"></font> <p align="justify"><font size="3">2. For every other activity, there is one commonality – each command (pertaining to an activity) in a workflow is executed in its own runspace. This is true for all the types specified in #2 to #4 above. </font></p> <font size="3"></font> <p align="justify"><font size="3">3. When a command runs in-process, a runspace is obtained from a local cache of runspaces, the command is executed; the runspace is cleaned up and returned to the cache (<i>Maintaining a cache of runspaces is a performance-enhancing feature of Windows PowerShell Workflows</i>).</font></p> <font size="3"></font> <p align="justify"><font size="3">4. When a command is run on a remote machine, a runspace is obtained from the Connection Manager, the command is executed, and the runspace is returned to the Connection Manager.</font></p> <font size="3"></font> <p align="justify"><font size="3">5. When a command needs to be run out-of-process, the command is submitted to the Activity Controller. The Activity Controller maintains a pool of PowerShell worker processes in which it runs the command and calls back when it is done.</font></p> <font size="3"></font> <p align="justify"><font size="3">If an activity takes a long time to run, the workflow may be passivated i.e. unloaded from memory, and all the information associated with the workflow is saved. After the activity completes, it reactivates the workflow i.e. loads the workflow’s state back into memory, and resumes execution.</font></p> <font size="3"></font> <h1>4. Connection Manager</h1> <font size="3"></font> <p align="justify"><font size="3">As mentioned in part 1, the Connection Manager is responsible for pooling, throttling and managing all connections from workflows within the process. The Connection Manager maintains a pool of connections indexed first by the computer name and then by the session configuration name. </font></p> <font size="3"></font> <h2>4.1 Servicing a Connection Request</h2> <font size="3"></font> <p align="justify"><font size="3">1. When an activity requests a connection to a specified computer, the Connection Manager checks to see if there is an available connection that matches all the required remoting parameters (computer name, authentication, credentials, etc). If it finds one, it marks the connection as busy, and returns the existing connection. </font></p> <font size="3"></font> <p align="justify"><font size="3">2. If there is no match, it checks to see if the maximum allowed connections to a particular computer have been reached. If there is room for creation, it creates a new connection with the specified parameters. </font></p> <font size="3"></font> <p align="justify"><font size="3">3. If there are open connections, but they do not match the required remoting parameters, and the maximum allowed connections to a computer has been reached, the Connection Manager finds an open connection that is free, closes that connection, and then creates a new one with the required parameters. This ensures that no more than the maximum number of remote connections is created to a particular computer.</font></p> <font size="3"></font> <p align="justify"><font size="3">4. When there are no available existing connections, and a new connection cannot be created, the request is queued until a connection is freed up.</font></p> <font size="3"></font> <p align="justify"><i><font size="3"> To maintain a fair servicing policy, Connection Manager ensures that queued requests are serviced before new incoming requests.</font></i></p> <font size="3"></font> <h2>4.2 Closing Connections Not in Use</h2> <font size="3"></font> <p align="justify"><font size="3">A timer in the Connection Manager periodically iterates through all the connections available and checks if a connection is busy or free. If the connection is free, it is flagged. If the connection is already flagged (which means it is free since the last check), it is closed. When a connection is open, it not only amounts to resource consumption on the local computer, but there is also an active, but unused process on the remote computer. Closing a connection ensures that a process does not stay open on the remote computer unless it is necessary.</font></p> <font size="3"></font> <h2>4.3 Disconnect/Reconnect Operations</h2> <font size="3"></font> <p align="justify"><font size="3">When the number of outbound connections increases, the Connection Manager starts to disconnect the connections. It then connects to the remote computers few at a time to obtain the data. This ensures that PowerShell Workflows can connect to a large set of machines and start commands and then obtain data in a controlled manner. There is also a limit to the total number of disconnected sessions that the Connection Manager will maintain.</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3755.image_5F00_6A37CED7.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4426.image_5F00_thumb_5F00_0A52DB95.png" width="718" height="99" /></a></p> <p align="justify"><i><font size="3">MaxSessionPerRemoteNode is the maximum number of connections that will be made to each remote computer.</font></i></p> <font size="3"></font> <h2>4.4 Throttling</h2> <font size="3"></font> <p align="justify"><font size="3">The Connection Manager throttles all operations – <font size="4" face="Courier New">open, close, connect</font> and <font size="4" face="Courier New">disconnect</font> - using a single queue. This ensures that there are no more than a specified maximum number of network operations in progress. The throttling works similar to the throttling in PowerShell remoting.</font></p> <font size="3"></font> <h1>5. Activity Controller</h1> <font size="3"></font> <p align="justify"><font size="3">Whenever an activity is considered unreliable (<i>like a script that was grabbed from a blog post</i>), the workflow author or the administrator might want to run the activity in a separate process. This will ensure that, in case there is a crash, the whole session is not brought down; only the activity fails. The Activity Controller maintains a pool of PowerShell processes and is responsible for executing activities out of process. </font></p> <font size="3"></font> <h2>5.1 Executing Activities Out of Process</h2> <font size="3"></font> <p align="justify"><font size="3">The Activity Controller maintains an unbounded queue of incoming requests. The request typically contains the command to execute and its input, the output buffer, the variables that need to set and the modules that need to be made available for the command to execute.</font></p> <font size="3"></font> <p align="justify"><font size="3">The activities that will be run out of process, the number of processes that the Activity Controller will create, and the amount of time a process will stay idle, are determined by the properties of the session configuration.</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0624.image_5F00_2A6DE852.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1205.image_5F00_thumb_5F00_1C9BA257.png" width="726" height="79" /></a></p> <font size="3"></font> <p align="justify"><font size="3">A servicing thread in the Activity Controller picks requests from the queue, creates a new PowerShell process if required, creates a new runspace (out-of-process runspace) for every command execution, prepares the runspace, and finally executes the command. Once complete the Activity Controller calls back into the activity and the workflow execution resumes.</font></p> <font size="3"></font> <p align="justify"><font size="3">If the process crashes during execution of the command, the activity fails and the workflow handles this failure.</font></p> <font size="3"></font> <h1>6. Persistence</h1> <font size="3"></font> <p align="justify"><font size="3">Persistence is the operation within the execution of the workflow that saves information about the workflow to a store. Windows PowerShell Workflow uses a file-based store. The persisted information consists of the workflow definition, workflow parameters, workflow job state, internal state information, input and output, metadata associated with the workflow, etc.</font></p> <font size="3"></font> <p><font size="3">Every workflow has a –<font size="4" face="Courier New">PSPersist</font> common parameter that has a tri-state value:</font></p> <font size="3"></font> <p><font size="3">1. Not specified – persist at the beginning and end of a workflow</font></p> <font size="3"></font> <p><font size="3">2. <font size="4" face="Courier New">$true</font> – persist after execution of every activity</font></p> <font size="3"></font> <p><font size="3">3. <font size="4" face="Courier New">$false</font> – do not persist at all</font></p> <font size="3"></font> <p align="justify"><font size="3">Persistence can also be managed within the workflow itself. If the workflow has a <font size="4" face="Courier New">CheckPoint-Workflow</font> or a <font size="4" face="Courier New">Suspend</font> activity specified at any point, persistence happens at those points as well.</font></p> <font size="3"></font> <p><font size="3">When a workflow is resumed, it always resumes from the last persisted point.</font></p> <font size="3"></font> <h2>6.1 Begin Persistence</h2> <font size="3"></font> <p align="justify"><font size="3">All the information, including the workflow definition and the input, are persisted when the workflow job is created. This is because a workflow job may not start running as soon as it is created due to throttling. Before the start of the workflow, if the process restarts (for whatever reason), the job can simply be resumed since all the parameters and input are available. This helps when there are a large number of jobs being executed, which is typical when managing a large number of machines.</font></p> <font size="3"></font> <h2>6.2 End Persistence</h2> <font size="3"></font> <p align="justify"><font size="3"><i>End persistence</i> is persistence that happens when the workflow reaches a terminal state (<font size="4" face="Courier New">Completed</font>, <font size="4" face="Courier New">Stopped</font> or <font size="4" face="Courier New">Failed</font>). The idea is that a user will be able to retrieve output and state of the workflow after a process restart. </font></p> <font size="3"></font> <p align="justify"><font size="3">Even if a user specifies –<font size="4" face="Courier New">PSPersist</font> as $<font size="4" face="Courier New">false</font>, we attempt to see if output from the workflow and other information can be persisted. If so, it will be persisted because it frees up memory resources. This helps Windows PowerShell Workflow scale to a large number of jobs. (<i>This is one of the scalability improvements. As a result, the number of jobs that can be executed simultaneously is very large).</i></font></p> <font size="3"></font> <h2>6.3 Persistence at Persistence Point</h2> <font size="3"></font> <p align="justify"><font size="3">When there is a <font size="4" face="Courier New">CheckPoint-Workflow</font> or a <font size="4" face="Courier New">Suspend</font> activity in a workflow, persistence takes place at that point. This allows the workflow author to specify logical points in the execution sequence where it makes sense for the workflow to be resumed from that point.</font></p> <font size="3"></font> <h1>7. Conclusion</h1> <font size="3"></font> <p align="justify"><font size="3">This blog post concludes the two-part series on the high level architecture of Windows PowerShell Workflow.</font></p> <p align="justify">&#160;</p> <p align="left"><font size="3">Narayanan Lakshmanan [MSFT]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </font><font size="3">Software Design Engineer – Windows PowerShell&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </font><font size="3">Microsoft Corporation</font></p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10321960" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+Workflow/">PowerShell Workflow</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>High Level Architecture of Windows PowerShell Workflow (Part 1)</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/15/high-level-architecture-of-windows-powershell-workflow-part-1.aspx</link><pubDate>Fri, 15 Jun 2012 11:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10317574</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10317574</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/15/high-level-architecture-of-windows-powershell-workflow-part-1.aspx#comments</comments><description><p>&#160;</p> <h3><a name="_Toc261617278"></a><a name="_Toc261617277">1 Summary</a></h3> <p>In March we introduced <a href="http://blogs.msdn.com/b/powershell/archive/2012/03/17/when-windows-powershell-met-workflow.aspx">Windows PowerShell Workflow</a> (PSWF), which explained why we integrated workflows with PowerShell, and what were our major investment areas for our first release. </p> <p><a href="http://blogs.technet.com/b/windowsserver/archive/2012/05/29/windows-server-2012-powershell-3-0-and-devops-part-2.aspx">In a recent post</a>, Jeffrey Snover summarizes this decision:</p> <blockquote> <p><i>“</i><i>We integrated the </i><a href="http://blogs.msdn.com/b/powershell/archive/2012/03/17/when-windows-powershell-met-workflow.aspx"><i>Windows Workflow Foundation</i></a><i> engine into PowerShell to make it simple and easy to automate things that take a long time, that operate against a very large scale, or that require the coordination of multiple steps across multiple machines.</i><i>” </i></p> </blockquote> <p>While these posts talked about workflows as robust multi-machine commands, it didn’t address all the work we’ve done under the covers to make that happen. For the developers, architects, and highly-technical among you, here’s your chance to look under the hood. This is the first part of a two-blog series about the high-level architecture of the Windows PowerShell Workflow. The first one is a general description of the architecture; the second one will go into more details.</p> <p>After these initial two blogs regarding the architecture, we will have a series of blogs that will go deeper into each area of functionality.</p> <h3><a name="_Toc261617291">2 Goals</a></h3> <p>The main high-level goals and requirements that influenced the Windows PowerShell Workflow architecture are:</p> <blockquote> <p>a. Provide a platform to minimize the complexity of managing multi-machine environments. For example, to simplify the execution of a large number of concurrent operations performed on many computers.</p> <p>b. Provide ability for robust execution of tasks despite failed network connections, reboots, and system crashes. </p> <p>c. Make workflows available to existing Windows PowerShell users:</p> </blockquote> <blockquote> <ul> <li>Provide support to author workflows as scripts and host them in a Windows PowerShell environment.</li> </ul> <ul> <li>Provide a built in library of management tasks.</li> </ul> <ul> <li>Provide workflow management through job cmdlets.</li> </ul> </blockquote> <blockquote> <p>d. Provide a runtime that achieves good performance and a reasonable level of scalability without imposing a lot of complexity on the user. </p> <p>e. Support delegated administration.</p> <p>f. Provide a “one true PowerShell workflow implementation” that everyone could take advantage of, allowing people to share workflows in the same way that they currently share scripts, etc.</p> <p>g. Provide extensibility points that others can use to provide workflow hosting and execution functionality.</p> </blockquote> <h3>3 Architectural Overview</h3> <p>This section covers the high-level architecture for Windows PowerShell Workflow and its components. We will start with the Windows PowerShell Workflow architecture when workflows are executed in-process in the client application. The client application can be the Windows PowerShell console host, Windows PowerShell Integrated Scripting Environment (ISE) process or other client executable, including 3<sup>rd</sup> party host.</p> <p>Once we finished with in-process execution, we’ll move to describing the Windows PowerShell Workflow high level architecture when workflows are executed in the dedicated Windows PowerShell Workflow Configuration. Windows PowerShell Workflow Configuration is the default Windows Remote Management (WinRM) configuration for Windows PowerShell Workflow. (Look for why we created a new configuration in a future blog). WinRM is the Microsoft implementation of the WS-Management protocol. WS-Management is a general Web services protocol based on SOAP for managing systems such as PCs, servers, devices, Web services and other applications, and other manageable entities. The WinRM Configuration is a node you connect to, identified by a ConnectionURI and ConfigurationName. Sometimes, a WinRM Configuration is called WinRM Endpoint.</p> <p>At the end of this section, we will describe the components of the Windows PowerShell Workflow Executive.</p> <h4>3.1 In-process execution of workflows </h4> <p>The following diagram outlines the high-level architecture of the Windows PowerShell Workflow when the workflow is executed in-process within Powershell.exe, Powershell_ise.exe or another client application executable. In the diagram, the outer boxes represent machine boundaries, dotted red lines represent process boundaries, and the smallest boxes represent conceptual components.</p> <p>&#160;</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1031.image_5F00_6347517D.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4670.image_5F00_thumb_5F00_7523E54A.png" width="695" height="412" /></a></p> <p>&#160;</p> <p>&#160;</p> <p>A workflow comprises a series of programming steps called <i>activities</i>. Workflows are integrated into Windows PowerShell thorough a set of extensions to the Windows PowerShell scripting language. One of these extensions is the <b>workflow</b> keyword. A workflow is defined by the <b>workflow</b> keyword followed by the name and the body of the workflow. In addition, Windows PowerShell provides a built-in library of activities.</p> <p>A <i>script workflow</i> is a workflows written in the Windows PowerShell language.</p> <p>Example of a script workflow in Windows PowerShell ISE:</p> <p>#using parallel foreach <br />workflow <font color="#0000ff">Invoke-ParallelForEach</font> <br />{ <br />&#160;&#160;&#160; foreach -parallel (<font color="#ff0000">$i</font> in 1..10) <br />&#160;&#160;&#160; { <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#0000ff">InlineScript</font> <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; { <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &quot;foo: $using:i&quot; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; } <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#0000ff">Get-Process</font> -Name PowerShell* <br />&#160;&#160;&#160; } <br />} <br /><font color="#0000ff">Invoke-ParallelForEach</font> -PSComputerName <font color="#4f81bd">localhost</font> -AsJob </p> <p>Let’s see how this script is transformed into a working workflow. </p> <p>When you run a script workflow, Windows PowerShell parses the script into an abstract syntax tree (AST). The presence of the “workflow” keyword causes the script-to-workflow compiler to use this AST to generate XAML, the format required by the Windows Workflow Foundation runtime. To create the user experience for interacting with this workflow, we then create a wrapper function that has the same parameters – but instead coordinates execution of the workflow within the PowerShell Workflow executive. You can see both the wrapper function and the generated XAML by executing: </p> <p><font color="#0000ff">Get-Command</font> <font color="#8064a2">Invoke-ParallelForEach</font> |<font color="#0000ff">Format-List</font> * </p> <p>To create the wrapper function from the XAML workflow, Windows PowerShell uses .NET 4.0 ActivityXamlServices class to compile the XAML into an activity tree, which is the basis for all workflows in Windows Workflow Foundation 4.0. Then, it adds the activity tree to an internal cache so it can be re-used in subsequent workflow executions. (Our performance and scalability blog will explain why this is important.) </p> <p>The activity tree is then executed by the Windows PowerShell Workflow Executive. Each workflow instance wraps a .NET 4 WorkflowApplication, which is instantiated by using the activity tree as the workflow definition.</p> <p>If the workflow is executed in-process, such as is done in Windows PowerShell ISE, the Windows PowerShell Workflow Executive is hosted by the client application. The Executive is responsible for running the workflow and passivating and reactivating the workflow, as necessary. <i>Passivation</i> is the process of removing the workflow state from memory and saving it in a database. <i>Reactivation</i> is the process of loading the workflow’s state into memory and executing the workflow.</p> <p>By default, most activities run in the same process as the Windows PowerShell Workflow Executive. If the Windows PowerShell Workflow Executive determines that an activity has the potential to be unreliable (based on its configuration), it will run the activity out of process in a pool of available Windows PowerShell Workflow Activity Host processes. The InlineScript activity is, by default, executed out of process in one of the Windows PowerShell Workflow Activity Host processes. </p> <p>The activity can target different managed nodes and can take advantage of different remote management technologies, such as Windows PowerShell Remoting (PSRP), Common Information Model (CIM) or Windows Management Instrumentation (WMI) technologies. CIM is a remotable object model defined and published by the Distributed Management Task Force (DMTF). WMI is the Microsoft implementation of the CIM standard.</p> <h4>3.2 Execution of workflows within Windows PowerShell Workflow Configuration</h4> <p>The following diagram outlines the high-level architecture of the Windows PowerShell Workflow while the workflow is executed in the Windows PowerShell Workflow Configuration. The short version of why you would want to do this is that a process can invoke a workflow and then go away and the workflow continues to execute.</p> <p>&#160;</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1145.image_5F00_18ECAF93.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1638.image_5F00_thumb_5F00_11614026.png" width="731" height="301" /></a></p> <p>&#160;</p> <p>Example of a workflow executed in the Windows PowerShell Workflow Configuration:</p> <p><font color="#ff0000">$s</font> = <font color="#0000ff">New-PSWorkflowSession</font> <br /><font color="#0000ff">Invoke-Command</font> <font color="#ff0000">$s</font> { <br />workflow <font color="#9b00d3">Invoke-ParallelForEach <br /></font>{ <br />&#160;&#160;&#160; foreach -parallel (<font color="#ff0000">$i</font> in 1..10) <br />&#160;&#160;&#160; { <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#0000ff">InlineScript</font> <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; { <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#333333">&quot;foo: $using:i&quot; <br /></font>&#160;&#160;&#160;&#160;&#160;&#160;&#160; } <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#0000ff">Get-Process</font> -Name PowerShell* <br />&#160;&#160;&#160; } <br />} <br />} <br /><font color="#0000ff">Invoke-Command</font> <font color="#ff0000">$s</font> { <font color="#0000ff">Invoke-ParallelForEach</font> -PSComputerName <font color="#9b00d3">localhost</font> } </p> <p>In this case, the client connects to the Windows PowerShell Workflow Configuration using Windows PowerShell Remoting. Typically, workflows are installed on the machine that contains the Windows PowerShell Workflow Executive. </p> <p>In the example above, the Invoke-ParallelForEach workflow is sent to the Windows PowerShell Workflow Executive by using Windows PowerShell remoting. The Windows PowerShell Workflow Executive, which is responsible for the execution of the workflow, is hosted by the WinRM provider host (wsmprovhost.exe). The WinRM service, which is the server-side implementation of the WS-Management protocol, implements a provider subsystem. </p> <p>Each WinRM provider, including Windows PowerShell Workflow Executive, is hosted by the wsmprovhost.exe. Wsmprovhost.exe (the Windows PowerShell Workflow Executive) runs under the security context of the remote client. By default, all workflows in a given security context run under the same wsmprovhost.exe and are orchestrated by the same Windows PowerShell Workflow Executive. Different users run workflows in different wsmprovhost.exe instances. </p> <p>If the admin creates a Windows PowerShell Workflow “RunAs” configuration, the WinRM service translates all incoming, configured user identities into one trusted security context. “RunAs” configuration is a WinRM Configuration configured for delegated administration, which runs with the permissions of a pre-defined user identity, instead of the remote user. Therefore, the workflows for all configured users for the particular “RunAs” configuration are routed to the same Windows PowerShell Workflow host and run under the same “RunAs” configured identity. </p> <h4>3.3 Windows PowerShell Workflow components</h4> <p>Now let’s break the Windows PowerShell Workflow Executive into its high level sub components:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1651.image14_5F00_7F187963.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6332.image14_5F00_thumb_5F00_77F93CEB.png" width="717" height="423" /></a></p> <p>&#160;</p> <p>&#160;</p> <p>All workflows are executed as jobs. This allows us to manage more operations at a time, which is critical for multi-machine management. They are also long-running – you don’t want to be sitting at your console for 2 days waiting for the task to complete. All operations related to jobs are handled by the Windows PowerShell job infrastructure component (“Job Infra” in the diagram above). The job infrastructure creates the job and returns a local proxy job that can be used to manage the workflow execution. The client can use the standard Windows PowerShell Job cmdlets to start, stop, suspend, resume, and remove the job. This will be illustrated in a separate blog.</p> <p>The Job infrastructure interacts with “Workflow Compilation, Caching and Validation” component which is responsible for compiling the XAML into the activity tree, validating the activity tree by using the .NET 4.0 ActivityValidationServices class based on the Windows PowerShell Workflow configuration, and caching the XAML and the activity tree. More about these later.</p> <p>For each job, “Workflow Execution Engine” component instantiates a WorkflowApplication using the activity tree as the workflow definition. WorkflowApplication is a component introduced in Windows Workflow Foundation (WF) 4.0 that provides a host for a single workflow instance. WorkflowApplication is basically a thread-safe proxy for the actual workflow instance managed by the WF runtime. For more details, see the WF 4.0 documentation.</p> <p>Since a workflow is a series of activities, the “Workflow Execution Engine” interacts with the “Activities” component. Windows PowerShell Workflow provides a default set of PowerShell activities that any host can adopt. These activities are based on Windows PowerShell Remoting, CIM, or WMI, or are special activities, such as Pipeline, PowerShellValue, GetPSWorkflowData and SetPSWorkflowData activities. Most of these built-in activities are derived from the PSActivity base class, with the exception of the special activities specified above. When you look at the ecosystem of previous PowerShell + Workflow integrations, there’s not much of a “network effect”. If somebody makes a great PowerShell-based activity, they make their own decisions around serialization, remoting behavior, and user experience. The activities that work in one product rarely work in anyone else’s. By providing a base activity implementation and many immediately-useful PowerShell activities, we tame that inconsistency so that every new activity adds broader value.</p> <p>These activities can run:</p> <blockquote> <p>- In-process with the Workflow Execution Engine. For example, CIM activities (GetCimInstanceActivity, InvokeCimMethodActivity etc) or WMI activities (GetWmiObject, InvokeWmiMethod)</p> </blockquote> <blockquote> <p>- Out-of-Process in the ActivityHost process. For example, the InlineScript activity. Activities are executed out of process to provide isolation for reliability.</p> </blockquote> <blockquote> <p>- Remotely, if the PSComputerName parameter is specified</p> </blockquote> <p>Windows PowerShell remoting activities and, to some extent, CIM activities that are executed remotely, interact with the “ConnectionManager” subcomponent. ConnectionManager is responsible for connection pooling and throttling. After all, if you’re invoking high number of workflows in parallel – the last thing you need is to be killing your own servers. The connections pool is indexed based on the machine and session configuration, and uniquely identified by the rest of remoting parameters (authentication, credentials, certificate thumbprint, proxy settings, etc.), in addition to the machine and session configuration.</p> <p>If executed out of process, the activity interacts with the “Activity Controller” subcomponent. The Activity Controller is responsible for queuing all out-of-process activities and executing them in the pool of Activity Host processes. The out-of-process activities are specified by the configuration. </p> <p>By default, on both Windows client and server operating system, the WorkflowApplication in the Workflow Execution Engine uses a file-based store to store the workflow definition, metadata, streams, job state. This is handled by the “Persistence” subcomponent. </p> <p>Windows PowerShell Workflow is also a library that others can use to provide workflow hosting and execution functionality. The hosting SDK will be presented in a separate blog.</p> <h3>4 More info</h3> <p>While you wait for our next post, which will go deeper into the Windows PowerShell Workflow architecture, here are some additional resources about Windows PowerShell 3.0 and Windows PowerShell Workflow:</p> <p><a href="http://blogs.msdn.com/b/powershell/archive/2012/03/17/when-windows-powershell-met-workflow.aspx">When Windows PowerShell Met Workflow</a> (by Mir Rosenberg [MSFT], Senior Program Manager, Windows PowerShell)</p> <p><a href="http://www.microsoft.com/download/en/details.aspx?id=27548">Getting started with Windows PowerShell Workflow</a> (Download WMF3 CTP2 Windows PowerShell Workflow.pdf)</p> <p><a href="http://www.windowsitpro.com/blog/powershell-with-a-purpose-blog-36/windows-powershell/powershell-v3-workflow-flagship-feature-140712">PowerShell v3: Workflow is the Flagship Feature</a> (by Don Jones – PowerShell MVP)</p> <p><a href="http://halr9000.com/article/947">PowerShell Workflow, Defined</a> (by Hal Rottenberg – PowerShell MVP)</p> <p><a href="http://blogs.technet.com/b/windowsserver/archive/2012/03/07/rocking-the-windows-server-8-administrative-experience.aspx">Rocking the Windows Server 8 Administrative Experience</a></p> <p><a href="http://go.microsoft.com/fwlink/?LinkId=246563">TechNet docs on the Workflow module</a></p> <p><a href="http://go.microsoft.com/fwlink/?LinkId=246399">Writing a Windows PowerShell Workflow in the Visual Studio Designer</a></p> <p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.powershell.workflow(v=VS.85).aspx">SDK/MSDN documentation</a></p> <p>Sorin Oprea [MSFT] <br />Senior SDE Lead <br />Windows PowerShell</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10317574" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell/">PowerShell</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+Release/">PowerShell Release</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Management+Framework/">Windows Management Framework</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Workflow/">Workflow</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+Workflow/">PowerShell Workflow</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Getting+Started/">Getting Started</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/XAML/">XAML</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>New V3 Language Features</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/14/new-v3-language-features.aspx</link><pubDate>Thu, 14 Jun 2012 00:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10317042</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10317042</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/14/new-v3-language-features.aspx#comments</comments><description><p>We&rsquo;ve already discussed the biggest new PowerShell language feature &ndash; workflows &ndash; in a previous post.&nbsp; In this post, I&rsquo;m going to describe a number of small changes we&rsquo;ve made to the language.&nbsp; Most of the changes described here don&rsquo;t introduce any new syntax, but I think you&rsquo;ll agree that most of these changes make various aspects of scripting in PowerShell simpler.&nbsp; To me, many of these features are what make PowerShell a joy to use.</p> <p>&nbsp;</p> <h3></h3> <h3><span style="color: #4f81bd;" color="#4f81bd">Member Enumeration</span></h3> <p>To start, I&rsquo;m going to describe a little feature that had no official name until I started this blog post.&nbsp; I&rsquo;m also starting with this feature because it was a surprise hit (to me anyway) when we demonstrated to the PowerShell MVPs recently.</p> <p>If you find yourself frequently piping a collection to ForEach-Object or Select-Object (or more likely the aliases % or select) to get a single property, then you&rsquo;ll love this feature.</p> <p>Say you want a list of full paths to some files.&nbsp; In PowerShell V2.0, you&rsquo;d write:</p> <p align="left"></p> <p><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2"><span style="color: #000000;" color="#000000"></span>dir</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">|</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">%</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> { </span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$_</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">FullName }</span></span></p> <p align="left">In PowerShell V3.0, you can write:</p> <p><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">(dir)</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">FullName</span></p> <p>It doesn&rsquo;t matter if the cmdlet is returning one result or multiple results.&nbsp; Under the covers, PowerShell is automatically handling the differences for you, as though you were using ForEach-Object in the first example, except it&rsquo;s faster because the ForEach-Object cmdlet isn&rsquo;t actually running.</p> <p>This new capability doesn&rsquo;t introduce any new syntax and it just works wherever you would get a property or invoke a method.&nbsp; But you can&rsquo;t use this syntax to set properties.</p> <p>We added this feature to make it easier to deal with commands that return one or many objects.&nbsp; Experienced PowerShell scripters knew they needed to use @() to handle that situation correctly, but we really thought that was less than perfect.</p> <p>Member enumeration is one piece of handling commands that return one or many objects, but there are a few other details that we&rsquo;ve taken care of as well.</p> <p>You can now use Count or Length on any object, even if it didn&rsquo;t have the property.&nbsp; If the object didn&rsquo;t have a Count or Length property, it will will return 1 (or 0 for $null).&nbsp; Objects that have Count or Length properties will continue to work as they always have.</p> <p><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; <span style="color: #ff4500;" color="#ff4500">$a</span><span style="color: #000000;" color="#000000"> </span><span style="color: #a9a9a9;" color="#a9a9a9">=</span><span style="color: #000000;" color="#000000"> </span><span style="color: #800080;" color="#800080">42</span></span></span> <br /><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; <span style="color: #ff4500;" color="#ff4500">$a<span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">Count</span></span> <br /></span></span><span style="font-family: Lucida Console;" face="Lucida Console"><span style="color: #ff4500;" color="#ff4500"><span style="font-size: x-small;" size="2"><span style="color: #000000;" color="#000000">1</span></span></span></span></p> <p>You can also index into any object even if it didn&rsquo;t have an index operation.&nbsp; If the object has no indexer, index 0 simply returns the object, any other index returns nothing (or an error if strict-mode is enabled).</p> <p><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; <span style="color: #ff4500;" color="#ff4500">$a</span><span style="color: #a9a9a9;" color="#a9a9a9">[<span style="color: #800080;" color="#800080">0</span>] <br /><span style="font-family: Lucida Console;" face="Lucida Console"><span style="color: #ff4500;" color="#ff4500"><span style="font-size: x-small;" size="2"><span style="color: #000000;" color="#000000">42 <br /><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; <span style="color: #ff4500;" color="#ff4500">$a</span><span style="color: #a9a9a9;" color="#a9a9a9">[<span style="color: #800080;" color="#800080">-1</span>] <br /><span style="font-family: Lucida Console;" face="Lucida Console"><span style="color: #ff4500;" color="#ff4500"><span style="font-size: x-small;" size="2"><span style="color: #000000;" color="#000000">42</span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> <p>Combining indexing and Count, you can now use for loops without worrying if the input is an array or single object:<span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"></span></p> <p align="left"></p> <p><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$x</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">dir</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #006400; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#006400" size="2"># returns 1 or more objects <br /></span><span style="color: #00008b; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#00008b" size="2">for</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> (</span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$i</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">0</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">; </span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$i</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">&ndash;lt</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$x</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">Count; </span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$i</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">++</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">) <br />{ <br /></span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">&nbsp;&nbsp;&nbsp; $x</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$i</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">... <br /></span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">}</span></p> <p align="left"></p> <p>These language features could actually change the behavior some scripts.&nbsp; We&rsquo;ve found a few real-world scripts that stopped working due to these changes.&nbsp; But we also found, after closer review of these scripts, that they were already broken.&nbsp; In one example the script was actually failing to process all of the data it was trying to verify.&nbsp; We are not aware of any scripts where this change broke a script, but did not expose an underlying problem in the script.</p> <p>&nbsp;</p> <p></p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">New Redirection Operators</span></p> <p class="MsoNormal">There are new redirection operators so you can redirect verbose, warning, and debug streams.&nbsp; Merging and file redirections work in the same way as error redirection.&nbsp; Here are some examples:</p> <p align="left"></p> <p><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">Do-Something</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">3&gt;</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">warning.txt</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">&nbsp; </span><span style="color: #006400; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#006400" size="2"># Writes warning output to warning.txt <br /></span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">Do-Something</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">4&gt;&gt;</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">verbose.txt</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #006400; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#006400" size="2"># Appends verbose.txt with the verbose output <br /></span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">Do-Something</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">5&gt;&amp;1</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #006400; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#006400" size="2"># Writes debug output to the output stream <br /></span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">Do-Something</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">*&gt;</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">out.txt</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #006400; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#006400" size="2"># Redirects all streams (output, error, warning, verbose, and debug) to out.txt</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"></span></span></span></p> <p align="left"></p> <p class="Code">We didn&rsquo;t get a chance to add redirection support for host output (Write-Host, $host.UI.Write&hellip;).</p> <p class="Code">&nbsp;</p> <p></p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Passing Local Variables to Remote Sessions</span></p> <p>In PowerShell 2.0, if you want to use local variables when executing a script block remotely, you have to do something like:</p> <p><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; <span style="color: #ff4500;" color="#ff4500">$localVar</span><span style="color: #000000;" color="#000000"> </span><span style="color: #a9a9a9;" color="#a9a9a9">=</span><span style="color: #000000;" color="#000000"> </span><span style="color: #800080;" color="#800080">42 </span></span></span> <br /><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; <span style="color: #0000ff;" color="#0000ff">Invoke-Command</span><span style="color: #000000;" color="#000000"> </span><span style="color: #000080;" color="#000080">-cn</span><span style="color: #000000;" color="#000000"> </span><span style="color: #8a2be2;" color="#8a2be2">srv123</span><span style="color: #000000;" color="#000000"> { </span><span style="color: #00008b;" color="#00008b">param</span><span style="color: #000000;" color="#000000">(</span><span style="color: #ff4500;" color="#ff4500">$localVar</span><span style="color: #000000;" color="#000000">) </span><span style="color: #0000ff;" color="#0000ff">echo</span><span style="color: #000000;" color="#000000"> </span><span style="color: #ff4500;" color="#ff4500">$localVar</span><span style="color: #000000;" color="#000000"> } </span><span style="color: #000080;" color="#000080">&ndash;ArgumentList</span><span style="color: #000000;" color="#000000"> </span></span></span><span style="font-family: Lucida Console;" face="Lucida Console"><span style="color: #ff4500;" color="#ff4500"><span style="font-size: x-small;" size="2">$localVar <br /><span style="color: #000000;" color="#000000">42</span></span></span></span></p> <p>In PowerShell 3.0, variables prefixed with $using: are automatically recognized as local variables and are sent to the remote machine:</p> <p><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; </span><span style="color: #0000ff; font-size: x-small;" color="#0000ff" size="2">Invoke-Command</span><span style="color: #000000; font-size: x-small;" color="#000000" size="2"> </span><span style="color: #000080; font-size: x-small;" color="#000080" size="2">&ndash;cn</span><span style="color: #000000; font-size: x-small;" color="#000000" size="2"> </span><span style="color: #8a2be2; font-size: x-small;" color="#8a2be2" size="2">srv123</span><span style="color: #000000; font-size: x-small;" color="#000000" size="2"> { </span><span style="color: #0000ff; font-size: x-small;" color="#0000ff" size="2">echo</span><span style="color: #000000; font-size: x-small;" color="#000000" size="2"> </span><span style="color: #ff4500; font-size: x-small;" color="#ff4500" size="2">$using:localVar</span></span><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2"><span style="color: #000000;" color="#000000"> } <br /></span><span style="color: #000000;" color="#000000">42</span></span></span></p> <p>&nbsp;&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">PSItem</span></p> <p>We sometimes receive feedback that $_ is cryptic and confusing to people who are new to PowerShell and scripting.&nbsp; Some people see $_ as a magic symbol.&nbsp; To help those people, we introduced an alias for $_.&nbsp; You can use $PSItem anywhere you would have used $_.&nbsp; For example, instead of writing:</p> <p align="left"></p> <p><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2"><span style="color: #000000;" color="#000000"></span>dir</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">|</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">%</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> { </span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$_</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">FullName }</span></span></p> <p>You can write:</p> <p align="left"></p> <p><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2"><span style="color: #000000;" color="#000000"></span>dir</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">|</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">%</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> { </span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$PSItem</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">FullName }</span></p> <p>&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">More Flexible Script Formatting</span></p> <p>We reviewed many places where newlines were previously required and relaxed those restrictions whenever it didn&rsquo;t introduce any ambiguities or break existing scripts.</p> <p>One of the more interesting places you might find this useful is in using a fluent API.&nbsp; You can now have whitespace/newlines after the &lsquo;.&rsquo; or &lsquo;::&rsquo; tokens in expression mode.</p> <p align="left"></p> <p><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">PowerShell</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]::</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">Create()</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">. <br />&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">AddCommand(</span><span style="color: #8b0000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8b0000" size="2">"echo"</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">)</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">. <br />&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">AddParameter(</span><span style="color: #8b0000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8b0000" size="2">"InputObject"</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">,</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">42</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">)</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">. <br />&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">Invoke()</span></span></span></p> <p align="left"></p> <p class="MsoNormal">In PowerShell 2.0, this needs to be all on one line, or broken into multiple statements.&nbsp; For example, the following probably doesn&rsquo;t do what you think it should.</p> <p align="left"></p> <p><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">Write-Output</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> (</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">int</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]::</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">MaxValue)</span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">&nbsp;&nbsp;&nbsp; </span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">GetType</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">() <br /></span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">Write-Output</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> (</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">int</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]::</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">MaxValue)</span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">. <br />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">GetType</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">()</span></span></span></p> <p align="left"></p> <p class="MsoNormal">The same expressions work when they don&rsquo;t begin with a command:</p> <p align="left">(<span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">int</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]::</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">MaxValue)</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">.</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> GetType() <br />(</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">int</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]::</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">MaxValue)</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">. <br />&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">GetType()</span></p> <p align="left">&nbsp;</p> <p></p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Attributes on Variables</span></p> <p>Validation attributes and argument transformation attributes are familiar to anyone who writes advanced functions.&nbsp; In PowerShell V2.0, these attributes can be used only on parameters.&nbsp; In PowerShell V3.0, you can place an attribute on any variable.</p> <p class="Code"><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; <span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #00bfff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#00bfff" size="2">ValidateRange</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">(</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">1</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">,</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">10</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">)</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">][</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">int</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]</span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$x</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">1</span> <br />PS&gt; <span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$x</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">11</span> <br />The variable cannot be validated because the value 11 is not a valid value for the x variable. <br />At line:1 char:1 <br />+ $x = 11 <br />+ ~~~~~~~ <br />&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : MetadataError: (:) [], ValidationMetadataException <br />&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : ValidateSetFailure</span></span></p> <p class="Code">&nbsp;&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Attribute Arguments Don&rsquo;t Need = $true</span></p> <p class="MsoNormal">In PowerShell V2.0, you write:</p> <p class="MsoNormal"><span style="font-family: 'Lucida Console'; color: darkblue; font-size: 9pt;">param</span><span style="font-family: 'Lucida Console'; font-size: 9pt;">(<span style="color: darkgray;">[</span><span style="color: deepskyblue;">Parameter</span>(Mandatory<span style="color: darkgray;">=</span><span style="color: orangered;">$true</span>)<span style="color: darkgray;">]</span><span style="color: orangered;">$p</span>)</span></p> <p class="MsoNormal">In PowerShell V3.0, you can write:</p> <p class="MsoNormal"><span style="font-family: 'Lucida Console'; color: darkblue; font-size: 9pt;">param</span><span style="font-family: 'Lucida Console'; font-size: 9pt;">(<span style="color: darkgray;">[</span><span style="color: deepskyblue;">Parameter</span>(Mandatory)<span style="color: darkgray;">]</span><span style="color: orangered;">$p</span>)</span></p> <p class="MsoNormal"></p> <p>If you omit the argument, there is an implied argument value of $true.</p> <p>&nbsp;</p> <p></p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Smarter Parsing of Command Names</span></p> <p>In PowerShell V2.0, if you are running 7z or another command that starts with a number, you have to use the command invocation operator:</p> <p><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2"><span style="color: #000000;" color="#000000">PS&gt; <span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">&amp;</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">7z </span></span></span></p> <p>In PowerShell V3.0, you don&rsquo;t need the &lsquo;&amp;&rsquo; anymore.</p> <p>&nbsp;</p> <p></p> <p></p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Easier Reuse of Command Lines From Cmd.exe</span></p> <p>The web is full of command lines written for Cmd.exe.&nbsp; These commands lines work often enough in PowerShell, but when they include certain characters, e.g. a semicolon (;) a dollar sign ($), or curly braces, you have to make some changes, probably adding some quotes.&nbsp; This seemed to be the source of many minor headaches.</p> <p>To help address this scenario, we added a new way to &ldquo;escape&rdquo; the parsing of command lines.&nbsp; If you use a magic parameter --%, we stop our normal parsing of your command line and switch to something much simpler.&nbsp; We don&rsquo;t match quotes.&nbsp; We don&rsquo;t stop at semicolon.&nbsp; We don&rsquo;t expand PowerShell variables.&nbsp; We do expand environment variables if you use Cmd.exe syntax (e.g. %TEMP%).&nbsp; Other than that, the arguments up to the end of the line (or pipe, if you are piping) are passed as is.&nbsp; Here is an example:</p> <p><span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2"><span style="color: #000000;" color="#000000">PS&gt; </span>echoargs.exe</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">--%</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #8a2be2; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8a2be2" size="2">%USERNAME%,this=$something{weird}</span> <br /><span style="font-family: Lucida Console; font-size: x-small;" face="Lucida Console" size="2">Arg 0 is &lt;jason,this=$something{weird}&gt;</span></p> <p>&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Better Splatting of Arrays</span></p> <p class="MsoNormal">Sometimes you want to write a quick wrapper for a script or cmdlet, but you don&rsquo;t want to write a full-on proxy cmdlet.&nbsp; For example:</p> <p class="MsoNormal"><span style="font-family: 'Lucida Console'; color: darkblue; font-size: 9pt;"><span style="font-size: x-small;" size="2">function</span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2"> <span style="color: blueviolet;">mkdir</span>(<span style="color: orangered;">$path</span>) <br /></span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2">{ <br /></span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2">&nbsp;&nbsp;&nbsp; <span style="color: blue;">New-Item</span> <span style="color: navy;">-Path</span> <span style="color: orangered;">$path</span> <span style="color: navy;">-ItemType</span> <span style="color: blueviolet;">Directory</span> </span><span style="color: orangered;"><span style="font-size: x-small;" size="2">@args <br /></span></span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2">} </span></span></p> <p class="MsoNormal">Now if I pass -Force or whatever to mkdir, it will be passed on correctly, but I didn&rsquo;t need to specify any of the parameters to New-Item.</p> <p class="MsoNormal"><br />&nbsp;</p> <p class="MsoNormal"><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">New Operators</span></p> <p>We added a few operators:</p> <table style="width: 523px;" border="1" cellspacing="0" cellpadding="2"> <tbody> <tr> <td width="138" valign="top">-shl</td> <td width="383" valign="top">Shift bits left</td> </tr> <tr> <td width="140" valign="top">-shr</td> <td width="381" valign="top">Shift bits right &ndash; preserves sign for signed values</td> </tr> <tr> <td width="142" valign="top">-in</td> <td width="380" valign="top">Like &ndash;contains, but with the operands reversed</td> </tr> <tr> <td width="143" valign="top">-notin</td> <td width="379" valign="top">Like &ndash;notcontains, but with the operands reversed</td> </tr> </tbody> </table> <p>-in/-notin were added to complement the &ldquo;simplified foreach&rdquo; feature.&nbsp; We couldn&rsquo;t support the &ndash;contains/-notcontains operators in simplified foreach, but by reversing the operands, we could have ForEach-Object support and operator support.</p> <p>&nbsp;&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">New Conversions</span></p> <p>Sometimes you want the keys of a hash literal to be ordered.&nbsp; You can now cast to [ordered] and we create an OrderedDictionary instead of HashTable.&nbsp; This only works with literals &ndash; if you try it on a variable, the ordering is no longer available.</p> <p align="left"></p> <p><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">ordered</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">@{a</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">1</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">; b</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">2</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">} </span></span></p> <p>In a similar manner, you can create custom objects with a simple cast:</p> <p align="left"></p> <p><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">pscustomobject</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">@{x</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">1</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">; y</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">2</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">} </span></span></p> <p>This does not create a HashTable; it creates a PSObject with note properties.&nbsp; If you are casting a literal, the note properties are added in the order they appear in the literal.&nbsp; If you are casting anything else, the ordering is determined by the IDictionary iterator.</p> <p>If a type has a default constructor and settable properties, you can also use a hash table to case an object to that type:</p> <p></p> <p align="left"></p> <p><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">[</span><span style="color: #008080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#008080" size="2">System.Drawing.Point</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">]</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">@{X</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">1</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">; Y</span><span style="color: #a9a9a9; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#a9a9a9" size="2">=</span><span style="color: #800080; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#800080" size="2">2</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">}</span></p> <p align="left">This will call the default constructor and set the properties named in the hash table.</p> <p>In a similar manner, deserialized objects can be reconstructed if the properties are all settable.</p> <p>&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">ForEach statement does not iterate over $null</span></p> <p>In PowerShell V2.0, people were often surprised by:</p> <p><span style="font-family: Lucida Console;" face="Lucida Console"><span style="font-size: x-small;" size="2">PS&gt; </span><span style="color: #00008b; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#00008b" size="2">foreach</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> (</span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$i</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #00008b; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#00008b" size="2">in</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> </span><span style="color: #ff4500; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#ff4500" size="2">$null</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2">) { </span><span style="color: #8b0000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8b0000" size="2">'got here'</span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"> }</span> <br /><span style="font-size: x-small;" size="2">got here</span></span></p> <p>This situation often comes up when a cmdlet doesn&rsquo;t return any objects.&nbsp; In PowerShell V3.0, you don&rsquo;t need to add an if statement to avoid iterating over $null.&nbsp; We take care of that for you.</p> <p>&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Comment Based Help Improvements</span></p> <p>PowerShell V2.0 comment based help supports most of the features available in xml based help, but there were a couple of holes that we&rsquo;ve addressed in V3, both related to parameter help.&nbsp; If you use Get-Help &ndash;full, you see a bunch of parameter descriptions that include text like the following:</p> <p>Required?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true <br />Position?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; named <br /><span style="background-color: #ffff00;">Default value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; False <br /></span>Accept pipeline input?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; false <br /><span style="background-color: #ffff00;">Accept wildcard characters?&nbsp; false <br /></span></p> <p>PowerShell V2.0 didn&rsquo;t provide any way to specify what help gets displayed for the highlighted fields above.&nbsp; In PowerShell V2.0, we&rsquo;ve fixed that.</p> <p>For default values, if you&rsquo;ve specified a default value, we include that.&nbsp; If you want finer control over what gets displayed, say to provide some context about the default value, you can use the attribute PSDefaultValue.</p> <p>If your parameter supports wildcards, you can add the SupportsWildCards attribute.</p> <p>Note that these 2 attributes are only used for help.&nbsp; PowerShell doesn&rsquo;t use these attributes for anything else.</p> <p>Here is an example:</p> <p><span style="font-family: 'Lucida Console'; color: darkblue; font-size: 9pt;"><span style="font-size: x-small;" size="2">function</span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2"> <span style="color: blueviolet;">Test-Something</span>(<span style="color: orangered;">$path</span>) <br /></span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2">{ <br /></span></span><span style="font-family: 'Lucida Console'; color: darkblue; font-size: 9pt;">&nbsp;&nbsp;&nbsp; param</span><span style="font-family: 'Lucida Console'; font-size: 9pt;">(<span style="color: darkgray;">[</span><span style="color: deepskyblue;">PSDefaultValue</span>(Help = <span style="color: #8b0000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#8b0000" size="2">'A random number.'</span>)<span style="color: darkgray;">]</span><span style="color: orangered;">$p</span> = $(<span style="color: #0000ff; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#0000ff" size="2">Get-Random</span>), <br /><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="color: darkgray;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [</span><span style="color: deepskyblue;">SupportsWildcards</span>()<span style="color: darkgray;">]</span><span style="color: orangered;">$q</span>)</span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2"> <br /></span></span><span style="font-family: 'Lucida Console'; font-size: 9pt;"><span style="font-size: x-small;" size="2">} </span></span><span style="color: #000000; font-family: Lucida Console; font-size: x-small;" face="Lucida Console" color="#000000" size="2"></span></p> <p>&nbsp;</p> <p><span style="color: #4f81bd; font-size: medium;" color="#4f81bd" size="4">Conclusion</span></p> <p>We hope these new language features make scripting easier and more fun.&nbsp; In an upcoming post, we&rsquo;ll cover other ways that we&rsquo;ve made scripting easier.</p> <p>&nbsp;</p> <p>Jason Shirk <br />Software Design Engineer &ndash; Windows PowerShell <br />Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10317042" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/LANGUAGE/">LANGUAGE</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>Intellisense in Windows PowerShell ISE 3.0</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/13/intellisense-in-windows-powershell-ise-3-0.aspx</link><pubDate>Wed, 13 Jun 2012 01:30:39 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10319137</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10319137</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/13/intellisense-in-windows-powershell-ise-3-0.aspx#comments</comments><description><p><em><font color="#a5a5a5">This blog post applies to the Windows PowerShell Integrated Scripting Environment (ISE) in Windows 8 and Windows Server 2012.&#160; The ISE is also fully supported and available when Server 2012 is deployed using the <a href="http://blogs.technet.com/b/windowsserver/archive/2012/03/20/building-an-optimized-private-cloud-using-windows-server-8-server-core.aspx">Minimal Server Interface</a>.&#160; To start ISE, type <font style="background-color: rgb(255, 255, 255);"><font face="Lucida Console"><strong>ise</strong></font>&#160; </font>in a PowerShell console and press <font face="Lucida Console"><strong>Enter</strong></font></font></em></p> <p>Very few things can be considered “cool” in an interactive command-line environment. Intellisense sure counts as one of the few exceptions.&#160; While tab completion has always been a cornerstone of PowerShell usability (and continues to be), my struggle with tab completion is that after cycling through the 5th option, I would have already forgotten the first 3 :-).&#160; Discoverability is not optimal either, because a user doesn’t always know when tab completion would work, so it becomes a bit of a trial-and-error exercise.&#160; Intellisense provides the following added benefits over tab completion:</p> <ul> <li>Automatic drop-down when options are available – better discoverability</li> <li>A view of a dozen (or so) options at a glance – no need to remember the options</li> <li>Icons to help identify the type of options available</li> <li>Syntax tooltips </li> </ul> <em></em> <h3>Commands, Parameters, and Values</h3> <p>Type <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">Set-</font> and a list of cmdlets is dropped down (as well as scripts if you have any in the current path).&#160; If you click (or navigate via keyboard) to <font style="background-color: rgb(255, 255, 255);" face="Lucida Console">Set-ExecutionPolicy</font> for example, a tooltip displays the syntax of the cmdlet.&#160; Of course, if you start typing <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">Ex</font>, the list in the drop-down is narrowed down to the matching set only. (More on matching later)</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1643.image_5F00_5CE1C76B.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6445.image_5F00_thumb_5F00_5F8A831C.png" width="829" height="179" /></a></p> <p>You can press <font face="Lucida Console"><strong>Enter</strong></font> or <strong><font face="Lucida Console">Tab</font></strong> to accept the value and once you press <strong><font face="Lucida Console">Space</font></strong> and type <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">-</font>, another drop-down appears, this time with the parameter options:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8182.image_5F00_1F5469A2.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4477.image_5F00_thumb_5F00_18352D2A.png" width="280" height="184" /></a></p> <p>&#160;</p> <p>Go ahead and select <font face="Lucida Console">–ExecutionPolicy</font>, and once you press <strong><font face="Lucida Console">Space</font></strong>, the allowed values appear (this works for enumerations and ValidateSet):</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6114.image_5F00_53F4C5DD.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6136.image_5F00_thumb_5F00_4CD58965.png" width="387" height="151" /></a></p> <p>By the way … the Intellisense icon colors for parameters and parameter values match ISE’s default color scheme for parameters and parameter values.&#160; Of course, if you’re typing in the console, parameters and parameter values have totally different colors to match the blue background, and you might be going: “Huh? what’s with the weird colors?” :-)</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4073.image_5F00_45B64CED.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8267.image_5F00_thumb_5F00_538892E8.png" width="379" height="16" /></a></p> <h3>Smart Matching</h3> <p>When you type <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">Get-</font>, Intellisense kicks in.&#160; If you continue to type <font style="background-color: rgb(204, 204, 204);">Get-Switch</font>, Intellisense displays all the options which match <font face="Lucida Console">Get-*Switch*</font>.&#160; This comes in really handy when you’re looking for a cmdlet, and don’t remember its exact name or prefix.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4786.image_5F00_615AD8E3.png"><img title="image" style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6433.image_5F00_thumb_5F00_5A3B9C6B.png" width="261" height="153" /></a></p> <p>&#160;</p> <h3>Paths</h3> <p>Type <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">dir c:\</font> and Intellisense displays a list of files and folders (items) in the path you specified.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7103.image_5F00_15FB351F.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8182.image_5F00_thumb_5F00_3CC94B5F.png" width="254" height="158" /></a></p> <p>&#160;</p> <p>Here, too, we try to do smart matching: If you use <font face="Lucida Console">Set-Location</font>, we only display containers (folders), not files (items), since it wouldn’t make sense.&#160; Here’s <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">cd c:\</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0753.image_5F00_6397619F.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3480.image_5F00_thumb_5F00_2E8AD26F.png" width="240" height="153" /></a></p> <p>Path completion works for any PowerShell provider, not just the file system. Try: <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">dir hklm:\</font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6136.image_5F00_5558E8AF.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0763.image_5F00_thumb_5F00_7C26FEEF.png" width="203" height="112" /></a>Note that using tab completion and/or Intellisense with environment variables may produce undesired results, for example when you’re trying to specify the Windows folder using the SystemDrive environment variable: </p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8015.image_5F00_7ECFBAA0.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7028.image_5F00_thumb_5F00_259DD0E1.png" width="148" height="39" /></a></p> <p>When you press <font face="Lucida Console"><strong>Enter</strong></font> or <strong><font face="Lucida Console">Tab</font></strong>, the entire string becomes: “C:\Windows&quot;, which is machine-specific, and may not be what you want.</p> <h3>Variables</h3> <p>As soon as you type <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">$</font>, Intellisense kicks in, showing user-defined and pre-defined variables:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2313.image_5F00_709141B0.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8512.image_5F00_thumb_5F00_7E6387AB.png" width="232" height="142" /></a></p> <h3>History</h3> <p>Type <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">#</font> followed by <font face="Lucida Console"><strong>Ctrl</strong></font>+<strong><font face="Lucida Console">Space</font></strong> to show your command history at a glance:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3806.image_5F00_0C35CDA7.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5543.image_5F00_thumb_5F00_3303E3E7.png" width="240" height="128" /></a></p> <h3>Types &amp; Namespaces</h3> <p>Another cool feature is namespace completion.&#160; Try <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">[Initials</font> and press <font face="Lucida Console"><font face="Lucida Console"><strong>Ctrl</strong></font>+<strong><font face="Lucida Console">Space</font></strong></font></p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6114.image_5F00_59D1FA27.png"><img title="image" style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6136.image_5F00_thumb_5F00_67A44022.png" width="198" height="80" /></a></p> <p>Press <strong><font face="Lucida Console">Enter</font></strong><font face="Segoe UI"> and you should see the namespace &amp; type expanded to: </font><font face="Lucida Console">[System.Management.Automation.Runspaces.InitialSessionState</font><font face="Segoe UI">.&#160; Yes, this means that you no longer have to know which namespace a type lives in, before you can use it. :-)</font></p> <h3>Properties &amp; Methods</h3> <p>Try <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">[int]::</font> and notice how Intellisense kicks in and displays the static members of the integer class:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7607.image_5F00_608503AA.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6840.image_5F00_thumb_5F00_5965C732.png" width="215" height="123" /></a></p> <p>Try <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">(“PowerShell rocks!”).</font> (notice the period at the end), and observe how Intellisense kicks in and displays the members of the string object:</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5852.image_5F00_15255FE6.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8508.image_5F00_thumb_5F00_0E06236E.png" width="297" height="153" /></a></p> <h3>Helpful Tips</h3> <ul> <li>If you accidentally dismiss the Intellisense drop-down, use <font face="Lucida Console"><strong>Ctrl</strong></font>+<strong><font face="Lucida Console">Space</font></strong> to invoke Intellisense again.</li> <li>Use the Options dialog if you want to turn Intellisense ON/OFF for each pane, or if you want to change the default behavior of the <font face="Lucida Console"><strong>Enter</strong></font> key for selection.</li> <li>Here is the list of icons and what they mean:</li> <ul> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6445.image_5F00_06E6E6F6.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7026.image_5F00_thumb_5F00_29AAAF64.png" width="20" height="20" /></a>: Command</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0753.image_5F00_749E2033.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0675.image_5F00_thumb_5F00_4959892C.png" width="20" height="20" /></a>: Container</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7522.image_5F00_423A4CB4.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4478.image_5F00_thumb_5F00_221F3FF7.png" width="20" height="20" /></a>: File / item</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0268.image_5F00_16F5B5AD.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7115.image_5F00_thumb_5F00_48ED5637.png" width="20" height="20" /></a>: Method</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6840.image_5F00_3DC3CBED.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4786.image_5F00_thumb_5F00_1DA8BF30.png" width="20" height="20" /></a>: Property</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3718.image_5F00_2B7B052B.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3731.image_5F00_thumb_5F00_245BC8B3.png" width="20" height="20" /></a>: Parameter</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5468.image_5F00_601B6166.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0753.image_5F00_thumb_5F00_06E977A7.png" width="20" height="20" /></a>: Parameter value</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8270.image_5F00_2DB78DE7.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8203.image_5F00_thumb_5F00_6D81746C.png" width="20" height="20" /></a>: Variable</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7115.image_5F00_666237F4.png"><img title="image" style="margin: 0px; display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/8015.image_5F00_thumb_5F00_2221D0A8.png" width="20" height="20" /></a>: History</li> <li><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7028.image_5F00_1B029430.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/7041.image_5F00_thumb_5F00_13E357B8.png" width="21" height="22" /></a>: Type</li> </ul> </ul> <p>&#160;</p> <h3>More Cool Intellisense</h3> <p>Start a new script and type: <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">$x = Get-Process m*</font>.&#160; Without even running this, as soon as you type <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">$x.</font>, you see Intellisense for the members of a <u>process</u> object. :-)</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2235.image_5F00_4FA2F06B.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3324.image_5F00_thumb_5F00_4883B3F3.png" width="240" height="194" /></a></p> <p>You can experience this at the command line as well: Try <font style="background-color: rgb(204, 204, 204);" face="Lucida Console">Get-Service a* | where {$_.</font> and notice how Intellisense kicks in, and displays all members of a service object.&#160; No more Get-Member before you run a where filter :-)</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6052.image_5F00_6F51CA33.png"><img title="image" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/3312.image_5F00_thumb_5F00_440D332C.png" width="314" height="133" /></a></p> <p>&#160;</p> <p>This is just the tip of the iceberg, so look out for an upcoming blog from Jason Shirk on more cool Intellisense features.</p> <p>&#160;</p> <p>&#160;</p> <p>ref@ </p> <p>Refaat Issa</p> <p>Program Manager, Windows Server Manageability</p> <p>Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10319137" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+ISE/">PowerShell ISE</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>Windows Management Framework 3.0 RC is Available for Download</title><link>http://blogs.msdn.com/b/powershell/archive/2012/06/02/windows-management-framework-3-0-rc-is-available-for-download.aspx</link><pubDate>Fri, 01 Jun 2012 23:12:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10313843</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10313843</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/06/02/windows-management-framework-3-0-rc-is-available-for-download.aspx#comments</comments><description><p>Yesterday we published an RC version of the Windows Management Framework 3.0.</p> <p><a href="http://go.microsoft.com/fwlink/?LinkId=251995">Windows Management Framework 3.0 RC</a> makes some updated management functionality available to earlier versions of Windows. Windows Management Framework 3.0 RC can be installed on the following Operating Systems:</p> <ul> <li>Windows 7 Service Pack 1 (32-bit &amp; 64-bit)</li> <li>Windows Server 2008 R2 Service Pack 1 (64-bit only) – Server Core now supported with the RC release.</li> <li>Windows Server 2008 Service Pack 2 (32-bit &amp; 64-bit) – </li> </ul> <p>&#160;</p> <p>Windows Management Framework 3.0 contains Windows PowerShell 3.0, WMI and WinRM. The package also includes a CIM provider that allows you to collect management data from servers with Windows Management Framework 3.0 installed with the new Server Manager in <a href="http://technet.microsoft.com/en-us/evalcenter/hh670538.aspx">Windows Server 2012 RC</a>.&#160; </p> <p>&#160;</p> <p><strong>Feedback &amp; Bugs</strong><strong> <br /></strong>We welcome any feedback or bug submissions to the Windows PowerShell Connect site: <a href="http://connect.microsoft.com/PowerShell">http://connect.microsoft.com/PowerShell</a>. The release notes for Windows Management Framework 3.0 RC include a list of user submitted Connect bugs that have been fixed since Windows Management Framework 3.0 Beta.</p> <p>&#160;</p> <p><strong>Additional Information: <br /></strong>Release notes are available on the download page. They contain important information about changes since Windows PowerShell 2.0 and a list of known issues.</p> <p>You must uninstall any other copies of Windows Management Framework 3.0 before installing Windows Management Framework 3.0 RC.</p> <p>This software is a pre-release version. Features and behavior are likely to change before the final release.</p> <p>Check out the two blog posts about PowerShell 3.0 written by Jeffrey Snover on the Windows Server blog this week: <a href="http://blogs.technet.com/b/windowsserver/archive/2012/05/29/windows-server-2012-powershell-3-0-and-devops-part-1.aspx">Part I</a> &amp; <a href="http://blogs.technet.com/b/windowsserver/archive/2012/05/30/windows-server-2012-powershell-3-0-and-devops-part-2.aspx">Part II</a>.</p> <p>&#160;</p> <p>Travis Jones [MSFT] <br />Program Manager – Windows PowerShell <br />Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10313843" width="1" height="1"></description></item><item><title>Going to TechEd? Join Us to Build a Solution on Windows PowerShell 3.0</title><link>http://blogs.msdn.com/b/powershell/archive/2012/05/09/going-to-teched-join-us-to-build-a-solution-on-windows-powershell-3-0.aspx</link><pubDate>Wed, 09 May 2012 16:39:42 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10303299</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10303299</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/05/09/going-to-teched-join-us-to-build-a-solution-on-windows-powershell-3-0.aspx#comments</comments><description><p>&#160;</p> <p>To cap off TechEd North America this year we are going to host a half day Windows PowerShell scenario walkthrough. </p> <p>The event will take place at the Rosen Center on Friday June 15 from 8am – noon. During this time we will collectively solve a problem from the ground up using many of the new features in Windows PowerShell 3.0 and Windows Server 2012. </p> <p>Starting from base Windows Server 2012 images, we will walk you through:</p> <ul> <li>Writing a PowerShell script workflow to perform Server deployments</li> <li>Creating a constrained endpoint that hosts only the deployment workflow</li> <li>Delegate a set of credentials for the workflow to use</li> <li>Exposing the workflow and it's results through a RESTful webservice</li> <li>Using Windows PowerShell Web Access to manage the workflow</li> </ul> <p>You will need to bring your own laptop to follow along.</p> <p>Our room has space to accommodate 40 people.&#160; If you are interested please send a note to us at <a href="mailto:powershellteam@hotmail.com">powershellteam@hotmail.com</a> </p> <p>&#160;</p> <p>Thanks</p> <p>Travis Jones [MSFT] <br />Program Manager – Windows PowerShell <br />Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10303299" width="1" height="1"></description></item><item><title>Running show-command for a cmdlet</title><link>http://blogs.msdn.com/b/powershell/archive/2012/04/13/running-show-command-for-a-cmdlet.aspx</link><pubDate>Fri, 13 Apr 2012 01:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10293413</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10293413</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/04/13/running-show-command-for-a-cmdlet.aspx#comments</comments><description><h3>&nbsp;</h3> <h4>Problem: Figuring out a cmdlet from its syntax can be overwhelming, especially for people new to PowerShell.</h4> <p>PS C:\&gt; get-command get-process -syntax</p> <p>Get-Process [[-Name] &lt;string[]&gt;] [-ComputerName &lt;string[]&gt;] [-Module] [-FileVersionInfo] [&lt;CommonParameters&gt;]</p> <p>Get-Process -Id &lt;int[]&gt; [-ComputerName &lt;string[]&gt;] [-Module] [-FileVersionInfo] [&lt;CommonParameters&gt;]</p> <p>Get-Process -InputObject &lt;Process[]&gt; [-ComputerName &lt;string[]&gt;] [-Module] [-FileVersionInfo] [&lt;CommonParameters&gt;]</p> <p>Get-command &ndash;syntax displays the syntax for the command. The top of get-help will also show this syntax information.</p> <h4>What are all those lines and braces?</h4> <p>If you know the answer, please skip this section.</p> <p>There is one line per parameter set. The square braces around a parameter indicate the parameter is optional. Square braces around a parameter name, indicate the name is optional (which means the parameter is positional). Angle brackets indicate the parameter type.</p> <p>A Parameter Set is a mutually exclusive set of parameters. Mutually exclusive means you can either get a process by name, or by id, but not by name and id at the same time. Each parameter set is a different way to interact with the cmdlet, almost like a different cmdlet with the same name.</p> <p>Some can ask if the parameter sets are a necessary complication. The only way to achieve the same 3 ways to get a process without something like parameter sets would be to have 3 cmdlets like Get-ProcessByName, Get-ProcessById and Get-ProcessByInputObject. If we extend this idea to all cmdlets, Nouns would be on average larger, there would be several names to remember for each cmdlet, separate documentations would be necessary and they would have repeated content referring to what is common between the cmdlets, etc. In summary, Parameter Sets are a great way to solve a somewhat complex problem of different ways to call a cmdlet.</p> <p>Despite all this greatness, all those braces and lines can be a bit overwhelming for people starting PowerShell and trying to understand a cmdlet (and even for some experts, at a first glance).</p> <h4>Solution: Show-Command is a new cmdlet in PowerShell V3 that displays a graphical user interface for a command with a simpler overview of a cmdlet.</h4> <p>PS C:\&gt; Show-Command Get-Process</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/5756.clip_5F00_image002_5F00_6064E5CD.jpg"><img width="287" height="338" title="clip_image002" style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" alt="clip_image002" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0042.clip_5F00_image002_5F00_thumb_5F00_7241799A.jpg" border="0" /></a></p> <p>Each tab is one Parameter Set for Get-Process. Cmdlets with parameter sets have a default parameter set. In case of get-process the default parameter set is Name, so this is the tab selected by default. Selecting the other tabs will display the following results:</p> <div align="center"> <table align="center" style="width: 569px;" border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td width="287" valign="top"> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4274.clip_5F00_image004_5F00_0013BF96.jpg"><img width="267" height="317" title="clip_image004" style="display: inline; background-image: none;" alt="clip_image004" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/4744.clip_5F00_image004_5F00_thumb_5F00_0DE60591.jpg" border="0" /></a></p> </td> <td width="280" valign="top"> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0363.clip_5F00_image006_5F00_3FDDA61B.jpg"><img width="268" height="318" title="clip_image006" style="display: inline; background-image: none;" alt="clip_image006" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1033.clip_5F00_image006_5F00_thumb_5F00_38BE69A3.jpg" border="0" /></a></p> </td> </tr> </tbody> </table> </div> <p>Notice that for Name, the Run button is enabled and for Id and InputObject, Run is disabled. This is because there is no mandatory parameter in the Name parameter set, so it is ready to run, even with no parameter values. The Id parameter in the Id parameter set is mandatory (needs a value). This is indicated by the * near the parameter name. The InputObject parameter in the InputObject parameter set is also mandatory.</p> <p>It is a very simple GUI, but it achieved some nice results so far regarding the problem it set out to solve:</p> <ol> <li>Initially, the parameters for only one parameter set are displayed (the default parameter set), reducing the information to be understood compared to the syntax.</li> <li>The braces indicating optional parameters are replaced by the friendlier GUI language of * and enabled/disabled buttons.</li> <li>The visual separation of the parameter set tabs is an excellent way to convey they are mutually exclusive.</li> </ol> <p>&nbsp;</p> <p>Additional details:</p> <ul> <li>In each parameter set tab, parameter names are displayed alphabetically, but mandatory parameters are listed first.</li> </ul> <ul> <li>The command run will be placed in history, so if you use &ldquo;Arrow Up&rdquo; after running show-command, you can see/modify what was run.</li> </ul> <ul> <li>The Common Parameters section displays Debug, ErrorAction and other parameters common to all cmdlets.</li> </ul> <ul> <li>The Copy button will copy the cmdlet to be run to the clipboard.</li> </ul> <ul> <li>Hovering over a parameter will display a tooltip with additional information about the parameter:</li> </ul> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1856.clip_5F00_image008_5F00_319F2D2B.jpg"><img width="278" height="330" title="clip_image008" style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" alt="clip_image008" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/0451.clip_5F00_image008_5F00_thumb_5F00_1184206E.jpg" border="0" /></a></p> <p>&nbsp;</p> <p>Lucio Silveira [MSFT]</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10293413" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+ISE/">PowerShell ISE</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Windows+Server+2012/">Windows Server 2012</category></item><item><title>Microsoft Script Explorer for Windows PowerShell Beta 1 Now Available</title><link>http://blogs.msdn.com/b/powershell/archive/2012/04/09/microsoft-script-explorer-for-windows-powershell-beta-1-now-available.aspx</link><pubDate>Mon, 09 Apr 2012 22:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10292046</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10292046</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/04/09/microsoft-script-explorer-for-windows-powershell-beta-1-now-available.aspx#comments</comments><description><p>We are very excited to announce the availability of Microsoft Script Explorer for Windows PowerShell (Script Explorer) Beta 1. Script Explorer is an extension of the Windows PowerShell content and guidance experience, combining the vast amount of knowledge held in the community with resources that are available from Microsoft.</p> <p>Script Explorer is integrated as an Add-On to Windows PowerShell Integrated Scripting Environment (ISE).&nbsp; With Script Explorer, you can:</p> <p>&middot; Discover information that is related to Windows PowerShell from across the community and Microsoft.</p> <p>&middot; Search seamlessly across repositories such as the Microsoft TechNet Script Center and PoshCode.org to locate samples that are relevant to you.</p> <p>&middot; Establish, grow, and search local file systems and corporate repositories.</p> <p><b>Search across multiple repositories</b></p> <p>Script Explorer enables a single search experience across multiple repositories, including local file system, network file share, PoshCode.org and the Microsoft Script Center, which allows you to locate script samples, snippets, and modules. You can filter search results, read reviews and comments, and seamlessly integrate script code into Windows PowerShell ISE or other script editors.</p> <p><b>Community and Microsoft guidance in one place</b></p> <p>Script Explorer combines the rich information from the community and the guidance that is available from Microsoft, which helps you realize more of the benefits of Windows PowerShell. Script Explorer brings together resources such as the Windows PowerShell Survival Guide and how-to guidance.</p> <p><b>Build a trusted library of scripts for your company</b></p> <p>Script Explorer makes it easy to build a library of scripts for personal use or to establish and grow a corporate library of trusted scripts, modules, and snippets.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2514.Script_2D00_Explorer_5F00_0C44959C.jpg"><img width="535" height="373" title="Script Explorer" style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" alt="Script Explorer" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/6708.Script_2D00_Explorer_5F00_thumb_5F00_371CF9AE.jpg" border="0" /></a></p> <p>As shown in the illustration, Script Explorer allows you to search for PowerShell scripts on your local computer, your local network and intranet, and online script repositories. You are shown available scripts organized by category, and you can search for scripts from local and trusted community repositories by applying filters based on focus areas.&nbsp; Script search results return information about script usage, code samples, and details about the scripts.</p> <p>When you find the scripts you that you need, you can store the scripts locally and use them at a later time or you can insert/copy in the editor.</p> <p>Script Explorer isn't just about scripts. It also allows you to find other Windows PowerShell information such as modules, script snippets and even allows you to view how-to guidance topics from Windows PowerShell cmdlets and community resources, such as TechNet Wiki pages, to help you get started using Windows PowerShell.</p> <p><b>Free download now!</b></p> <p>Get started today with this free download of <a href="http://go.microsoft.com/fwlink/?LinkId=246229">Microsoft Script Explorer for Windows PowerShell Beta 1</a>.</p> <p><b>Extensibility</b></p> <p>You can also extend Script Explorer to include your own repository by using the <a href="http://scriptexplorer.codeplex.com/">Script Explorer Repository SDK</a>.</p> <p><b>Support</b></p> <p>For support, visit <a href="http://social.technet.microsoft.com/Forums/en-US/scriptexplorer">Script Explorer for Windows PowerShell</a> at the Microsoft Script Center online forums.</p> <p>Also visit the forum for the latest status on Script Explorer services, to ask questions, and to provide feedback about Script Explorer. If you currently host a public repository, and you would like to make it available through Script Explorer, please contact <a href="mailto:secustsupp" target="_blank">Microsoft Script Explorer Customer Support</a>.</p> <p><b>Additional information</b></p> <ul> <li><a href="http://social.technet.microsoft.com/wiki/contents/articles/8051.deploying-microsoft-script-explorer-for-windows-powershell.aspx">Deploying Microsoft Script Explorer for Windows PowerShell </a></li> <li><a href="http://social.technet.microsoft.com/wiki/contents/articles/8052.configure-the-microsoft-script-explorer-for-windows-powershell-aggregation-service.aspx">Configuring Microsoft Script Explorer for Windows PowerShell</a></li> <li><a href="http://social.technet.microsoft.com/wiki/contents/articles/8053.uninstalling-the-microsoft-script-explorer-for-windows-powershell.aspx">Uninstalling Microsoft Script Explorer for Windows PowerShell</a></li> <li><a href="http://social.technet.microsoft.com/wiki/contents/articles/8054.troubleshooting-the-microsoft-script-explorer-for-windows-powershell.aspx">Troubleshooting Microsoft Script Explorer for Windows PowerShell</a></li> <li><a href="http://social.technet.microsoft.com/wiki/contents/articles/8056.microsoft-script-explorer-for-windows-powershell-user-guide.aspx">Using Microsoft Script Explorer for Windows PowerShell</a></li> </ul> <p>Joshy Joseph [MSFT]<br />Program Manager<br />Windows Server Information Experience</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10292046" width="1" height="1"></description></item><item><title>Improved WMI experience in PowerShell 3.0</title><link>http://blogs.msdn.com/b/powershell/archive/2012/04/04/improved-wmi-experience-in-powershell-3-0.aspx</link><pubDate>Wed, 04 Apr 2012 08:21:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10290660</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10290660</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/04/04/improved-wmi-experience-in-powershell-3-0.aspx#comments</comments><description><p>There is a famous quote often attributed to Jeffrey Snover, &ldquo;IT Pros love and hate WMI. They love it because there is so much great stuff there. They hate it because it is complex to use&rdquo;. Not to our surprise, most of the IT Pros and developers we talked to agree with this.</p> <p>This is going to change with Windows &ldquo;8&rdquo;. We listened to your feedback and have made heavy investment in this area. This blog post <a href="http://blogs.technet.com/b/windowsserver/archive/2012/03/30/standards-based-management-in-windows-server-8.aspx">standards based management in Windows Server 8</a> by Jeffrey Snover and Wojtek Kozaczynski provides an&nbsp;excellent overview. I would like to highlight two important aspect of improved PS+WMI integration that Wojtek talked about..</p> <p>-&nbsp;&nbsp;&nbsp;<strong>CIM Cmdlets:</strong> &nbsp;<b>PowerShell cmdlets to manage Standard Compliant CIM capable systems. </b>Now you can manage any CIM+WSMan compliant&nbsp;system using the same set of cmdlets shipping with PowerShell 3.0. Imagine managing a hardware device or a non-Windows server from PowerShell, just like you would manage Windows.</p> <p>-&nbsp;&nbsp;&nbsp;<strong>CIM-Based Cmdlets</strong><b>: PowerShell cmdlets written as a CIM Provider. </b>For many IT Pros, terms like CIM operations, namespace, associations seemed to be way too complex, and many of them get nightmare about not getting WQL right. We heard the shout loud and clear. We are giving WMI developer right infrastructure and API to write cmdlets in native code, complete with PS semantics like verbose, warning, whatif/confirm etc. Out of the box, Windows "8" ships with a large number of new cmdlets that have been implemented as a WMI provider.</p> <p>Our goal in&nbsp;PowerShell 3.0&nbsp;is to provide &nbsp;'first-class'&nbsp; experience for WMI. In the next few weeks, we will take you through a deep dive providing details of these&nbsp;investments . Stay tuned.</p> <p>- Osama Sajid</p> <p>Program Manager, WMI</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10290660" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/WMI/">WMI</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/WsMan/">WsMan</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/CIM/">CIM</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/WinRM/">WinRM</category><category domain="http://blogs.msdn.com/b/powershell/archive/tags/Powershell+3-0/">Powershell 3.0</category></item><item><title>Schedule for the upcoming PowerShell Deep Dive and a few videos from Frankfurt</title><link>http://blogs.msdn.com/b/powershell/archive/2012/03/26/schedule-for-the-upcoming-powershell-deep-dive-and-a-few-videos-from-frankfurt.aspx</link><pubDate>Sun, 25 Mar 2012 23:50:45 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10287383</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10287383</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/03/26/schedule-for-the-upcoming-powershell-deep-dive-and-a-few-videos-from-frankfurt.aspx#comments</comments><description><p>We&rsquo;ve got a great lineup of sessions and speakers scheduled for the upcoming PowerShell Deep Dive in San Diego, CA on April 30 &ndash; May 2! The <a href="http://www.theexpertsconference.com/us/2012/powershell-deep-dive/agenda/">schedule</a>&nbsp;was recently published on The Experts Conference site<a href="http://www.theexpertsconference.com/us/2012/">,</a> and is also listed below for convenience. Be sure to check out the TEC site for abstracts and speaker bios.</p> <p>If you&rsquo;re still thinking about registering, it is not too late. Just follow the instructions listed on <a href="http://blogs.msdn.com/b/powershell/archive/2012/01/27/it-s-time-for-another-powershell-deep-dive.aspx">this earlier blog post</a>.</p> <p>Here are a couple videos from last PowerShell Deep Dive in Frankfurt that Dmitry Sotnikov has recently posted on his blog:</p> <ul> <li><a href="http://dmitrysotnikov.wordpress.com/2012/03/22/video-james-oneill-and-his-powershell-profile/">James O&rsquo;Neill </a>and his PowerShell Profile (part of the Lightning round)</li> <li><a href="http://dmitrysotnikov.wordpress.com/2012/03/19/video-tobial-weltner-regular-expressions-in-5-minutes/">Tobias Weltner </a>on Regular Expressions in 5 minutes (also part of the Lightninground)</li> <li><a href="http://dmitrysotnikov.wordpress.com/2012/03/14/video-bruce-payette-powershell-workflows/">Bruce Payette</a> covers Windows PowerShell Workflows in PowerShell 3.0. CTP2</li> </ul> <p>And now for the schedule:</p> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td colspan="3"> <p>Monday</p> </td> </tr> <tr> <td> <p>Time</p> </td> <td> <p>Session</p> </td> <td> <p>Speaker</p> </td> </tr> <tr> <td> <p>9:00 - 10:00am</p> </td> <td> <p>PowerShell Deep Dive Keynote</p> </td> <td> <p>Jeffrey Snover</p> </td> </tr> <tr> <td> <p>10:00 - 10:30am</p> </td> <td> <p>Break</p> </td> <td></td> </tr> <tr> <td> <p>10:30&nbsp;- 11:05am</p> </td> <td> <p>When old APIs save the day (pinvoke and native windows dlls)</p> </td> <td> <p>Tome Tanasovski</p> </td> </tr> <tr> <td> <p>11:10 -&nbsp;11:45am</p> </td> <td> <p>Proxy functions</p> </td> <td> <p>Kirk Munro</p> </td> </tr> <tr> <td> <p>11:45 -&nbsp;1:00pm</p> </td> <td> <p>Lunch</p> </td> <td></td> </tr> <tr> <td rowspan="2"> <p>1:00 - 2:15pm</p> </td> <td nowrap="nowrap" rowspan="2"> <p>Using Splunk ResKit with PowerShell to revolutionize your script process</p> </td> <td nowrap="nowrap" rowspan="2"> <p>Brandon&nbsp;Shell</p> </td> </tr> <tr></tr> <tr> <td> <p>2:20&nbsp;- 2:55pm</p> </td> <td nowrap="nowrap"> <p>Lightning&nbsp;Round</p> </td> <td nowrap="nowrap"></td> </tr> <tr> <td> <p>3:00 - 3:45pm</p> </td> <td> <p>Remoting in V3</p> </td> <td nowrap="nowrap"> <p>Krishna Vutukuri</p> </td> </tr> <tr> <td> <p>3:45&nbsp;- 4:15pm</p> </td> <td> <p>Break</p> </td> <td></td> </tr> <tr> <td rowspan="2"> <p>4:15&nbsp;- 5:30pm</p> </td> <td rowspan="2"> <p>New&nbsp;Hyper-V PowerShell Module in Windows Server 8</p> </td> <td nowrap="nowrap" rowspan="2"> <p>Adam&nbsp;Driscoll</p> </td> </tr> <tr></tr> <tr> <td> <p>5:30&nbsp;- 6:30pm</p> </td> <td nowrap="nowrap"> <p>Meet the experts</p> </td> <td nowrap="nowrap"> <p>--</p> </td> </tr> <tr> <td> <p>6:00 - 8:00pm</p> </td> <td nowrap="nowrap"> <p>TEC Party</p> </td> <td nowrap="nowrap"> <p>--</p> </td> </tr> </tbody> </table> <p>&nbsp;</p> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td> <p>Tuesday</p> </td> <td> <p>&nbsp;</p> </td> <td> <p>&nbsp;</p> </td> </tr> <tr> <td> <p>8:00&nbsp;- 8:35am</p> </td> <td nowrap="nowrap"> <p>Formatting in Windows PowerShell</p> </td> <td nowrap="nowrap"> <p>Jim Truher</p> </td> </tr> <tr> <td> <p>8:40&nbsp;- 9:15am</p> </td> <td nowrap="nowrap"> <p>PowerShell&nbsp;and WMI: a love story</p> </td> <td nowrap="nowrap"> <p>Kirk&nbsp;Munro</p> </td> </tr> <tr> <td> <p>9:15&nbsp;- 9:45am</p> </td> <td> <p>Break&nbsp;</p> </td> <td> <p>&nbsp;</p> </td> </tr> <tr> <td rowspan="2"> <p>9:45&nbsp;- 11:00am</p> </td> <td rowspan="2"> <p>PowerShell as a Web Language</p> </td> <td rowspan="2"> <p>James Brundage</p> </td> </tr> <tr></tr> <tr> <td> <p>11:15&nbsp;- 11:50am</p> </td> <td> <p>PowerShell V3 in Production</p> </td> <td> <p>Steven Murawski</p> </td> </tr> <tr> <td> <p>11:55&nbsp;- 12:30pm&nbsp;</p> </td> <td nowrap="nowrap"> <p>Lightning&nbsp;Round</p> </td> <td nowrap="nowrap"> <p>&nbsp;</p> </td> </tr> <tr> <td> <p>12:30&nbsp;- 1:45pm</p> </td> <td> <p>Lunch&nbsp;</p> </td> <td> <p>&nbsp;</p> </td> </tr> <tr> <td rowspan="2"> <p>1:45&nbsp;- 3:00pm</p> </td> <td rowspan="2"> <p>How Microsoft IT Uses PowerShell for Testing Automation and Deployment of FIM</p> </td> <td rowspan="2"> <p>Kinnon McDonell</p> </td> </tr> <tr></tr> <tr> <td> <p>3:15&nbsp;- 3:50pm</p> </td> <td nowrap="nowrap"> <p>Job&nbsp;Types in Windows PowerShell 3.0</p> </td> <td nowrap="nowrap"> <p>Travis&nbsp;Jones</p> </td> </tr> <tr> <td> <p>3:55 - 4:30pm</p> </td> <td nowrap="nowrap"> <p>Creating&nbsp;a corporate PowerShell Module Repository</p> </td> <td nowrap="nowrap"> <p>Tome&nbsp;Tanasovski</p> </td> </tr> <tr> <td> <p>4:30&nbsp;- 5:00pm</p> </td> <td> <p>Break</p> </td> <td> <p>&nbsp;</p> </td> </tr> <tr> <td> <p>5:00&nbsp;- 6:00pm</p> </td> <td nowrap="nowrap"> <p>BOF&nbsp;/ Roundtable</p> </td> <td nowrap="nowrap"> <p>&nbsp;</p> </td> </tr> </tbody> </table> <p>&nbsp;</p> <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td> <p>Wednesday</p> </td> <td> <p>&nbsp;</p> </td> <td> <p>&nbsp;</p> </td> </tr> <tr> <td> <p>8:00&nbsp;- 8:35am</p> </td> <td> <p>Cmdlets over Objects (CDXML)</p> </td> <td> <p>Richard Siddaway&nbsp;</p> </td> </tr> <tr> <td> <p>8:40&nbsp;- 9:15am</p> </td> <td> <p>Build your own remoting endpoint with PowerShell v3</p> </td> <td> <p>Aleksandar Nikolic</p> </td> </tr> <tr> <td> <p>9:15&nbsp;- 9:45am</p> </td> <td> <p>Break&nbsp;</p> </td> <td> <p>&nbsp;</p> </td> </tr> <tr> <td rowspan="2"> <p>9:45&nbsp;- 11:00am</p> </td> <td rowspan="2"> <p>PowerShell Workflows and the Windows Workflow Foundation for the IT Pro</p> </td> <td rowspan="2"> <p>Steven Murawski</p> </td> </tr> <tr></tr> <tr> <td> <p>11:15&nbsp;- 12:50pm</p> </td> <td> <p>Incorporating Microsoft Office into Windows PowerShell</p> </td> <td> <p>Jeffrey Hicks&nbsp;</p> </td> </tr> <tr> <td> <p>11:55&nbsp;- 12:30pm&nbsp;</p> </td> <td> <p>TBD</p> </td> <td> <p>Bruce Payette</p> </td> </tr> <tr> <td> <p>12:30&nbsp;- 1:45pm</p> </td> <td> <p>Lunch&nbsp;</p> </td> <td> <p>&nbsp;</p> </td> </tr> </tbody> </table> <p>&nbsp;</p> <p>See you there!</p> <p>Travis Jones [MSFT]<br />Program Manager - Windows PowerShell<br />Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10287383" width="1" height="1"></description><category domain="http://blogs.msdn.com/b/powershell/archive/tags/PowerShell+Deep+Dive/">PowerShell Deep Dive</category></item><item><title>Troubleshooting Windows Management Framework 3.0 Beta Installation</title><link>http://blogs.msdn.com/b/powershell/archive/2012/03/23/troubleshooting-windows-management-framework-3-0-beta-installation.aspx</link><pubDate>Fri, 23 Mar 2012 00:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10286675</guid><dc:creator>PowerShell Team</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/powershell/rsscomments.aspx?WeblogPostID=10286675</wfw:commentRss><comments>http://blogs.msdn.com/b/powershell/archive/2012/03/23/troubleshooting-windows-management-framework-3-0-beta-installation.aspx#comments</comments><description><p>This blog post explains how to resolve problems that may occur when you install Windows Management Framework (WMF) 3.0 Beta. WMF 3.0 Beta includes Windows PowerShell 3.0 Beta. You can find the WMF 3.0 Beta installation package on the Microsoft Download Center at http://go.microsoft.com/fwlink/?LinkID=240290.</p> <p>The WMF 3.0 package installation is blocked when one or more of the following prerequisites are not met:</p> <ul> <li>The package must support the platform and operating system.</li> <li>Prerequisites must be met.</li> <li>The package must not be a duplicate.</li> </ul> <p>When one or more of the conditions is not met, an error message, such as the following one, explains that the update does not apply to the system.</p> <p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/1351.clip_5F00_image001_5F00_2084D1A6.png"><img style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="clip_image001" border="0" alt="clip_image001" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-63-74-metablogapi/2821.clip_5F00_image001_5F00_thumb_5F00_527C7230.png" width="207" height="102" /></a></p> <p>WMF 3.0 Beta is shipped in four different packages. Each package is designed for a different operating system and service pack and a specific architecture. The following table lists the WMF 3.0 Beta packages:</p> <p>&nbsp;</p> <p></p> <div align="center"> <table style="width: 468px;" border="1" cellspacing="0" cellpadding="2" align="center"> <tbody> <tr> <td valign="top" width="200">WMF 3.0 Package</td> <td valign="top" width="266">Target OS</td> </tr> <tr> <td valign="top" width="200"> <p>Windows6.1-KB2506143-x86.msu</p> </td> <td valign="top" width="266"> <p>Windows 7 SP1 Client (x86)</p> </td> </tr> <tr> <td valign="top" width="200"> <p>Windows6.1-KB2506143-x64.msu</p> </td> <td valign="top" width="266"> <p>Windows 7 SP1 Client (amd64), Windows 2008 R2 SP1</p> </td> </tr> <tr> <td valign="top" width="200"> <p>Windows6.0-KB2506146-x86.msu</p> </td> <td valign="top" width="266"> <p>Windows 2008 SP2 (x86)</p> </td> </tr> <tr> <td valign="top" width="200"> <p>Windows6.0-KB2506146-x64.msu</p> </td> <td valign="top" width="266"> <p>Windows 2008 SP2 (amd64)</p> </td> </tr> </tbody> </table> </div> <p><b>WMF 3.0 Beta Validation:</b></p> <p></p> <p>If Windows PowerShell is installed on the computer, you can use the <b>WMF3BetaPrerequisiteCheck.ps1</b>script that is attached to this blog post to verify that WMF 3.0 Beta is installed.</p> <p></p> <p><b>Package applicability:</b></p> <p>The installation of the package might fail for one of the following reasons:</p> <ul> <li>Architecture:</li> <ul> <li>WMF 3.0 Beta packages are applicable only to computers with x86 and x64 architectures. WMF 3.0 Beta package installation fails if you try to install an x86 version of the package on an x64 computer, or an x64 version on an x86 computer.</li> </ul> <li>Operating system:</li> <ul> <li>WMF 3.0 Beta package is applicable only to Windows 7 with Service Pack 1, Windows Server 2008 R2 with Service Pack 1, and Windows Server 2008 with Service Pack 2.The WMF 3.0 Beta package installation fails on all other operating systems.</li> </ul> <li>Service pack:</li> <ul> <li>WMF 3.0 Beta package installation fails when the target computer does not have the minimum required service packs installed. The minimum service pack requirements are as follows:</li> </ul> <li>Windows 7, Windows Server 2008 R2: Service Pack 1</li> <li>Windows Server 2008 : Service Pack 2</li> </ul> <p>The following table summarizes the WMF 3.0 Beta package applicability</p> <div align="center"> <table style="width: 500px;" border="1" cellspacing="0" cellpadding="0" align="center"> <tbody> <tr> <td valign="top" width="20%"> <p>Windows</p> </td> <td valign="top" width="20%"> <p>Windows6.1-KB2506143-x86.msu</p> </td> <td valign="top" width="20%"> <p>Windows6.1-KB2506143-x64.msu</p> </td> <td valign="top" width="20%"> <p>Windows6.0-KB2506146-x86.msu</p> </td> <td valign="top" width="20%"> <p>Windows6.0-KB2506146-x64.msu</p> </td> </tr> <tr> <td valign="top" width="20%"> <p>Windows 7 SP1 (x86)</p> </td> <td valign="top" width="20%"> <p align="center">Yes</p> </td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%">&nbsp;</td> </tr> <tr> <td valign="top" width="20%"> <p>Windows 7 SP1 (x64)</p> </td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%"> <p>Yes</p> </td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%">&nbsp;</td> </tr> <tr> <td valign="top" width="20%"> <p>Windows Server 2008 R2 SP1 (x64)</p> </td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%"> <p>Yes</p> </td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%">&nbsp;</td> </tr> <tr> <td valign="top" width="20%"> <p>Windows Server 2008 SP2 (x86)</p> </td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%"> <p>Yes</p> </td> <td valign="top" width="20%">&nbsp;</td> </tr> <tr> <td valign="top" width="20%"> <p>Windows Server 2008 SP2 (x64)</p> </td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%">&nbsp;</td> <td valign="top" width="20%"> <p>Yes</p> </td> </tr> </tbody> </table> </div> <p><b>Prerequisites:</b></p> <p>The following items are required for WMF 3.0 Beta package installation:</p> <ul> <li>Microsoft .NET Framework 4: Full Installation:</li> <ul> <li>The Microsoft .NET Framework 4 full installation must be installed on the computer before installing WMF 3.0 Beta.</li> <li>To verify that .NET 4 full installation is installed on the computer, use one of the following methods:</li> <ul> <li>Check for the presence of the registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full. The key should contain the <b>Install</b> registry entry with a value of 1.</li> <li>In Programs and Features in Control Panel, check for the presence of the &ldquo;Microsoft .NET Framework 4 Extended&rdquo; update.</li> <li>To install Microsoft.NET Framework 4 Full installation, go to <a href="http://www.microsoft.com/download/en/details.aspx?id=17718">http://www.microsoft.com/download/en/details.aspx?id=17718</a>.</li> </ul> </ul> <li>Windows Management Framework 2.0 [WMF 2.0]:</li> <ul> <li>If the computer is running Windows Server 2008 SP2, you need to install WMF 2.0 before installing WMF 3.0 Beta. WMF 2.0 is not required for any other operating systems. You can download WMF 2.0 from <a href="http://support.microsoft.com/kb/968930">http://support.microsoft.com/kb/968930</a>.</li> <li>To verify that WMF 2.0 is installed on the computer, in Programs and Features in Control Panel, in Installed Updates, search for the <b>Windows Management Framework Core (KB 968930)</b> update.</li> </ul> </ul> <p><b>Duplicate package installation:</b></p> <p>If either the current version, on an earlier version of the WMF 3.0 Beta package is already installed on the computer, the WMF 3.0 Beta installation fails with the following error message: "Update for Windows (KB250614X) is already installed on this computer."</p> <p>To fix this problem, use the following procedure:</p> <ul> <li>On Windows 7 SP1 and Windows Server 2008 R2 SP1, use Programs and Features in Control Panel to uninstall update KB2506143. To find it, click <b>View installed updates</b> and then search for KB2506143.</li> <li>On Windows Server 2008 SP2, use Programs and Features in Control Panel to uninstall update KB2506146. To find it, click <b>View installed updates</b> and then search for KB2506146.</li> </ul> <p>To complete the installation, restart the computer.</p> <p>&nbsp;</p> <p>Sharath Gopalappa [MSFT]<br />Software Design Engineer - Windows PowerShell<br />Microsoft Corporation</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10286675" width="1" height="1"></description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-28-66-75/WMF3BetaPrerequisiteCheck.ps1" length="11805" type="application/octet-stream" /></item></channel></rss> |