WinUI 3中使用Process.Start RunAs启动高权限进程卡顿问题求助
我通过以下代码从低权限进程启动高权限C#控制台应用Something.exe时,UAC弹窗确认后,程序陷入卡顿,无任何输出或报错,且CPU占用较高。但右键点击程序选择「以管理员身份运行」则一切正常。
已尝试用Fody.Costura打包依赖DLL、设置WorkingDirectory,问题仍未解决(排除DLL缺失问题)。环境为.NET Core 6 + Windows App SDK 1.2.230217.4,启动代码如下:
Process P = new Process(); P.StartInfo.UseShellExecute = true; P.StartInfo.Verb = "runas"; P.StartInfo.FileName = ApplicationHelper.GetFullPathToExe() + "\Win64\SomeThing.exe"; P.StartInfo.Arguments = msg; P.Start();
可能的原因及解决方法
控制台交互权限隔离
使用UseShellExecute=true+runas启动高权限控制台程序时,低权限父进程的控制台与高权限子进程的控制台存在权限隔离,导致子进程无法正常输出到父进程关联的控制台,进而引发死锁或循环等待,表现为卡顿高CPU。右键管理员运行时,程序直接创建独立的高权限控制台,不存在交互冲突。
解决:显式让子进程创建独立控制台,确保输出不依赖父进程:P.StartInfo.CreateNoWindow = false; // 显式创建新窗口,默认也是false但显式设置更稳妥 P.StartInfo.RedirectStandardOutput = false; // 禁止重定向输出,让子进程使用自身控制台路径拼接的转义错误
代码中用+ "\Win64\SomeThing.exe"拼接路径,C#字符串中\是转义字符,若ApplicationHelper.GetFullPathToExe()返回的路径末尾带反斜杠,会导致路径出现\\Win64,虽然系统通常能兼容,但可能引发启动时的隐性错误,导致进程卡住。
解决:用Path.Combine安全拼接路径,避免转义和格式错误:string targetExe = Path.Combine(ApplicationHelper.GetFullPathToExe(), "Win64", "SomeThing.exe"); P.StartInfo.FileName = targetExe;Windows App SDK的环境上下文异常
Windows App SDK应用的权限上下文、环境变量与普通.NET Core进程存在差异,从WinUI/Windows App SDK进程启动高权限程序时,可能出现环境变量传递不全或权限上下文继承异常,导致目标进程初始化失败,陷入循环。
解决:显式设置子进程的工作目录为自身所在目录,确保依赖加载路径正确:string targetExe = Path.Combine(ApplicationHelper.GetFullPathToExe(), "Win64", "SomeThing.exe"); P.StartInfo.WorkingDirectory = Path.GetDirectoryName(targetExe);同时可以尝试重置子进程的环境变量为系统默认:
P.StartInfo.EnvironmentVariables.Clear(); P.StartInfo.EnvironmentVariables.AddRange(Environment.GetEnvironmentVariables());跨权限进程交互死锁
若Something.exe代码中存在依赖父进程的逻辑(比如读取父进程的管道、共享内存、等待父进程信号),由于权限隔离,高权限子进程无法访问低权限父进程的资源,会进入无限重试的死循环,导致高CPU占用。
解决:检查Something.exe的初始化逻辑,移除对父进程的依赖,改为独立初始化;若需要跨进程通信,使用支持跨权限的机制(比如命名管道设置SECURITY_ATTRIBUTES允许低权限进程访问)。
内容的提问来源于stack exchange,提问作者IShirai_KurokoI

