getsentry / getsentry/sentry-dotnet
Support platform specific version formats
- Dominant language
- C#
- Stars
- 770
- Forks
- 248
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 49
Description
### Description
Originally came up in https://github.com/getsentry/sentry-dotnet/issues/3801
When we [set a release](https://docs.sentry.io/platforms/dotnet/configuration/releases/#setting-a-release) we currently use the same format, regardless of the platform being targeted. However it appears different platforms have different conventions for version formats.
According to my LLM (so all of this probably needs to be fact checked):
## 📦 .NET MAUI Versioning Summary by Platform
| Platform | Format / Convention | MSBuild Properties / Notes |
|-------------|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
| **.NET Assembly** | `a.b.c.d` | `AssemblyVersion`, `AssemblyFileVersion`, `AssemblyInformationalVersion` |
| **Android** | `versionName`: `a.b.c (dddddd)`
`versionCode`: Integer | `1.2.3`
`456`
Common to append build metadata in parentheses |
| **iOS / macOS** | `CFBundleShortVersionString`: `a.b.c`
`CFBundleVersion`: `dddddd` | `1.2.3`
`456`
`CFBundleShortVersionString` **must** be in `a.b.c` format (Apple requirement) |
| **Windows** | `PackageVersion`: `a.b.c.d` | `1.2.3.4` |
### 🔍 Notes
- **Android:**
- `versionName` is shown to users, often includes build metadata (e.g., `1.2.3 (456)`).
- `versionCode` is used internally to determine update precedence and must increase with each build.
- **iOS/macOS:**
- `CFBundleShortVersionString` is the public version shown to users and must follow `a.b.c`.
- `CFBundleVersion` is the internal build number and can be any string, but Apple prefers it to be incrementing.
- **Windows:**
- `PackageVersion` must be a full four-part version (`a.b.c.d`).
- This format is consistent with traditional .NET assembly versioning.
- **.NET Assemblies:**
- Use standard four-part versioning: `AssemblyVersion`, `AssemblyFileVersion`, `AssemblyInformationalVersion`.
## 🔍 How to Access Version Information in .NET MAUI (Build-Time & Runtime)
| Platform | Build-Time Access | Runtime Access |
|----------------|-------------------------------------------------------|--------------------------------------------------------------------------------------------------|
| **.NET Assembly** | - `AssemblyVersion`, `AssemblyFileVersion`, etc.
- Read from `csproj`, `Directory.Build.props`, or `AssemblyInfo.cs` | - `typeof(App).Assembly.GetName().Version`
- `Assembly.GetExecutingAssembly()` with reflection |
| **Android** | - `` and `` in `csproj`
- `AndroidManifest.xml` generated from MSBuild props | - `Context.PackageManager.GetPackageInfo()` in Java/Android code
- MAUI: `Platform.CurrentActivity.PackageManager...`
- Or use [Plugin.VersionTracking](https://github.com/jamesmontemagno/VersionTrackingPlugin) |
| **iOS / macOS** | - `` and `` in `csproj`
- Placed into `Info.plist` by MSBuild | - `NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleShortVersionString")`
- Or use `VersionTracking` plugin |
| **Windows** | - `` in `csproj` → used in `AppxManifest.xml` | - `Package.Current.Id.Version` from `Windows.ApplicationModel` namespace |
## 🏃 Runtime Version Access Examples in .NET MAUI
### 🔧 .NET Assembly (All Platforms)
Access the version embedded in the .NET assembly metadata.
```csharp
// Gets the version from the assembly identity (e.g., 1.2.3.4)
var version = typeof(App).Assembly.GetName().Version;
// Gets the file version (AssemblyFileVersion)
var fileVersion = Assembly
.GetExecutingAssembly()
.GetCustomAttribute()?.Version;
```
### 🤖 Android
Use Android APIs via `Platform.CurrentActivity` (from `Microsoft.Maui.ApplicationModel`) to retrieve version info.
```csharp
using Android.Content.PM;
using Microsoft.Maui.ApplicationModel;
var context = Platform.CurrentActivity;
var packageInfo = context.PackageManager.GetPackageInfo(context.PackageName, 0);
string versionName = packageInfo.VersionName; // e.g., "1.2.3"
int versionCode = (int)packageInfo.LongVersionCode; // e.g., 456
```
> 💡 Note: `LongVersionCode` is used for API level 28+ and is backward-compatible when cast to int.
### 🍏 iOS / macOS
Use `NSBundle` to read values from the native `Info.plist`.
```csharp
using Foundation;
// User-visible version (e.g., "1.2.3")
var shortVersion = NSBundle.MainBundle
.ObjectForInfoDictionary("CFBundleShortVersionString")?.ToString();
// Internal build number (e.g., "456")
var buildVersion = NSBundle.MainBundle
.ObjectForInfoDictionary("CFBundleVersion")?.ToString();
```
> 📘 CFBundleShortVersionString is the public version shown in the App Store.
> 📘 CFBundleVersion is the internal build number submitted to Apple.
### 🪟 Windows (UWP / WinAppSDK)
Use `Windows.ApplicationModel.Package` to retrieve the app version from the package metadata.
```csharp
using Windows.ApplicationModel;
var version = Package.Current.Id.Version;
string fullVersion = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
// Example output: "1.2.3.4"
```
> ℹ️ This retrieves the version defined in your MSBuild property,
which maps to the Identity.Version field in the app package manifest (AppxManifest.xml).
Contributor guide
Assessment
This issue has not been assessed yet.