Hello Stack Community :)
У меня есть простая цель. Я хотел бы запустить сценарий PowerShell из другого сценария Powershell, но есть 3 условия:
- Я должен передать учетные данные (выполнение подключается к базе данных, которая имеет конкретного пользователя)
- Это должно принять некоторые параметры
- Я хотел бы передать вывод в переменную
Есть похожий вопрос Ссылка . Но ответ заключается в том, чтобы использовать файлы как способ связи между двумя сценариями PS. Я просто хотел бы избежать конфликтов доступа. @ Обновление: основной сценарий собирается запустить несколько других сценариев. поэтому решение с файлами может быть сложным, если выполнение будет выполняться от нескольких пользователей одновременно.
Script1.ps1 - это скрипт, который должен иметь строку в качестве вывода. (Просто чтобы прояснить, это вымышленный сценарий, реальный имеет 150 строк, поэтому я просто хотел привести пример)
param(
[String]$DeviceName
)
#Some code that needs special credentials
$a = "Device is: " + $DeviceName
$a
ExecuteScripts.ps1 должен вызвать тот с этими 3 условиями, упомянутыми выше
Я пробовал несколько решений. Это для примера:
$arguments = "C:\..\script1.ps1" + " -ClientName" + $DeviceName
$output = Start-Process powershell -ArgumentList $arguments -Credential $credentials
$output
Я не получаю вывод от этого, и я не могу просто вызвать скрипт с
&C:\..\script1.ps1 -ClientName PCPC
Потому что я не могу передать -Credential
параметр к нему ..
Заранее спасибо!
источник
Ответы:
Замечания:
Следующее решение работает с любой внешней программой и сохраняет выходные данные в виде текста .
Чтобы вызвать другой экземпляр PowerShell и записать его выходные данные как расширенные объекты (с ограничениями), см. Вариант решения в нижнем разделе или рассмотрите полезный ответ Матиаса Р. Джессена , в котором используется PowerShell SDK .
Вот подтверждение концепции, основанное на прямом использовании типов
System.Diagnostics.Process
иSystem.Diagnostics.ProcessStartInfo
.NET для захвата выходных данных процесса в памяти (как указано в вашем вопросе,Start-Process
не вариант, потому что он поддерживает только захват выходных данных в файлах , как показано в этом ответе ) :Замечания:
Поскольку он работает от имени другого пользователя, он поддерживается только в Windows (начиная с .NET Core 3.1), но в обеих версиях PowerShell.
Из - за необходимости запуска в качестве другого пользователя и необходимости вывода захвата,
.WindowStyle
не может быть использована для запуска команды скрытый (потому что использование.WindowStyle
требует ,.UseShellExecute
чтобы быть$true
, что несовместимо с этими требованиями); однако, поскольку весь вывод фиксируется , установка.CreateNoNewWindow
на$true
результат приводит к скрытому выполнению.Выше приведено что-то вроде следующего, показывающее, что процесс успешно запущен с заданным идентификатором пользователя:
Поскольку вы вызываете другой экземпляр PowerShell , вы можете воспользоваться преимуществами возможности интерфейса командной строки PowerShell представлять выходные данные в формате CLIXML, что позволяет десериализовать выходные данные в расширенные объекты , хотя и с ограниченной точностью типов , как объясняется в этом связанном ответе. ,
Выше приведено что-то вроде следующего, показывающее, что выход
[datetime]
instance (System.DateTime
)Get-Date
был десериализован так:источник
Start-Process
будет моим последним выбором для вызова PowerShell из PowerShell - особенно потому, что все операции ввода-вывода становятся строками, а не (десериализованными) объектами.Две альтернативы:
1. Если пользователь является локальным администратором и настроен PSRemoting
Если возможен удаленный сеанс на локальном компьютере (к сожалению, доступ ограничен локальными администраторами), я бы определенно выбрал
Invoke-Command
:$strings
будет содержать результаты.2. Если пользователь не является администратором в целевой системе
Вы можете написать свой собственный «только для локальных
Invoke-Command
», раскручивая пространство вне процесса:PowerShellProcessInstance
под другим логиномЯ собрал такую функцию ниже, см. Встроенные комментарии для ознакомления:
Затем используйте так:
источник
rcv.ps1
выполнение из другого скрипта:
вывод:
источник
Что вы можете сделать следующим образом, чтобы передать параметр в скрипт ps1.
Первый скрипт может быть origin.ps1, где мы пишем:
Сценарий назначения dest.ps1 может иметь следующий код для захвата переменных
И результат будет
источник
-Credential $credentials
параметр для этого выполнения и получить вывод из него в переменную. PS1. Сценарий, который я выполняю, бросает отдельную строку слова в конце. Просто посмотрите, как я это сделал,Start-process
но эта функция не генерирует вывод$output
переменной, это NULL. Другая идея, пришедшая от @ mklement0, заключается в сохранении вывода в файл. Но в моем случае это приведет к огромному количеству файлов в одном месте. Все создано от разных пользователей с разными скриптами