Estou tentando executar um comando do Powershell com privilégios de administrador no Flutter/Dart. O comando executa um arquivo .ps1 dentro do diretório temporário.
Encontrei este artigo , que implementei e funciona bem. No entanto, depois que o comando do PowerShell é executado, vejo uma saída na janela do PowerShell e espero imprimir essa saída, mas não recebo nada.
Future<void> executePowerShellCommand() async {
String tempFilePath = '${Directory.systemTemp.path}\\COMMAND.ps1';
try {
String command = 'powershell';
List<String> args = [
'-Command',
'Start-Process -FilePath "powershell" -ArgumentList "-ExecutionPolicy Bypass -NoProfile -File `"$tempFilePath`"" -Verb RunAs -Wait'
];
final ProcessResult result = await Process.run(command, args, runInShell: true, stdoutEncoding: utf8, stderrEncoding: utf8);
String output = result.stdout.toString().trim();
String errorOutput = result.stderr.toString().trim();
int exitCode = result.exitCode;
if (exitCode == 0 && errorOutput.isEmpty) {
debugPrint('>>>Powershell Command succeeded: $output');//output is empty
}
} catch (e, s) {
debugPrint(">>>Error $e");
}
}
Pesquisei e descobri que isso Start-Process
gera um processo separado e é por isso que a saída está vazia. Então pensei que poderia capturar a saída do comando e salvá-la em um arquivo, depois ler o conteúdo do arquivo.
Algo assim:
Future<void> executePowerShellCommandWithOutput() async {
String tempFilePath = '${Directory.systemTemp.path}\\COMMAND.ps1';
String outputFilePath = '${Directory.systemTemp.path}\\OUTPUT.txt';
try {
String command = 'powershell';
List<String> args = [
'-Command',
'''Start-Process -FilePath "powershell" -ArgumentList '-ExecutionPolicy Bypass -NoProfile -File "$tempFilePath" | Out-File "$outputFilePath" -Encoding utf8' -Verb RunAs -Wait'''
];
final ProcessResult result = await Process.run(command, args, runInShell: true, stderrEncoding: utf8);
String errorOutput = result.stderr.toString().trim();
int exitCode = result.exitCode;
if (exitCode == 0 && errorOutput.isEmpty) {
File file = File(outputFilePath);
String fileContent = file.readAsString().toString();
debugPrint('>>>File Content: $fileContent');
}
} catch (e, s) {
debugPrint(">>>Error $e");
}
}
Infelizmente, essa abordagem não está funcionando. Como faço para que funcione?
Muito obrigado.
Para que sua abordagem funcione, você deve usar,
-Command
em vez de-File
compowershell.exe
, o Windows PowerShell CLI.Ao contrário do
-File
, que suporta apenas um caminho de script de destino (*.ps1
) opcionalmente seguido por argumentos de passagem literal,-Command
permite que você passe um trecho do código-fonte do PowerShell , que é necessário para executar um pipeline inteiro como o seu (... | Out-File ...
)Observe o uso de
-Command
em vez de-File
, bem como o uso de&
, o operador de chamada para invocar o*.ps1
arquivo (o que é uma necessidade sintática, porque o caminho do arquivo de script é entre aspas).Observe que, embora seja tentador tentar usar
Start-Process
parâmetros-RedirectStandardOut
e-RedirectStandardError
para capturar diretamente a saída do comando em arquivos, isso não funciona em combinação com-Verb RunAs
, ou seja, ao iniciar um processo elevado - veja esta resposta para mais detalhes.