PSExec и Powershell не могут запустить программу, расположенную в Program Files (x86)

Я изо всех сил пытаюсь использовать Psexec внутри сценария PS для выполнения интерактивной программы. Я пробовал это:

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c "echo . | powershell notepad" 2> $null

... и работает отлично. Блокнот запускается на удаленной машине. Теперь, когда я хочу запустить .exe из Program Files (x86), я ничего не получаю. Я пробовал эти варианты для запуска 1.exe, расположенного в ProgramFiles (x86):

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c "echo . | powershell "${env:ProgramFiles(x86)}\1.exe"" 2> $null

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c "echo . | powershell "${env:ProgramFiles(x86)}" + "\1.exe"" 2> $null

Однако ни один из них не работает. Есть идеи, что не так?


person Okrx    schedule 14.03.2016    source источник


Ответы (2)


Попробуйте следующее:

psexec cmd /c 'echo . | powershell "& \"${env:ProgramFiles(x86)}\1.exe\"' 2>$null

Примечание. Чтобы лучше сосредоточиться на основах решения, я упростил команду psexec, но исходная команда тоже должна работать.

  • Вся строка, переданная в cmd /k, заключена в одинарные кавычки, чтобы предотвратить интерполяцию элементов PS заранее, особенно ${env:ProgramFiles(x86)}, раскрытие которого следует отложить до тех пор, пока команда не будет выполнена на целевом компьютере.

    • Note that you normally need a double-quoted string when you pass a command line to cmd /c when invoking from cmd.exe itself. From within PowerShell, however, this is not a requirement: PowerShell first parses the string - whether single- or double-quoted originally - interpolates, if applicable, and then passes the resulting string double-quoted to the external command.
  • Обратите внимание на конструкцию & \"...\" в контексте аргумента powershell, которая обеспечивает правильное выполнение пути со встроенными пробелами.

    • Любопытно, что для PS требуется " символов. экранируется как \" при передаче параметра из внешнего мира (в отличие от экранирования как `" внутри области PS).

    • Команда, переданная powershell, в целом должна быть в двойных кавычках, потому что cmd.exe, в контексте которого powershell вызывается из-за cmd /c, распознает только двойные кавычки как разделители параметров и только двойные кавычки защищают заключенный контент (в основном) от интерпретации.


Почему ваши команды не работали:

  • Основная проблема заключалась в том, что путь к исполняемому файлу, который вы хотели вызвать с помощью powershell.exe, в конечном итоге содержал пробелы (C:\Program Files...), из-за чего PowerShell не распознавал весь путь как один аргумент. Такой путь должен быть (а) в кавычках и (б) вызываться с помощью &, оператора вызова.
    (Во второй попытке, с + ... (конкатенация строк), вам пришлось бы использовать & также и заключите конкатенацию в (...)).

    • For debugging, using cmd /k instead of cmd /c can give you a better sense of how the command is ultimately executed (/k keeps the console window open after execution of the command).
  • Более тонкий момент заключается в том, что при использовании всей строки в двойных кавычках ${env:ProgramFiles(x86)} расширялось на исходном компьютере, а не на целевом компьютере, где определение этой переменной окружения может совпадать, а может и не совпадать.

person mklement0    schedule 15.03.2016
comment
Это просто потрясающе. Отличный разбор того, как это должно быть сделано. Спасибо @mklement0. Мне пришлось удалить пробел между ProgramFiles и (x86), чтобы заставить его работать, но в остальном ваш комментарий безупречен. - person Okrx; 15.03.2016
comment
@Okrx: с удовольствием; рад слышать это. Что касается лишнего пространства: мне очень подходит для подделки переменной на моей 32-битной машине... Спасибо за отзыв; Я исправил ответ. - person mklement0; 15.03.2016

Вы попадаете в «Побег из ада», смешивая PowerShell, CMD и PsExec. Если все, что вам нужно, это запустить исполняемый файл на удаленном хосте, просто придерживайтесь CMD и PsExec (также запустите команду из CMD):

PsExec.exe -i \\192.168.100.95 -u Administrador -p Test1234 cmd /c echo. ^| "%ProgramFiles(x86)%\1.exe" 2>nul

Таким образом, вам просто нужно выйти из канала (^|) и указать путь с пробелами в двойных кавычках.

person Ansgar Wiechers    schedule 14.03.2016
comment
Хотя это, безусловно, упрощает вызов, обратите внимание, как OP упоминает о попытках использовать Psexec внутри сценария PS (выделено мной). - person mklement0; 15.03.2016
comment
Эта команда отлично работает, и я очень благодарен за вашу помощь, но ее нужно запускать из сценария PS. - person Okrx; 15.03.2016