Stop Manually Bumping Version Numbers in Your .NET MAUI Apps
"Automate .NET MAUI version bumps with this free PowerShell script. Sync iOS and Android versions, increment build numbers, and push Git changes in seconds."
Stop Manually Bumping Version Numbers in Your .NET MAUI Apps
If you maintain more than one .NET MAUI app, you have probably lived this moment: you just shipped a fix, you open Info.plist to bump the iOS build, then open AndroidManifest.xml to do the same for Android, then realize the .csproj also needs updating, then wonder if the other three apps you maintain are even in sync โ and you haven't touched git yet.
It is tedious. It is error-prone. And it scales terribly.
This post introduces a free, open-source PowerShell script that automates all of it.
The Problem With Manual Version Management
In a .NET MAUI project, the version of your app lives in three different places:
Platforms/iOS/Info.plist
The file Xcode and App Store Connect read during archive and submission.
CFBundleShortVersionStringโ the version string your users see (5.48)CFBundleVersionโ the build number Apple uses to distinguish uploads (607)
Platforms/Android/AndroidManifest.xml
The file the Android build tools and Google Play read on every upload.
android:versionNameโ the version string your users see (5.48)android:versionCodeโ a strictly increasing integer Google Play enforces (607)
*.csproj
Where .NET MAUI's MSBuild pipeline reads version information at build time.
<ApplicationDisplayVersion>โ version string<ApplicationVersion>โ build number
Keep these in sync across one project and it is manageable. Keep them in sync across four, six, or ten apps โ every release โ and mistakes start to happen. A forgotten build number causes an App Store rejection. A mismatched version confuses your testers. A rushed commit leaves Android on 5.47 and iOS still on 5.46.
There has to be a better way.
Introducing the .NET MAUI Version Manager
The MAUI Version Manager is a single PowerShell 7 script that gives you a clean, colorized terminal UI to manage versions across all your MAUI apps at once.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ .NET MAUI ยท Version Manager โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
v2.0 ยท K:\Projects\MyApps
# App Branch iOS Android Status
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1 MyApp - Core main 5.48 #607 5.48 #607
2 MyApp - Pro main 5.43 #595 5.43 #595
3 MyApp - Lite feature/login 5.43 #27 5.43 #595 โ DESSYNC
4 MyApp - Enterprise main 5.51 #601 5.51 #601
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
G Git Pull todos 0 Sair
โบ App (nรบmero) ou opรงรฃo:
You see everything at once. You act with a single keypress.
Features at a Glance
- ๐ Auto-discovery โ drop the script in your root folder and it finds every MAUI app in subfolders automatically, with configurable search depth
- ๐จ Colorized terminal UI โ app names, branches, versions, and status badges are color-coded for instant scanning
- ๐ Git branch per app โ each row shows the current branch so you always know what state each project is in
- โ ๏ธ Sync detection โ automatically warns when iOS and Android versions have drifted apart
- โ Dirty and ahead indicators โ see uncommitted changes and unpushed commits at a glance without leaving the tool
- โฌ๏ธ Increment version + build โ bumps the minor version and the build number in one step across all three files
- ๐ข Increment build only โ for patch releases where the version string stays the same
- โ๏ธ Manual entry โ type any version string and build number you need
- ๐ Sync iOS โ Android โ when platforms drift, pick which one is the source of truth and the script aligns the other
- ๐ฆ iOS build โ calls
dotnet publishagainst a remote Mac build host via SSH - ๐ Git commit + push โ after any version change, one prompt creates a conventional commit and pushes
Requirements
- PowerShell 7+ (
pwsh) โ download here - Git โ must be on your PATH
- .NET SDK โ only required if you use the iOS build option
- A Mac build host via SSH โ only required for iOS builds
That is it. No npm, no NuGet packages, no configuration files to maintain.
Quickstart: Up and Running in 60 Seconds
Step 1 โ Download the script
Place maui-version.ps1 in the root folder that contains your MAUI app subfolders.
MyProjects/
โโโ maui-version.ps1 โ script goes here
โโโ AppCore/
โ โโโ Platforms/iOS/Info.plist
โ โโโ Platforms/Android/AndroidManifest.xml
โโโ AppPro/
โ โโโ Platforms/iOS/Info.plist
โ โโโ Platforms/Android/AndroidManifest.xml
โโโ AppLite/
โโโ Platforms/Android/AndroidManifest.xml
Step 2 โ Run it
pwsh maui-version.ps1
If your apps are nested more than one level deep, use -Depth:
pwsh maui-version.ps1 -Depth 3
Step 3 โ Pick an app and act
Type the app number, choose an action, confirm, and optionally push. Done.
A Tour of the Menus
Main table
Every time the script loads (and after every action), it refreshes the table. Each row shows:
| Column | What it tells you |
|---|---|
# |
The number to type to select this app |
App |
Folder name โ yellow if iOS and Android are out of sync |
Branch |
Current git branch โ green for main/master, magenta for others |
iOS |
Version string and build number from Info.plist |
Android |
Version string and build number from AndroidManifest.xml |
Status |
โ DESSYNC if platforms differ, โ if dirty, โN if ahead of remote |
App detail menu
When you select an app, you get a detail panel:
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ MyApp - Core โ
โ Branch: main โ
โ iOS v5.48 #607 โ
โ Android v5.48 #607 โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
1 Incrementar Versรฃo + Build 2 Incrementar sรณ Build
3 Definir versรฃo manualmente 4 Sincronizar iOS โ Android
5 Gerar Build iOS 6 Git Pull
0 Voltar
| Option | When to use it |
|---|---|
| 1 โ Increment version + build | New feature release. 5.47 โ 5.48, build 606 โ 607 |
| 2 โ Increment build only | Bug fix or patch. Version stays 5.47, build 606 โ 607 |
| 3 โ Set manually | Jumping to a specific version, e.g. 6.0.0 for a major release |
| 4 โ Sync platforms | iOS drifted from Android (or vice versa) โ pick the reference and align |
| 5 โ iOS build | Triggers dotnet publish against your Mac build host |
| 6 โ Git Pull | Pull the latest for this specific app |
After options 1โ4, the script shows a before/after preview and asks you to confirm before writing anything:
Antes : v5.47 #606
Depois: v5.48 #607
Confirmar? (S/n):
Then:
Deseja fazer Commit + Push? (s/N):
If you say yes, it stages everything, commits with a message like chore(version): bump MyApp to v5.48 build 607, and pushes.
What Gets Modified โ and Why All Three Files
You might wonder why the script touches three files. Here is why each one matters:
Info.plist is read by Xcode and the App Store Connect pipeline. CFBundleShortVersionString is the user-facing version (5.48). CFBundleVersion is the build number that Apple uses to distinguish uploads (607). Both must be present and correct or your archive will be rejected.
AndroidManifest.xml is read by the Android build tools and Google Play. android:versionName is the user-facing string. android:versionCode must be a strictly increasing integer โ Google Play rejects any upload where the code is not higher than the previous release.
*.csproj is where .NET MAUI's MSBuild pipeline reads version information. <ApplicationDisplayVersion> and <ApplicationVersion> can override the platform-specific files during a build. Keeping them in sync ensures that any CI pipeline that reads version from the project file agrees with what the platform manifests declare.
Touching all three in a single operation eliminates the most common source of version mismatch.
Real-World Scenarios
Scenario 1: You maintain a suite of related apps
You have a Core app, a Pro app, and a Lite app. They all ship on the same release cadence. Today you want to bump all three to 5.49 with build 610.
With this script: open the tool, select app 1, choose option 1, confirm, push. Repeat for apps 2 and 3. Total time: under a minute.
Without this script: open each project, edit three files each, commit separately, push separately. Hope you didn't forget one.
Scenario 2: Hotfix on Android only
A critical crash on Android needs a fast fix. iOS is fine. You want to increment only the Android build number without touching the iOS version.
Select the app, choose option 2 (build only), confirm. The script syncs all three files. Push.
Scenario 3: iOS and Android have drifted
A developer pushed an Android build directly without updating iOS. The table shows โ DESSYNC. Select the app, choose option 4, pick Android as the reference, confirm. Both platforms now agree.
Scenario 4: Major version jump
You are releasing version 6.0.0. Select the app, choose option 3 (manual), type 6.0.0 as the version and 700 as the build. Confirm, push.
Frequently Asked Questions
Does it work with apps that only target Android (no Info.plist)?
Yes. The script handles apps that have only one platform's files. It reads and writes whatever is present and skips what is not.
Does it work with iOS-only apps (no AndroidManifest.xml)?
Yes, same logic applies.
What if my .csproj does not have <ApplicationDisplayVersion>?
The script checks whether the tags exist before replacing them. If they are absent, it skips the .csproj silently โ it will not inject new tags.
Can I run it from CI?
The script is interactive by design. For CI, you would call the individual functions (Set-IosVersion, Set-AndroidVersion, Set-CsprojVersion) directly after dot-sourcing the file. A non-interactive mode may be added in a future version.
Does it support monorepos where apps are more than one level deep?
Yes. Use the -Depth parameter. -Depth 3 searches three levels deep, for example.
Will it accidentally modify apps it should not? It only modifies the app you explicitly select and confirm. The table is read-only until you take an action.
Get the Script
The script is free and available as a GitHub Gist:
๐ github.com/wagenheimer/6e27938c32dd667e2d8bf2e135dad2f1
The Gist contains:
maui-version.ps1โ the scriptREADME.mdโ English documentationREADME.pt-BR.mdโ Portuguese documentation
Found a bug or want to suggest a feature? Leave a comment on the Gist โ feedback is welcome.
Conclusion
Version management in .NET MAUI is a small but persistent source of friction. Three files, two platforms, N apps โ it adds up. The MAUI Version Manager collapses that friction into a single interactive session: you see all your apps, you pick one, you act, you push.
It requires no installation beyond PowerShell 7. It modifies only what you confirm. And it is free.
If you maintain more than one MAUI app, give it a try. The first time it saves you from a rejected App Store upload, you will not go back.
Found this useful? Share it with your team or anyone building .NET MAUI apps.
