Introduction
I was trying to resolve some project solution generation issues a few weeks ago and it led me to wonder: What are those ?
What exactly happens when we click those commands ? Well I searched a bit and thought I'd write down my findings here 😄. Let's have fun.
The Windows Contextual Menu
In case you didn't know, the windows contextual menu is actually fairly customizable. The way it's stored is through the windows Registry in the file association department :)
I invite you to go take a look at the documentation page ! But I'm going to detail the adventure a bit.
So ! Win+R to bring up the start menu, regedit
and enter to open the registry editor ! We're in (relatively) dangerous territory here so don't change anything until you know what you're doing.
It should look something like that :
From there you might be asking what are we looking for ? There's a bajillion keys and the organization is a secret known only to the gods ! Well no worries, we actually have some piece of texts to put our foot in the door, chiefly "Switch Unreal Engine version" ! It's a sufficiently unique string that whatever match we find should represent the contextual menu command we're looking for.
So, CTRL+F, input the string (we don't care about the settings just make sure Data is checked), and search ! It's going to take a little while, there's a lot of stuff in there, but it should find an entry like HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell\switchversion
.
What are we looking at ? The anatomy of a registry entry is relatively simple :
Each "folder" is a key, each key can have child keys which builds a hierarchy. Each key can also have one or multiple values associated (always at least one, the Default). And each value can have Data associated. To be noted that everything here is identified with a string.
It's here that I encourage you to check the documentation page again 😁
Windows has 2 levels of file association, machine and user space, the defaults are stored in HKEY_LOCAL_MACHINE\Software\Classes, the user specifics in HKEY_CURRENT_USER\Software\Classes, and HKEY_CLASSES_ROOT is actually just a merged view of both those keys !
if you've ever ran an installer and got the question "Do you want to install for all users or just the current one" now you know what's happening behind the scene ! (Well there's some subtilties depending on context but the idea is the same)
Alright ! Let's take a look at this registry structure. Unreal stores all the commands under HKEY_CLASSES_ROOT\Unreal.ProjectFile\shell
, Windows knows to display those commands thanks to the file association found in HKEY_CLASSES_ROOT\.uproject
! You can this key's value is set to Unreal.ProjectFile
.
If we check the structure of that key, we'll find DefaultIcon which points to the icon displayed in the explorer, and a bunch of shell commands :
Taking a look at switchversion
, you can find the (Default) and Icon values are used by the contextual menu, while a command
child key registers the actual shell code that runs when we click the menu item.
In particular, on my current version and install : "D:\Epic Games\Launcher\Engine\Binaries\Win64\UnrealVersionSelector.exe" /switchversion "%1"
Alright ! One mystery solved. We now know that all those commands boils down to executing UnrealVersionSelector.exe
with various / commands and the file path (%1
)
On to the next one, what up with UnrealVersionSelector ? ╰(°▽°)╯
UnrealVersionSelector
Lucky for us, the UnrealVersionSelector tool source code is available on the official Unreal github ! We can go take a look at exactly what those command arguments do, as a quick list the registered commands looks like this:
- switchversion: /switchversion
- rungenproj: /projectfiles
- run: /game
- open: /editor
A quick search gives us all of the commands, and even new ones >:)
// Note: Cut down for brevity
if (Arguments.Num() == 0)
// Add the current directory to the list of installations
bRes = RegisterCurrentEngineDirectoryWithPrompt();
else if (Arguments.Num() == 1 && Arguments[0] == TEXT("-register"))
// Add the current directory to the list of installations
else if (Arguments.Num() == 2 && Arguments[0] == TEXT("-register") && Arguments[1] = TEXT("-unattended"))
// Add the current directory to the list of installations
else if (Arguments.Num() == 1 && Arguments[0] == TEXT("-fileassociations"))
// Update all the settings.
else if (Arguments.Num() == 2 && Arguments[0] == TEXT("-switchversion"))
// Associate with an engine label
else if (Arguments.Num() == 3 && Arguments[0] == TEXT("-switchversionsilent"))
// Associate with a specific engine label
else if (Arguments.Num() == 2 && Arguments[0] == TEXT("-editor"))
// Open a project with the editor
else if (Arguments[0] == TEXT("-projectlist"))
// Open the editor
else if (Arguments.Num() == 2 && Arguments[0] == TEXT("-game"))
// Play a game using the editor executable
else if (Arguments.Num() == 2 && Arguments[0] == TEXT("-projectfiles"))
// Generate Visual Studio project files
else
// Invalid command line
If we dive a bit into the code we can find a lot of details about how unreal finds installations and how it registers stuff, notably I was wondering what the GUID found under EngineAssociation
corresponds to in the .uproject file.
Well you can register custom installations of the engine by navigating to your unreal source folder and running UnrealVersionSelector.exe -register
.
This adds a key to the registry under the path HKEY_CURRENT_USER\SOFTWARE\Epic Games\Unreal Engine\Builds
which matches that GUID to your install folder ! I think that was pretty interesting, if you're curious to learn more it's all happening in those files (on windows) :
Source\Developer\DesktopPlatform\Private\DesktopPlatformBase.cpp
Source\Developer\DesktopPlatform\Private\DesktopPlatformWindows.cpp
An other interesting function to look at is EnumerateLauncherEngineInstallations
, we can see here that everything that the Epic Launcher installs is actually saved in a .dat file in ProgramData C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat
. I won't spoil the content but you can parse the file yourself 😏
Conclusion
I hope you liked this little dive in windows belly ! And some of those keys about the unreal version selector. I think it's good knowledge to have when we're trying to debug project setup issues 😁
If you make new tools now you should be able to plug them in the contextual menu fairly easily for your clients ! And if you ever wonder what a tool does when you click its contextual menu button you should be able to find out what 😄