Elevando o privilégio do processo programaticamente?


147

Estou tentando instalar um serviço usando o InstallUtil.exe, mas invocado Process.Start. Aqui está o código:

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

onde m_strInstallUtilé o caminho completo e exe para "InstallUtil.exe" e strExePathé o caminho / nome completo para o meu serviço.

A execução da sintaxe da linha de comando em um prompt de comando elevado funciona; a execução do meu aplicativo (usando o código acima) não. Suponho que estou lidando com algum problema de elevação de processo, então como eu executaria meu processo em um estado elevado? Preciso olhar ShellExecutepara isso?

Isso é tudo no Windows Vista. Estou executando o processo no depurador VS2008 elevado ao privilégio de administrador.

Eu também tentei configurar, startInfo.Verb = "runas";mas não parecia resolver o problema.


Depois de adicionar startInfo.UseShellExecute = true;, além disso startInfo.Verb = "runas";, funcionou bem para mim.
Matt

Respostas:


172

Você pode indicar que o novo processo deve ser iniciado com permissões elevadas, definindo a propriedade Verb do seu objeto startInfo como 'runas', da seguinte maneira:

startInfo.Verb = "runas";

Isso fará com que o Windows se comporte como se o processo tivesse sido iniciado no Explorer com o comando de menu "Executar como Administrador".

Isso significa que o prompt do UAC será exibido e precisará ser reconhecido pelo usuário: se isso for indesejável (por exemplo, porque isso aconteceria no meio de um processo demorado), você precisará executar todo o processo do host com permissões elevadas por Criar e incorporar um UAC (Manifesto de aplicativo) para exigir o nível de execução 'maximumAvailable': isso fará com que o prompt do UAC apareça assim que o aplicativo for iniciado e fará com que todos os processos filhos sejam executados com permissões elevadas sem aviso adicional .

Editar: vejo que você acabou de editar sua pergunta para declarar que "runas" não funcionaram para você. Isso é realmente estranho, como deveria (e faz por mim em vários aplicativos de produção). Exigir que o processo pai seja executado com direitos elevados incorporando o manifesto definitivamente deve funcionar.


9
"runas" também não funcionou para mim. Pode ser que ele só funcione com o UAC desativado?
Dirk Vollmar

18
@LukePuplett eu agradeceria a eles. É uma ótima maneira de reduzir a instalação do kit raiz, sem realmente segregar completamente as funções do usuário.
Colton

6
@ Sparksis, mas também há outro ponto de vista. As pessoas que sabem como defender seu sistema operacional sabem como fazê-lo sem o UAC. E usuários fictícios, que não sabem o que é defesa, estão clicando em 'SIM' toda vez que vêem a janela do UAC. Também nada pode impedir maus-hackers-Virus-escritores de usar exploits para ignorá-lo;) Então, eu concordo com LukePuplett =)
Jet

24
Parece que você deve definir startInfo.ShellExecute=truetambém para que isso funcione ... também não consegui fazer esse método funcionar com arquivos executáveis ​​que estão em um compartilhamento de rede (é necessário copiá-los para o diretório temporário local antes de executar). ..
TCC

7
@ Jet Desculpe, mas essa é a mentalidade errada. Toda vez que uma caixa de diálogo do UAC é exibida durante a instalação, há uma falha no sistema. O valor é quando você vê uma caixa do UAC sem executar algo que exija elevação. Não importa o quão profissional você - qualquer um de nós - pense que estamos em nossos PCs, você não pode bloquear magicamente zero dias / downloads drive-by (por exemplo, um recente no site oficial do Prêmio Nobel). Se você navegasse até esse site e recebesse um prompt do UAC, saberia que havia algo errado. Com o UAC desativado, você nunca saberia que acabou de ingressar em uma botnet. O custo do aviso prévio é ter que clicar em Sim ocasionalmente
Básico

46

Este código reúne tudo isso e reinicia o aplicativo wpf atual com admin privs:

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)

Atualização: a maneira de manifesto do aplicativo é preferida:

Clique com o botão direito do mouse no projeto no visual studio, adicione um novo arquivo de manifesto do aplicativo, altere o arquivo para que você exija o administrador definido como mostrado acima.

Um problema com a maneira original: se você colocar o código de reinicialização no app.xaml.cs OnStartup, ele ainda poderá iniciar a janela principal brevemente, mesmo que o desligamento tenha sido chamado. Minha janela principal explodiu se init app.xaml.cs não foi executado e, em determinadas condições de corrida, ele faria isso.


Veja abaixo as melhorias.
precisa saber é o seguinte

requireAdministrator não funcionou no meu caso. Então eu tive que fazer do seu jeito. Isso resolveu meu problema! obrigado. Mas eu tive que definir o aplicativo de instância única como false.
Chris19 /

Isso funcionou para mim. Também passei o original string[] argspara o processo reaparecido.
DotNetPadawan


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

Isso será feito sem o UAC - não é necessário iniciar um novo processo. Se o usuário em execução for membro do grupo Admin, como no meu caso.


3
Usando este código, recebo um erro de permissão: "Falha na solicitação de permissão da entidade de segurança". :(
Leonardo

Talvez "Se o usuário em execução for membro do Admin" *
hB0

1
interessante - isso pode ir em qualquer método, não apenas um método de ação (Eu até tentei no método definido em uma página ASPX)
Simon_Weaver

1

Você deve usar a representação para elevar o estado.

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

Não se esqueça de desfazer o contexto representado quando terminar.


28
Você não disse como obter o accessToken. O LogonUser fornecerá o contexto de segurança restrito de um usuário quando o UAC estiver ativado.
cwa 30/03

Se você estiver usando o VSTS, poderá obter um token de acesso pessoal nas configurações do portal da web. (Procure o ícone de configurações ao lado da imagem do usuário.) MSDocs
Su Llewellyn
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.