diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
index e551a7dcb..cd1cc051c 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
@@ -97,5 +97,7 @@
Successfully disabled this program from displaying in your query
This app is not intended to be run as administrator
Unable to run {0}
+ User Account Control
+ Do you want to allow this app to make changes to your device?
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index d28845994..f220190e2 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
@@ -32,6 +33,8 @@ namespace Flow.Launcher.Plugin.Program
internal static PluginInitContext Context { get; private set; }
+ internal static bool IsAdmin = IsAdministrator();
+
private static readonly List emptyResults = new();
private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 };
@@ -459,5 +462,12 @@ namespace Flow.Launcher.Plugin.Program
{
Win32.Dispose();
}
+
+ private static bool IsAdministrator()
+ {
+ using var identity = WindowsIdentity.GetCurrent();
+ var principal = new WindowsPrincipal(identity);
+ return principal.IsInRole(WindowsBuiltInRole.Administrator);
+ }
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs
index cb33250e1..182f3fed5 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs
@@ -4,17 +4,17 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Principal;
+using System.Threading.Channels;
using System.Threading.Tasks;
+using System.Windows.Input;
using System.Windows.Media.Imaging;
-using Windows.ApplicationModel;
-using Windows.Management.Deployment;
+using System.Xml;
using Flow.Launcher.Plugin.Program.Logger;
using Flow.Launcher.Plugin.SharedModels;
-using System.Threading.Channels;
-using System.Xml;
-using Windows.ApplicationModel.Core;
-using System.Windows.Input;
using MemoryPack;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Core;
+using Windows.Management.Deployment;
namespace Flow.Launcher.Plugin.Program.Programs
{
@@ -454,7 +454,9 @@ namespace Flow.Launcher.Plugin.Program.Programs
bool elevated = e.SpecialKeyState.ToModifierKeys() == (ModifierKeys.Control | ModifierKeys.Shift);
bool shouldRunElevated = elevated && CanRunElevated;
- _ = Task.Run(() => Launch(shouldRunElevated)).ConfigureAwait(false);
+
+ Launch(shouldRunElevated);
+
if (elevated && !shouldRunElevated)
{
var title = api.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_error");
@@ -497,7 +499,8 @@ namespace Flow.Launcher.Plugin.Program.Programs
Title = api.GetTranslation("flowlauncher_plugin_program_run_as_administrator"),
Action = c =>
{
- _ = Task.Run(() => Launch(true)).ConfigureAwait(false);
+ Launch(true);
+
return true;
},
IcoPath = "Images/cmd.png",
@@ -510,12 +513,17 @@ namespace Flow.Launcher.Plugin.Program.Programs
private void Launch(bool elevated = false)
{
- string command = "shell:AppsFolder\\" + UserModelId;
+ var command = "shell:AppsFolder\\" + UserModelId;
command = Environment.ExpandEnvironmentVariables(command.Trim());
- var info = new ProcessStartInfo(command) { UseShellExecute = true, Verb = elevated ? "runas" : "" };
+ var info = new ProcessStartInfo()
+ {
+ FileName = command,
+ UseShellExecute = true,
+ Verb = elevated ? "runas" : ""
+ };
- Main.StartProcess(Process.Start, info);
+ _ = Task.Run(() => Main.StartProcess(Process.Start, info)).ConfigureAwait(false);
}
internal static bool IfAppCanRunElevated(XmlNode appNode)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
index a87b002d4..3dd7ec012 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
@@ -1,21 +1,22 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
+using System.Threading.Channels;
using System.Threading.Tasks;
-using Microsoft.Win32;
+using System.Windows;
+using System.Windows.Input;
using Flow.Launcher.Plugin.Program.Logger;
+using Flow.Launcher.Plugin.Program.Views.Models;
using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Plugin.SharedModels;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Threading.Channels;
-using Flow.Launcher.Plugin.Program.Views.Models;
using IniParser;
-using System.Windows.Input;
using MemoryPack;
+using Microsoft.Win32;
namespace Flow.Launcher.Plugin.Program.Programs
{
@@ -196,15 +197,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
// Ctrl + Shift + Enter to run as admin
bool runAsAdmin = c.SpecialKeyState.ToModifierKeys() == (ModifierKeys.Control | ModifierKeys.Shift);
- var info = new ProcessStartInfo
- {
- FileName = FullPath,
- WorkingDirectory = ParentDirectory,
- UseShellExecute = true,
- Verb = runAsAdmin ? "runas" : "",
- };
-
- _ = Task.Run(() => Main.StartProcess(Process.Start, info));
+ Launch(runAsAdmin);
return true;
}
@@ -213,6 +206,44 @@ namespace Flow.Launcher.Plugin.Program.Programs
return result;
}
+ private void Launch(bool elevated = false)
+ {
+ var info = new ProcessStartInfo
+ {
+ FileName = FullPath,
+ WorkingDirectory = ParentDirectory,
+ UseShellExecute = true,
+ Verb = elevated ? "runas" : "",
+ };
+
+ if (Main.IsAdmin)
+ {
+ if (elevated)
+ {
+ // Since we are already elevated, we need to create UAC dialog manually
+ if (Main.Context.API.ShowMsgBox(
+ Main.Context.API.GetTranslation("flowlauncher_plugin_program_user_account_control_subtitle"),
+ Main.Context.API.GetTranslation("flowlauncher_plugin_program_user_account_control_title"),
+ MessageBoxButton.YesNo) != MessageBoxResult.Yes)
+ {
+ return;
+ }
+ }
+ else
+ {
+ // Use explorer.exe as workaround to start process as standard user
+ info = new ProcessStartInfo
+ {
+ FileName = "explorer.exe",
+ Arguments = $"\"{FullPath}\"",
+ WorkingDirectory = ParentDirectory,
+ UseShellExecute = true,
+ };
+ }
+ }
+
+ _ = Task.Run(() => Main.StartProcess(Process.Start, info)).ConfigureAwait(false); ;
+ }
public List ContextMenus(IPublicAPI api)
{
@@ -228,7 +259,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
FileName = FullPath, WorkingDirectory = ParentDirectory, UseShellExecute = true
};
- _ = Task.Run(() => Main.StartProcess(ShellCommand.RunAsDifferentUser, info));
+ _ = Task.Run(() => Main.StartProcess(ShellCommand.RunAsDifferentUser, info)).ConfigureAwait(false);;
return true;
},
@@ -240,15 +271,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
Title = api.GetTranslation("flowlauncher_plugin_program_run_as_administrator"),
Action = c =>
{
- var info = new ProcessStartInfo
- {
- FileName = FullPath,
- WorkingDirectory = ParentDirectory,
- Verb = "runas",
- UseShellExecute = true
- };
-
- _ = Task.Run(() => Main.StartProcess(Process.Start, info));
+ Launch(true);
return true;
},