Call PowerShell Commands from AppleScript/JXA

This will probably work within ASOC too, since do shell script works there. On macOS, the powershell “executable” is pwsh, usually in usr/local/bin/pwsh for the non-beta versions. If you run pwsh -h, you see that the pwsh utility is quite versatile, and by using the -c parameter, you can treat it like osascript, in that you can pass it a single command as a string, or an entire script block. You can also pass it a PowerShell script with the -f command. So to use this from within AppleScript/JXA, (AppleScript syntax shown), it looks like:

do shell script "/usr/local/bin/pwsh -c \"Get-PSDrive\" "

You can also use this with custom modules:

do shell script "/usr/local/bin/pwsh -c \"Get-MacInfo HardwareModelID\" "

So if you want to use a slightly more coherent shell environment like PowerShell from within AppleScript, you can.

Shortcuts in Monterey Beta 5

Has Anything Actually Improved?

When last I talked about Shortcuts, there wasn’t much there. It seemed clear that the entire purpose of Shortcuts was for iOS Shortcuts and that the AppleScript and other functionality only exists as a path away from Automator. Shortcuts support in the OS was kind of meh at best, unsurprising given Apple. So has anything improved? Sort of.

Shortcuts is “Scriptable”

The quotes are deliberate, because this is the barest implementation one could have and still be technically scriptable. There’s one class in the suite, “shortcut” which has for properties a collection of identifers:

  • color
  • id
  • name
  • subtitle

and Action Count, which is the number of actions in the shortcut. All these are read-only values, so you can’t use this class to create a new empty shortcut. That’s fine, because there’s only one command, “run”, and that is all this dictionary is designed to do: let you run existing shortcuts via AppleScript/JXA/whatever. So it’s not “automation” in any useful sense. There’s one handy feature, the addition of the “Shortcuts Events” app, which is a helper app that lives in  /Applications/Shortcuts/Contents/Library/Helpers/Shortcuts Events, and if you target it within a tell block instead of Shortcuts, then you can run the shortcut without having to start Shortcuts.

I mean, that’s handy, right? But that’s the extent of the usefulness of this dictionary. You can get a list of existing shortcuts and run one of them.

w00t

Other Support

The support for Shortcuts in the OS and associated utilities is about what it was, and as uneven and uncoordinated as one would expect from Apple. For example, I can create an event on my Exchange Calendar in the “Add New Event” shortcut, or any calendar Calendars can see, (which is something you can’t do via AppleScript, and has been that way since iCal first supported Exchange. Can’t imagine why I am so cynical about Apple’s automation “commitment”), but you can’t do that for Contacts. Disk Utility has some basic shortcuts and no other way to automate it other than dumping into the shell environment, which bypasses Disk Utility entirely. FaceTime lets you call/FaceTime a contact in Contacts. That’s it. The Finder shortcuts are still so basic as to be not useful. You can’t just make a new file. You can’t make a new folder. I don’t know why Apple bothered with it if they’re going to limit it that much.

Mail has two shortcuts around measurements(??) but they both say “this requires an app but it may not be installed” Really Apple? Really. That’s good UI? How? All but one of Messages shortcuts involve iTunes for some reason, and the one actual messaging shortcut doesn’t even let you attach a file to a message. Again, why even bother? In an unsurprising limitation, Shortcuts shortcuts are every bit as limited as its “scripting” dictionary.

In what is a truly WAT moment, the macOS version of Shortcuts has a “Set Flashlight” shortcut. For Macs. Which, last I checked, don’t have flashlight functionality. But sure, Shortcuts main priority isn’t roundtripping shortcuts between macOS and i(Pad)OS. It’s not just that one. There’s a whole host of shortcuts that make no sense on a Mac, unless Apple plans on actually merging iPads and Macs. I know I often wish I could more easily manage my Voice & Data settings on my Mac.

Sigh.

Oh, and the UI in Shortcuts is kind of awful. Good luck finding the close control for a shortcut. It’s a wee tiny dark grey “x” that is almost invisible on a black background. Doesn’t even highlight when you mouse over it, which makes me wonder is there anyone over the age of 25 on the Shortcuts team? Heck, anyone over 19? Anyone with any form of vision acuity issues? Because that is a design that only works for young, perfect eyes. It wouldn’t be so bad if I could remove a shortcut from a workflow any other way. But I can’t.

Evidently, I need to get new iGlasses.

See what I did there?

There’s one Siri shortcut: to dismiss Siri. Why? Why is that a thing at all? System Preferences has no shortcuts, but shows up in the app list.

So no, there is nothing about Shortcuts on macOS to be even interested in, much less excited about. There’s nothing particularly useful about Shortcuts, unless you’re just into automation that doesn’t let you really automate anything.

Which describes, again how Apple views user-created automation. They don’t like it, they haven’t since the return of Jobs, and the only reason Shortcuts exists on macOS, based on what I’ve seen, is to have feature “parity” with iOS. I mean, I can set my Mac’s flashlight with it. So there’s that.

Apple and Automation

Boy, there’s a title fraught with weirdness and uncertainty. Like going back to System 7 Pro and the introduction of AppleScript.

But anyway, watching the 2021 WWDC keynote, I realized that for all intents and purposes, Apple doesn’t have a single automation model/framework. It has like elebenty and they ignore each other almost entirely. Want to operate at the user level? You’re going to use AppleScript, Apple’s very weird JavaScript for Automation implemenation, sharing panes, etc. Individual apps may implement OSA (the framework behind AppleScript and Automator) or they may roll their own.

Oh, did I say Automator? Well other than the fact that’s going away in a few years to be replaced by Shortcuts, you could write Automator Actions using like four languages.

Then there’s the various scripting bridge lanugages like AppleScriptObjectiveC, (ASOC), PyObjC…and at the shell level, well, shell, Python, PowerShell if you like…

And other than within Automator, none of these work well together. You can build actual apps in ASOC, but you can’t debug them in Xcode. Well, display dialog and log statements. So 1990s debugging. Roundtripping between shell and AppleScript is annoying and fragile, and you’re doing a lot of write to a file/read from a file.

AppleScript is barely functional outside of the user GUI context and shell doesn’t really work well in there.

And then there’s Shortcuts. Which do a good job of taking over for automator, and surprised me with the ability to run AppleScript/JSX/Shell commands.

But that’s not a unified automation model, and that’s what Apple needs. Along with documentation, because Apple’s Dev/Automation documentation is, to put it as kindly as I can, pants. Like just pants. What they need, and I try to avoid saying that, but in this case, it works, what Apple needs to do is basically steal the idea behind PowerShell and the documentation of powershell.

Before the shellistas come for me, PowerShell is an object-oriented implementation of .NET, which is way, way more powerful for scripting across all OS levels than shell, which assumes everything is text and is tedious as hell for a lot of things. Like anything where text as your i/o medium doesn’t work well. Shell isn’t bad, but PowerShell is better. It also has some things going on that Apple should use.

PowerShell and .NET

Basically, (and I am drastically simplifying), PowerShell is an object language that takes the .NET frameworks and infrastructure, and simplifies it in a way that makes it more useful to scripters. The syntax is very similar to “real” .NET/C# (Even though you can code for .NET in other things, C# is the “default” and I’m going to use them fairly interchangeably here.)That’s not to say PowerShell is “dumbed down”, not by any means. But, it does mean that PowerShell as a language is targeted more at scripting and automation than full app development. For example, (unlike AppleScript), PowerShell has no UI primitives, which is quite the pain in the keister for when you need scripts that interact end users. Things like choosing from a list, etc., are much easier in AppleScript than in PowerShell. For example, in AppleScript, display dialog is a single line, where it is a bit more complicated in PowerShell.

The AppleScript version:

display dialog "You have to be an admin to do this"

Powershell:

$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("You have to be an admin to do this:,0,"Script Info",0x0 + 0x10)

Not hugely more complicated, but still, having to manually create objects that way for simple things is tedium, and the syntax is a bit more awkward.

But, the thing is, PowerShell out of the box gives you access to basically the entire .NET frameworks, which means you have access to basically all of Windows. And, because of Microsoft not only pushing ISVs to adapt PowerShell as an automation language, and leading the way, you get a lot of support for using PowerShell throughout windows.

PowerShell is also regularly updated, and they’ve even managed to do this in a way that breaks very little. Now, that can be a pain, because the current version is 7.x and Windows, by default, ships with 5.1, but still, you can easily get 7.x. In addition, thanks to things like PowerShell Get, they have a whole setup to add new packages as needed via different “official” and unofficial repositories, something that to my knowledge, Apple never even attempted with any of their automation tools. Not even shell, not really. Maybe sorta/kinda Swift, but still, very thin.

So with PowerShell you have a consistent OS-wide object model that works at all levels, remotely, Application automation, whatever you need. It has a way to create modules for packaging up well, libraries to be easier to use for other folks. Creating modules is far too painful for its own good, but it’s there.

And then, there’s the documentation, and this my friend, is where PowerShell shines. Like Apple has nothing close to the level of documentation, not at the API/Language level, and my god, not even close to the implemenation level. Apple has literally nothing close to this: https://devblogs.microsoft.com/scripting/, and the old “Hey, Scripting Guy!” blog has, now that the guy who created it retired, been turned into a community resource. Here: https://devblogs.microsoft.com/scripting/heyscriptingguyupdate/

On the best day of its life, Automation at Apple never. ever. ever. had that level of support for implementation help just there on a web site. (DTS never supported automation outside of low-level ObjC/Swift for creating OSA implementations in apps. Even ASOC, which mind you, is still a part of Xcode 13 gets you no DTS support, just a “go use a mailing list/forums.” response. Boy, that makes me want to take the time to learn ASOC. Even better, Xcode has NEVER had any debugging support for ASOC. sigh) But that’s not all. The actual language, model, and implementation documentation for PowerShell is light years ahead of what Apple has, especially in terms of consistency.

Apple did, a few years back, finally, finally port the AppleScript language guide from a PDF to a part of the Apple Developer site, and that is pretty solid, because it was written a long time ago when Apple’s core AppleScript team was more than like three people, (and I may be overestimating the current size of that team), but that’s it. There’s nothing compared to what PowerShell has going on. For example: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/write-host?view=powershell-7.1

While you’re looking at that, take a gander at the lefthand column. Note that it shows different versions of PowerShell. Yeah. Apple doesn’t even document ObjC and Swift that well, much less automation. Also, at least with PowerShell, I have full access to the clipboard. Apple still can’t give us that, or won’t, or whatever. That dates back to System 7 Pro I think. So what, 20 years? 30? Meanwhile, PowerShell has a full suite of clipboard commands. That’s what taking automation seriously does.

So the upshot is, because PowerShell is based on .NET, and gives you such access to it, as you find yourself outgrowing PowerShell, moving into .NET, or mixing in full .NET commands as needed is really easy. Way easier than even moving from ASOC to ObjC or Swift. Like right now, I might be able to code macOS apps easier with .NET than I can with Swift, because I’m more familiar, thanks to my PowerShell work, with .NET than I am with Swift. Given my background with writing code for both macOS and Windows, that’s really sad. But Microsoft gives you that path, Apple does not.

That is something that Apple has, to be frank, failed at. Miserably. Apple’s support, as a company for keeping their automation frameworks and implementations consistent and supported and using them themselves is really quite awful, and as a result, no one else has consistently cared. I doubt it’s even occurred to Apple to structure things so you could move easily from AppleScript to ASOC to ObjC/Swift. I can damned sure tell you Apple has nothing out there to help you with macOS automation from an educational perspective. Which is why, even though the new macOS Shortcuts look cool, I’ve real doubts, because I’ve seen this same thing from Apple before with regard to automation:

Apple: NEW AUTOMATION THING

Customers: Oh cool, where’s the documentation?

Apple: THERE IS NONE

Customers: Oh…okay, are you going to have any courses or training for it?

Apple: OF COURSE NOT

Customers: Okaaay…you going to lead the way and use this internally and in your own applications?

Apple: DON’T BE SILLY, WE’D NEVER DO THAT

Customers: …you going to support people building solutions and systems with this beyond stuff like forums and mailing lists?

Apple: NOT A CHANCE

Customers: …you ever gonna update this?

Apple: LMAO, NO WAY

Customers: …

Apple: NEW AUTOMATION THING

The list here is long. Again, for ASOC, which has been a part of Xcode since…10.5…you can’t even debug it. Even though, there’s actual AppleScript/ASOC IDEs that will debug AppleScript, aka Script Debugger.

So even though Shortcuts on macOS looks really cool, based on past history, it’s going to get ignored as anything other than a way to run iOS Shortcuts on a Mac.

I would love to be wrong here, but Apple has been jerking people around hard in terms of OS automation on the Mac for longer than some of its current employees have been alive. (I’m not exaggerating here, AppleScript is 28 years old, introduced in 1993.) So telling me I have no reason to be so doubtful is going to get you a very long rant.

However…let us pretend that Apple is serious here. That they want to fix the deficiencies. Let’s take a look at those.

Current Issues with macOS Automation

The biggest issue the macOS has is that unlike Windows, there’s no consistent way to do stuff. If you want to do interapplication automation, there’s AppleScript, JavaScript (multiple implementations depending on application developer), custom application-specific stuff, some shell and python.

AppleScript actually has a decent object model, most of the inconsistencies come from the number of different applications supporting it. There’s no way to avoid that, ISVs are going to do things differently. No syntax in the world makes up for that. As well, syntax preferences, for the most part, are personal and a lot of the hate for AppleScript as a syntax is just the worst kind of elitism and nerd gatekeeping.

The problem with the object model is that it really is only designed to work locally, in the context of a logged in user. Remote Apple Events have always been ugly, and a security issue. Even then, Remote Apple Events are simply not designed for a Unix-based OS. Unsurprising, given they predate OS X by about half a decade.

For remote stuff, you’re now in the shell environment, which is its own mess, since you may be using shell, you may be using python, SQL…and the security on those ain’t that great either. Relying on SSH keys et al causes its own special set of problems. Then there’s exchanging data between AppleScript/Apple Events and the shell. Ugh. Yes, you have a lot of options, but after a while, it’s all just more ways of shooting yourself in the foot, with wildly inconsistent syntax and no organized, secure way to communicate across the network.

Oh, and it doesn’t help that the OSA stuff uses Apple Events to exchange data and the shell environment thinks everything is text. sigh

Then there’s the previously detailed issues with Apple’s lack of support for this beyond the barest of efforts. Aka, Apple is lazy as hell some times.

So how do you fix it?

Swiftscript

Yeah, stupid name, but I’m not in marketing. So there’s a few things we want out of real automation on macOS (and this could easily carry over to i(Pad)OS et al. More easily than the current…stuff.)

The current list:

  1. An OS-wide object model. This, by the way, already exists, it’s the Cocoa frameworks. We literally have a solid foundation for an updated object model that can be used between applications, at the shell level, at the user level, it’s all there already. Even has a cool name: Cocoa. Okay, it already has an accepted name.
  2. A consistent OS-wide way to pass data. This is a big weakness of the current system. Honestly, I think adapting the way PowerShell does things and doing a major revamp on the OSA object model so that it extends down into the core os is not just more painless way to go, it’s the way to go that will last the longest. We already can exchange text and objects, let’s just create a single model that creates a consistent, known, documented and supported way of doing this. Since it’s based on Cocoa, it’d work pretty well for i(Pad)OS as appropriate.
  3. Security. Since this is going to be slanging data o’er the land, it should just be encrypted from the start. Apple has a nice infrastructure for this already, so this would be an extension of that. This would also make it easier to handle transparent, effortless secure remoting, and yes, it has to be effortless. The most secure way, (and not that Windows PowerShell ExecutionPolicy idiocy) has to be the default. Build it right the first time, your life gets so much easier.
  4. The syntax should basically be Swift, only like how PowerShell:.NET. That’s pretty braindead, and yes, I know what this would mean for AppleScript, but part of this has to be using Swiftscript as a way to move into “full on” application development in a way that’s not as…Swift Playgrounds are too artificial, I can’t use them to solve the problems I have in my day to day. The Swiftscript syntax being similar, although not identical to Swift would be a huge help. That’s not to say you jettison AppleScript completely. There’s a few concepts from that language that work really well, for example, directing code at an application via a tell block.

    tell application “Finder”
    blah blah blah
    end tell

    may not appeal to the Swift purists, but a) I don’t care about them, and b) it’s pretty intuitive. I’m telling the Finder to do stuff. That’s pretty straightforward. Also, I like “Using terms from” where you have to intermingle code from different applications (a problem you don’t see in Swift now, because that’s not a use case.) It’s a quick way, within an existing code block or a tell block to jam in a bunch of code for a different application. Again, straightforward. What am I doing here? I’m using terms from Microsoft Word.

    Also take a good look at just how the current OSA object model works. It’s old, but it really works well. It needs attention to be sure, but it does a lot of things right. Don’t be afraid to plagiarize yourself, you’re the best source for your own needs.
  5. Documentation and Support. To be fair, Apple’s existing developer documentation is kind of meh anyway, so use this as an excuse to fix that too. Hire technical writers and let them do that. I know Apple has the money, it’s a will issue, not a resource issue. Add Swiftscript into DTS. For the first time, put some real wood behind that damned arrow. Like seriously.
  6. Dogfood it. Apple is horrible here. (I have receipts, please save yourself some grief, don’t challenge me on this.) Everything Apple does has to have the best scripting support in the macOS ecosystem. Period. Again, Apple has the resources, they just don’t care enough to actually do it.
  7. Evangelize it. Like y’all need to create a legion of Chloe Condons and let them loose. Not just at Apple events. Y’all need to be everywhere, and annoyingly so.

I think that covers most of it. Like you don’t have to jack things up too much. Just have this be a slightly higher level of Swift. For example, as AppleScript does now, the runtime should support all the core OS functions (think Standard Additions + Core Language + System Events here) without having to reference any other modules. If a module is needed, consider the PowerShell concept where you add the module/framework to your setup and then just use the methods and properties it brings in. If a script detects a missing module that’s part of the standard OS build, offer to add it in to that person’s setup.

Oh, right, almost forgot:

  1. Create a repository for third-party modules. You already know how to do this, it’s called the App Store. Like Swift packages, only not full-on that. But a place for people to contribute and access third-party modules that they can trust. Only maybe be more transparent. Somtimes, y’all’s App Store shit is extra.
  2. If you wanted a way for third-party languages to plug into this, that wouldn’t be awful.

Is any of this easy? No. But if Apple wants people to take new things like Shortcuts for macOS and whatever else is coming down the pike seriously, then Apple has to do more than the “if we build it and sort of make it possible to use, maybe they’ll come…whatever” stuff they’ve been doing for the last three decades. There’s a lot of ill-will with “official” Apple automation initiatives, and honestly, it’s fully and totally justified. Apple is just the master of the half-assed effort here.

And, if they really want to make automation work the way it should on the OS, well, I started a solution here. There’s good examples in wide-scale production use now (POWERSHELL) that can be improved upon and made more suitable. Apple has the money, the question is, do they have the fucks?