Recently I put together a Windows Installer package (MSI file) for our team to use internally. The package installs a system tray app (sometimes called a notification app or notification area app). One common property of system tray apps is that they don’t actually close on exit — they simply return to the system tray and continue running in the background.
In order to properly uninstall this component, the app needs to be shut down by the installer/uninstaller. Typically, in WiX, you’d do this with the CloseApplication element, which sends a WM_CLOSE message to the system tray app, which it ignores completely. What to do?
Here was my solution, embedded in the WiX WXS source file (toolset v3.9):
<?define SysTrayAppExe = "mySysTrayApp.exe" ?>
<CustomAction Id="KillApp" Directory="InstallDir" Return="ignore" ExeCommand=""[SystemFolder]taskkill.exe" /F /IM "$(var.SysTrayAppExe)"" />
First, we define a custom action that will execute the taskkill Windows system command. We ignore the return value because we don’t care if the app was actually running. Just in case the Windows system folder has embedded spaces, we wrap the command in quotes using the XML quote specifier. The /F flag requests a forceful termination, and the /IM flag requests that we terminate the specifically named process, which is again wrapped in quotes in case it has embedded spaces.
Next, we set up the custom action to execute in the first phase of the install process. This ensures that the system tray app is always shut down when the install/uninstall begins.
Ideally, we’d use the CAQuietExec special custom action to avoid a command screen from briefly flashing on the screen, but CAQuietExec must be run after the InstallInitialize phase, by which time the Windows Installer has already detected that the system tray app is running, and it’s too late for us to do anything about it.
It was fun to compare and contrast the toolset we’re using at HBO for the creation of VR products with what the folks at Oculus Story Studio are using. More similarities than differences. Story Studios’ Dropbox solution as a backup system is rather clever.
For the past year, I’ve been working on virtual reality projects at HBO. We’ve learned a ton, but there is still so much we don’t know.
Although VR experiences borrow from the language of film and borrow from the language of video games, one of the most important things we’ve learned is that VR is truly a new medium.
With traditional media, you are on the outside looking in. You read a book. You watch a movie. You play a game. The view you have of the book or the film or the game is a window into another world. It may be an immersive experience, but you can easily exit that experience by simply casting your gaze in a different direction.
With virtual reality, you’re on the inside looking out. You can’t look away, because everywhere you turn is part of the experience that’s been created for you.
Perhaps the most apt metaphor is Disneyland rides. When you’re on the Pirates of the Caribbean ride, you are in the center of the experience. The experience surrounds you, engulfs you. Cannons roar. Water sprays. Fires rage. Wenches run. Pirates sing. And you are in the middle of it all. You can’t look away.
The “inside looking out” notion is key to understanding VR. For instance, it’s one of the reasons we no longer talk about having a camera in VR, because the very notion of a camera harkens back to an “outside looking in” perspective, with a window on the world. Instead, we talk about the person in VR — a person who can (and often will) look in every direction, the person who is completely immersed in the experience, and the person who can’t escape the experience without physically removing their headset!
Recently I needed to package up an Unreal build for distribution. You can do this from the Unreal Editor v4.6 by selecting File->Package Project. However, I wanted to automatically create packages on a build machine without human intervention. That meant I needed to find a command I could execute in a script. Skipping to the hard won result, here’s the wooly command line I ended up with:
.\Engine\Build\BatchFiles\RunUAT.bat -verbose BuildCookRun -nocompileeditor -nop4 -project=MyProject.uproject -cook -allmaps -CrashReporter -stage -archive -archivedirectory=c:\Package -package -WindowsNoEditor -clientconfig=Shipping -ue4exe=UE4Editor-Cmd.exe -clean -pak -prereqs -targetplatform=Win64 -build -utf8output
Over twenty command line parameters. How did I figure that all out?
First I searched on the web for “Unreal command line package.” That led me to a promising page, so I tried the recommended command line there. However, when I compared my output with the output generated by the in-editor packaging step, not only were most of the files quite different, there were some files that were in one place and not the other. No dice.
Time to think like a software engineer.
Unreal distributes source code for their engine and editor. So I searched the code for the word archivedirectory (one of the parameters mentioned at the link above), which led me to .\Engine\Source\Editor\…\MainFrameActions.cpp. It has a line that starts with
FString CommandLine = ...
I set a breakpoint on that line in Visual Studio, started up the Unreal Editor, attached to the Unreal Editor from Visual Studio (Debug->Attach to Process), and then selected File->Package Project->Win64 in UE. Breakpoint hit! From there it was simple to copy the actual CommandLine value that UE uses to a batch file and tweak path names as needed.
- I repeated this process a few times, tweaking the settings at Packaging Project->Packaging Settings so I could extract the various command line parameters that can be configured in the editor.
- The –project setting must be the fully qualified path name
- For shipping builds, use –clientconfig=Shipping. For development builds, use –clientconfig=Development. I didn’t try creating a Test build, but that would be an interesting experiment, since you can’t package test builds from inside the editor.
- –clean ensure a full build is done, –build builds code, –cook builds content, and –pak puts the content in a single pak file
- The only platform I was targeting was 64-bit Windows, so you’ll need to validate the targetplatform parameter for other platforms
One of my common software interview questions involves the creation of a game board. Part of the problem includes the generation of random numbers. If the candidate is writing in C/C++, the typical code I see looks something like this:
srand(seed); // one time seeding of generator
// later on ...
r = (rand() % 6) + 1; // throw the dice
r = Math.Floor((Math.Random() * 5) + 1); // [1...6] ?
Takeaway: getting random numbers correct is a non-trivial problem. A lot of information available on the Internet about generating random numbers is plan wrong. Beware. Test your generators to ensure that they are both random and uniform. If I was writing C++ code today that needed to throw a d6, it would look like this:
std::mt19937 mt(seed); // generation engine
std::uniform_int_distribution<int> ud(1,6); // distribution engine
// later on ...
r = ud(mt); // [1...6], uniformly distributed
For a hilarious 30 min excursion into the pitfalls of C/C++ rand(), see Stephan’s talk: rand Considered Harmful. You’ll never use rand() again.
My current project has me writing C# scripts in Unity. Cool. I haven’t written C# for more than a decade. Today I was reviewing code, and noticed this line:
foreach (var child in Children)
Nothing too exciting. Readable. Easy to understand. But as I took a second look, I realized I didn’t truly know what var is all about. Is it defining a variable? What’s the type of child? Could var be replaced with ChildType? What’s best practice? Should I be using var?
Var was introduced in C# v3.0 circa 2007. It turns out it’s the equivalent to auto in C++, which I wrote about not long ago. Var allows the compiler to determine the type automatically.
So, var defines a variable. The type of var is the type that the compiler deduces. Var could be replaced with the actual type, but best practice is to use var whenever you can, just like auto. I’ll be using it regularly from now on.
I’ve always been a proponent of ease of development. All things being equal, when I have a choice I will pick the easier language/tool/environment.
But all things are never equal. Developers have to consider development costs and their personal skillsets and platform install base and hundreds of other variables in their decision to build a product on a particular platform using a particular set of tools.
What wins? Install base.
Example #1: Playstation. Writing games for the original PlayStation, PlayStation 2 — and even PlayStation 3 — is incredibly challenging. The hardware is complex. The documentation is abysmal. C/C++ is de rigueur. But the PlayStation line of game consoles has sold hundreds of millions of units, and developers have risen to the challenge of making PS games, because that huge install base represents the chance of making a fortune.
Example #2: iPhone. Creating apps for iOS is no easy task. Objective-C is an obscure language that is only popular due to the runaway success of iPhones and iPods.
That’s why I was surprised at the recent announcement of Swift. Apple has no business need to create better tools or languages. Developers are not blocked creating iOS apps. Yet Apple continues to improve the Xcode development environment and now introduces a new programming language that should appeal to many developers. Fascinating.
iOS install base. Check.
Apple winning the hearts and minds of developers. Check.