Comunidade Hello Stack :)
Eu tenho um objetivo simples. Gostaria de iniciar um script do PowerShell a partir de outro script do PowerShell, mas existem três condições:
- Eu tenho que passar credenciais (a execução se conecta a um banco de dados que possui usuário específico)
- Tem que levar alguns parâmetros
- Eu gostaria de passar a saída para uma variável
Existe uma pergunta semelhante Link . Mas a resposta é usar arquivos como uma maneira de se comunicar entre scripts de 2 PS. Eu só gostaria de evitar conflitos de acesso. @ Update: O script principal vai iniciar alguns outros scripts. portanto, a solução com arquivos pode ser complicada, se a execução for executada por vários usuários ao mesmo tempo.
Script1.ps1 é o script que deve ter string como saída. (Só para deixar claro, é um script fictício, o real tem 150 linhas, então eu só queria dar um exemplo)
param(
[String]$DeviceName
)
#Some code that needs special credentials
$a = "Device is: " + $DeviceName
$a
ExecuteScripts.ps1 deve chamar aquele com as três condições mencionadas acima
Eu tentei várias soluções. Este por exemplo:
$arguments = "C:\..\script1.ps1" + " -ClientName" + $DeviceName
$output = Start-Process powershell -ArgumentList $arguments -Credential $credentials
$output
Eu não recebo nenhuma saída disso e não posso simplesmente chamar o script com
&C:\..\script1.ps1 -ClientName PCPC
Porque eu não posso passar -Credential
parâmetro para ele ..
Agradeço antecipadamente!
fonte
Respostas:
Nota:
A solução a seguir funciona com qualquer programa externo e captura a saída invariavelmente como texto .
Para invocar outra instância do PowerShell e capturar sua saída como objetos ricos (com limitações), consulte a solução variante na seção inferior ou considere a resposta útil de Mathias R. Jessen , que usa o PowerShell SDK .
A seguir, uma prova de conceito baseada no uso direto dos tipos .NET
System.Diagnostics.Process
eSystem.Diagnostics.ProcessStartInfo
para capturar a saída do processo na memória (conforme declarado na sua pergunta,Start-Process
não é uma opção, pois suporta apenas a captura de saída nos arquivos , conforme mostrado nesta resposta ) :Nota:
Devido à execução como um usuário diferente, isso é suportado apenas no Windows (a partir do .NET Core 3.1), mas nas duas edições do PowerShell.
Devido à necessidade de executar como um usuário diferente e à captura de saída,
.WindowStyle
não pode ser usado para executar o comando oculto (porque o uso.WindowStyle
exige.UseShellExecute
que seja$true
, o que é incompatível com esses requisitos); No entanto, uma vez que toda a saída está sendo capturado , definição.CreateNoNewWindow
de$true
resultados de forma eficaz na execução escondido.O exemplo acima produz algo como o seguinte, mostrando que o processo foi executado com sucesso com a identidade de usuário fornecida:
Como você está chamando outra instância do PowerShell , convém aproveitar a capacidade da CLI do PowerShell para representar a saída no formato CLIXML, que permite desserializar a saída em objetos ricos , embora com fidelidade de tipo limitada , conforme explicado nesta resposta relacionada .
O resultado acima é semelhante ao seguinte, mostrando que a
[datetime]
instância (System.DateTime
) gerada porGet-Date
foi desserializada da seguinte maneira:fonte
Start-Process
seria minha última opção de recurso para chamar o PowerShell do PowerShell - especialmente porque todas as E / S se tornam cadeias de caracteres e não objetos (desserializados).Duas alternativas:
1. Se o usuário for um administrador local e o PSRemoting estiver configurado
Se uma sessão remota na máquina local (infelizmente restrita a administradores locais) for uma opção, eu definitivamente aceitaria
Invoke-Command
:$strings
conterá os resultados.2. Se o usuário não for um administrador no sistema de destino
Você pode escrever seu próprio "somente local
Invoke-Command
" girando um espaço de execução fora de processo:PowerShellProcessInstance
, com um login diferenteEu montei essa função abaixo, veja comentários embutidos para uma explicação passo a passo:
Então use assim:
fonte
rcv.ps1
execução de outro script:
resultado:
fonte
O que você pode fazer da seguinte maneira para passar um parâmetro para um script ps1.
O primeiro script pode ser um origin.ps1 onde escrevemos:
O script de destino dest.ps1 pode ter o seguinte código para capturar as variáveis
E o resultado será
fonte
-Credential $credentials
parâmetros para esta execução e obter a saída dele em uma variável. O ps1. O script em execução está lançando uma sequência de palavras simples no final. Basta olhar para o jeito que eu fiz isso,Start-process
mas essa função não gera saída$output
variável, é NULL. A outra idéia que veio de @ mklement0 é salvar a saída em um arquivo. Mas no meu caso, isso causará uma enorme quantidade de arquivos em um só lugar. Tudo criado a partir de diferentes usuários com diferentes scripts