|
|
@@ -1,4 +1,7 @@
|
|
|
using System.Collections.ObjectModel;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
+using System.Security.Principal;
|
|
|
using PicView.Core.FileHandling;
|
|
|
using PicView.Core.Localization;
|
|
|
|
|
|
@@ -85,25 +88,71 @@ public static class FileTypeHelper
|
|
|
return groups;
|
|
|
}
|
|
|
|
|
|
- public static async Task SetFileAssociations(ReadOnlyObservableCollection<FileTypeGroup> groups)
|
|
|
+
|
|
|
+ public static async Task<bool> SetFileAssociations(ReadOnlyObservableCollection<FileTypeGroup> groups)
|
|
|
{
|
|
|
- foreach (var group in groups)
|
|
|
+ try
|
|
|
{
|
|
|
- foreach (var fileType in group.FileTypes)
|
|
|
+ // If we're on Windows, check for admin permissions
|
|
|
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !IsAdministrator())
|
|
|
{
|
|
|
- foreach (var extension in fileType.Extensions)
|
|
|
+ // Build list of extensions to associate
|
|
|
+ var extensionsToAssociate = new List<string>();
|
|
|
+
|
|
|
+ foreach (var group in groups)
|
|
|
{
|
|
|
- // Make sure to properly handle extensions that contain commas
|
|
|
- var individualExtensions = extension.Split([',', ' '], StringSplitOptions.RemoveEmptyEntries);
|
|
|
-
|
|
|
- foreach (var ext in individualExtensions)
|
|
|
+ foreach (var fileType in group.FileTypes)
|
|
|
{
|
|
|
- var cleanExt = ext.Trim();
|
|
|
- if (!cleanExt.StartsWith('.'))
|
|
|
- cleanExt = "." + cleanExt;
|
|
|
+ if (!fileType.IsSelected.HasValue || !fileType.IsSelected.Value)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ foreach (var extension in fileType.Extensions)
|
|
|
+ {
|
|
|
+ // Make sure to properly handle extensions that contain commas
|
|
|
+ var individualExtensions = extension.Split([',', ' '], StringSplitOptions.RemoveEmptyEntries);
|
|
|
+
|
|
|
+ foreach (var ext in individualExtensions)
|
|
|
+ {
|
|
|
+ var cleanExt = ext.Trim();
|
|
|
+ if (!cleanExt.StartsWith('.'))
|
|
|
+ cleanExt = "." + cleanExt;
|
|
|
+
|
|
|
+ extensionsToAssociate.Add(cleanExt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (extensionsToAssociate.Count > 0)
|
|
|
+ {
|
|
|
+ // Create command arguments - keep argument string shorter to avoid issues
|
|
|
+ string associateArg = "associate:" + string.Join(",", extensionsToAssociate);
|
|
|
+
|
|
|
+ // Start new process with elevated permissions
|
|
|
+ return StartProcessWithElevatedPermission(associateArg);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true; // Nothing to do
|
|
|
+ }
|
|
|
|
|
|
- if (fileType.IsSelected.HasValue)
|
|
|
+ // Standard processing path (non-Windows or already has admin rights)
|
|
|
+ foreach (var group in groups)
|
|
|
+ {
|
|
|
+ foreach (var fileType in group.FileTypes)
|
|
|
+ {
|
|
|
+ if (!fileType.IsSelected.HasValue)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ foreach (var extension in fileType.Extensions)
|
|
|
+ {
|
|
|
+ var individualExtensions = extension.Split([',', ' '], StringSplitOptions.RemoveEmptyEntries);
|
|
|
+
|
|
|
+ foreach (var ext in individualExtensions)
|
|
|
{
|
|
|
+ var cleanExt = ext.Trim();
|
|
|
+ if (!cleanExt.StartsWith('.'))
|
|
|
+ cleanExt = "." + cleanExt;
|
|
|
+
|
|
|
if (fileType.IsSelected.Value)
|
|
|
await FileAssociationManager.AssociateFile(cleanExt);
|
|
|
else
|
|
|
@@ -112,6 +161,75 @@ public static class FileTypeHelper
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ // Log the exception or handle it appropriately
|
|
|
+ Debug.WriteLine($"Error in SetFileAssociations: {ex}");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool IsAdministrator()
|
|
|
+ {
|
|
|
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ // Check if running as administrator
|
|
|
+ using var identity = WindowsIdentity.GetCurrent();
|
|
|
+ var principal = new WindowsPrincipal(identity);
|
|
|
+ return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool StartProcessWithElevatedPermission(string arguments)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var startInfo = new ProcessStartInfo
|
|
|
+ {
|
|
|
+ FileName = Process.GetCurrentProcess().MainModule?.FileName,
|
|
|
+ Arguments = arguments,
|
|
|
+ UseShellExecute = true,
|
|
|
+ Verb = "runas" // This requests elevated permissions
|
|
|
+ };
|
|
|
+
|
|
|
+ Process.Start(startInfo);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ // User declined the UAC prompt or other error
|
|
|
+ Debug.WriteLine($"Failed to start elevated process: {ex.Message}");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static async Task ProcessFileAssociationArguments(string arg)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (arg.StartsWith("associate:", StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ string extensionsString = arg["associate:".Length..];
|
|
|
+ if (string.IsNullOrWhiteSpace(extensionsString))
|
|
|
+ return;
|
|
|
+
|
|
|
+ var extensions = extensionsString
|
|
|
+ .Split(',', StringSplitOptions.RemoveEmptyEntries)
|
|
|
+ .Select(ext => ext.Trim())
|
|
|
+ .ToArray();
|
|
|
+
|
|
|
+ foreach (var extension in extensions)
|
|
|
+ {
|
|
|
+ await FileAssociationManager.AssociateFile(extension);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Debug.WriteLine($"Error processing file association arguments: {ex}");
|
|
|
}
|
|
|
}
|
|
|
}
|