Como posso elevar automaticamente meu arquivo em lotes, para que ele solicite direitos de administrador do UAC, se necessário?


209

Quero que meu arquivo em lotes seja executado apenas elevado. Se não for elevado, forneça uma opção para o usuário reiniciar o lote como elevado.

Estou escrevendo um arquivo em lotes para definir uma variável do sistema, copiar dois arquivos para um local de Arquivos de Programas e iniciar um instalador de driver. Se um usuário do Windows 7 / Windows Vista ( UAC ativado e mesmo se for um administrador local) executá-lo sem clicar com o botão direito do mouse e selecionar "Executar como Administrador", ele receberá 'Acesso Negado' copiando os dois arquivos e escrevendo a variável do sistema .

Eu gostaria de usar um comando para reiniciar automaticamente o lote como elevado se o usuário for de fato um administrador. Caso contrário, se eles não forem um administrador, desejo informar que eles precisam de privilégios de administrador para executar o arquivo em lotes. Estou usando o xcopy para copiar os arquivos e o REG ADD para gravar a variável do sistema. Estou usando esses comandos para lidar com possíveis máquinas Windows XP. Encontrei perguntas semelhantes sobre este tópico, mas nada que lida com o reinício de um arquivo em lotes como elevado.


2
Confira o que eu publiquei - você não precisa de nenhuma ferramenta externa, o script verifica automaticamente os direitos de administrador e se auto-eleva, se necessário.
Matt

1
Por favor, considere se a resposta de Matt seria a assinalada? Parece-me isso.
31615 akauppi


Por favor, considere as novas dicas do Windows 10 na seção de comentários do script em lote que eu publiquei.
Matt

4
De cmd: @powershell Start-Process cmd -Verb runas. De Powershell basta cair @powershell. Isso inicia o cmd com direitos elevados.
BrunoLM

Respostas:


20

Você pode fazer com que o script se chame com a opção de psexec-h para executar elevado.

Não tenho certeza de como você detectaria se ele já está funcionando como elevado ou não ... talvez tente novamente com permissões elevadas apenas se houver um erro de Acesso Negado?

Ou você pode simplesmente ter os comandos para xcopye reg.exesempre executar psexec -h, mas seria irritante para o usuário final se eles precisassem inserir sua senha a cada vez (ou inseguro se você incluísse a senha no script) ...


10
Obrigado pela resposta. Infelizmente, acho que não posso usar nada fora do estoque das ferramentas do Windows Vista / 7, porque isso será enviado para clientes fora do meu escritório. Acho que não posso distribuir legalmente o PSExec.
PDixon724

2
Sim, eu acho que você está certo sobre isso - embora PSExec é agora uma ferramenta Microsoft o EULA faz distribuição Forbid :( (desde que eles compraram os caras Sysinternals!)
eWall

2
Eu acho que minhas opções são bastante limitadas. Se soubesse codificar no VB, poderia torná-lo um exe com um manifesto de administrador, mas nem sabia por onde começar. Acho que vou avisar no início do lote para executar como administrador se eles estiverem executando o Windows Vista / 7. Obrigado a todos.
PDixon724

1
Outra ferramenta de terceiros que pode ser livremente redistribuível e fácil de integrar e aprender é o AutoIt ; Esta página demonstra como o script solicita privilégios elevados.
eWall

4
psexec -hnão funciona: 'Não foi possível instalar o serviço PSEXESVC: acesso negado.'. Você já precisa ter os direitos de administrador para executar o psexec.
Nicolas

319

Existe uma maneira fácil, sem a necessidade de usar uma ferramenta externa - ela funciona bem com o Windows 7, 8, 8.1 e 10 e também é compatível com versões anteriores (o Windows XP não possui UAC, portanto, a elevação não é necessária - pois caso o script continue).

Confira este código (fui inspirado pelo código de NIronwolf publicado no tópico Arquivo em Lote - "Acesso Negado" no Windows 7? ), Mas eu o melhorei - na minha versão não há nenhum diretório criado e removido para verifique os privilégios de administrador):

::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
:: see "https://stackoverflow.com/a/12264592/1016343" for description
::::::::::::::::::::::::::::::::::::::::::::
 @echo off
 CLS
 ECHO.
 ECHO =============================
 ECHO Running Admin shell
 ECHO =============================

:init
 setlocal DisableDelayedExpansion
 set cmdInvoke=1
 set winSysFolder=System32
 set "batchPath=%~0"
 for %%k in (%0) do set batchName=%%~nk
 set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
 setlocal EnableDelayedExpansion

:checkPrivileges
  NET FILE 1>NUL 2>NUL
  if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )

:getPrivileges
  if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
  ECHO.
  ECHO **************************************
  ECHO Invoking UAC for Privilege Escalation
  ECHO **************************************

  ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
  ECHO args = "ELEV " >> "%vbsGetPrivileges%"
  ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
  ECHO args = args ^& strArg ^& " "  >> "%vbsGetPrivileges%"
  ECHO Next >> "%vbsGetPrivileges%"

  if '%cmdInvoke%'=='1' goto InvokeCmd 

  ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
  goto ExecElevation

:InvokeCmd
  ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
  ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"

:ExecElevation
 "%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
 exit /B

:gotPrivileges
 setlocal & cd /d %~dp0
 if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul  &  shift /1)

 ::::::::::::::::::::::::::::
 ::START
 ::::::::::::::::::::::::::::
 REM Run shell as admin (example) - put here code as you like
 ECHO %batchName% Arguments: P1=%1 P2=%2 P3=%3 P4=%4 P5=%5 P6=%6 P7=%7 P8=%8 P9=%9
 cmd /k

O script aproveita o fato de NET FILEexigir privilégios de administrador e retorna errorlevel 1se você não o tiver. A elevação é alcançada através da criação de um script que reinicia o arquivo em lotes para obter privilégios. Isso faz com que o Windows apresente a caixa de diálogo do UAC e solicita a conta e a senha do administrador.

Eu testei com o Windows 7, 8, 8.1, 10 e com o Windows XP - funciona bem para todos. A vantagem é que, após o ponto de início, você pode colocar qualquer coisa que exija privilégios de administrador do sistema, por exemplo, se você pretende reinstalar e executar novamente um serviço do Windows para fins de depuração (assumindo que mypackage.msi é um pacote de instalação do serviço) :

msiexec /passive /x mypackage.msi
msiexec /passive /i mypackage.msi
net start myservice

Sem esse script de elevação de privilégio, o UAC solicitaria três vezes seu usuário e senha de administrador - agora você é solicitado apenas uma vez no início e somente se necessário.


Se o seu script precisar apenas mostrar uma mensagem de erro e sair se não houver privilégios de administrador em vez de elevar automaticamente, isso é ainda mais simples: você pode conseguir isso adicionando o seguinte no início do script:

@ECHO OFF & CLS & ECHO.
NET FILE 1>NUL 2>NUL & IF ERRORLEVEL 1 (ECHO You must right-click and select &
  ECHO "RUN AS ADMINISTRATOR"  to run this batch. Exiting... & ECHO. &
  PAUSE & EXIT /D)
REM ... proceed here with admin rights ...

Dessa forma, o usuário deve clicar com o botão direito do mouse e selecionar "Executar como administrador" . O script continuará após a REMinstrução se detectar direitos de administrador, caso contrário, sairá com um erro. Se você não precisar PAUSE, basta removê-lo. Importante: NET FILE [...] EXIT /D) deve estar na mesma linha. É exibido aqui em várias linhas para melhor legibilidade!


Em algumas máquinas, encontrei problemas que já foram resolvidos na nova versão acima. Um foi devido ao tratamento de aspas duplas diferentes, e o outro problema foi devido ao fato de o UAC ter sido desativado (definido no nível mais baixo) em uma máquina com Windows 7; portanto, o script se autodenomina várias vezes.

Corrigi isso agora removendo as aspas no caminho e adicionando-as novamente mais tarde, e adicionei um parâmetro extra que é adicionado quando o script é reiniciado com direitos elevados.

As aspas duplas são removidas pelo seguinte (detalhes estão aqui ):

setlocal DisableDelayedExpansion
set "batchPath=%~0"
setlocal EnableDelayedExpansion

Você pode acessar o caminho usando !batchPath!. Ele não contém aspas duplas, por isso é seguro dizer "!batchPath!"posteriormente no script.

A linha

if '%1'=='ELEV' (shift & goto gotPrivileges)

verifica se o script já foi chamado pelo script VBScript para elevar direitos, evitando recursões sem fim. Ele remove o parâmetro usando shift.


Atualizar:

  • Para evitar ter que registrar a .vbsextensão no Windows 10 , eu ter substituído a linha
    "%temp%\OEgetPrivileges.vbs"
    por
    "%SystemRoot%\System32\WScript.exe" "%temp%\OEgetPrivileges.vbs"
    no script acima; também adicionado cd /d %~dp0como sugerido por Stephen (resposta separada) e por Tomáš Zato (comentário) para definir o diretório de scripts como padrão.

  • Agora, o script honra os parâmetros da linha de comando que estão sendo passados ​​para ele. Obrigado a jxmallet, TanisDLJ e Peter Mortensen pelas observações e inspirações.

  • De acordo com a dica de Artjom B., analisei e substituí SHIFTpor SHIFT /1, que preserva o nome do arquivo para o %0parâmetro

  • Adicionado del "%temp%\OEgetPrivileges_%batchName%.vbs"à :gotPrivilegesseção para limpeza (como mlt sugerido). Adicionado %batchName%para evitar impacto se você executar lotes diferentes em paralelo. Observe que você precisa usar forpara poder tirar proveito das funções avançadas de string, como %%~nk, que extrai apenas o nome do arquivo.

  • Estrutura de script otimizada, melhorias (variável adicionada vbsGetPrivilegesque agora é referenciada em todos os lugares, permitindo alterar facilmente o caminho ou o nome do arquivo, exclua o .vbsarquivo apenas se o lote precisar ser elevado)

  • Em alguns casos, era necessária uma sintaxe de chamada diferente para elevação. Se o script não funcionar, verifique os seguintes parâmetros:
    set cmdInvoke=0
    set winSysFolder=System32
    Altere o 1º parâmetro para set cmdInvoke=1e verifique se isso já corrige o problema. Ele será adicionado cmd.exeao script que executa a elevação.
    Ou tente alterar o segundo parâmetro para winSysFolder=Sysnative, isso pode ajudar (mas na maioria dos casos não é necessário) em sistemas de 64 bits. (ADBailey relatou isso). "Sysnative" é necessário apenas para iniciar aplicativos de 64 bits a partir de um host de scripts de 32 bits (por exemplo, um processo de criação do Visual Studio ou chamada de script de outro aplicativo de 32 bits).

  • Para deixar mais claro como os parâmetros são interpretados, eu estou exibindo isso agora P1=value1 P2=value2 ... P9=value9. Isso é especialmente útil se você precisar incluir parâmetros como caminhos entre aspas duplas, por exemplo "C:\Program Files".

  • Se você quiser depurar o script VBS, poderá adicionar o //Xparâmetro ao WScript.exe como primeiro parâmetro, conforme sugerido aqui (ele é descrito para CScript.exe, mas também funciona para WScript.exe).

Links Úteis:


9
Ótima resposta, embora me surpreenda um pouco que você precise fazer tudo isso para fazer algo que é claramente necessário em alguns casos.
jcoder

50
De fato, um comando como ELEVATE está claramente ausente no idioma do lote do Windows.
Matt

2
Talvez seja mais fácil com o PowerShell, que parece ser o lanaguge scripting aprovado para coisas mais complexas, mas eu nunca se preocupou em aprender isso até agora :(
jcoder

1
A sintaxe no PowerShell é completamente diferente (sintaxe do verbo-substantivo), mas permite chamar assemblies .NET facilmente. Mas é um pouco mais difícil lidar com isso (assinar scripts, etc.).
Matt

2
@ Matt Você pode verificar se há alguma verdade por trás dessa edição rejeitada na sua resposta?
Artjom B.

41

Como jcoder e Matt mencionaram, o PowerShell facilitou e pode até ser incorporado no script em lote sem criar um novo script.

Eu modifiquei o script de Matt:

:: Check privileges 
net file 1>NUL 2>NUL
if not '%errorlevel%' == '0' (
    powershell Start-Process -FilePath "%0" -ArgumentList "%cd%" -verb runas >NUL 2>&1
    exit /b
)

:: Change directory with passed argument. Processes started with
:: "runas" start with forced C:\Windows\System32 workdir
cd /d %1

:: Actual work

3
Você está certo, se o PowerShell estiver instalado, você poderá usá-lo para executar o arquivo em lotes com elevação (obrigado pelo trecho de código!). E sim, o rótulo não é necessário. Obrigado pelas dicas, vale a pena um ... :-)
Matt

2
Quando invocado no cmd, o Powershell.exe não possui a opção -verb runas. Existe se você já estiver no PowerShell.
Adil Hindistan

1
Eu realmente gosto desta solução, funciona muito bem para mim. No Windows 8.1, exigi o rótulo: gotPrivileges para que ele funcionasse.
ShaunO 27/03

Estou com um problema se esse arquivo em lotes for remoto em um caminho UNC.
Ryan Beesley

Eu adicionei o diretório de mudança no início, simplifiquei o fluxo e limpei um pouco. Dir trabalho não pode ser alterada através WorkingDirectorydo parâmetro em Start-Processcausa de razões de segurança em runasprocessos
ceztko

28

Estou usando a excelente resposta de Matt, mas vejo uma diferença entre meus sistemas Windows 7 e Windows 8 ao executar scripts elevados.

Depois que o script é elevado no Windows 8, o diretório atual é definido como C:\Windows\system32. Felizmente, existe uma solução fácil, alterando o diretório atual para o caminho do script atual:

cd /d %~dp0

Nota: Use cd /dpara garantir que a letra da unidade também seja alterada.

Para testar isso, você pode copiar o seguinte em um script. Execute normalmente em qualquer versão para ver o mesmo resultado. Execute como administrador e veja a diferença no Windows 8:

@echo off
echo Current path is %cd%
echo Changing directory to the path of the current script
cd %~dp0
echo Current path is %cd%
pause

1
Boa dica, Stephen. Portanto, o script deve terminar com cd %~dp0para manter seu caminho atual (presumo que isso funcione também no Win7, portanto o mesmo comando pode ser usado, embora seja necessário apenas para o Win8 +). +1 para isso!
Matt

2
De notar isso também era necessário no meu sistema com o Windows 7.
meh-uk

1
ou usar em pushd %~dp0vez disso ... por quê? porquepopd
Jaroslav Záruba

27

Eu faço assim:

NET SESSION
IF %ERRORLEVEL% NEQ 0 GOTO ELEVATE
GOTO ADMINTASKS

:ELEVATE
CD /d %~dp0
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 1);close();"
EXIT

:ADMINTASKS
(Do whatever you need to do here)
EXIT

Dessa forma, é simples e use apenas os comandos padrão do Windows. É ótimo se você precisar redistribuir seu arquivo em lote.

CD /d %~dp0 Define o diretório atual como o diretório atual do arquivo (se ainda não estiver, independentemente da unidade em que o arquivo está, graças ao /d opção).

%~nx0 Retorna o nome do arquivo atual com a extensão (se você não incluir a extensão e houver um exe com o mesmo nome na pasta, ele será chamado).

Há tantas respostas neste post que eu nem sei se minha resposta será vista.

Enfim, acho isso mais simples do que as outras soluções propostas nas outras respostas, espero que ajude alguém.


4
cd% ~ dp0 não funcionará em unidades de rede, use pushd% ~ dp0.
Stavm

1
Eu amo a simplicidade desta resposta. E, finalmente, um motivo para usar o Jscript!
Joe Coder

1
Magia! Muito obrigado.
Daniele Orlando

1
@ Wolf Digitei uma resposta enorme apenas para perceber que o entendi errado ... Entendi o que você quer dizer agora. Vou editá-lo para incluir o /d. Obrigado pal :) (PS: Pianista aqui também!)
Matheus Rocha

1
Isso funciona muito bem, mas pode ser uma boa idéia mover o cdcomando para o início (isso garante que o caminho também esteja disponível para o script elevado - caso contrário, o script elevado será executado apenas no system32). Você também deve redirecionar o comando net para nul para ocultar sua saída:net session >nul 2>&1
Nulano 08/08/17

23

Matt tem uma ótima resposta, mas retira todos os argumentos passados ​​para o script. Aqui está a minha modificação que mantém argumentos. Também incorporei a correção de Stephen para o problema do diretório de trabalho no Windows 8.

@ECHO OFF
setlocal EnableDelayedExpansion

NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto START ) else ( goto getPrivileges ) 

:getPrivileges
if '%1'=='ELEV' ( goto START )

set "batchPath=%~f0"
set "batchArgs=ELEV"

::Add quotes to the batch path, if needed
set "script=%0"
set script=%script:"=%
IF '%0'=='!script!' ( GOTO PathQuotesDone )
    set "batchPath=""%batchPath%"""
:PathQuotesDone

::Add quotes to the arguments, if needed.
:ArgLoop
IF '%1'=='' ( GOTO EndArgLoop ) else ( GOTO AddArg )
    :AddArg
    set "arg=%1"
    set arg=%arg:"=%
    IF '%1'=='!arg!' ( GOTO NoQuotes )
        set "batchArgs=%batchArgs% "%1""
        GOTO QuotesDone
        :NoQuotes
        set "batchArgs=%batchArgs% %1"
    :QuotesDone
    shift
    GOTO ArgLoop
:EndArgLoop

::Create and run the vb script to elevate the batch file
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"
ECHO UAC.ShellExecute "cmd", "/c ""!batchPath! !batchArgs!""", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"
"%temp%\OEgetPrivileges.vbs" 
exit /B

:START
::Remove the elevation tag and set the correct working directory
IF '%1'=='ELEV' ( shift /1 )
cd /d %~dp0

::Do your adminy thing here...

1
Esta é uma resposta útil. No entanto, na ECHO UAC.ShellExecute....linha, "batchArgs!"não expandirá a variável. Use "!batchArgs!". Minha edição foi rejeitada, por isso comento.
flied cebola

1
@fliedonion bem avistado! Não sei por que sua edição foi rejeitada, porque definitivamente foi um erro de digitação e sua correção funciona. Fiz a alteração sozinho e testei no Win 8.1. Agora, para encontrar todos os scripts que eu uso este código ....
jxmallett

2
O script foi interrompido ao usar argumentos citados, como test.bat "a thing"ou "test script.bat" arg1 arg2. Tudo consertado agora.
Jxmallett

Eu consegui quebrá-lo (devido à minha falha: executando o script da unidade de rede mapeada, pois o administrador e o usuário normal não têm o mesmo mapeamento). Ainda: existe uma maneira de ver a saída? Para mim, eu tive que encontrar o .vbs e alterar o / c para a / K e depois o vi manualmente.
precisa

21

Eu uso o PowerShell para reiniciar o script elevado, se não estiver. Coloque essas linhas no topo do seu script.

net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~fnx0 %*'"
goto :eof
:run
:: TODO: Put code here that needs elevation

Copiei o método 'net name' da resposta de @ Matt. Sua resposta é muito melhor documentada e possui mensagens de erro e coisas do gênero. Este tem a vantagem de o PowerShell já estar instalado e disponível no Windows 7 e superior. Nenhum arquivo temporário VBScript (* .vbs) e você não precisa fazer o download de ferramentas.

Esse método deve funcionar sem qualquer configuração ou instalação, desde que suas permissões de execução do PowerShell não estejam bloqueadas.


Ao fornecer uma lista com argumentos separados por espaços em branco, entre aspas, para tratá-lo como um só, a /c %~fnx0 %*'parte parece deixar todas as partes além da primeira. Por exemplo, test.bat "arg1 arg2 arg3"somente de arg1 é passado adiante
Nicolas Mommaerts 10/10

Parece que não importa o que, o Start-processo remove todas as aspas duplas na ArgumentList ..
Nicolas Mommaerts

Funciona para mim! Eu estou usando isso para netsh int set int %wifiname% Enable/Disable.
Marslo

2
Eu tive o mesmo problema que Nicolas Mommaerts acima. Eu não entendo por que ele funciona (o melhor tipo de correção), mas o seguinte funciona como deveria (observe todas as aspas extras no final): net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c ""%~fnx0""""'"
treme

Outro problema (inconveniente) é que o script pausa (aguarda a entrada do usuário) se o serviço do servidor não estiver sendo executado (eu o desabilitei por motivos). Normalmente, testo as permissões de administrador tentando gravar no local do arquivo HOSTS , mas talvez seja melhor chamar o comando powershell -Verb runas , em vez de confiar nos serviços do Windows ativados ou na tentativa de gravar arquivos.
script'n'code

15

Para alguns programas, a configuração da __COMPAT_LAYERvariável de ambiente super secreta como RunAsInvoker funcionará. Verifique isto:

set "__COMPAT_LAYER=RunAsInvoker"
start regedit.exe

Embora assim, não haverá UAC solicitando que o usuário continue sem permissões de administrador.


1
O link para o site da Microsoft não funcionou mais, então mudei para o conteúdo em archive.org. Se alguém puder encontrar um link funcional para o conteúdo no site da Microsoft, mas todos os meios, atualize-o para isso.
RockPaperLizard

1
ele ainda está com integridade média e não elevado , então você não pode editar o HKLM no regedit. Apenas pulou o uac.
HackingAddict1337

5

Eu colei isso no começo do script:

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\icacls.exe" "%SYSTEMROOT%\system32\config\system"

REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo args = "" >> "%temp%\getadmin.vbs"
    echo For Each strArg in WScript.Arguments >> "%temp%\getadmin.vbs"
    echo args = args ^& strArg ^& " "  >> "%temp%\getadmin.vbs"
    echo Next >> "%temp%\getadmin.vbs"
    echo UAC.ShellExecute "%~s0", args, "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs" %*
    exit /B

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------

2
Eu gosto do processamento de arg no seu script. Mas observe que isso caclsfoi preterido no Windows 7 e nas versões mais recentes do Windows.
Matt

Fsutil sujo é ainda melhor
Lobo

1
Você sabia que a linha pushd "%CD%"salva o diretório de trabalho atual e muda para o diretório de trabalho atual?
8372 Wolf

3

Eu escrevi gsudo, um sudopara Windows : que eleva no console atual (sem alternância de contexto para uma nova janela), com um cache de credenciais (pop-ups de UAC reduzidos) e também eleva os comandos do PowerShell .

Ele permite elevar comandos que exigem privilégios de administrador ou todo o lote, se você desejar. Basta colocar gsudo antes de qualquer coisa que precise ser elevada.

Arquivo em lote de exemplo que se eleva usando gsudo:

EDIT: Nova versão one-liner que funciona com qualquer idioma do Windows e evita problemas de whoami :

net session >nul 2>nul & net session >nul 2>nul || gsudo "%~f0" && exit /b || exit /b
:: This will run as admin ::

Alternativa (versão original):

@echo off
  rem Test if current context is already elevated:
  whoami /groups | findstr /b BUILTIN\Administrators | findstr /c:"Enabled group" 1> nul 2>nul && goto :isadministrator
  echo You are not admin. (yet)
  :: Use gsudo to launch this batch file elevated.
  gsudo "%~f0"
  goto end
:isadministrator
  echo You are admin.
  echo (Do admin stuff now).
:end

Instalar:

Veja gsudo em ação: demo do gsudo


Legal. Obrigado. Em quais versões do Windows ele funciona?
RockPaperLizard

O conjunto de testes é executado no Server 2019 e minha caixa de desenvolvimento local é o Windows 10 1909. Desculpe, não testei a compatibilidade com outros sistemas operacionais mais antigos.
Gerardo Grignoli 11/04

Obrigado Gerardo. Se alguém tentar em outras versões do Windows, publique seus resultados.
RockPaperLizard

Acabei de testar o gsudo v0.7 no Windows 8.1 e funcionou. Não é trivial instalar .Net Framework 4.6lá. Felizmente, choco install dotnet4.6.2trouxe algumas dependências difíceis de obter. Em seguida, foi gsudo config Prompt "$p# "corrigido um problema ao ConHostexibir um prompt errado (caracteres de sequência de escape em vez do vermelho acentuado). @RockPaperLizard
Gerardo Grignoli

Muito obrigado, Gerardo. Ele poderia ser recompilado para funcionar com qualquer versão do .Net Framework anterior à 4.6 ou depende de alguma funcionalidade específica da 4.6?
RockPaperLizard 18/04

2

Embora não seja diretamente aplicável a essa pergunta, porque deseja algumas informações para o usuário, o google me trouxe aqui quando eu queria executar meu arquivo .bat elevado a partir do agendador de tarefas.

A abordagem mais simples foi criar um atalho para o arquivo .bat, pois, para um atalho, você pode definir Run as administrator diretamente nas propriedades avançadas.

Executando o atalho do agendador de tarefas, o arquivo .bat é elevado.


1

Se você não precisar passar argumentos, aqui está um script compacto de solicitação do UAC com uma única linha. Isso é semelhante ao script de elevação na resposta mais votada, mas não passa argumentos, pois não há uma maneira infalível de fazer isso que lida com todas as combinações possíveis de caracteres suspeitos.

@echo off
net sess>nul 2>&1||(echo(CreateObject("Shell.Application"^).ShellExecute"%~0",,,"RunAs",1:CreateObject("Scripting.FileSystemObject"^).DeleteFile(wsh.ScriptFullName^)>"%temp%\%~nx0.vbs"&start wscript.exe "%temp%\%~nx0.vbs"&exit)

:: Your batch file goes here

0

Usando o PowerShell.

Se o arquivo cmd for longo, eu uso o primeiro para exigir elevação e depois chamo o que está realizando o trabalho.

Se o script for um comando simples, tudo poderá caber em um arquivo cmd. Não esqueça de incluir o caminho nos arquivos de script.

Modelo:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c " comands or another script.cmd go here "'"

Exemplo 1:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\BIN\x.ps1"'"

Exemplo 2:

@echo off
powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "c:\bin\myScript.cmd"'"

0

Tente o seguinte:

@echo off
CLS
:init
setlocal DisableDelayedExpansion
set cmdInvoke=1
set winSysFolder=System32
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " "  >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
if '%cmdInvoke%'=='1' goto InvokeCmd 
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
goto ExecElevation
:InvokeCmd
ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"
:ExecElevation
"%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul  &  shift /1)
REM Run shell as admin (example) - put here code as you like
ECHO %batchName% Arguments: P1=%1 P2=%2 P3=%3 P4=%4 P5=%5 P6=%6 P7=%7 P8=%8 P9=%9
cmd /k

Se você precisar de informações sobre esse arquivo em lotes, execute o Snippet HTML / JS / CSS:

document.getElementsByTagName("data")[0].innerHTML="ElevateBatch, version 4, release<br>Required Commands:<ul><li>CLS</li><li>SETLOCAL</li><li>SET</li><li>FOR</li><li>NET</li><li>IF</li><li>ECHO</li><li>GOTO</li><li>EXIT</li><li>DEL</li></ul>It auto-elevates the system and if the user presses No, it just doesn't do anything.<br>This CANNOT be used to create an Elevated Explorer.";
data{font-family:arial;text-decoration:none}
<data></data>


-3

A solução a seguir está limpa e funciona perfeitamente.

  1. Faça o download do arquivo zip Elevate em https://www.winability.com/download/Elevate.zip

  2. Dentro do zip, você deve encontrar dois arquivos: Elevate.exe e Elevate64.exe. (A última é uma compilação nativa de 64 bits, se você precisar que, embora a versão normal de 32 bits, Elevate.exe, deva funcionar bem com as versões de 32 e 64 bits do Windows)

  3. Copie o arquivo Elevate.exe em uma pasta na qual o Windows possa sempre encontrá-lo (como C: / Windows). Ou melhor, você pode copiar na mesma pasta em que planeja manter seu arquivo bat.

  4. Para usá-lo em um arquivo em lotes, basta acrescentar o comando que você deseja executar como administrador ao comando elevate, da seguinte maneira:

 elevate net start service ...

2
Esse comando abre apenas uma janela de diálogo que pergunta ao usuário se esse comando pode ser executado. Portanto, você não pode usar esse comando em um arquivo em lotes, o que deve ser executado SEM as interações do usuário.
Radon8472

Se fosse possível elevar SEM a interação do usuário, seria uma enorme falha de segurança, não é? Todo vírus começaria a usar esse método para se elevar sem a aprovação do usuário.
Andrei Belogortseff 21/04
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.