diff --git a/BedrockLauncher.Core/BedrockCore.cs b/BedrockLauncher.Core/BedrockCore.cs
index 902294e..e62e9e6 100644
--- a/BedrockLauncher.Core/BedrockCore.cs
+++ b/BedrockLauncher.Core/BedrockCore.cs
@@ -230,7 +230,8 @@ await ZipExtractor.ExtractWithProgressAsync(options.FileFullPath, options.Instal
config.PackagePath = Path.Combine(options.InstallDstFolder, "AppxManifest.xml");
config.CancellationToken = options.CancellationToken.GetValueOrDefault();
config.Timeout = new TimeSpan(0, 3, 0);
- config.DeploymentOptions = is_installed ? DeploymentOptions.DevelopmentMode | DeploymentOptions.ForceUpdateFromAnyVersion
+ config.DeploymentOptions = is_installed
+ ? DeploymentOptions.DevelopmentMode | DeploymentOptions.ForceUpdateFromAnyVersion
: DeploymentOptions.DevelopmentMode;
config.ProgressCallback = options.DeployProgress;
diff --git a/BedrockLauncher.Core/BedrockLauncher.Core.csproj b/BedrockLauncher.Core/BedrockLauncher.Core.csproj
index c188aa9..4a7bcc7 100644
--- a/BedrockLauncher.Core/BedrockLauncher.Core.csproj
+++ b/BedrockLauncher.Core/BedrockLauncher.Core.csproj
@@ -20,7 +20,7 @@
true
- 2.0.4.1-dev
+ 2.0.4.2
diff --git a/BedrockLauncher.Core/UwpRegister/UwpRegister.cs b/BedrockLauncher.Core/UwpRegister/UwpRegister.cs
index 648abfd..910e2af 100644
--- a/BedrockLauncher.Core/UwpRegister/UwpRegister.cs
+++ b/BedrockLauncher.Core/UwpRegister/UwpRegister.cs
@@ -1,137 +1,187 @@
+using System;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Management.Deployment;
-namespace BedrockLauncher.Core.UwpRegister;
-
-public class DeploymentOptionsConfig
-{
- ///
- /// Gets or sets the file system path to the package.
- ///
- public string PackagePath { get; set; } = string.Empty;
-
- ///
- /// Gets or sets the options used to configure deployment behavior.
- ///
- public DeploymentOptions DeploymentOptions { get; set; }
-
- ///
- /// Gets or sets the cancellation token that is used to observe cancellation requests for the associated operation.
- ///
- ///
- /// Assign a cancellation token to enable cooperative cancellation of the operation. If no token is
- /// provided, the operation cannot be cancelled through this property.
- ///
- public CancellationToken CancellationToken { get; set; } = default;
-
- ///
- /// Progress callback
- ///
- public IProgress? ProgressCallback { get; set; }
-
- ///
- /// Gets or sets the maximum duration to wait before the operation times out.
- ///
- public TimeSpan? Timeout { get; set; }
-}
-
-public class UwpRegister
+namespace BedrockLauncher.Core.UwpRegister
{
- ///
- /// Registers an appx package with flexible configuration
- ///
- /// Deployment configuration options
- /// Deployment result containing operation status
- [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(PackageManager))]
- public static async Task RegisterAppxAsync(DeploymentOptionsConfig config)
- {
- ValidateConfig(config);
- var manager = new PackageManager();
- var asyncOperation = manager.RegisterPackageAsync(
- new Uri(config.PackagePath),
- null,
- config.DeploymentOptions | DeploymentOptions.DevelopmentMode);
-
- return await ExecuteWithTimeout(asyncOperation, config);
- }
-
- ///
- /// Adds a framework appx package with flexible configuration
- ///
- /// Deployment configuration options
- /// Deployment result containing operation status
- [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(PackageManager))]
- public static async Task AddAppxAsync(DeploymentOptionsConfig config)
- {
- ValidateConfig(config);
-
- var packageManager = new PackageManager();
- var asyncOperation = packageManager.AddPackageAsync(
- new Uri(config.PackagePath),
- null,
- config.DeploymentOptions);
-
- return await ExecuteWithTimeout(asyncOperation, config);
- }
-
- private static async Task ExecuteWithTimeout(
- IAsyncOperationWithProgress asyncOperation,
- DeploymentOptionsConfig config)
- {
- if (config.Timeout.HasValue)
- {
- using var timeoutCts = new CancellationTokenSource(config.Timeout.Value);
- using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
- config.CancellationToken, timeoutCts.Token);
-
- return await asyncOperation.AsTask(linkedCts.Token, config.ProgressCallback);
- }
-
- return await asyncOperation.AsTask(config.CancellationToken, config.ProgressCallback);
- }
- public static bool CheckForPackageVersion(string packageName, string version)
- {
- PackageManager packageManager = new PackageManager();
-
- foreach (var package in packageManager.FindPackages())
- {
- if (package.Id.Name == packageName)
- {
- var currentVersion = $"{package.Id.Version.Major}.{package.Id.Version.Minor}.{package.Id.Version.Build}.{package.Id.Version.Revision}";
-
- if (currentVersion == version)
- {
- return true;
- }
- }
- }
-
- return false;
- }
- public static bool IsPackageInstalled(string packageName)
- {
- if (string.IsNullOrWhiteSpace(packageName))
- throw new ArgumentException("Package name cannot be null or empty", nameof(packageName));
-
- PackageManager packageManager = new PackageManager();
-
- foreach (var package in packageManager.FindPackages())
- {
- if (package.Id.Name.Equals(packageName, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- }
-
- return false;
- }
- private static void ValidateConfig(DeploymentOptionsConfig config)
- {
- if (string.IsNullOrWhiteSpace(config.PackagePath))
- throw new ArgumentException("Package path cannot be null or empty", nameof(config));
-
- if (!Uri.TryCreate(config.PackagePath, UriKind.Absolute, out _))
- throw new ArgumentException("Package path must be a valid absolute URI", nameof(config));
- }
+ public class DeploymentOptionsConfig
+ {
+ ///
+ /// Gets or sets the file system path to the package.
+ ///
+ public string PackagePath { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the options used to configure deployment behavior.
+ ///
+ public DeploymentOptions DeploymentOptions { get; set; }
+
+ ///
+ /// Gets or sets the cancellation token that is used to observe cancellation requests for the associated operation.
+ ///
+ ///
+ /// Assign a cancellation token to enable cooperative cancellation of the operation. If no token is
+ /// provided, the operation cannot be cancelled through this property.
+ ///
+ public CancellationToken CancellationToken { get; set; } = default;
+
+ ///
+ /// Progress callback
+ ///
+ public IProgress? ProgressCallback { get; set; }
+
+ ///
+ /// Gets or sets the maximum duration to wait before the operation times out.
+ ///
+ public TimeSpan? Timeout { get; set; }
+ }
+
+ public class UwpRegister
+ {
+ ///
+ /// Registers an appx package with flexible configuration (no admin required)
+ ///
+ /// Deployment configuration options
+ /// Deployment result containing operation status
+ [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(PackageManager))]
+ public static async Task RegisterAppxAsync(DeploymentOptionsConfig config)
+ {
+ ValidateConfig(config);
+
+ // 处理包路径,确保是文件夹路径
+ string packageFolderPath = config.PackagePath;
+ if (packageFolderPath.StartsWith("file://"))
+ {
+ packageFolderPath = new Uri(packageFolderPath).LocalPath;
+ }
+
+ // 移除签名文件(如果存在)
+ RemoveSignatureFile(packageFolderPath);
+
+ var manager = new PackageManager();
+ var asyncOperation = manager.RegisterPackageAsync(
+ new Uri(config.PackagePath),
+ null,
+ config.DeploymentOptions | DeploymentOptions.DevelopmentMode);
+
+ return await ExecuteWithTimeout(asyncOperation, config);
+ }
+
+ ///
+ /// Adds a framework appx package with flexible configuration
+ ///
+ /// Deployment configuration options
+ /// Deployment result containing operation status
+ [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(PackageManager))]
+ public static async Task AddAppxAsync(DeploymentOptionsConfig config)
+ {
+ ValidateConfig(config);
+
+ // 处理包路径,确保是文件夹路径
+ string packageFolderPath = config.PackagePath;
+ if (packageFolderPath.StartsWith("file://"))
+ {
+ packageFolderPath = new Uri(packageFolderPath).LocalPath;
+ }
+
+ // 移除签名文件(如果存在)
+ RemoveSignatureFile(packageFolderPath);
+
+ var packageManager = new PackageManager();
+ var asyncOperation = packageManager.AddPackageAsync(
+ new Uri(config.PackagePath),
+ null,
+ config.DeploymentOptions | DeploymentOptions.DevelopmentMode);
+
+ return await ExecuteWithTimeout(asyncOperation, config);
+ }
+
+ ///
+ /// Removes the signature file from the package folder
+ ///
+ /// Path to the unpacked package folder
+ private static void RemoveSignatureFile(string packageFolderPath)
+ {
+ try
+ {
+ string signaturePath = Path.Combine(packageFolderPath, "AppxSignature.p7x");
+ if (File.Exists(signaturePath))
+ {
+ File.Delete(signaturePath);
+ }
+ }
+ catch (Exception ex)
+ {
+ // 记录错误但继续执行
+ Console.WriteLine($"Error removing signature file: {ex.Message}");
+ }
+ }
+
+ private static async Task ExecuteWithTimeout(
+ IAsyncOperationWithProgress asyncOperation,
+ DeploymentOptionsConfig config)
+ {
+ if (config.Timeout.HasValue)
+ {
+ using var timeoutCts = new CancellationTokenSource(config.Timeout.Value);
+ using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
+ config.CancellationToken, timeoutCts.Token);
+
+ return await asyncOperation.AsTask(linkedCts.Token, config.ProgressCallback);
+ }
+
+ return await asyncOperation.AsTask(config.CancellationToken, config.ProgressCallback);
+ }
+
+ public static bool CheckForPackageVersion(string packageName, string version)
+ {
+ PackageManager packageManager = new PackageManager();
+
+ foreach (var package in packageManager.FindPackages())
+ {
+ if (package.Id.Name == packageName)
+ {
+ var currentVersion = $"{package.Id.Version.Major}.{package.Id.Version.Minor}.{package.Id.Version.Build}.{package.Id.Version.Revision}";
+
+ if (currentVersion == version)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static bool IsPackageInstalled(string packageName)
+ {
+ if (string.IsNullOrWhiteSpace(packageName))
+ throw new ArgumentException("Package name cannot be null or empty", nameof(packageName));
+
+ PackageManager packageManager = new PackageManager();
+
+ foreach (var package in packageManager.FindPackages())
+ {
+ if (package.Id.Name.Equals(packageName, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static void ValidateConfig(DeploymentOptionsConfig config)
+ {
+ if (string.IsNullOrWhiteSpace(config.PackagePath))
+ throw new ArgumentException("Package path cannot be null or empty", nameof(config));
+
+ if (!Uri.TryCreate(config.PackagePath, UriKind.Absolute, out _))
+ throw new ArgumentException("Package path must be a valid absolute URI", nameof(config));
+ }
+ }
}
\ No newline at end of file