Using AppleScript’s “Display Dialog” with PowerShell

Okay, I didn’t have a clever title. Sue me

One of my biggest complaints about PowerShell is the lack of UI primitives. Coming from AppleScript, I’m used to having a variety of very basic UI options for the using, without needing to do anything to set them up. Need to get a simple response from the user? Display Dialog. Want them to choose from a list? Choose From List. Choose Folder, Choose File, etc. They’re all a part of core AppleScript.

You can eventually do the same with PowerShell, but even on Windows, there’s a lot of .NET setup and silliness you have to deal with. Which is dumb, and something the PowerShell team should address at some point. But that’s way off in the future, if ever. So I set about solving this for myself, and came up with method that seems to work, albeit in an awkward way. The sample script and readme are up on my GitHub site, and it’s not all that complicated. I spend more time shoving the results of the command into a hashtable than I do running the command.

I used “Display Dialog” because it’s a simple command that is fairly representative of most AppleScript UI primitives. It’s a single-line command with various parameters, and it returns a record (hashtable in PowerShell parlance) as a comma- and colon- delimited string, at least as far as using it this way is concerned.

This uses the osascript command to run the AppleScript command(s). One thing that failed miserably was trying to use Invoke-Expression -Command for this. Primarily, this seems due to the complex use of single and double quotes within osascript that causes PowerShell to vomit all over itself. However, if you pipe the command to osascript, then it works alright, as seen below:

$results = 'display dialog "this is a test" default answer "default answer" with icon caution'|/usr/bin/osascript

this runs display dialog as expected, and gives you a single, comma-delimited string for the record returned. Each item in the record is split by a comma, so the initial return looks like:

button returned:OK, text returned:default answer

Okay, that works, it’s consistent. The next thing I do is split the string into an array with the split command:

$results = $results.Split(",")

So if all you want is each record in its own element, you can stop there. For my case, I wanted the return in PowerShell to be a hashtable, aka AppleScript record, so there’s a couple more steps. First, we iterate through $results to look at each item separately. Since the second item in the array is going to have a leading space, we run each item through Trim() to remove leading/trailing whitespace characters.

$result = $result.Trim()

Then I take each item and split it on the colon which creates a new array entry.

$temp = $result.Split(":")

From there, I take the elements of the array, and insert them into a hashtable:

$dialogReply.Add($temp[0],$temp[1])

If you’re dealing with truly large returns/strings, this would be a suboptimal method. But, AppleScript display primitives don’t really return massive amounts of data, so it’s not a big deal. Here’s the entire code block for the whole script below. The first line creates the dialogReply hashtable:

$dialogReply = [ordered]@{}
$results = 'display dialog "this is a test" default answer "default answer" with icon caution'|/usr/bin/osascript

$results = $results.Split(",")

foreach ($result in $results) {
     $result = $result.Trim()

     $temp = $result.Split(":")
     $dialogReply.Add($temp[0],$temp[1])
}

Then to display the hashtable, just call $dialogReply and you get:

$dialogReply

Name                Value
----                -----
button returned     OK
text returned       default answer

This should work with a large number of, if not all the AppleScript primitives. I’ll be looking at playing with different ones as I have time.