Porting an Application from AppleScriptObjectiveC to Xamarin/C#

This ended up taking less time than I thought it would, as it turns out, about 90% of the work I did on the Swift version was usable with little modifications in the Xamarin version. Like mostly differences between variable declarations in C# vs Swift, object inits, etc.

Links:

ASOC Original
Swift Version
Xamarin/C# Version

So in terms of just coding, MS and the Xamarin team have done a really good job. Like, there’s very few things that actually tripped me up going from Cocoa to Xamarin. Usually, it was odd things, like having to use Environment.Username to get the current user name because NSUsername() isn’t an option, or similar. Like little things that are annoying more than OH GOD NO. The syntax MS uses for the .NET Core Mac bits is really similar to the Swift implementation in Cocoa, which is a huge benefit to anyone looking to use VS.

I think a lot of that is just C# and .NET being things that have existed for a while outside of the Mac, and so you’re going to have odd little differences where they’re not going to implement NSUsername() when they have something that already works.

As an aside, Git is just awful, can someone please invent something that doesn’t have a UI/UX that only Linus Torvalds could love? Also, VS’s Git interface is…it is a thing, it exists but it is not very good even for simple things. Also, if you have any idea you may ever want to use Github et al for your project ALWAYS SAY YOU WANT TO USE GIT WHEN YOU CREATE THE PROJECT. Ye gods did dealing with that suck.

The major thing is dealing with the UI. It’s very reminiscent of when Interface Builder was not a part of Xcode. To build a UI in Visual Studio, you basically shell out to Xcode, build your storyboards there, then dump back in to VS. No SwiftUI yet, but there’s no reason you couldn’t do it. (It is still amusing to me that VS will have native ARM support on the Mac before it does on Windows.) You also need Xcode to publish to the MAS if that is your wish. I’m honestly not sure there’s a way to not need Xcode for the UI bits that wouldn’t be more trouble than it’s worth, but I could be wrong, and I’d be happy to be wrong.

Could you use Visual Studio: Mac for “real” development or cross-platform development? I think you could and if they fix a few relatively minor issues, it would be not awful at all.

I mean, for the purposes of my experiment, I was rather happy with VS/Xamarin/C#/.NET, and I am glad I’ve done the work I have in PowerShell, that was quite a help. Now, if you could use PowerShell in VS:Mac, that would be awesome, since you know, PowerShell is available for the Mac and all.

Just sayin’…

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.