{"id":884,"date":"2014-08-02T00:01:00","date_gmt":"2014-08-02T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/08\/02\/weekend-scripter-fixing-powershell-gui-examples\/"},"modified":"2014-08-02T00:01:00","modified_gmt":"2014-08-02T00:01:00","slug":"weekend-scripter-fixing-powershell-gui-examples","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-fixing-powershell-gui-examples\/","title":{"rendered":"Weekend Scripter: Fixing PowerShell GUI Examples"},"content":{"rendered":"<p align=\"left\"><b>Summary<\/b>: Microsoft PowerShell MVP, Dave Wyatt, talks about using Windows PowerShell GUI example code.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Welcome back guest blogger, Dave Wyatt. To read more of Dave&rsquo;s previous guest posts, see these <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/tag\/dave-wyatt\/\" target=\"_blank\">Hey, Scripting Guy! Blog posts<\/a>.<\/p>\n<p style=\"margin-left:30px\">Dave is a Windows PowerShell MVP and a member of the board of directors at PowerShell.org. He works in IT, and he mainly focuses on automation, configuration management, and production support of computers running the Windows Server operating system and point-of-sale systems for a large retail company.<\/p>\n<p style=\"margin-left:30px\">Blog: <a href=\"http:\/\/davewyatt.wordpress.com\/\" target=\"_blank\">http:\/\/davewyatt.wordpress.com\/<br \/><\/a><span style=\"font-size:12px\">Twitter: @MSH_Dave<\/span><\/p>\n<p>Take it away, Dave&#8230;<\/p>\n<p>In the early days of Windows PowerShell, there was a series of &ldquo;Windows PowerShell Tip of the Week&rdquo; posts about how to create GUIs with Windows PowerShell, including:<\/p>\n<ul>\n<li>Creating a Custom Input Box<\/li>\n<li>Creating a Graphical Date Picker<\/li>\n<li>Selecting Items From a List Box<\/li>\n<li>Multi-Select List Boxes &ndash; And More!<\/li>\n<\/ul>\n<p>These examples worked until Windows PowerShell 3.0 was released. If you tried to run them after that, they would not work. I can&rsquo;t tell you how many times I&rsquo;ve seen people asking questions about why the code based on these examples doesn&rsquo;t work. This week, we released <a href=\"http:\/\/technet.microsoft.com\/library\/dn792466.aspx\" target=\"_blank\">updated versions of these topics<\/a> on TechNet because people still seem to be interested in writing GUIs.<\/p>\n<p>I&rsquo;m not going to spend a lot of time talking about most of the code in these examples. I&rsquo;m going to focus on why they stopped working, and discuss some other cleanup I did on the code. The main reason they no longer work has to do with variable scope. All four examples had code similar to this:<\/p>\n<p style=\"margin-left:30px\">OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close()})<\/p>\n<p>This line assigns a script block as an event handler for the button&rsquo;s Click event. When the button is clicked, the results of <b>$objTextBox.Text<\/b> are assigned to variable <b>$x<\/b>, and the form is closed. However, this variable assignment is local to the script block. It doesn&rsquo;t modify any variable named <b>$x<\/b> in the parent scope where the rest of the code is running.<\/p>\n<p>I honestly can&rsquo;t tell you why it worked in Windows PowerShell&nbsp;1.0 and Windows PowerShell 2.0, or why that behavior changed. However, the current behavior in Windows PowerShell&nbsp;3.0 is more in line with what I would expect to see. Script blocks are supposed to have their own scope, and variable assignments are local unless you specify otherwise.<\/p>\n<p>There is a very quick-and-dirty way to &ldquo;fix&rdquo; these scripts. You can change the variable assignments to use a scope modifier, for example:<\/p>\n<p style=\"margin-left:30px\">$script:x=$objTextBox.Text<\/p>\n<p>However, I decided to clean up these scripts a bit, and I took a different approach. You can see the complete scripts on GitHub: <a href=\"https:\/\/github.com\/dlwyatt\/WinFormsExampleUpdates\" target=\"_blank\">WinFormsExampleUpdates<\/a>. Here&rsquo;s a summary of the changes I made:<\/p>\n<ul>\n<li>I got rid of all the <b>KeyPreview<\/b> and <b>KeyDown<\/b> bits, in addition to the Click events. These sections of code were intended to allow you to press ENTER or Escape to activate the same effects as the <b>OK<\/b> and <b>Cancel<\/b> buttons. However, Windows Forms already has a much simpler way of accomplishing this. You simply assign the buttons to the form&rsquo;s <b>AcceptButton<\/b> and <b>CancelButton<\/b> properties:<br \/> $form.AcceptButton = $OKButton<br \/> $form.CancelButton = $CancelButton<\/li>\n<li>I stopped throwing away the dialog&rsquo;s results. In the original script, the return value of the <b>ShowDialog()<\/b> method was discarded by casting it to <b>[void]<\/b>. However, this return value is normally intended to tell you how the user closed the form (OK, Cancel, Abort, Retry, Ignore, Yes, or No) depending on what buttons you&rsquo;ve shown.\n<p><span style=\"font-size:12px\">You also need to assign these dialog result values to the corresponding buttons. If the user pressed OK, the code inside the &ldquo;If&rdquo; block performs basically the same thing that the old <\/span><b style=\"font-size:12px\">Click<\/b><span style=\"font-size:12px\"> and <\/span><b style=\"font-size:12px\">KeyDown<\/b><span style=\"font-size:12px\"> event code used to do in each example. This avoids the scope issue that caused the old scripts to fail in Windows PowerShell&nbsp;3.0. The code that checks the user&rsquo;s input no longer happens in a separate event handler script block.<\/span><\/li>\n<\/ul>\n<p style=\"margin-left:90px\">$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK<br \/> $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel<\/p>\n<p> $result = $form.ShowDialog()<br \/> if ($result &ndash;eq [System.Windows.Forms.DialogResult]::OK)<br \/> {<br \/> &nbsp;# Examine the form controls to retrieve the user&rsquo;s selection<br \/> }<\/p>\n<ul>\n<li>I renamed many of the variables. Names like <b>$objForm<\/b>, <b>$objListBox<\/b>, and <b>$dtmDate<\/b> are an old VBScript convention, and they are generally discouraged in Windows PowerShell. These variables became <b>$form<\/b>, <b>$listBox<\/b>, and <b>$date<\/b>, respectively.<\/li>\n<li>I replaced the calls to Assembly.LoadWithPartialName() with <b>Add-Type<\/b> instead. The <b>LoadWithPartialName()<\/b> method is deprecated, and it is often not necessary anyway. The <b>Add-Type<\/b> cmdlet maintains a table that maps the short names of many built-in .NET Framework assemblies to their full names. This allows you to do things like this:<\/li>\n<\/ul>\n<p style=\"margin-left:90px\">Add-Type -AssemblyName System.Windows.Forms<\/p>\n<p>Here&rsquo;s the end result of the first example (a custom input box):<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/wes-8-2-14-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/wes-8-2-14-1.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>If you&rsquo;d like to read the updated Windows PowerShell GUI-building topics on TechNet, they&rsquo;re right here:<\/p>\n<ul>\n<li><a href=\"http:\/\/technet.microsoft.com\/library\/dn792463.aspx\" target=\"_blank\">Creating a Custom Input Box<\/a><\/li>\n<li><a href=\"http:\/\/technet.microsoft.com\/library\/dn792464.aspx\" target=\"_blank\">Selecting Items from a List Box<\/a><\/li>\n<li><a href=\"http:\/\/technet.microsoft.com\/library\/dn792467.aspx\" target=\"_blank\">Creating a Graphical Date Picker<\/a><\/li>\n<li><a href=\"http:\/\/technet.microsoft.com\/library\/dn792468.aspx\" target=\"_blank\">Multiple-selection List Boxes<\/a><\/li>\n<\/ul>\n<p>Thanks to Gaby Kaplan on the documentation team for updating the topics on TechNet.<\/p>\n<p>~Dave<\/p>\n<p>Thank you, Dave, for taking time to share your time and knowledge.<\/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 PowerShell MVP, Dave Wyatt, talks about using Windows PowerShell GUI example code. Microsoft Scripting Guy, Ed Wilson, is here. Welcome back guest blogger, Dave Wyatt. To read more of Dave&rsquo;s previous guest posts, see these Hey, Scripting Guy! Blog posts. Dave is a Windows PowerShell MVP and a member of the board of [&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":[501,71,56,3,4,61,45],"class_list":["post-884","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-dave-wyatt","tag-graphical","tag-guest-blogger","tag-scripting-guy","tag-scripting-techniques","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft PowerShell MVP, Dave Wyatt, talks about using Windows PowerShell GUI example code. Microsoft Scripting Guy, Ed Wilson, is here. Welcome back guest blogger, Dave Wyatt. To read more of Dave&rsquo;s previous guest posts, see these Hey, Scripting Guy! Blog posts. Dave is a Windows PowerShell MVP and a member of the board of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/884","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=884"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/884\/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=884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}