В одной сети установлены две машины с Windows 7.
Я включил все необходимое, чтобы они могли общаться с winrm
.
Когда я запускаю следующую команду:
Invoke-Command -ComputerName REMOTE-PC -ScriptBlock { Start-Process calc.exe }
Он работает правильно, но программа никогда не отображается на удаленном компьютере. Насколько я могу судить, это ожидаемое поведение.
Я предполагаю, что процесс запускается правильно, а затем сразу же закрывается по окончании сеанса. Как мне запустить программу, чтобы она появилась на хост-машине?
По замыслу, вы не должны запускать процессы в сессиях других людей.
(Чтобы уточнить, даже если вы вошли в систему в интерактивном режиме на рабочем столе компьютера, а также имеете другой отдельный сетевой вход на тот же компьютер в то же время с теми же учетными данными, они все равно считаются двумя разными сеансами входа.)
Это просто противоречит модели безопасности самой Windows, и попытки подорвать ее будут осуждены. Так что вы вряд ли найдете простой и приемлемый способ сделать это. Это технически возможно, но это включает запуск в качестве локальной системы, копирование токена безопасности другого зарегистрированного пользователя и запуск процесса с этим альтернативным токеном. Для этого вам понадобится Windows API, и это почти единственное, в чем Powershell не очень хорош. Видеть WTSQueryUserToken
и CreateProcessAsUser
в Windows API для более подробной информации.
Еще одна идея, чтобы полностью не мочиться в Cheerios, вы могли бы выполнить это, удаленно создав запланированное задание, которое запускает процесс. Видеть https://devblogs.microsoft.com/scripting/how-can-i-remotely-start-an-interactive-process/ для получения дополнительной информации об этом.
Редактировать: О, и я забыл ... почти наверняка PsExec с -i
параметр может это сделать. Вы должны указать идентификатор сеанса входа в систему. И иметь на это разрешение. Скорее всего, он использует тот же Windows API, о котором я упоминал, который использует тот факт, что PsExec устанавливает временную службу, которая работает как локальная система.
Я смог заставить это работать с помощью PsExec, как упоминалось в другом ответе.
C:\Windows\PSTools
C:\Windows\PSTools
на ваш ПУТЬtasklist
будет работать, или причудливый однострочный: $session = tasklist /fo CSV | findstr RDP ; $session = $session.Split(",")[3] ; $session.Split('"')[1]
)PsExec.exe -s -i 123 calc.exe
(«123» - это идентификатор сеанса RDP)Вот как я делаю это с Ansible 2.3.0:
- name: get RDP session number
win_shell: "{{ item }}"
with_items:
- $session = tasklist /fo CSV | findstr RDP ; $session = $session.Split(",")[3] ; $session.Split('"')[1]
register: rdp_session
- name: start calc.exe
win_shell: PsExec.exe -s -i {{ rdp_session.results[0].stdout_lines[0] }} calc.exe
Вы можете создать «вызываемую ловушку» на удаленном компьютере: это запланированная задача, настроенная на «запускать только при входе пользователя в систему», назначенная для запуска под учетной записью пользователя, который будет входить в систему после выполнения. Действие задачи - это исполняемый файл, который вы хотите запустить.
Запланированные задачи могут быть созданы удаленно с помощью powershell или schtasks, а затем вызываться просто по «имени» самой задачи с помощью schtasks или Start-ScheduledTask в PowerShell.
Чтобы вызвать задачу, вы ссылаетесь на задачу по имени, которое вы ей дали:
schtasks /run /TN "mytaskname" /s "host" /u "user" /p "password"
Удаленное создание запланированной задачи возможно с помощью schtasks.exe или New-ScheduledTaskPrincipal в PowerShell. Если исполняемый файл или элемент «Действие» в задаче помечен как «запускать от имени администратора» в файловой системе, задача потребует присоединения учетных данных New-ScheduledTaskPrincipal во время создания задачи, чтобы установить это свойство соответствующим образом.
Пользователь, вошедший в систему в данный момент, может быть движущейся целью, хотя его можно запросить с помощью Get-LoggedOnUser через PowerShell до самого создания запланированной задачи.
Подробный код для этого появится в ближайшие 48 часов, я хотел сделать базовую структуру доступной для всех вас.
Если вы хотите избежать RDPing для получения идентификатора процесса в ответе Виктора, вы можете сделать это, вызвав query session
команда на удаленном компьютере. Пример сценария Powershell
$user = "some_user"
$password = "password of the user"
$ComputerName = "name of the remote machine"
$processId = Invoke-Command $session -ScriptBlock {
param($user)
$sessions = query session $user;
return $sessions[1].split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)[2];
} -ArgumentList ($user)
PsExec \\$ComputerName -u $user -p $password -h -i $processId [some executable name] [arguments to be passed if any]