Use o Powershell para iniciar um programa GUI em uma máquina remota

4

Existem duas máquinas com Windows 7 configuradas na mesma rede. Ativei tudo o que é necessário para que eles pudessem se comunicar com winrm .

Quando eu executo o seguinte comando:

Invoke-Command -ComputerName REMOTE-PC -ScriptBlock { Start-Process calc.exe }

Funciona corretamente, mas o programa nunca é visto na máquina remota. Tanto quanto eu posso dizer, isso é um comportamento esperado.

Eu assumo que o processo inicia corretamente, e então é imediatamente fechado quando a sessão termina. Como executo o programa para que ele apareça na máquina host?

    
por Trevor Hickey 09.05.2015 / 21:43

3 respostas

7

Por design, você não deveria ser capaz de iniciar processos nas sessões de outras pessoas.

(Para esclarecer, mesmo se você estiver conectado interativamente em uma área de trabalho do computador e também tiver outro logon de rede separado na mesma máquina ao mesmo tempo usando as mesmas credenciais, elas ainda contam como duas sessões de logon diferentes .)

Isso é simplesmente contra o modelo de segurança do próprio Windows e tentativas de subversão serão desaprovadas. Portanto, você provavelmente não encontrará uma maneira fácil e suportável de fazer isso. É tecnicamente possível, mas envolve executar como Sistema Local, copiar outro token de segurança do usuário conectado e iniciar um processo com esse token alternativo. Você precisaria da API do Windows para isso, que é praticamente a única coisa em que o Powershell não é muito bom. Veja WTSQueryUserToken e CreateProcessAsUser na API do Windows para mais detalhes sobre isso.

Uma outra ideia, para não fazer xixi nas suas Cheerios, você pode conseguir isso criando remotamente uma tarefa agendada que inicia o processo. Consulte o link para mais informações sobre isso.

Editar: Ah, e esqueci ... tenho certeza que o PsExec com o parâmetro -i pode fazer isso. Você precisa fornecer o ID da sessão de logon. E tem permissões para isso. Ele provavelmente usa a mesma API do Windows que mencionei, o que aproveita o fato de que o PsExec instala um serviço temporário que é executado como Sistema Local.

    
por 09.05.2015 / 23:50
5

Consegui fazer isso funcionar usando o PsExec, como mencionado em outra resposta.

  1. Faça o download de PSTools
  2. Descompacte para C:\Windows\PSTools
  3. Adicione C:\Windows\PSTools ao seu PATH
  4. Obtenha o ID do processo da sessão do RDP ( tasklist funcionará ou uma linha exclusiva: $session = tasklist /fo CSV | findstr RDP ; $session = $session.Split(",")[3] ; $session.Split('"')[1] )
  5. Processo inicial: PsExec.exe -s -i 123 calc.exe ("123" é o ID da sessão RDP)

É assim que estou fazendo com o 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
    
por 29.05.2017 / 21:37
3

Você pode criar um 'gancho de chamada' na máquina remota: é uma tarefa agendada definida como "executar somente quando o usuário estiver conectado", designada para ser executada na conta do usuário que efetuará login após a execução. A ação da tarefa é o executável que você deseja executar.

Tarefas agendadas podem ser criadas remotamente via powershell ou schtasks e, posteriormente, chamadas simplesmente pelo 'nome' da tarefa em si usando o schtasks ou o Start-ScheduledTask do powershell.

  1. Na máquina remota, crie uma tarefa agendada de barebones que é executada pelo usuário que está executando a sessão atual.
  2. Definir a tarefa para ser executada "somente quando o usuário estiver conectado"
  3. Se o arquivo .exe ou item na guia "Ação" da tarefa agendada tiver "Executar como administrador" definido no item do sistema de arquivos (clique com o botão direito, Propriedades, Compatibilidade > Executar como administrador), a tarefa agendada precisará ser executar com privilégios elevados também ou irá falhar ou não aparecer.
  4. O autor da tarefa agendada deve ter privilégios de administrador, para que, quando chamado remotamente, você possa usar essa conta de administrador para chamar uma tarefa agendada que será executada no perfil de usuário especificado em "executar somente quando o usuário estiver conectado "
  5. Verifique se a máquina está conectada como esse usuário.
  6. Pode ser dependente do aplicativo se essa tarefa for executada corretamente se a máquina estiver bloqueada. Na minha experiência, faz.
  7. A partir daqui, você pode usar schtasks.exe e chamar o Nome da tarefa agendada juntamente com o nome do host e transmitir as credenciais da conta elevada usada para criar a tarefa agendada (não o usuário que fará logon) .
  8. Você pode alternativamente chamá-lo no powershell se a máquina remota estiver executando uma versão do PowerShell que suporte Start-ScheduledTask.

Para chamar a tarefa, você faz referência à tarefa pelo Nome que você atribuiu:

schtasks /run /TN "mytaskname" /s "host" /u "user" /p "password"

É possível criar uma tarefa agendada remotamente com schtasks.exe ou New-ScheduledTaskPrincipal no powershell. Se o executável ou item "Ação" na tarefa for sinalizado como "executar como administrador" no sistema de arquivos, a tarefa exigirá que uma credencial New-ScheduledTaskPrincipal seja anexada durante a criação da tarefa para definir essa propriedade apropriadamente.

O usuário atualmente conectado pode ser um alvo em movimento, embora possa ser consultado com Get-LoggedOnUser via powershell antes da própria criação da tarefa agendada.

O código detalhado para tal será publicado nas próximas 48 horas. Eu queria disponibilizar a estrutura básica para todos vocês.

    
por 07.03.2017 / 21:55