Почему pypsexec не отображает приложение на экране?

Добрый день! 

Мне нужно запустить приложение на удаленном ПК с помощью psexec. Я пробовал использовать модуль subprocess и запустил следующий код:

<pre><code class="python">def tray_pcard_kpp4_reboot(self):
    print('КПП ребут')
    command = f'C:\PsTools\psexec.exe -i 1 -s \\192.168.11.18 -u user -p password calc.exe'
    return subprocess.call(command, stdout=subprocess.DEVNULL)</code></pre>

Однако в консоли PyCharm появляются непонятные символы, и отображается сообщение: "psexec could not start \\192.168.11.18 on Arm" (это имя хоста, на котором запущен PyCharm). При этом, если я запускаю команду из обычной командной строки, все работает корректно. Затем я решил установить Pypsexec и использовал следующий код:

<pre><code class="python">def tray_pcard_kpp1_reboot(self):
    print('KNN1 ребут')
    c = Client('192.168.11.18', username='user', password='password')
    c.connect()
    c.create_service()
    c.run_executable(executable="cmd.exe", arguments=r"/c start calc.exe", interactive=True)
    c.remove_service()
    c.disconnect()</code></pre>

Этот код успешно запускает процесс на удаленной машине, но окна калькулятора, блокнота и т.п. не отображаются на экране. В psexec эта проблема решалась добавлением ключа -i 1, но с pypsexec мне не удается добиться аналогичного результата.

Поделитесь, пожалуйста, возможными решениями этой проблемы как с использованием psexec, так и pypsexec.
  • 18 октября 2024 г. 11:12
Ответы на вопрос 2
Проблема, с которой вы сталкиваетесь, связана с тем, что при использовании `psexec` и `pypsexec` процессы, запущенные на удаленной машине, не выводят графические интерфейсы на основной экран пользователя. 

В случае с `psexec` параметр `-i 1` указывает, что приложение должно быть запущено в интерактивной сессии с конкретным идентификатором (ID) сессии. Однако в `pypsexec` вы не можете напрямую управлять идентификаторами сессии, и поэтому приложения могут не отображаться на экране.

Вот несколько решений и рекомендаций:

### 1. Использование psexec с ключом `-i`

Если `psexec` работает корректно из командной строки, но не из `subprocess`, то попробуйте:

- Убедитесь, что путь к `psexec.exe` правильно экранирован или используйте сырые строки (например, `r'C:\PsTools\psexec.exe'`).
- Используйте `shell=True` в вызове `subprocess.call()`:

```python
import subprocess

def tray_pcard_kpp4_reboot(self):
    print('КПП ребут')
    command = r'C:\PsTools\psexec.exe -i 1 -s \\192.168.11.18 -u user -p password calc.exe'
    return subprocess.call(command, shell=True)
```

### 2. Использование pypsexec с интерактивным запуском

`pypsexec` допускает взаимодействие, но процесс может запускаться даже в фоновом режиме. Убедитесь, что у вас есть подходящие права доступа на удаленной машине и попробуйте передать правильные аргументы.

Причина, по которой `pypsexec` не отображает графическое окно, может быть связана с тем, что вызов `cmd.exe` в интерактивном режиме не создает окно в текущей сессии пользователя. Вы можете попробовать другую конструкцию для выполнения:

```python
from pypsexec.client import Client

def tray_pcard_kpp1_reboot(self):
    print('KNN1 ребут')
    c = Client('192.168.11.18', username='user', password='password')
    c.connect()
    c.create_service()
    c.run_executable(executable=r"calc.exe", interactive=True)
    c.remove_service()
    c.disconnect()
```

### 3. Работа с правами и пользователями

Убедитесь, что:

- У пользователя, под которым вы выполняете команды, есть доступ к интерактивной сессии удаленного компьютера.
- `pypsexec` запущен с правами администратора.

### 4. Альтернатива - использование PowerShell

Вы также можете попробовать запустить приложение через PowerShell, который может иметь более гибкие настройки для запуска GUI-приложений на удаленной машине:

```python
import subprocess

def tray_pcard_kpp4_reboot(self):
    print('Запуск калькулятора через PowerShell')
    command = 'Invoke-Command -ComputerName 192.168.11.18 -ScriptBlock {Start-Process "calc.exe"}'
    subprocess.call(['powershell.exe', command], shell=True)
```
Это позволит вам выполнять команду PowerShell на удаленном ПК, и, возможно, позволит запустить приложение интерактивно.

Попробуйте одно из предложенных решений, чтобы достичь желаемого результата.
1. Используйте r перед ф-строкой во избежание нескольких invalid escape sequence: 
command = rf'C:\PsTools\psexec.exe -i 1 -s \\192.168.11.18 -u user -p password calc.exe'

У меня код с subprocess отрабатывает корректно:
import subprocess


def f():
    command = rf'C:\Portable\Sysinternal\PsExec.exe -i 1 -s \\192.168.0.3 -u user -p password calc.exe'
    return subprocess.call(command, stdout=subprocess.DEVNULL)


2. Вариант с pypsexec у меня отрабатывает некорректно - GUI запускается, но с артефактами.
Помимо interactive=True , надо указать номер сессии (можно узнать через cmd -> query user ), например: interactive_session=1 . Это аналог -i 1 в psexec.

c.run_executable (executable: "cmd.exe", arguments=r"/c start calc.exe", interactive=True, interactive_session=1)
Похожие вопросы