A WPF application for generating new game installer projects from templates for the Ukrainify project.
InstallerCreator streamlines the process of creating new game localization installers by:
- Generating boilerplate project structure
- Filling template files with game-specific information
- Adding game themed image assets
- Including only the game detection libraries needed for selected platforms
The application provides a simple form with the following fields:
- Hero image - Select hero banner image (800x250)
- Logo image - Select logo image
- GameTitle - Display name of the game
- GameIdentifiers - Store-specific game codenames (semicolon separated)
- AssemblyName - .NET assembly name for the installer
- ProjectName - Folder name for the project (no spaces)
- Supported Platforms - Checkboxes for Steam, GOG, and Epic Games Store
cd Tools/InstallerCreator
dotnet publish -c Release
# or use the main build script from project root
../../build.ps1- Add the variable to template files with
{VariableName}syntax - Update
ProjectCreator.csto include the replacement:ReplaceInFile(path, "{VariableName}", replacementValue);
Edit files in the InstallerProjectTemplate/ directory to change the generated project structure.
cd Publish/Tools/InstallerCreator
InstallerCreator.exe-
Fill in all required fields in the form
-
Select hero and logo images
-
Check the platforms the game is available on (Steam, GOG, Epic Games Store)
-
Click "Create Installer Project"
-
The new project will be created in the selected target directory as
Ukrainify.{ProjectName} -
Open the solution in Visual Studio and add the new project to the solution
-
Fill Metadata.cs with game information:
- The file structure is already generated with
CommonandPlatformSpecificLocalizations - Go through each field and fill or remove as needed:
Important Note: If your localization works identically across all platforms, you can use only
Commonmetadata and replacePlatformSpecificLocalizationswith an empty dictionary:public IReadOnlyDictionary<string, MetadataEntry> PlatformSpecificLocalizations { get; } = new Dictionary<string, MetadataEntry>();
Common MetadataEntry:
executable- Game executable name (e.g.,"Game.exe")- Remove parameter if different per platform
markerFile- Platform detection file (e.g.,"steam_api.dll")- Remove parameter if different per platform
changedFiles- Files to modify (e.g.,["Game.exe"])- Remove parameter if no files are changed
addedFiles- List of localization files to add (e.g.,["ukr/0", "ukr/1"])- Remove parameter if no files are added
Platform-specific MetadataEntry (Steam, GOG, Epic): Only fill this section if your localization differs between platforms.
executable- Platform-specific executable name- Remove parameter if using common executable
markerFile- Platform detection file- Remove parameter if not needed for detection
changedFiles- Files to modify for this platform- Remove parameter if no files are changed
addedFiles- Platform-specific files to add- Remove parameter if no additional files
Remove entire platform entries you don't support.
Example (Common only):
public MetadataEntry Common { get; } = new MetadataEntry( executable: "MyAwesomeGame.exe", changedFiles: new[] { "MyAwesomeGame.exe", "data/config.xml" }, addedFiles: new[] { "localization/text.dat", "localization/audio/", "localization/fonts/" } ); public IReadOnlyDictionary<string, MetadataEntry> PlatformSpecificLocalizations { get; } = new Dictionary<string, MetadataEntry>();
Example (Platform-specific):
public MetadataEntry Common { get; } = new MetadataEntry( addedFiles: new[] { "shared/assets/", "shared/ui/" } ); public IReadOnlyDictionary<string, MetadataEntry> PlatformSpecificLocalizations { get; } = new Dictionary<string, MetadataEntry> { ["steam"] = new MetadataEntry( executable: "MyGameSteam.exe", markerFile: "steam_api64.dll", changedFiles: new[] { "MyGameSteam.exe" }, addedFiles: new[] { "platform/steam/overlay.dll" } ), ["gog"] = new MetadataEntry( executable: "MyGameGOG.exe", markerFile: "goggame-1234567890.info", changedFiles: new[] { "MyGameGOG.exe", "gog/config.ini" } ), ["epic"] = new MetadataEntry( executable: "MyGameEpic.exe", markerFile: "EOSSDK-Win64-Shipping.dll", changedFiles: new[] { "MyGameEpic.exe" }, addedFiles: new[] { "platform/epic/services.dat" } ) };
- The file structure is already generated with
-
Implement localization logic in
Installer.cs:- Override the
OnInstall()method to define file operations - Add resource extraction logic for executables and archives
- Example: Extract localized executable and unzip data folders
- Override the
Installers/Ukrainify.{ProjectName}/
├── Ukrainify.{ProjectName}.csproj # Project file
├── App.cs # Application entry point
├── Installer.cs # Installer logic
├── Metadata.cs # Game metadata
├── Properties/
│ └── AssemblyInfo.cs # Assembly information
├── Branding/
│ ├── hero.png # Hero banner
│ └── logo.png # Logo image
└── Resources/
└── localization # Embedded translation files
The installer creator replaces these placeholders in template files:
| Variable | Description | Example |
|---|---|---|
{ProjectName} |
Project folder name | A_Short_Hike |
{AssemblyName} |
.NET assembly name | Ukrainify.A_Short_Hike |
{GameTitle} |
Display name | A Short Hike |
{GameIdentifiers} |
Store-specific game codenames | "AShortHike", "ashorthike" |
{Year} |
Current year | 2026 |
{DetectorUsings} |
using statements for selected platform detectors |
(generated) |
{DetectorInstances} |
Detector constructor calls for selected platforms | (generated) |
{DetectorProjectReferences} |
MSBuild ProjectReference entries for selected platforms |
(generated) |
- "Template directory not found" - Ensure the application runs from its correct directory
- "File already exists" - Delete existing project or use different project name
- No platform selected - At least one platform must be checked before creating a project