CW
Navigation
๐Ÿ‡ง๐Ÿ‡ท PT ๐Ÿ‡บ๐Ÿ‡ธ EN
Home About Stack Companies Blog
CONTACT
Back to Blog
28 Apr 2026 20 Views
Stop Manually Bumping Version Numbers in Your .NET MAUI Apps

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 publish against 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

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 script
  • README.md โ€” English documentation
  • README.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.

Cezar Wagenheimer
Written By

Cezar Wagenheimer

Full Stack Developer & Game Creator. Specialized in building immersive digital experiences and advanced systems.

Connect:
Share this article

Comments

Be the first to comment!

Leave a comment