Repository navigation
Use GetCurrentPackageFamilyNameNative API instead of path matching to detect MSIX installation
#28029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use GetCurrentPackageFamilyNameNative API instead of path matching to detect MSIX installation
#28029
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #nullable enable | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| internal static partial class Interop | ||
| { | ||
| internal static partial class Windows | ||
| { | ||
| [LibraryImport("kernel32.dll", EntryPoint = "GetCurrentPackageFamilyName", StringMarshalling = StringMarshalling.Utf16)] | ||
| private static partial int GetCurrentPackageFamilyNameNative(ref uint packageFamilyNameLength, Span<char> packageFamilyName); | ||
|
|
||
| /// <summary> | ||
| /// Returns the package family name of the current process when it has package (MSIX) identity; otherwise null. | ||
| /// </summary> | ||
| internal static string? GetCurrentPackageFamilyName() | ||
| { | ||
| const int ErrorSuccess = 0; | ||
| const int PackageFamilyNameMaxLength = 65; // Maximum name plus null terminator. | ||
|
|
||
| try | ||
| { | ||
| uint length = PackageFamilyNameMaxLength; | ||
| Span<char> buffer = stackalloc char[PackageFamilyNameMaxLength]; | ||
| int result = GetCurrentPackageFamilyNameNative(ref length, buffer); | ||
| if (result is not ErrorSuccess || length is 0) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| // The returned length includes the null terminator, which we don't want in the managed string. | ||
| return new string(buffer[..(int)(length - 1)]); | ||
| } | ||
| catch (Exception exception) when (exception is DllNotFoundException or EntryPointNotFoundException) | ||
| { | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -475,6 +475,27 @@ internal static string GetWindowsPowerShellVersionFromRegistry() | |
|
|
||
| return string.Empty; | ||
| } | ||
|
|
||
| private static string s_packageFamilyName; | ||
| private static bool? s_isMSIXInstallation; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could avoid s_isMSIXInstallation altogether and use s_packageFamilyName as flag:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be used by other code in future, for example the configuration migration that Justin is working on. We don't want to call that API over and over again when it's not running in a MSIX installation.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that maybe Ilya (@iSazonov) is suggesting instead of using
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, sorry I misunderstood the intent :) |
||
|
|
||
| /// <summary> | ||
| /// Determine whether the current process has package (MSIX) identity, caching the result | ||
| /// so the native API is only called once. | ||
| /// </summary> | ||
| /// <param name="packageFamilyName">Receives the package family name when the process has package identity; otherwise null.</param> | ||
| /// <returns>True if the current process has package (MSIX) identity; otherwise false.</returns> | ||
| internal static bool IsMSIXInstallation(out string packageFamilyName) | ||
| { | ||
| if (s_isMSIXInstallation is null) | ||
|
daxian-dbw marked this conversation as resolved.
Resolved
|
||
| { | ||
| s_packageFamilyName = Interop.Windows.GetCurrentPackageFamilyName(); | ||
| s_isMSIXInstallation = s_packageFamilyName is not null; | ||
| } | ||
|
|
||
| packageFamilyName = s_packageFamilyName; | ||
| return s_isMSIXInstallation.Value; | ||
| } | ||
| #endif | ||
|
|
||
| internal static string DefaultPowerShellAppBase => GetApplicationBase(DefaultPowerShellShellID); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not the best naming style:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the name is clear enough and relatively short :)