以编程方式提升进程权限?

问题描述 投票:0回答:7

我正在尝试使用 InstallUtil.exe 安装服务,但通过

Process.Start
调用。这是代码:

ProcessStartInfo startInfo = new ProcessStartInfo (m_strInstallUtil, strExePath);
System.Diagnostics.Process.Start (startInfo);

其中

m_strInstallUtil
是“InstallUtil.exe”的完全限定路径和 exe,
strExePath
是我服务的完全限定路径/名称。

从提升的命令提示符运行命令行语法是可行的;从我的应用程序运行(使用上面的代码)没有。我假设我正在处理一些流程提升问题,那么我将如何在提升状态下运行我的流程?我需要为此看

ShellExecute
吗?

这都是在 Windows Vista 上进行的。我在提升为管理员权限的 VS2008 调试器中运行该进程。

我也试过设置

startInfo.Verb = "runas";
但是好像没有解决问题

c# .net windows windows-services process-elevation
7个回答
194
投票

您可以通过将 startInfo 对象的 Verb 属性设置为“runas”来指示新进程应该以提升的权限启动,如下所示:

startInfo.Verb = "runas";

这将导致 Windows 的行为就好像进程是从资源管理器中使用“以管理员身份运行”菜单命令启动的一样。

这确实意味着 UAC 提示将出现并且需要用户确认:如果这是不可取的(例如因为它会在一个漫长的过程中发生),您将需要运行整个主机进程通过 Create and Embed an Application Manifest (UAC) 提升权限以要求“highestAvailable”执行级别:这将导致 UAC 提示在您的应用程序启动后立即出现,并导致所有子进程以提升的权限运行无需额外提示。

编辑:我看到您刚刚编辑了您的问题以说明“runas”对您不起作用。这真的很奇怪,因为它应该(并且在几个生产应用程序中对我来说确实如此)。不过,通过嵌入清单要求父进程以提升的权限运行应该绝对有效。


56
投票

此代码将以上所有内容放在一起,并使用管理员权限重新启动当前的 wpf 应用程序:

if (IsAdministrator() == false)
{
    // Restart program and run as admin
    var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
    ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
    Application.Current.Shutdown();
    return;
}

private static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}


// To run as admin, alter exe manifest file after building.
// Or create shortcut with "as admin" checked.
// Or ShellExecute(C# Process.Start) can elevate - use verb "runas".
// Or an elevate vbs script can launch programs as admin.
// (does not work: "runas /user:admin" from cmd-line prompts for admin pass)

更新:首选应用清单方式:

在 visual studio 中右键单击项目,添加,新的应用程序清单文件,更改文件,以便您具有如上所示的 requireAdministrator 设置。

原方法的一个问题:如果将重启代码放在app.xaml.cs OnStartup中,即使调用了Shutdown,它仍然可能短暂地启动主窗口。如果 app.xaml.cs init 没有运行,我的主窗口就会爆炸,在某些竞争条件下它会这样做。


23
投票

根据文章 Chris Corio:教您的应用程序使用 Windows Vista 用户帐户控制很好地运行,MSDN 杂志,2007 年 1 月,只有

ShellExecute
检查嵌入式清单并在需要时提示用户提升,而
CreateProcess
而其他 API 则没有。希望对您有所帮助。

另请参阅:与 .chm 相同的文章.


8
投票
[PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]

这将在没有 UAC 的情况下完成 - 无需启动新进程。对于我的情况,如果运行用户是管理员组的成员。


3
投票

我知道这是一篇很老的帖子,但我只是想分享我的解决方案:

System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo
{
    UseShellExecute = true, //<- for elevation
    Verb = "runas",  //<- for elevation
    WorkingDirectory = Environment.CurrentDirectory,
    FileName = "EDHM_UI_Patcher.exe",
    Arguments = @"\D -FF"
};
System.Diagnostics.Process p = System.Diagnostics.Process.Start(StartInfo);

注意: 如果 VisualStudio 已经在运行 Elevated,那么 UAC 对话框将不会显示,要测试它,请运行 bin 文件夹中的 exe。


2
投票

你应该使用模拟来提升状态。

WindowsIdentity identity = new WindowsIdentity(accessToken);
WindowsImpersonationContext context = identity.Impersonate();

完成后不要忘记撤消模拟上下文。


0
投票

有另一种方法可以启动需要提升的进程,而不必使用窗口

Task Scheduler
在父进程中进行提升。基本上你创建一个任务并在
Run with highest privileges
选项卡中检查
General
。可以使用 Windows API 或 nuget 库以编程方式运行该任务。甚至可以动态创建这样的任务,运行它并再次删除它。

使用 TaskScheduler 库在代码中创建任务如下所示:

TaskDefinition td = ts.NewTask();
td.Principal.RunLevel = TaskRunLevel.Highest; // <-- for elevation
// Set trigger and action and other properties...
ts.RootFolder.RegisterTaskDefinition("Test", td);
© www.soinside.com 2019 - 2024. All rights reserved.