{"id":892,"date":"2014-08-01T00:01:00","date_gmt":"2014-08-01T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/08\/01\/ive-got-a-powershell-secret-adding-a-gui-to-scripts\/"},"modified":"2014-08-01T00:01:00","modified_gmt":"2014-08-01T00:01:00","slug":"ive-got-a-powershell-secret-adding-a-gui-to-scripts","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/ive-got-a-powershell-secret-adding-a-gui-to-scripts\/","title":{"rendered":"I&#039;ve Got a PowerShell Secret: Adding a GUI to Scripts"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Microsoft PFE, Chris Conte, talks about adding a GUI for Windows PowerShell scripts.<\/span><\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Today Chris Conte is our guest blogger.<\/p>\n<p>Chris Conte is a premier field engineer at Microsoft who grew up with a passion for computers and the creative arts. At age 12, he started programming by copying assembly game code on his dad&#039;s Commodore 64. Eventually, he parlayed that experience into learning about Visual Basic for Applications (VBA), ASP.NET, C#, and a variety of client scripting languages and frameworks. You can learn more about Chris via <a href=\"http:\/\/www.linkedin.com\/pub\/chris-conte\/12\/720\/82a\" target=\"_blank\">LinkedIn<\/a> or Twitter <a href=\"https:\/\/twitter.com\/CrashConte\" target=\"_blank\">@CrashConte<\/a>.<\/p>\n<p>Now, Chris&#8230;<\/p>\n<p>This is not my original idea, but I&rsquo;ve been able to document the methodology presented in this post. Before we start, I&rsquo;d like the opportunity to thank my mentor, Donald Scott, and my colleague Michael Melone. Mike is the guru who figured this out, and Don and I created the helper cmdlet.<\/p>\n<p>Windows Server admins have a lot of choices for automating routine tasks, but for those looking to stay up-to-date, the lingua franca is certainly Windows PowerShell. Windows PowerShell allows you to deal with objects instead of only strings and it has a syntax that C# and JavaScript programmers can easily relate to. In addition, with Microsoft heavily investing to propagate this awesome language throughout the ecosystem, you can be sure it&#039;s not going away soon.<\/p>\n<p>So it&rsquo;s settled, right? Learn Windows PowerShell and thrive. But honestly, I didn&#039;t get into Windows to work from the command line. I&#039;m what you call a &quot;GUI Guy.&quot; I love Windows, and as a developer, I have spent more than my share of time designing beautiful interfaces for the web. I believe that good design can have a huge influence on the success or failure of the underlying code. Don&#039;t get me wrong, I love the power and speed of scripted tasks. But that&#039;s why this &quot;secret&quot; is so special. You don&#039;t lose anything that Windows PowerShell has to offer.<\/p>\n<p>What do you get when you mix XML, XPath, XAML, WPF, Windows PowerShell and a little creativity? Well, I say it&#039;s nothing short of magic. Even after you understand how it works, I hope you still get that little twinkle in your eyes that keeps the inner geek excited.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-1.png\" alt=\"Image of chart\" title=\"Image of chart\" \/><\/a><\/p>\n<h2>Tooling up<\/h2>\n<p>To follow along, you&#039;ll need to get a few tools. You&#039;ve probably got these lying around. Here&#039;s what you&#039;ll need:<\/p>\n<ul>\n<li><a href=\"http:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=17851\" target=\"_blank\">Microsoft .NET Framework 4 (Web Installer)<\/a><\/li>\n<li>Windows PowerShell and the Windows PowerShell ISE<\/li>\n<\/ul>\n<p>The Windows PowerShell ISE is an optional feature, and it requires .NET Framework 3.51 to be installed. To install the Windows PowerShell ISE on Windows Server&nbsp;2008&nbsp;R2, use the Add Features Wizard or run the following Windows PowerShell command:<\/p>\n<p style=\"margin-left:30px\">Import-Module ServerManager; Add-WindowsFeature PowerShell-ISE<\/p>\n<ul>\n<li>Visual Studio 2013 or <a href=\"http:\/\/www.visualstudio.com\/en-us\/products\/visual-studio-express-vs.aspx\" target=\"_blank\">Visual Studio Express 2013 for Windows Desktop<\/a><\/li>\n<\/ul>\n<p>Visual Studio Express for Windows Desktop lets you take full advantage of Windows with XAML designers, a productive IDE, and a variety of programming languages.<\/p>\n<h2>Getting started<\/h2>\n<p>I&#039;m going to presume a lot here. I&#039;m going to assume you&#039;ve got modern Windows Server admin skills and are a proficient Windows PowerShell scripter. I&#039;m also going to assume you&#039;ve heard of XML and XPath, event-driven programming, and some basics about object-oriented programming. If not, please get started with the following resources.<\/p>\n<p><b>&nbsp; &nbsp; &nbsp;Note<\/b>&nbsp; The mention of these resources is not an endorsement. &nbsp;<\/p>\n<ul>\n<li><a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/bb978526.aspx\" target=\"_blank\">Scripting with Windows PowerShell<\/a><\/li>\n<li><a href=\"https:\/\/channel9.msdn.com\/Series\/C-Sharp-Fundamentals-Development-for-Absolute-Beginners\/Understanding-Event-Driven-Programming-23\" target=\"_blank\">Understanding Event Driven Programming &#8211;&nbsp;23<\/a><\/li>\n<li><a href=\"http:\/\/www.w3schools.com\/xpath\/default.asp\" target=\"_blank\">XPath Tutorial<\/a>&nbsp;<\/li>\n<li>Windows Presentation Foundation (WPF) interface fundamentals<\/li>\n<\/ul>\n<p>WPF and XAML are important concepts to grasp for this methodology. To begin, let&#039;s review a bit about WPF and XAML (from the documentation). Here are some significant pieces of the documentation that should help you understand a bit more about why we are using them.<\/p>\n<ul>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa970268(v=vs.110).aspx\" target=\"_blank\">Introduction to WPF<\/a><\/li>\n<\/ul>\n<p>WPF is a next-generation presentation system for building Windows client applications. It is a resolution-independent and vector-based rendering engine. WPF extends the core with a comprehensive set of application development features that include Extensible Application Markup Language (XAML). WPF is included in the Microsoft .NET Framework, so you can build applications that incorporate other elements of the .NET Framework class library.<\/p>\n<p>WPF&nbsp;exists as a subset of .NET Framework&nbsp;types that are for the most part located in the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows(v=vs.110).aspx\" target=\"_blank\">System.Windows<\/a> namespace. You instantiate classes, set properties, call methods, and handle events by using your favorite .NET Framework programming language.<\/p>\n<p>WPF offers the ability to develop an application by using markup and code-behind, which is an experience that ASP.NET developers should be familiar with. You generally use XAML&nbsp;markup to implement the appearance of an application while using managed programming languages (code-behind) to implement its behavior.<\/p>\n<ul>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms752059(v=vs.110).aspx\" target=\"_blank\">XAML Overview (WPF)<\/a><\/li>\n<\/ul>\n<p>XAML is an XML-based markup language that is used to implement an application&#039;s appearance declaratively.&nbsp;It is typically used&nbsp;to create windows, dialog boxes, pages, and user controls, and to fill them with controls, shapes, and graphics. Because XAML&nbsp;is XML-based, the UI&nbsp;that you compose with it is assembled in a hierarchy of nested elements known as an element tree.<\/p>\n<h2>Building the interface<\/h2>\n<p>To create the interface, fire up Visual Studio and create a new WPF project. The path is: File &gt; New &gt; Project.<\/p>\n<p>&nbsp;<a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-2.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>When the project loads, you will see a prebuilt Window. Simply drag-and-drop controls onto the canvas from common WPF controls. In the following screenshot, I&#039;ve added a text box and a button. Notice the handles that surround the control. You are welcome to use these handles to resize the control.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-3.png\" alt=\"Image of controls\" title=\"Image of controls\" \/><\/a><\/p>\n<p>Notice the XAML in the window under the design canvas. You can see a Label and Button control added to the Grid element. Use the XAML resource documentation if you want to get fancy, but you now have all the XAML you need to continue. Simply copy and XAML and paste it into a Notepad window. Remove the <b>x:Class<\/b> attribute from the Window element. Leave the XML namespace elements (<b>xmlns<\/b> and <b>xmlns:x<\/b>), Title, Height, and Width. Save the file with the .xaml extension (for example, MyForm.xaml). Here is the code:<\/p>\n<p style=\"margin-left:30px\">&lt;Window<\/p>\n<p style=\"margin-left:30px\">&nbsp; xmlns=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&quot;<\/p>\n<p style=\"margin-left:30px\">&nbsp; xmlns:x=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&quot;<\/p>\n<p style=\"margin-left:30px\">&nbsp; Title=&quot;MainWindow&quot; Height=&quot;350&quot; Width=&quot;525&quot;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&lt;Grid&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;Label Content=&quot;Label&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;68,38,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;197&quot;\/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;Button Content=&quot;Button&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;307,41,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;75&quot;\/&gt;<\/p>\n<p style=\"margin-left:30px\">&lt;\/Grid&gt;<\/p>\n<p style=\"margin-left:30px\">&lt;\/Window&gt;<\/p>\n<h2>Loading the dialog box<\/h2>\n<p>To make this easier (but admittedly more complex to understand), you&#039;ll need the following helper cmdlet to load and interpret the XAML. Simply save the following text as loadDialog.ps1:<\/p>\n<p style=\"margin-left:30px\">[CmdletBinding()]<\/p>\n<p style=\"margin-left:30px\">Param(<\/p>\n<p style=\"margin-left:30px\">&nbsp;[Parameter(Mandatory=$True,Position=1)]<\/p>\n<p style=\"margin-left:30px\">&nbsp;[string]$XamlPath<\/p>\n<p style=\"margin-left:30px\">)<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">[xml]$Global:xmlWPF = Get-Content -Path $XamlPath<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">#Add WPF and Windows Forms assemblies<\/p>\n<p style=\"margin-left:30px\">try{<\/p>\n<p style=\"margin-left:30px\">&nbsp;Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms<\/p>\n<p style=\"margin-left:30px\">} catch {<\/p>\n<p style=\"margin-left:30px\">&nbsp;Throw &quot;Failed to load Windows Presentation Framework assemblies.&quot;<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">#Create the XAML reader using a new XML node reader<\/p>\n<p style=\"margin-left:30px\">$Global:xamGUI = [Windows.Markup.XamlReader]::Load((new-object System.Xml.XmlNodeReader $xmlWPF))<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">#Create hooks to each named object in the XAML<\/p>\n<p style=\"margin-left:30px\">$xmlWPF.SelectNodes(&quot;\/\/*[@Name]&quot;) | %{<\/p>\n<p style=\"margin-left:30px\">&nbsp;Set-Variable -Name ($_.Name) -Value $xamGUI.FindName($_.Name) -Scope Global<\/p>\n<p style=\"margin-left:30px\">&nbsp;}<\/p>\n<h2>LoadDialog walkthrough<\/h2>\n<p>This loadDialog helper cmdlet is extremely important, so let&#039;s break it down. This cmdlet accepts one parameter: the <b>FileName<\/b> and <b>Path<\/b> of the XAML file. The contents are loaded into a global variable (typed as XML) by using the following line:<\/p>\n<p style=\"margin-left:30px\">[xml]$Global:xmlWPF = Get-Content -Path $XamlPath<\/p>\n<p>Next, WPF and Windows Forms assemblies are loaded from the .NET Framework. These allow us to make sense of the XAML to display the dialog.<\/p>\n<p style=\"margin-left:30px\">Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms<\/p>\n<p>With the power of our loaded assemblies, we load the XML variable, <b>xmlWPF<\/b>, as a parameter into a <b>XmlNodeReader<\/b> method, and subsequently, <b>XamlReader<\/b>. The result is loaded into a global XAML-typed variable. Thanks to our loaded assemblies, our code now &quot;understands&quot; how to interpret this XAML (more about this later).<\/p>\n<p>Last, we wire the XAML notes in the tree to Windows PowerShell variables. By using the power of XPath, we scan through all the XAML tree nodes to extract the <b>Name<\/b> attribute. This name is passed down the pipe and turned into a global variable.<\/p>\n<p style=\"margin-left:30px\">$xmlWPF.SelectNodes(&quot;\/\/*[@Name]&quot;) | %{<\/p>\n<p style=\"margin-left:30px\">&nbsp;Set-Variable -Name ($_.Name) -Value $xamGUI.FindName($_.Name) -Scope Global<\/p>\n<p style=\"margin-left:30px\">&nbsp;}<\/p>\n<p>Those of you who are following intently have noticed that there isn&#039;t a <b>Name<\/b> attribute by default using Visual Studio. You&#039;ll need to add this manually. Simple enough. Simply edit the XAML file and add a <b>Name<\/b> attribute in the elements that you want to control via Windows PowerShell. Continuing with our example, I have added name &quot;Label1&quot; to our <b>Label<\/b> element and &quot;Button1&quot; to the <b>Button<\/b> element in the XAML.<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;Label Name=&quot;Label1&quot; Content=&quot;Label&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;68,38,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;197&quot;\/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&lt;Button Name=&quot;Button1&quot; Content=&quot;Button&quot; HorizontalAlignment=&quot;Left&quot; Margin=&quot;307,41,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;75&quot;\/&gt;<\/p>\n<p>Finally, notice that nothing is actually displaying our dialog box&#8230;yet! We&#039;re getting there.<\/p>\n<h2>Putting it all together<\/h2>\n<p>So, we&#039;ve finally arrived. You&#039;re ready to build your HelloWorld.ps1. Of course, by now you&#039;ve realized that to make this work, there are actually three files involved. This may seem like a lot, but as you build multiple scripts, this will make sense. You have your primary script named &quot;HelloWorld.ps1&quot;, the loadDialog.ps1 helper cmdlet, and your XAML form (MyForm.xaml).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-4.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-4.png\" alt=\"Image of flow chart\" title=\"Image of flow chart\" \/><\/a><\/p>\n<p>For clean separation, I recommend that you store your .ps1 files in a Scripts folder and the XAML forms in a Forms folder.<\/p>\n<p>To review what&#039;s going on, your original Windows PowerShell script calls the loadDialog.ps1 helper cmdlet, which in turn, loads the XAML form into a variable and creates matching Windows PowerShell variables for all the elements in the tree, based on the <b>Name<\/b> attribute. Near the top of your HelloWorld.ps1 script, you should see a line like this:<\/p>\n<p style=\"margin-left:30px\">#Required to load the XAML form and create the PowerShell Variables<\/p>\n<p style=\"margin-left:30px\">.\\loadDialog.ps1 -XamlPath &#039;..\\Forms\\MyForm.xaml&#039;<\/p>\n<p>After this line successfully executes, we have access to the form via Windows PowerShell variables.<\/p>\n<p style=\"margin-left:30px\">$Label1<\/p>\n<p style=\"margin-left:30px\">$Button1<\/p>\n<p>The properties to set and get are a matter of research on websites like MSDN or exploring the properties window inside of Visual Studio. For example, here is an example of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/apps\/windows.ui.xaml.controls.button.aspx\" target=\"_blank\">Button class<\/a>.<\/p>\n<h2>Adding events<\/h2>\n<p>Remember when I mentioned event-driven programming? At this point, you&#039;ll want to wire-up an event to the button. Here&#039;s how:<\/p>\n<p style=\"margin-left:30px\">#EVENT Handler<\/p>\n<p style=\"margin-left:30px\">$button1.add_Click({<\/p>\n<p style=\"margin-left:30px\">&nbsp;$Label1.Content = &quot;Hello World&quot;<\/p>\n<p style=\"margin-left:30px\">})<\/p>\n<p>When the button is clicked, the code is setting the <b>Content<\/b> property of our <b>Label1<\/b> Windows PowerShell variable with &quot;Hello World.&quot; Because this is wired directly to the WPF form, we actually get to see the results on our screen.<\/p>\n<h2>Launching the window<\/h2>\n<p>With everything set, we are finally able to load the window by using the <b>ShowDialog()<\/b> method of our XAML object:<\/p>\n<p style=\"margin-left:30px\">#Launch the window<\/p>\n<p style=\"margin-left:30px\">$xamGUI.ShowDialog() | out-null<\/p>\n<p>This must be the last statement in your script. From that point forward, everything is controlled via the events you have configured.<\/p>\n<h2>Execution policy<\/h2>\n<p>We have it all put together and we&#039;re ready to launch. If you haven&#039;t already, remember to set the execution policy so that you can run the script:<\/p>\n<p style=\"margin-left:30px\">Set-ExecutionPolicy -ExecutionPolicy Unrestricted<\/p>\n<p>Also, remember to run Windows PowerShell as an administrator. Otherwise you&#039;ll hit this error message:<\/p>\n<p style=\"margin-left:30px\">Set-ExecutionPolicy : Access to the registry key<\/p>\n<p style=\"margin-left:30px\">&#039;HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\PowerShell\\1\\ShellIds\\Microsoft.PowerShell&#039; is denied. To change the execution policy for the default (LocalMachine) scope, start Windows PowerShell with the &quot;Run as administrator&quot; option. To change the execution policy for the current user, run &quot;Set-ExecutionPolicy -Scope CurrentUser&quot;.<\/p>\n<h2>Kick off your HelloWorld script: .\\HelloWorld.ps1<\/h2>\n<p>When the window loads, simply click the button to see the results. They should look like this:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-5.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-1-14-5.png\" alt=\"Image of window\" title=\"Image of window\" \/><\/a><\/p>\n<p>Methods like this don&rsquo;t come along by chance. This mountain top of Windows PowerShell GUI is viewed on the shoulders of giant minds. My heartfelt thanks go to the engineering rock stars who made this possible: Microsoft senior premier field engineers, <a href=\"http:\/\/www.linkedin.com\/in\/mjmelone\" target=\"_blank\">Mike Melone<\/a> and <a href=\"mailto:donscott@microsoft.com?subject=PowerShell%20GUI\" target=\"_blank\">Don Scott<\/a>.<\/p>\n<p>The methodology to create a Windows PowerShell GUI is somewhat advanced, but not beyond the reach of those who spend a great deal of time scripting Windows PowerShell solutions for others to use. I have personally used this method to create input validation and to control the choices of input from my users.<\/p>\n<p>This is a very basic example, but WPF forms can be very sophisticated. The fun part is the creativity you bring that will help empower and guide others to be successful without getting stuck at the command line.<\/p>\n<p>The files demonstrated in this blog post are available for download from the Scripting Guys Script Repository: <a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/PowerShell-GUI-dc224be6\" target=\"_blank\">PowerShell GUI<\/a>.<\/p>\n<p>~Chris<\/p>\n<p>Thanks for this innovative post, Chris.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft PFE, Chris Conte, talks about adding a GUI for Windows PowerShell scripts. Microsoft Scripting Guy, Ed Wilson, is here. Today Chris Conte is our guest blogger. Chris Conte is a premier field engineer at Microsoft who grew up with a passion for computers and the creative arts. At age 12, he started programming [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[519,71,56,520,3,4,45],"class_list":["post-892","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-chris-conte","tag-graphical","tag-guest-blogger","tag-gui","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft PFE, Chris Conte, talks about adding a GUI for Windows PowerShell scripts. Microsoft Scripting Guy, Ed Wilson, is here. Today Chris Conte is our guest blogger. Chris Conte is a premier field engineer at Microsoft who grew up with a passion for computers and the creative arts. At age 12, he started programming [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/892","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=892"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/892\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=892"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=892"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=892"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}