How to Add a Graphical User Interface to a PowerShell Script by Using HTML Applications
If you like writing PowerShell scripts and you need a simple solution to add a graphical user interface (GUI) to your scripts, you might want to read this article.
It is amazing to see how much you can do with a few lines of PowerShell script code. However, there are cases where we need something that is a bit better than a simple console output of data. A configuration report is a good example for this.
Looking through the available information, we have not been able to find something really simple. What does really simple in this context mean? An HTML page is an example for this.
Introduction to HTML Applications
A very simple method to create a GUI without using, for example, Visual Studio to develop it is known as HTML Application (HTA). HTAs are HTML pages that include one special tag in the <head> section called <hta:application>.
The following HTML code is an example for the simplest implementation of a HTA:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Simple</title>
<hta:application/>
</head>
<body>
</body>
</html>
You can use this code to develop your first HTA by copying it into a new file and saving it with a ".hta" extension. For example, "simple.hta". When you run this file, you will get a first impression for what HTAs are.
The gist of a HTA is that you can run scripts that are included in HTML pages outside of the Internet Explorer's security model. You can customize the look and feel of your HTA by setting properties of your HTA object. For more details about these properties, see the HTML Applications Reference.
Note
The process that runs your HTA file is called mshta.exe.
When you start a HTA, you should see the HTA GUI.
If you don't see your GUI, it is possible that you have a "hanging" mshta process.
The first step to troubleshoot this issue is to open the Windows Task Manager and to close all running mshta instances.
Adding Code to HTAs
To add some activities your HTA, you need to write some VBA code. While you can include the code into your HTML file, it is easier to keep the script code in a separate file and to include it by using the <script> tag into a HTA:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Simple</title>
<script src="default.vbs" type="text/vbscript" >
</script>
<hta:application
id="oHTA"
applicationname="Simple"
application="yes">
</hta:application>
</head>
<body onload="Initialize()">
</body>
</html>
The HTA code above has a reference to a file called "Default.vbs" and calls during the onload event of the HTA file a procedure called Initialize() in this file.
Below is the related code for this file:
Sub Initialize()
MsgBox "Hello World"
End Sub
When you run your HTA, the Initialize procedure is called which displays a message box:
Adding a Menu to HTAs
The simplest implementation of a menu is a table with clickable cells. This means, table cells with an event handler that calls a procedure in your script file.
The script code below shows the related HTA code for this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Simple</title>
<script src="default.vbs" type="text/vbscript">
</script>
<style type="text/css">
body {
margin-top: 0px;
margin-left: 0px;
margin-right: 0px;
margin-bottom: 0px;
font-family: Tahoma;
font-size: 11px;
}
table.menu {
width: 100%;
background:#CCCCCC;
}
</style>
<hta:application
id="oHTA"
applicationname="Simple"
application="yes">
</hta:application>
</head>
<body onload="Initialize()">
<table class="menu">
<tr>
<td onclick="Test()">Test</td>
</tr>
</table>
</body>
</html>
To test this code, you need to modify your default.vbs file:
Sub Test()
msgbox "Test"
End Sub
Sub Initialize()
End Sub
When you run your updated HTA, you can click the Test cell to trigger an activity:
Combining HTAs with PowerShell Scripts
In the previous examples, you have learned, how to add VBScript code to your HTA to trigger activities. However, the goal of this article is to show you how you can add a GUI to your PowerShell script code.
While you can't include PowerShell script code directly into your HTA, you can use VBScript to launch external processes:
To run external processes by using VBScript, you can use the run method. For more details about the run method, see Run Method (Windows Script Host).
You can use this method to start PowerShell and pass the name of your PowerShell script as parameter to it.
To test this technique, you can use the following PowerShell script code and save it as "Test.ps1":
001 |
write-host "Hello World" |
Note
To run PowerShell scripts from VBScript code, you need to set the execution policy on your computer to enable this activity.
For example, Set-ExecutionPolicy Unrestricted enables all PowerShell scripts to run on your system.
For more details, see Using the Set-Execution Policy Cmdlet.
After you have set the execution policy on your system, you can use the following VBScript script code to run it:
Dim oShell, scriptPath, appCmd
Set oShell = CreateObject("WScript.Shell")
scriptPath = oShell.CurrentDirectory & "\Test.ps1"
appCmd = "powershell -noexit &'" & scriptPath & "'"
msgbox appCmd
oShell.Run appCmd, 4, true
You can use this technique also from your HTA's VBScript code to run PowerShell scripts by. For example, including it into the procedure that handles your menu events.
Fine-tuning the PowerShell Integration
In the last HTA example, you have seen a simple implementation for an event handler that displays a message box. The objective of this section is to show you, how to call a PowerShell script and how your HTA can communicate with it.
There are several methods you can use to implement interprocess communication between your HTA and your PowerShell script. For example, you could use files to exchange data.
For convenience, you can also use the clipboard to exchange data. To write data to the clipboard, in PowerShell, you can use the clip object. The PowerShell code below throws an exception and has an exception handler. The exception handler writes the exception message to the clipboard and sets an exit code.
001 002 003 004 005 006 007 008 |
throw "An error occurred in your script" trap { $_.Exception.Message | clip Exit 1 } |
In your HTA script code, you can use the clipboarddata object to read clipboard data. To identify the type of the data in your clipboard, you should read the return value of the run method. If an exception occurs in your PowerShell script, the exception handler sets an exit code of 1.
In the case of an exception, the value of retVal in the VBScript code below is also 1:
Sub Test()
Dim oShell, scriptPath, appCmd, retVal, retData
Set oShell = CreateObject("WScript.Shell")
scriptPath = oShell.CurrentDirectory & "\Test.ps1"
appCmd = "powershell &'" & scriptPath & "'"
retVal = oShell.Run(appCmd, 4, true)
retData = window.clipboarddata.getdata("Text")
If(retVal = 1) Then
msgbox retData, vbExclamation, "Error"
Else
msgbox retData, vbInformation, "Return Value"
End If
End Sub
Sub Initialize()
End Sub
Running your updated HTA and PowerShell script code returns the following message box:
You can also use the clipboard method to exchange with your PowerShell script data you want to display in your HTA. By using DHTML and XSLT, you have a variety of options to render the data or to add dynamic affects to the rendered data.
The following list provides examples for HTAs that are based on this method:
- FIM Attribute Flow Precedence Viewer
- FIM Get Resource By Name
- FIM Scriptor
- FIM CS Synchronization Viewer Plus
- FIM Object Visualizer
The DHTML options is also a nice method to make the menu in your HTA look nicer. FIM Hello ScriptBox is an example for a HTA that uses DHTML to implement a nicer menu.
Note
After you have downloaded the Zip file to your computer, you should unblock it.
To unblock the file, right-click it, select Properties, and then click Unblock.
HTAs on 64-bit Windows
On 64-bit Windows computers, the 32-bit and the 64-bit versions of PowerShell and mshta are installed. In the case of PowerShell, you quickly identify what version your are running by looking at the path of the powershell.exe that is used to run PowerShell.
If the path includes SysWOW64, you are running the 64-bit version:
In case of the mshta, you can identify the version you are running by looking at the Windows Task Manager. If the Image Name includes *32, you are running the 32-bit version:
Summary
HTML applications provide a very simple mechanism to add a graphical user interface to your PowerShell scripts. While you can't use PowerShell scripts directly from within a HTA, you can use VBScript's run method to run PowerShell scripts and the clipboard for the interprocess communication. Separating your HTA implantation into individual files, for example, a separate .vbs file for the VBScript logic and a .css file to format your HTML page, makes it easier to quickly apply updates to your HTAs. This is helpful if you have several HTAs developed.
Note
To provide feedback about this script, create a post on the FIM TechNet Forum.
For more FIM related Windows PowerShell scripts, see the FIM ScriptBox.