Some Reasons why Installers are a mess

The other day, I was kvetching about installers (if you’re new here, I do that. A lot. You get used to it) and got an interesting reply on twitter:

Installers should be a 100% solved problem these days. Use a freakin’ msi on Windows, and use a pkg on macOS and all will be right with the world. Do not use bloated Java-based installers. Yes, I’m looking at you, InstallAnywhere and whatever they use (used to use?) for Archicad.

So the thing is, yes and no. Installers are, as this person said, something that should be solved, but it is not, and the problem is far, far worse on Windows, even if one uses MSI’s, than it is on macOS. Like far worse, for a variety of reasons.

First, and this exists regardless of platforms, outside of a very small number of companies, the amount of care put into installers is basically none. It’s scutwork, it generates zero direct income, it’s the first circle of hell for interns, etc. One of the best reasons for drag and drop installs on macOS is that it literally avoids installer executables.

The problem with this is that an application that has unit tests galore, UI/UX research by the pound, endless resources devoted to making sure it runs in a way that makes angel sing gets installed by executables that take all that and shove it into some of the most awful UI with almost zero testing on anything but the programmer’s machine. (I have literally dealt with installers that had hardcoded paths to the dev’s machine in the config files. More than once.)

It is also a place where the worst sorts of unnecessary cleverness lives, especially if we’re talking about high-end applications that have roaming license servers. In some cases, I have seen installers for Linux servers that:

  1. Require manual undocumented hacks to install on RedHat
  2. Don’t have a command-line option, so the only documented way to install is to install a GUI. On a Linux server. To install software. Shoot. Me.

There is no realm of software that can begin to touch installers for sheer, mind-numbing WAT. The things I have seen…

But even if you do things “the right way”, there’s a lot of problems. I’m going to talk about Windows here, because it’s…well, honestly, it’s easy.

First, MSIs are not a magical end-all. For example, I have seen MSI over MSI that has to be run as an admin, but if you’re not physically logged in as an admin and double-click on the MSI, you’re never asked to elevate to run the installer, it just fails with a mostly-useless error message. This is a trivial thing to avoid, and yet it happens a lot. I’m pretty sure I know why, the one dev building the installer logs in as an admin, so this problem doesn’t exist for them.

Sometimes you get a “you need to be an admin, start over” dialog. Thanks a pantload Chet, you could have handled this as part of the install. But you didn’t, and now you suck.

You end up getting really good with running msiexec from administrator PowerShell windows after a while.

MSI has a fairly standard set of switches for quiet installs, etc., but a lot of MSI installers don’t always use them all for some reason. So the install either fails, (sans logging, and logging on Windows is awful) or it runs in default mode with nary an error message to be found.

Did I mention installers are regularly awful? Because they are. Autodesk for example, has arbitrary filename length limits for its installers. That it regularly violates. Let me say that again, the company that sets the rules for how long a filename can be to work with its installer names files that break that rule. Not filename and path, just the filename. Make it make sense.

But even if you don’t hit that kind of nonsense, even if the MSI is perfect, then there’s the library issue. Also known as the endless strings of VC++ and .NET runtimes that have to be installed, often in a specific order, and when you uninstall, those stay behind, because if some other app is also using it, (and you have no way of knowing this), then removing it breaks other things, often, again, with no useful error message.

This is one place where the package format macOS uses is literal brilliance, a brilliance I did not truly appreciate until I had to deal with Windows deployments again. In some cases, we’re talking about nine or more separate MSIs that have to run in a specific order before the actual installer for the app you want to install can run. None of these will be visible to the user in Settings or the Control Panel. So when you “uninstall” the application, you’re only uninstalling the actual application, not the n things that were actually installed. Because there’s no safe way to do that in Windows.

On macOS, you just shove all the libraries in the application bundle and you’re good to go. For example, Adobe Photoshop 2022 has 121 frameworks, 8 “required” plugins, 52+ other “required” pieces of code and image files, and hundreds of various localization files. All of them are in the application bundle. There’s some other things outside in the Application Folder, some config files in ~/Library/Application Support/Adobe, some in /Library/Application Support/Adobe, and really, that’s mostly it. Compared to how things work in Windows, that’s almost nothing.

There’s also, on Windows, no good way around it. The architecture of the OS forces you into doing stuff like the VC++ redistributable/.NET Runtime dance. You don’t have a choice, because you absolutely can’t make assumptions about anything. Linux is literally more predictable than Windows.

However, that being said, there’s ways to make things easier.

  1. Fully support deployment tools, and no, I do not mean your weird .hta file. I mean SCCM/Intune/MEM, or other managed deployment tools. Out of the box, with support documentation. Autodesk is particularly good here. Solidworks is particularly not good here. If you create the software, it’s your job to make it work with managed deployment tools. Not the IT department’s, not the VAR’s, yours. If you cannot actually test with any deployment tools, then at the very least, do the work so that your installer can be slotted into said tools without weird dances, and undocumented tricks.
  2. When you uninstall, clean up after yourself as much as possible. You can at least delete the application folders. That’s not too much to ask. Mathsoft is a rather annoying offender with this one.
  3. Make it easy to slipstream/update your deployment point. I should not have to build a new deployment point from scratch just to add a .x update file to it. Yes, it’s not zero work. It’s more work for me when I have to push that out to a few thousand machines, and I should start charging consulting fees for ISVs that make this harder than it should be
  4. If on Windows, use the registry as sparingly as possible, and for the love of christ, do not put application-level variables needed to run the app in the user-specific hive. Deployment tools don’t run as a logged in user, doing stuff like that adds a lot of work to deployments. There’s no good reason to do this, stop it.
  5. Avoid environment variables. Those suck to manage outside of your installer.
  6. Document your installers and the process in excruciating detail. Seriously, we don’t mind.
  7. Virtual machines are literally free. It costs only time to test your installer basics. Do that.
  8. If your installer doesn’t work perfectly smoothly in fully manual mode (manual double-click on the installer file), it is not ready to go. Periodt.
  9. If there are multiple post-install steps that have to be done before the installer quits, those aren’t post-install steps. Those are installer steps. Automate them as much as possible. Don’t pause things just so I can click “next”. If I have to click next to finish the install, then just assume “next” will always be clicked, and bake those steps into the installer. Don’t make people click when there’s no real need.

FInally, the installer is not only code, it is the first code your customers will run. Why do you want them to hate you that fast?

Advertisement

Porting an Application from AppleScriptObjectiveC to Swift

Okay, first, the links:

AppleScriptObjectiveC (ASOC) version: https://github.com/johncwelch/ScutilUtil
Swift version: https://github.com/johncwelch/scutil

So this took about…two days to do. Obviously, I am not an experienced Swift anything right? So there’s a lot of things i did someone more experienced would have done differently. No, it’s not done in SwiftUI, life is too short for that UI-as-CSS torture. I’m glad y’all like it, I find it tedious as hell. Way too much work to just put a button somewhere.

It is really hard to state just how a higher level language like ASOC spoils you. A LOT. It spoils you SO MUCH. So many thing you just don’t ever have to think about. I comment the hell out of the code, so i’m not going to go into detail about it. I will say that managing running a shell command with sudo privileges was way more difficult than I thought it would be. NSAppleScript() works, but it’s really fragile and without Swift playgrounds, I might have given up. Being able to just test a thing rapidly is really handy.

Also, for the love of god, think hard before you put a project you’re actively working on in a OneDrive folder. OneDrive handles code really badly. Like VERY BADLY.

I am also working on a Xamarin version just to see the differences. I just realized that doing the Swift version first would end up being way easier for the Xamarin version.

Sometimes, High-Level Languages don’t suck

So recently, as an exercise, I wanted to see about moving one of my simpler ASOC (AppleScript ObjectiveC) applications to a different language. Then I thought, why not two? So the first one I’ve been working with is C# via Visual Studio on the Mac (the 2022 preview). It’s um…interesting. First, you still need Xcode to do all the UI setup. I’m not sure why, and it’s a bit janky, but it’s not bad per se.

I think the Xamarin docs need a lot more sample code, it’s really intimidating if you’re new to the platform. But anyway, part of this app, ScutilUtil (https://github.com/johncwelch/ScutilUtil) uses the scutil command to pull info about the computer’s host name. (There may be a “proper” way to do it, but that’s not worth the search when scutil is right there.) To do so, you run scutil with various switches. i.e. /usr/sbin/scutil --get ComputerName to get the computer name.

In ASOC, this is trivial, literally one line thanks to AppleScript’s ‘do shell script’ command:

set my theCurrentComputerName to do shell script "/usr/sbin/scutil --get ComputerName"

Easy-peasy. In C#/Xamarin…sigh. The best way I found was:

Process scutilTest = new Process();
scutilTest.StartInfo.UseShellExecute = false;
scutilTest.StartInfo.RedirectStandardOutput = true;
scutilTest.StartInfo.FileName = "/usr/sbin/scutil";
scutilTest.StartInfo.Arguments = " --get LocalHostName";
scutilTest.Start();
string localHostName = scutilTest.StandardOutput.ReadToEnd();
scutilTest.WaitForExit();      

Like, it works right? But really? I mean, yes, this is a very cross-platform way to do it, but all that to run a single one-line command…it seems unelegant, and it seems unelegant on any of the platforms C#/Xamarin run on. Like, macOS/Linux/Windows all have a command line environment. They all have command line utilities that ship with the OS you might want to use because they’re there, and pretty fast.

Why make calling them so hard? Why not have something that gets you closer to do shell script. I mean, out of all of them, the only command/script environments you will never see on all three is cmd.exe, that’s windows-only and AppleScript is macOS – only, (but not something you’d run often in cases like this.) But shell? All three can have it. PowerShell? All three.

So wouldn’t it make more sense to have a way to test for the presence of a command environment, and a way to just use a command environment? Like say:

string localHostName = RunCommand -Environment zsh -Command "/usr/sbin/scutil" -Arguments "--get localHostName" -NoNewWindow -Wait

I’m using PowerShell-ish syntax here, because VS and .NET et al, but you get the idea. You could even have a way to check for a specific command environment if you wanted to be fancy, etc. Again, all the non-phone/non-tablet .NET platforms have a command-line environment of some form. Why not just allow for that to be used easily?

It’s times like these I wish Visual Studio Mac supported PowerShell as a language. Sigh.

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.