Skip to content
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

Fix: Fixed an issue were installing a font would freeze the app #13125

Merged
Merged
5 changes: 1 addition & 4 deletions src/Files.App/Actions/Content/Install/InstallFontAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ public InstallFontAction()

public Task ExecuteAsync()
{
foreach (ListedItem selectedItem in context.SelectedItems)
Win32API.InstallFont(selectedItem.ItemPath, false);

return Task.CompletedTask;
return Task.WhenAll(context.SelectedItems.Select(x => Win32API.InstallFont(x.ItemPath, false)));
}

public void Context_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
Expand Down
4 changes: 1 addition & 3 deletions src/Files.App/Actions/Content/Run/RunWithPowershellAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ public RunWithPowershellAction()

public Task ExecuteAsync()
{
Win32API.RunPowershellCommand($"{context.ShellPage?.SlimContentPage?.SelectedItem.ItemPath}", false);

return Task.CompletedTask;
return Win32API.RunPowershellCommandAsync($"{context.ShellPage?.SlimContentPage?.SelectedItem.ItemPath}", false);
}

private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
Expand Down
4 changes: 1 addition & 3 deletions src/Files.App/Actions/FileSystem/FormatDriveAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ public FormatDriveAction()

public Task ExecuteAsync()
{
Win32API.OpenFormatDriveDialog(context.Folder?.ItemPath ?? string.Empty);

return Task.CompletedTask;
return Win32API.OpenFormatDriveDialog(context.Folder?.ItemPath ?? string.Empty);
}

public void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
Expand Down
4 changes: 1 addition & 3 deletions src/Files.App/Actions/Open/OpenInVSAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ public OpenInVSAction()

public Task ExecuteAsync()
{
Win32API.RunPowershellCommand($"start \'{_context.SolutionFilePath}\'", false);

return Task.CompletedTask;
return Win32API.RunPowershellCommandAsync($"start \'{_context.SolutionFilePath}\'", false);
}

private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
Expand Down
4 changes: 1 addition & 3 deletions src/Files.App/Actions/Open/OpenInVSCodeAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ public OpenInVSCodeAction()

public Task ExecuteAsync()
{
Win32API.RunPowershellCommand($"code \'{_context.ShellPage?.FilesystemViewModel.WorkingDirectory}\'", false);

return Task.CompletedTask;
return Win32API.RunPowershellCommandAsync($"code \'{_context.ShellPage?.FilesystemViewModel.WorkingDirectory}\'", false);
}

private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
Expand Down
8 changes: 4 additions & 4 deletions src/Files.App/Helpers/MenuFlyout/ShellContextMenuHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,25 +194,25 @@ async Task InvokeShellMenuItem(ContextMenu contextMenu, object? tag)
case "install" when isFont:
{
foreach (string path in contextMenu.ItemsPath)
Win32API.InstallFont(path, false);
await Win32API.InstallFont(path, false);
}
break;

case "installAllUsers" when isFont:
{
foreach (string path in contextMenu.ItemsPath)
Win32API.InstallFont(path, true);
await Win32API.InstallFont(path, true);
}
break;

case "mount":
var vhdPath = contextMenu.ItemsPath[0];
Win32API.MountVhdDisk(vhdPath);
await Win32API.MountVhdDisk(vhdPath);
break;

case "format":
var drivePath = contextMenu.ItemsPath[0];
Win32API.OpenFormatDriveDialog(drivePath);
await Win32API.OpenFormatDriveDialog(drivePath);
break;

default:
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Utils/Shell/LaunchHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private static async Task<bool> HandleApplicationLaunch(string application, stri
if (FileExtensionHelpers.IsVhdFile(application))
{
// Use PowerShell to mount Vhd Disk as this requires admin rights
return Win32API.MountVhdDisk(application);
return await Win32API.MountVhdDisk(application);
}

try
Expand Down
72 changes: 49 additions & 23 deletions src/Files.App/Utils/Shell/Win32API.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,22 +370,35 @@ public static (byte[]? icon, byte[]? overlay) GetFileIconAndOverlay(string path,
}
}

public static bool RunPowershellCommand(string command, bool runAsAdmin)
public static async Task<bool> RunPowershellCommandAsync(string command, bool runAsAdmin)
{
using Process process = CreatePowershellProcess(command, runAsAdmin);
using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(30 * 1000));

process.Start();

try
{
using Process process = new Process();
await process.WaitForExitAsync(cts.Token);
return process.ExitCode == 0;
}
catch (OperationCanceledException)
{
return false;
}
catch (Win32Exception)
{
// If user cancels UAC
return false;
}
}

if (runAsAdmin)
{
process.StartInfo.UseShellExecute = true;
process.StartInfo.Verb = "runas";
}
public static bool RunPowershellCommand(string command, bool runAsAdmin)
{
try
{
using Process process = CreatePowershellProcess(command, runAsAdmin);

process.StartInfo.FileName = "powershell.exe";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.Arguments = command;
process.Start();

if (process.WaitForExit(30 * 1000))
Expand Down Expand Up @@ -499,16 +512,11 @@ public static bool SetCustomFileIcon(string? filePath, string? iconFile, int ico
return success;
}

public static void UnlockBitlockerDrive(string drive, string password)
{
RunPowershellCommand($"-command \"$SecureString = ConvertTo-SecureString '{password}' -AsPlainText -Force; Unlock-BitLocker -MountPoint '{drive}' -Password $SecureString\"", true);
}

public static void OpenFormatDriveDialog(string drive)
public static Task OpenFormatDriveDialog(string drive)
{
// Format requires elevation
int driveIndex = drive.ToUpperInvariant()[0] - 'A';
RunPowershellCommand($"-command \"$Signature = '[DllImport(\\\"shell32.dll\\\", SetLastError = false)]public static extern uint SHFormatDrive(IntPtr hwnd, uint drive, uint fmtID, uint options);'; $SHFormatDrive = Add-Type -MemberDefinition $Signature -Name \"Win32SHFormatDrive\" -Namespace Win32Functions -PassThru; $SHFormatDrive::SHFormatDrive(0, {driveIndex}, 0xFFFF, 0x0001)\"", true);
return RunPowershellCommandAsync($"-command \"$Signature = '[DllImport(\\\"shell32.dll\\\", SetLastError = false)]public static extern uint SHFormatDrive(IntPtr hwnd, uint drive, uint fmtID, uint options);'; $SHFormatDrive = Add-Type -MemberDefinition $Signature -Name \"Win32SHFormatDrive\" -Namespace Win32Functions -PassThru; $SHFormatDrive::SHFormatDrive(0, {driveIndex}, 0xFFFF, 0x0001)\"", true);
}

public static void SetVolumeLabel(string drivePath, string newLabel)
Expand All @@ -522,10 +530,10 @@ public static void SetNetworkDriveLabel(string driveName, string newLabel)
RunPowershellCommand($"-command \"(New-Object -ComObject Shell.Application).NameSpace('{driveName}').Self.Name='{newLabel}'\"", false);
}

public static bool MountVhdDisk(string vhdPath)
public static Task<bool> MountVhdDisk(string vhdPath)
{
// Mounting requires elevation
return RunPowershellCommand($"-command \"Mount-DiskImage -ImagePath '{vhdPath}'\"", true);
return RunPowershellCommandAsync($"-command \"Mount-DiskImage -ImagePath '{vhdPath}'\"", true);
}

public static Bitmap? GetBitmapFromHBitmap(HBITMAP hBitmap)
Expand Down Expand Up @@ -805,19 +813,37 @@ public static async Task<bool> InstallInf(string filePath)
}
}

public static void InstallFont(string fontFilePath, bool forAllUsers)
public static Task InstallFont(string fontFilePath, bool forAllUsers)
{
string fontDirectory = forAllUsers
? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Fonts")
: Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "Windows", "Fonts");

string registryKey = forAllUsers
string registryKey = forAllUsers
? "HKLM:\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
: "HKCU:\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";

var destinationPath = Path.Combine(fontDirectory, Path.GetFileName(fontFilePath));

RunPowershellCommand($"-command \"Copy-Item '{fontFilePath}' '{fontDirectory}'; New-ItemProperty -Name '{Path.GetFileNameWithoutExtension(fontFilePath)}' -Path '{registryKey}' -PropertyType string -Value '{destinationPath}'\"", forAllUsers);
return RunPowershellCommandAsync($"-command \"Copy-Item '{fontFilePath}' '{fontDirectory}'; New-ItemProperty -Name '{Path.GetFileNameWithoutExtension(fontFilePath)}' -Path '{registryKey}' -PropertyType string -Value '{destinationPath}'\"", forAllUsers);
}

private static Process CreatePowershellProcess(string command, bool runAsAdmin)
{
Process process = new();

if (runAsAdmin)
{
process.StartInfo.UseShellExecute = true;
process.StartInfo.Verb = "runas";
}

process.StartInfo.FileName = "powershell.exe";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.Arguments = command;

return process;
}
}
}
4 changes: 2 additions & 2 deletions src/Files.App/ViewModels/Settings/AdvancedViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private async Task SetAsDefaultExplorer()
var dataPath = Environment.ExpandEnvironmentVariables("%LocalAppData%\\Files");
if (IsSetAsDefaultFileManager)
{
if (!Win32API.RunPowershellCommand($"-command \"New-Item -Force -Path '{dataPath}' -ItemType Directory; Copy-Item -Filter *.* -Path '{destFolder}\\*' -Recurse -Force -Destination '{dataPath}'\"", false))
if (!await Win32API.RunPowershellCommandAsync($"-command \"New-Item -Force -Path '{dataPath}' -ItemType Directory; Copy-Item -Filter *.* -Path '{destFolder}\\*' -Recurse -Force -Destination '{dataPath}'\"", false))
{
// Error copying files
await DetectResult();
Expand All @@ -87,7 +87,7 @@ private async Task SetAsDefaultExplorer()
}
else
{
Win32API.RunPowershellCommand($"-command \"Remove-Item -Path '{dataPath}' -Recurse -Force\"", false);
await Win32API.RunPowershellCommandAsync($"-command \"Remove-Item -Path '{dataPath}' -Recurse -Force\"", false);
}

try
Expand Down