Я пытаюсь использовать psexec для запуска процесса в интерактивном сеансе, который уже был открыт. И моя машина, и удаленная машина работают под управлением Windows 7. Использование команды из командной строки работает нормально, исполняемый файл запускается и отображается в графическом интерфейсе.
psexec64 -accepteula -nobanner \\hostname -u domain\user -p password -h -i 2 -d C:\workingdir\subfolder\application.exe
Однако когда я пытаюсь выполнить тот же вызов в сценарии PowerShell, он не работает. Видеть полный сценарий для контекста.
# invalid args: $psExecArgs = "-accepteula", "-nobanner", "-u domain`\${username}", "-p ${password}", "-h", "-i ${sessionId}", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
# hangs: $psExecArgs = "-accepteula", "-nobanner", "-u domain`\${username}", "-p ${password}", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
$psExecArgs = "-accepteula", "-nobanner", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
& $EchoArgsPath $psExecArgs
$result = & $PsExecPath $psExecArgs #2>$null
$result
- это помощь psexec, как если бы был задан недопустимый аргумент.-i 2
удален, psexec отображается в списке запущенных процессов на моем компьютере и, кажется, зависает; на удаленном компьютере не запущен процесс psexecsvc.-u
и -p
удаляются, psexec запускается, но, как и ожидалось, процесс запускается в неинтерактивном сеансе моей учетной записи на удаленном компьютере.Я наблюдаю такое же поведение при использовании pslist и pskill, поэтому я заменил их на tasklist и taskkill. Я убедился, что UAC отключен и что я могу сопоставить его с общим ресурсом Admin $ на удаленном компьютере, используя предоставленные мной учетные данные.
При вводе этого вопроса я обнаружил вопрос предполагая, что stdin может быть проблемой но я не уверен, актуально ли это в моем случае.
Отладка всегда ваш друг - если вы проверите значение $ psExecArgs (в полном скрипте) во время выполнения, вы заметите, что вы не указываете значение для $ password. Это означает, что вы отправляете -p (ничего) в psexec, что снова приводит к зависанию psexec в ожидании ввода пароля.
C:\..\foobar.ps1
cmdlet foobar.ps1 at command pipeline position 1
Supply values for the following parameters:
hostname: myhostname
username: myusername
password: mypassword
sourcedirectory: c:\mysourcedir
targetdirectory: c:\mytargetdir
executablename: myexec.exe
Hit Line breakpoint on 'C:\...\foobar.ps1:34'
[DBG]: PS C:\Users\Zerqent>> $psExecArgs
-accepteula
-nobanner
\\myhostname
-u domain\myusername
-p
qwinsta
Чтобы избежать этого в PowerShell, сделайте параметры обязательными https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_functions_advanced_parameters
Обновление: вы также должны разделить часть имени пользователя и пароля, чтобы они были отдельными записями в списке. Обычно каждый раз, когда у вас есть пробел в cmd-команде, вы создаете отдельную запись в списке. Итак, ваш $ psexecArgs станет:
$psExecArgs = "-accepteula", "-nobanner", "-u", "domain`\${username}", "-p", "${password}", "-h", "-d", "`\`\${hostname}", "`"${executableDirectory}`\${executableName}`""
Не совсем уверен, будет ли это перенаправление работать, (# 2> $ null), или это также должно быть каким-то образом включено в список.
Объявление переменной типа $psExecArgs = "-accepteula", "-nobanner"
создает массив строк.
Вы выполняете все, что написано в строках (используя &
) вместо запуска процесса и предоставления аргументов, поэтому аргументы также должны быть простыми строками (а не массивом строк).
Затем, чтобы еще больше запутать это, если вы должны предоставить аргументы в одной строке ($psExecArgs = "-accepteula -nobanner"
), который на самом деле появляется только как один аргумент для PSExec и тоже не будет работать.
Итак, вместо того, чтобы пытаться запустить строки, один из вариантов - использовать PowerShell Start-Process
команда, которая ожидает, что аргументы будут переданы ей в массиве (как вы сейчас делаете).
Попробуйте изменить командные строки, например:
& $PsExecPath $psExecArgs
примерно так:
Start-Process $PsExecPath $psExecArgs
Вам придется обрабатывать код возврата и ошибки немного иначе, например:
try {
$process = (Start-Process -FilePath $psexec -ArgumentList $psExecArgs -NoNewWindow -PassThru)
}
catch {
Write-Output "Error launching process!"
Write-Output $_.Exception.Message
$process = $null
}
finally {
if ($process) {
$process.WaitForExit()
Write-Host "Process exit code: " $process.ExitCode
}
}