Executar script PowerShell como Administrador: Start-Process, aspas, UAC e execução elevada

Quer executar um script PowerShell como administrador e garantir que ele rode dentro da sessão elevada? Este guia mostra a causa do erro clássico “abre a janela, mas o script não roda”, explica o papel das aspas, e entrega modelos prontos para uso local e em larga escala.

Índice

Visão geral

Em ambientes Windows, é comum precisar rodar um .ps1 com privilégios administrativos para instalar software, ajustar chaves de registro, ou modificar serviços. Muitos profissionais tentam “Abrir como administrador” e, ao passar o caminho do script, veem apenas a janela elevada do PowerShell se abrir — sem o script ser executado. A causa mais frequente é simples: aspas incorretas no argumento que indica o caminho do script.

Neste artigo você aprenderá:

  • Por que o Windows só reconhece aspas duplas como delimitadoras de argumentos ao iniciar processos.
  • Como usar Start-Process -Verb RunAs para elevar e rodar o script dentro da sessão elevada.
  • Como definir a ExecutionPolicy de forma segura e pontual.
  • Como esperar o término e capturar o exit code.
  • Alternativas sem interação de UAC via Tarefa Agendada para distribuição em massa.
  • Um checklist de solução de problemas, exemplos práticos e boas práticas para ambientes corporativos.

O problema: aspas que “engolem” o script

No Windows, o delimitador de argumentos reconhecido na criação de processos é a aspa dupla ("). Já a aspa simples (') é interpretada como caractere literal. Se você envia 'C:\temp\MyScript.ps1' como argumento para powershell.exe -File, essas aspas simples vão chegar ao executável como parte do texto, e o PowerShell não encontrará o arquivo. Resultado: a janela abre elevada, mas seu script não é carregado.

Solução confirmada (modelo pronto)

Use Start-Process com -Verb RunAs e monte os argumentos corretamente. Prefira passar um array de argumentos para evitar problemas de “dupla citação”.

# Caminho do script
$script = 'C:\temp\MyScript.ps1'

Argumentos para a nova instância elevada do PowerShell

\$args = @(
'-NoProfile',
'-ExecutionPolicy', 'RemoteSigned',   # ou 'Bypass' se necessário e confiável
'-File', ('"{0}"' -f \$script)         # mantém ASPAS DUPLAS no caminho
)

Start-Process -FilePath 'powershell.exe' -Verb RunAs -ArgumentList \$args </code></pre>

<blockquote>
  <p><strong>Versão compacta (mesmo efeito)</strong></p>
  <pre><code class="language-powershell">Start-Process powershell.exe -Verb RunAs -ArgumentList `
 '-NoProfile -ExecutionPolicy RemoteSigned -File "C:\temp\MyScript.ps1"'
</code></pre>
  <p>O autor do cenário confirmou: <strong>trocar para aspas duplas</strong> no caminho do script resolveu imediatamente.</p>
</blockquote>

<h2>Por que as aspas importam tanto</h2>
<p>Quando você inicia <code>powershell.exe</code> (ou <code>pwsh.exe</code> no PowerShell 7+), a linha de comando é parseada pelo mecanismo padrão do Windows. Ele <strong>remove</strong> as aspas duplas usadas para delimitar cada argumento e trata aspas simples como <em>texto</em>. Então:</p>

<table>
  <thead>
    <tr>
      <th>Situação</th>
      <th>Exemplo</th>
      <th>Efeito</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Caminho com espaços usando aspas <em>duplas</em> (correto)</td>
      <td><code>-File "C:\temp\Meu Script.ps1"</code></td>
      <td>Arquivo encontrado e executado</td>
    </tr>
    <tr>
      <td>Caminho com aspas <em>simples</em> (incorreto)</td>
      <td><code>-File 'C:\temp\Meu Script.ps1'</code></td>
      <td>As aspas simples viram parte do texto; o arquivo não é localizado</td>
    </tr>
    <tr>
      <td>Sem aspas (caminho sem espaços)</td>
      <td><code>-File C:\temp\MyScript.ps1</code></td>
      <td>Funciona, mas não é resiliente; quebre se houver espaço</td>
    </tr>
  </tbody>
</table>

<h2>Boas práticas ao montar <code>-ArgumentList</code></h2>
<ul>
  <li><strong>Prefira array</strong> em vez de uma única string. Cada elemento vira um argumento isolado:
    <pre><code class="language-powershell">$args = @('-NoProfile','-ExecutionPolicy','RemoteSigned','-File','"C:\temp\My Script.ps1"')
Start-Process powershell.exe -Verb RunAs -ArgumentList $args

Se optar por string única, você mesmo deve cuidar de todas as aspas duplas internas:

Start-Process powershell.exe -Verb RunAs -ArgumentList `
  '-NoProfile -ExecutionPolicy RemoteSigned -File "C:\temp\My Script.ps1"'

Inclua sempre -NoProfile para eliminar interferência de perfis.
Especifique -ExecutionPolicy apenas para a sessão chamada (não altera a máquina).

Política de execução: segura e sob controle

Em clientes Windows, a política padrão geralmente é restritiva (Restricted), bloqueando scripts por padrão. Opções práticas:

  • RemoteSigned: permite scripts locais; exige assinatura para arquivos marcados como “da Internet”.
  • Bypass: ignora verificações nessa execução específica (use apenas quando a origem for confiável).

Se o script veio por download, remova a marca de Internet antes de executar:

Unblock-File 'C:\temp\MyScript.ps1'

Aguardando término e obtendo o código de saída

Para orquestração e automação, saber se deu certo é tão importante quanto executar:

$p = Start-Process powershell.exe -Verb RunAs -ArgumentList $args -PassThru -Wait
$p.ExitCode

Executando sem janela (quando apropriado)

Para tarefas em segundo plano sem exibir UI:

Start-Process powershell.exe -Verb RunAs -ArgumentList $args -WindowStyle Hidden

Atenção: ocultar a janela pode dificultar suporte e auditoria. Use com critério.

Execução sem interação/UAC: Tarefa Agendada

Para “push” remoto ou execução em escala, a forma mais previsível é criar uma Tarefa Agendada com “Executar com privilégios mais altos” (utilizando conta administrativa ou SYSTEM), acionar e remover depois:

$act = New-ScheduledTaskAction -Execute 'powershell.exe' `
  -Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\temp\MyScript.ps1"'
$prn = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -RunLevel Highest
$trg = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1)

Register-ScheduledTask -TaskName 'RunMyScript' -Action \$act -Trigger \$trg -Principal \$prn
Start-ScheduledTask -TaskName 'RunMyScript'

Opcional: aguarde e então remova a tarefa

Unregister-ScheduledTask -TaskName 'RunMyScript' -Confirm:\$false

Compatibilidade: Windows PowerShell 5.1 vs PowerShell 7+

Nos exemplos usamos powershell.exe (Windows PowerShell 5.1). Se seu padrão for PowerShell 7+, substitua por pwsh.exe:

Start-Process 'pwsh.exe' -Verb RunAs -ArgumentList @(
  '-NoProfile','-ExecutionPolicy','RemoteSigned','-File','"C:\temp\MyScript.ps1"'
)

Exemplos práticos

Elevar e executar passando parâmetros ao script

$script = 'C:\temp\MyScript.ps1'
$param1 = 'valor simples'
$param2 = 'texto com espaços'

\$args = @(
'-NoProfile',
'-ExecutionPolicy','RemoteSigned',
'-File', ('"{0}"' -f \$script),
'-Name', \$param1,
'-Description', ('"{0}"' -f \$param2)
)
Start-Process powershell.exe -Verb RunAs -ArgumentList \$args 

Autoelevação: o script se relança como administrador

Útil quando o usuário dispara o .ps1 sem ter aberto o PowerShell elevado:

# No início do seu script:
$IsAdmin = ([Security.Principal.WindowsPrincipal] `
  [Security.Principal.WindowsIdentity]::GetCurrent() `
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

if (-not \$IsAdmin) {
Write-Host 'Reiniciando como administrador...'
\$quoted = ('"{0}"' -f \$PSCommandPath)
Start-Process powershell.exe -Verb RunAs -ArgumentList @(
'-NoProfile','-ExecutionPolicy','Bypass','-File', \$quoted
)
exit
}

...código elevado continua aqui...

Definindo diretório de trabalho

Alguns scripts assumem diretório específico. Ajuste com -WorkingDirectory:

Start-Process powershell.exe -Verb RunAs -ArgumentList $args -WorkingDirectory 'C:\temp'

Tabela de opções úteis

Argumentos de powershell.exe/pwsh.exe

ArgumentoUsoObservação
-NoProfileIgnora perfisEvita comportamento imprevisível de perfil
-ExecutionPolicy <Policy>Define política da sessãoBypass, RemoteSigned, etc.
-File "C:\path\script.ps1"Executa arquivoUse aspas duplas no caminho
-Command "<comando>"Executa comandoÚtil para invocações rápidas

Parâmetros de Start-Process

ParâmetroPara que serveDicas
-FilePathExecutável alvopowershell.exe ou pwsh.exe
-Verb RunAsEleva via UACExige consentimento ou credenciais
-ArgumentListArgumentos do processoPrefira array; cuide das aspas
-PassThruRetorna objeto de processoCombine com -Wait para exit code
-WindowStyle HiddenOculta janelaUse com parcimônia
-WorkingDirectoryDefine diretórioEvita path relativo incorreto

Distribuição em massa: padrões confiáveis

Ao distribuir para dezenas ou milhares de máquinas (SCCM/MECM, Intune, scripts de logon, etc.), siga estes princípios:

  • Empacote dependências no mesmo diretório ou use caminhos absolutos.
  • Desbloqueie os arquivos (remova a marca “da Internet”).
  • Evite perfis e dependências de usuário (-NoProfile).
  • Capture logs (ex.: redirecione Start-Transcript ou write-out para arquivo).
  • Trate proxy e rede se o script baixar algo.
  • Escolha a técnica de elevação adequada:
    • RunAs interativo: bom para uso assistido.
    • Tarefa Agendada com “Maior nível de privilégios”: ideal para execução sem interação.
    • PSRemoting/WinRM: para orquestração remota controlada (exige pré-requisitos).

Erros comuns e como diagnosticar

  1. Aspas simples no caminho: substitua por aspas duplas e, se possível, passe -ArgumentList como array.
  2. ExecutionPolicy bloqueando: defina -ExecutionPolicy RemoteSigned ou Bypass apenas na execução.
  3. Arquivo marcado como Internet (Zone.Identifier): rode Unblock-File antes.
  4. Diretório de trabalho errado: use -WorkingDirectory ou caminhos absolutos.
  5. ESPAÇOS no caminho: sempre envolva em "aspas duplas".
  6. UNC sem permissões: copie para um caminho local com permissões adequadas.
  7. Herança de ambiente: defina explicitamente variáveis necessárias ou passe parâmetros ao script.
  8. Linhas muito longas (encadeando comandos): prefira arrays; legibilidade evita erros de citação.
  9. Executável errado: verifique se usa powershell.exe (5.1) ou pwsh.exe (7+).
  10. Sem privilégios apesar de RunAs: confirme com o snippet abaixo e valide política de UAC.

Como confirmar que está realmente elevado

$isAdmin = ([Security.Principal.WindowsPrincipal] `
  [Security.Principal.WindowsIdentity]::GetCurrent() `
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

if (\$isAdmin) { 'Elevado' } else { 'Não elevado' } 

Perguntas frequentes (FAQ)

Posso usar aspas simples em algum lugar?
Dentro do script PowerShell, sim — para construir strings literais sem interpolação. Mas ao passar caminhos/argumentos para um novo processo no Windows, as aspas que delimitam argumentos precisam ser duplas.

É melhor usar -Command ou -File?
Para scripts armazenados em disco, -File é mais direto (menos camadas de citação). -Command é útil para pequenos comandos inline.

Preciso mudar a política de execução do sistema?
Na maioria dos casos, não. Prefira passar -ExecutionPolicy na linha de comando, afetando apenas aquela sessão invocada.

Como capturo saída e logs do script elevado?
Implemente Start-Transcript no script, redirecione Write-Output para arquivo, ou use -File + parâmetros para apontar um caminho de log.

PowerShell 7 muda algo na citação?
A regra central permanece: aspas duplas delimitam argumentos ao criar o processo; aspas simples são literais. Apenas ajuste o executável alvo para pwsh.exe.

Modelos prontos para colar

Modelo seguro e verboso

$script = 'C:\temp\MyScript.ps1'
$log    = 'C:\temp\MyScript.log'

\$args = @(
'-NoProfile',
'-ExecutionPolicy','RemoteSigned',
'-File', ('"{0}"' -f \$script),
'-LogPath', ('"{0}"' -f \$log)
)

Start-Process powershell.exe -Verb RunAs -ArgumentList \$args -PassThru -Wait |
ForEach-Object { "PID=\$(\$.Id) ExitCode=\$(\$.ExitCode)" } 

Modelo compacto “sem janela”

Start-Process powershell.exe -Verb RunAs -ArgumentList `
 '-NoProfile -ExecutionPolicy Bypass -File "C:\temp\MyScript.ps1"' `
 -WindowStyle Hidden

Modelo de Tarefa Agendada (SYSTEM)

$taskName = 'RunMyScript'
$script   = 'C:\temp\MyScript.ps1'

\$act = New-ScheduledTaskAction -Execute 'powershell.exe' \`
-Argument ('-NoProfile -ExecutionPolicy Bypass -File "{0}"' -f \$script)
\$prn = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -RunLevel Highest
\$trg = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1)

Register-ScheduledTask -TaskName \$taskName -Action \$act -Trigger \$trg -Principal \$prn
Start-ScheduledTask -TaskName \$taskName 

Tabela de comparação: formas de executar elevado

TécnicaInteraçãoCenário idealPrósContras
Start-Process -Verb RunAsRequer consentimento/credencial UACAdmin local na frente da máquinaSimples, nativoDepende de UAC/usuário
Tarefa Agendada (Highest/SYSTEM)Sem interaçãoExecução em massa e horários programadosConfiável, previsívelGerência extra (criar/limpar tarefas)
PSRemoting (WinRM)Sem interaçãoOrquestração remotaEscalável, auditávelRequer habilitação e política

Checklist rápido de troubleshooting

  • O caminho do script está entre aspas duplas?
  • Você usou -File (e não apenas abriu a janela elevada)?
  • Há marca “da Internet”? Rode Unblock-File.
  • A política de execução da sessão foi definida (RemoteSigned ou Bypass)?
  • Há espaços no caminho? Use "C:\caminho com espaços\...".
  • Executa como a identidade correta (RunAs vs SYSTEM)?
  • Precisa de -WorkingDirectory para recursos relativos?
  • Está capturando o exit code com -PassThru -Wait?

Resumo e lição principal

Para rodar um script PowerShell com privilégios de administrador e garantir que o script execute dentro da sessão elevada, concentre-se no essencial:

  • Elevação: Start-Process powershell.exe -Verb RunAs.
  • Execução do script: passe -File e o caminho entre aspas duplas.
  • Política de execução: ajustada apenas para a chamada (RemoteSigned ou Bypass).
  • Confiabilidade: arrays em -ArgumentList, -NoProfile, e, quando necessário, Tarefa Agendada.

Resumo curto (copiar e colar)

  • Use Start-Process powershell.exe -Verb RunAs e aspas duplas no caminho do script em -ArgumentList.
  • Defina -ExecutionPolicy para permitir a execução (RemoteSigned ou Bypass apenas para a sessão).
  • Para execução silenciosa e sem prompts em larga escala, prefira uma Tarefa Agendada com privilégios elevados.
Índice