{"id":52583,"date":"2009-08-31T03:01:00","date_gmt":"2009-08-31T03:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/08\/31\/hey-scripting-guy-can-i-create-a-gui-for-a-windows-powershell-script\/"},"modified":"2009-08-31T03:01:00","modified_gmt":"2009-08-31T03:01:00","slug":"hey-scripting-guy-can-i-create-a-gui-for-a-windows-powershell-script","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-can-i-create-a-gui-for-a-windows-powershell-script\/","title":{"rendered":"Hey, Scripting Guy! Can I Create a GUI for a Windows PowerShell Script?"},"content":{"rendered":"<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"><\/p>\n<p class=\"MsoNormal\">Hey, Scripting Guy! I know this may sound like a strange question, but I would like to create a graphical user interface for a Windows PowerShell script. I could do these kinds of things using a HTML Application (HTA) file, but I like writing Windows PowerShell scripts. If I could use some sort of functionality that would create a drop-down list that would allow a user to select a specific item from the list, it would be great. Or do I need to continue creating HTAs if I want a graphical user interface? I guess I could figure out a way to run Windows PowerShell code from inside my HTA. Let me know. <\/p>\n<\/p>\n<p class=\"MsoNormal\">&#8212; MC<\/p>\n<p class=\"MsoNormal\">\n<p><span><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"><\/span><\/p>\n<\/p>\n<p class=\"MsoNormal\">Hello MC, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here. Graphical user interface (GUI) is not something I have been a big fan of in the IT pro\/scripting world. I have always figured that if I needed a GUI, I would use Visual Studio and write either a VB.NET or a C# application. Visual Studio makes it so easy to do this; it hardly seems worth the effort to write HTML code by hand. With the advent of the free versions of <a href=\"http:\/\/www.microsoft.com\/express\/vb\/\"><font face=\"Segoe\">VB.NET<\/font><\/a> and <a href=\"http:\/\/www.microsoft.com\/express\/vcsharp\/Default.aspx\"><font face=\"Segoe\">Visual C#<\/font><\/a>, there is no need for cost justification for the IT pro who wants to start using developer tools.<span>&nbsp; <\/span>The step from VBScript to VB.NET or from Windows PowerShell to C# is not a very big one. The big commitment, of course, is the time investment it takes to learn the new tools. <\/p>\n<p class=\"MsoNormal\">From having worked with thousands of IT pros in the last few years, I do know that there are some legitimate reasons for creating GUIs, and the HTA has been a faithful servant in that arena. Unfortunately, I have always found them to be an overly complex technology and a horribly documented one at that. If it were not for the few Hey, Scripting Guy! articles and the HTA Helpomatic (<a href=\"http:\/\/technet.microsoft.com\/en-us\/scriptcenter\/default.aspx\">available from our home page<\/a>), there would be almost no help for HTAs. <\/p>\n<p class=\"MsoNormal\">Here is an example of an HTA that creates a drop-down list and populates it with items from a text file. A similar HTA is discussed in the Hey, Scripting Guy! article, <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/2008\/07\/21\/how-can-i-load-a-drop-down-list-from-a-text-file.aspx\"><font face=\"Segoe\">How Can I Load a Drop-Down List from a Text File?<\/font><\/a> <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>DisplayListBox.hta<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlockScreened\"><span><font><font face=\"Lucida Sans Typewriter\">&lt;head&gt;<br>&lt;!&#8211;<br>&#8216;********************************************************************<br>&#8216;*<br>&#8216;*<span>&nbsp; <\/span>File:<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>DisplayListBox.hta<br>&#8216;*<span>&nbsp; <\/span>Author:<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Ed Wilson<br>&#8216;*<span>&nbsp; <\/span>Created:<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>8\/21\/2009<br>&#8216;*<span>&nbsp; <\/span>Version:<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>1.0<br>&#8216;*<br>&#8216;*<span>&nbsp; <\/span>Description:<span>&nbsp;&nbsp; <\/span>Reads a text file, and creates a list box<br>&#8216;*<br>&#8216;* Dependencies:<span>&nbsp;&nbsp; <\/span>You must modify path to the text file<br>&#8216;* HSG-08-31-09<br>&#8216;********************************************************************<br>&#8211;&gt;<br>&lt;title&gt;HTA List Box&lt;\/title&gt;<br>&lt;HTA:APPLICATION <br><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ID=&#8221;ListBox&#8221; <br><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>APPLICATIONNAME=&#8221;HTAListBox&#8221;<br><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>SCROLL=&#8221;yes&#8221;<br><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>SINGLEINSTANCE=&#8221;yes&#8221;<br>&gt;<br>&lt;\/head&gt;<\/p>\n<p>&lt;SCRIPT LANGUAGE=&#8221;VBScript&#8221;&gt;<\/p>\n<p>Sub Window_Onload<br><span>&nbsp; <\/span>LoadListBox<br>End Sub<\/p>\n<p>Sub LoadListBox<br><span>&nbsp;&nbsp;&nbsp; <\/span>ForReading = 1<br><span>&nbsp;&nbsp;&nbsp; <\/span>strNewFile = &#8220;c:FSOItemList.txt&#8221;<br><span>&nbsp;<\/span><span>&nbsp;&nbsp; <\/span>Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)<br><span>&nbsp;&nbsp;&nbsp; <\/span>Set objFile = objFSO.OpenTextFile _<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>(strNewFile, ForReading)<br><span>&nbsp;&nbsp;&nbsp; <\/span>strItems = objFile.ReadAll<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>objFile.Close<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>arrItems = Split(strItems,vbNewLine)<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>For Each stritem in arrItems<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Set objOption = Document.createElement(&#8220;OPTION&#8221;)<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>objOption.Text = strItem<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>objOption.Value = strItem<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Items.Add(objOption)<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Next<br>End Sub<\/p>\n<p><br>&lt;\/SCRIPT&gt;<\/p>\n<p>&lt;body&gt;<\/p>\n<p>&lt;select name=&#8221;Items&#8221;&gt;<br><span>&nbsp;&nbsp;&nbsp; <\/span>&lt;\/select&gt;<br>&lt;\/body&gt; <\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\">When the DisplayListBox.hta script is run, this GUI is displayed:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of GUI displayed when DisplayListBox.hta is run\" alt=\"Image of GUI displayed when DisplayListBox.hta is run\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/august\/hey0831\/hsg-8-31-09-01.jpg\" width=\"600\" height=\"279\"><\/p>\n<p class=\"MsoNormal\"><br>The ItemList.txt file is not anything special. It is a list of item names as seen here:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of ItemList.txt file\" alt=\"Image of ItemList.txt file\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/august\/hey0831\/hsg-8-31-09-02.jpg\" width=\"208\" height=\"373\"><\/p>\n<p class=\"MsoNormal\"><br>I created the ItemList.txt text file in Explorer, and was getting ready to add some content to the list. Then I realized, this is dumb, I am the Scripting Guy &hellip; I know how to write scripts. Therefore, I created the contents of the item list text file by typing the command seen here at a Windows PowerShell prompt. <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; 1..20 | ForEach-Object { Add-Content C:fsoItemList.txt &#8220;Item$_&#8221; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The Get-ListBoxFunction.ps1 script contains most of the code in a function called <b>Get-ListBox<\/b>. I could have called the function <b>New-ListBox<\/b> and thought about it pretty hard. However, when I looked at Windows PowerShell cmdlets that used the new verb, it did not seem to match up too well, so in the end I decided to call it <b>Get-ListBox<\/b>. Function names should conform to the Verb-Noun pattern in Windows PowerShell 2.0, or they will generate warning messages when placed into modules. It is a good idea to get in the habit of thinking about proper function names now. <\/p>\n<p class=\"MsoNormal\">The first thing you must do is load the assembly that contains the various graphical classes we want to use. To do this you use the <b>LoadWithPartialName<\/b> static method from the <b>System.Reflection.Assembly<\/b> class. In Windows PowerShell 2.0, this is easier because you can use the <b>Add-Type<\/b> cmdlet to do this for you. Because you do not want to be distracted with the confirmation message from calling the method, you pipe the results to the <b>Out-Null<\/b> cmdlet. This is seen here: <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">[System.Reflection.Assembly]::LoadWithPartialName(&#8220;System.windows.forms&#8221;) |<br><span>&nbsp;<\/span>out-null<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">You next need to create an instance of a Windows form. The <b>Form<\/b> class resides in the <b>System.Windows.Forms<\/b> namespace and is documented on <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.forms.form.aspx\"><font face=\"Segoe\">MSDN<\/font><\/a>. Because the <b>System<\/b> is the root namespace and is prepended automatically to the classes, you can leave it off when you create the class. You then assign a title for the Windows form of &#8220;ListBox Control&#8221; by assigning a value for the <b>text<\/b> property. This is seen here: <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$WinForm = new-object Windows.Forms.Form<span>&nbsp;&nbsp; <\/span><br>$WinForm.text = &#8220;ListBox Control&#8221;<span>&nbsp;&nbsp; <\/span><\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The size of the form is specified as an instance of a <b>Drawing.Size<\/b> structure. You need to create an instance of the <b>Drawing.Size<\/b> structure, and specify the height and the width of the form. The <b>Drawing.Size<\/b> structure is documented on <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.drawing.size.aspx\"><font face=\"Segoe\">MSDN<\/font><\/a>. One way to get the <b>Drawing.Size<\/b> dimensions is to draw the form in Visual Studio and look at the code behind the picture. You can also run the code and experiment with the sizes until you obtain a size that works for your particular application: <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$WinForm.Size = new-object Drawing.Size(200,125)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Once you have a form and a size for the form, you need to create a list box. The list box is an instance of the <b>ListBox<\/b> class that is found in the <b>Windows.Forms<\/b> namespace. It is documented on <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.forms.listbox.aspx\"><font face=\"Segoe\">MSDN<\/font><\/a> and has a number of methods and properties: <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$ListBox = new-object Windows.Forms.ListBox<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">You now need to add the controls to the Form. To do this, you use the controls.add method. Each item is added by using the items collection from the list box, and calling the add method. The Get-Content cmdlet is used to read the contents of the text file. Because you do not want to see the feedback from adding the item to the list box we pipeline the results to the Out-Null cmdlet. This is seen here. <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$winform.controls.add($listbox)<br>ForEach($i in (Get-Content c:fsoitemlist.txt))<br><span>&nbsp;<\/span>{ $ListBox.items.add($i) | Out-Null }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The last thing you need to do is to activate the Form and show the dialog. This is seen here. <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$WinForm.Add_Shown($WinForm.Activate())<span>&nbsp; <\/span><br><span>&nbsp;<\/span>$WinForm.showdialog() | out-null<span>&nbsp; <\/span><\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">When you select an item from the list box, it is assigned to the SelectedItem property of the ListBox class. The function returns this to the calling code. This is seen here. <\/p>\n<p class=\"CodeBlock\"><br><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$ListBox.SelectedItem<br>} #end function Get-ListBox<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The entry point to the script calls the Get-ListBox function. It does not pass any values to it; however, one improvement would be to modify the function to accept the path to the items it will use to populate the list box. This is seen here. <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"># *** Entry Point to Script ***<\/p>\n<p>Get-ListBox<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The complete Get-ListBoxFunction.ps1 script is seen here. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>Get-ListBoxFunction.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlockScreened\"><span><font><font face=\"Lucida Sans Typewriter\"># &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br># Get-ListBoxFunction.ps1<br># ed wilson, msft, 8\/20\/2009<br># <br># Keywords: .NET Framework, Reflection, windows.Forms,<br># graphical,gui<br>#<br># HSG-08-31-09<br># MSDN documentation for Listbox : http:\/\/bit.ly\/OaTCg<br># &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br>Function Get-ListBox<br>{<span>&nbsp;&nbsp; <\/span><br><span>&nbsp;<\/span>[System.Reflection.Assembly]::LoadWithPartialName(&#8220;System.windows.forms&#8221;) |<br><span>&nbsp;<\/span>out-null<br><span>&nbsp;<\/span>$WinForm = new-object Windows.Forms.Form<span>&nbsp;&nbsp; <\/span><br><span>&nbsp;<\/span>$WinForm.text = &#8220;ListBox Control&#8221;<span>&nbsp;&nbsp; <\/span><br><span>&nbsp;<\/span>$WinForm.Size = new-object Drawing.Size(200,125)<br><span>&nbsp;<\/span>$ListBox = new-object Windows.Forms.ListBox<br><span>&nbsp;<\/span><br><span>&nbsp;<\/span>$winform.controls.add($listbox)<br><span>&nbsp;<\/span>ForEach($i in (Get-Content c:fsoitemlist.txt))<br><span>&nbsp;<\/span>{ $ListBox.items.add($i) | Out-Null }<\/p>\n<p><span>&nbsp;<\/span>$WinForm.Add_Shown($WinForm.Activate())<span>&nbsp; <\/span><br><span>&nbsp;<\/span>$WinForm.showdialog() | out-null<span>&nbsp; <\/span><br><span>&nbsp;<\/span>$ListBox.SelectedItem<br>} #end function Get-ListBox<\/p>\n<p># *** Entry Point to Script ***<\/p>\n<p>Get-ListBox<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\">When the script is run, the Windows form seen here is created: <\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of the Windows form created when the script is run\" alt=\"Image of the Windows form created when the script is run\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/august\/hey0831\/hsg-8-31-09-03.jpg\" width=\"200\" height=\"125\"><\/p>\n<p class=\"MsoNormal\"><br>MC, thanks for asking a cool question. It has been quite some time since I wrote an HTA. The last one was about 10 months ago when I <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/2008\/10\/27\/how-can-i-create-an-hta-to-do-temperature-conversions.aspx\"><font face=\"Segoe\">created one to do temperature conversions<\/font><\/a>. We used your question to kick off graphical scripting week, as we answer some of the graphical scripting questions we have been getting. <\/p>\n<p class=\"MsoNormal\">Join us next week as graphical Windows PowerShell week continues. Tomorrow we will be looking at &hellip; wait you will need to follow us on <a href=\"https:\/\/twitter.com\/scriptingguys\/\">Twitter<\/a> or <a href=\"http:\/\/www.facebook.com\/group.php?gid=5901799452\"><span><font face=\"Segoe\">Facebook<\/font><\/span><\/a> for that information. If you have any questions, shoot us an e-mail at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\"><span><font face=\"Segoe\">scripter@microsoft.com<\/font><\/span><\/a> or post it to the <a href=\"http:\/\/social.technet.microsoft.com\/Forums\/en\/ITCG\/threads\/\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace!<\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/p>\n<p><\/span><\/b><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hey, Scripting Guy! I know this may sound like a strange question, but I would like to create a graphical user interface for a Windows PowerShell script. I could do these kinds of things using a HTML Application (HTA) file, but I like writing Windows PowerShell scripts. If I could use some sort of [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[71,3,4,30,45],"class_list":["post-52583","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-graphical","tag-scripting-guy","tag-scripting-techniques","tag-web-pages-and-htas","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Hey, Scripting Guy! I know this may sound like a strange question, but I would like to create a graphical user interface for a Windows PowerShell script. I could do these kinds of things using a HTML Application (HTA) file, but I like writing Windows PowerShell scripts. If I could use some sort of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/52583","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\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=52583"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/52583\/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=52583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=52583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=52583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}