пятница, 4 ноября 2016 г.

PowerShell: скрипт с графическим интерфейсом для подключения с помощью теневого сеанса ("Remote Desktop Shadow") к удалённым компьютерам в домене Active Directory

Данная утилита позволяет с удобством находить компьютеры в Active Directory и осуществлять подключение к консольным или RDP-сессиям пользователей с помощью теневого сеанса ("Remote Desktop Shadow"). Для ОС Windows ниже версии 8.1/2012 R2 будет использован стандартный "Удалённый помощник". Подключение происходит как в режиме просмотра, так и в режиме управления сеансом.


Скрипт обязательно сохранять в UTF-8 кодировке:

$HideWindow = '[DllImport("user32.dll")] public static extern bool ShowWindow(int handle, int state);'
Add-type -Name win -Member $HideWindow -Namespace native
[native.win]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0)
Add-Type -assembly System.Windows.Forms
Import-Module ActiveDirectory

Function OnLoad()
{
 $global:comps = Get-ADComputer -Filter * -Properties Name,OperatingSystem
 $listbox1.Items.Clear()
 foreach ($Item in $global:comps)
  {
   $listbox1.Items.Add($Item.Name)
  }
}

Function listbox1_SelectedIndexChanged()
{
 $label1.Text = ($global:comps | Where-Object {$_.Name -like $listbox1.SelectedItem}).OperatingSystem
}

Function listbox1_KeyUp()
{
 listbox1_SelectedIndexChanged
 if ($_.KeyCode -eq "Enter") {
  button1_Click
  return
 }
}

Function button1_Click()
{
 if ($listbox1.SelectedItem) {
  $compName = $listbox1.SelectedItem
 }
 else {
  $compName = $textbox1.Text
 }
 $os = Get-WmiObject -Computer $compName -Class Win32_OperatingSystem -ErrorVariable myerror
 if ($myerror) {
  [System.Windows.Forms.MessageBox]::Show($myerror.Exception.Message, "Ошибка")
  $myerror.clear()
  return
 }
 if ($os.Version.StartsWith("10") -or $os.Version.StartsWith("6.3")) {
  $regpath = "\\"+$compName+"\HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services"
  reg add $regpath /v Shadow /t REG_DWORD /d 2 /f
  $queryResults = (qwinsta /server:$compName | foreach { (($_.trim() -replace "\s+",","))})
  $sessionuserarray = @()
  $sessionidarray = @()
  foreach ($queryResult in $queryResults){
   if($queryResult.Split(",")[0] -eq "console" -and !$checkbox2.Checked){
    $global:sessionid = $queryResult.Split(",")[2]
   }
   elseif ($queryResult.Split(",")[0] -like "rdp-tcp#*" -and $checkbox2.Checked) {
    $sessionuserarray += $queryResult.Split(",")[1]
    $sessionidarray += $queryResult.Split(",")[2]
   }
  }
  if($global:sessionid -and !$checkbox2.Checked) {
   Connect
  }
  elseif ($sessionidarray -and $checkbox2.Checked) {
   $DialogForm = New-Object System.Windows.Forms.Form
   $DialogForm.Text = "Выбор удаленной сессии"
   $DialogForm.Width = 340
   $DialogForm.Height = 170
   $DialogForm.StartPosition = "CenterScreen"
   $DialogForm.AutoSize = $false
   
   $listboxDialog = New-Object System.Windows.Forms.ListBox
   $listboxDialog.Location  = New-Object System.Drawing.Point(0,0)
   $listboxDialog.Width = 325
   $listboxDialog.Height = 100
   $listboxDialog.Add_Click({listboxDialog_SelectedIndexChanged})
   $listboxDialog.Add_KeyUp({listboxDialog_SelectedIndexChanged})
   foreach ($ruser in $sessionuserarray) {
    $listboxDialog.Items.Add($ruser)
   }
   $DialogForm.Controls.Add($listboxDialog)
   
   $buttonDialog = New-Object System.Windows.Forms.Button
   $buttonDialog.Text = 'ОК'
   $buttonDialog.Location = New-Object System.Drawing.Point(90,100)
   $buttonDialog.Width = 160
   $buttonDialog.Height = 20
   $buttonDialog.Add_Click({buttonDialog_Click})
   $DialogForm.Controls.Add($buttonDialog)
   
   $DialogForm.ShowDialog()
  }
  else {
   if ($checkbox2.Checked) {
    [System.Windows.Forms.MessageBox]::Show("Невозможно идентифицировать RDP-сессию.", "Ошибка")
   }
   else {
   [System.Windows.Forms.MessageBox]::Show("Невозможно идентифицировать консольную сессию.", "Ошибка")
   }
  }
  Sleep(3)
  reg delete $regpath /v Shadow /f
 }
 else {
  msra /offerRA $compName
 }
}

Function listboxDialog_SelectedIndexChanged()
{
 $iter = 0
 foreach ($remuser in $sessionuserarray) {
  if ($remuser -like $listboxDialog.SelectedItem) {
   $global:sessionid = $sessionidarray[$iter]
  }
  $iter++
 }
}

Function buttonDialog_Click()
{
 Connect
 $DialogForm.Close()
}

Function textbox1_KeyUp()
{
 if ($_.KeyCode -eq "Enter") {
  button1_Click
  return
 }
 if ($_.KeyCode -eq "Down") {
  $listbox1.SelectedIndex++
  listbox1_SelectedIndexChanged
  return
 }
 if ($_.KeyCode -eq "Up") {
  $listbox1.SelectedIndex--
  listbox1_SelectedIndexChanged
  return
 }
 $listbox1.Items.Clear()
 $filtered_comps = $global:comps | Where-Object {$_.Name -like $textbox1.Text + '*'}
 foreach ($Item in $filtered_comps)
 {
  $listbox1.Items.Add($Item.Name)
 }
 $listbox1.SelectedIndex = 0
 listbox1_SelectedIndexChanged
}

Function Connect()
{
 if($checkbox1.Checked){
  mstsc /shadow:$global:sessionid /v:$compName /noConsentPrompt
 }
 else {
  mstsc /shadow:$global:sessionid /v:$compName /control /noConsentPrompt
 }
}

$MainForm = New-Object System.Windows.Forms.Form
$MainForm.Text = "Удаленный теневой сеанс"
$MainForm.Width = 360
$MainForm.Height = 345
$MainForm.StartPosition = "CenterScreen"
$MainForm.AutoSize = $false

$textbox1 = New-Object System.Windows.Forms.TextBox
$textbox1.Location  = New-Object System.Drawing.Point(0,0)
$textbox1.Width = 120
$textbox1.Height = 20
$textbox1.Text = ''
$textbox1.Add_KeyUp({textbox1_KeyUp})
$MainForm.Controls.Add($textbox1)

$button1 = New-Object System.Windows.Forms.Button
$button1.Text = 'Подключиться'
$button1.Location = New-Object System.Drawing.Point(165,0)
$button1.Width = 180
$button1.Height = 20
$button1.Add_Click({button1_Click})
$MainForm.Controls.Add($button1)

$checkbox1 = New-Object System.Windows.Forms.Checkbox
$checkbox1.Location  = New-Object System.Drawing.Point(165,20)
$checkbox1.Width = 180
$checkbox1.Height = 30
$checkbox1.Text = "Только просмотр"
$MainForm.Controls.Add($checkbox1)

$checkbox2 = New-Object System.Windows.Forms.Checkbox
$checkbox2.Location  = New-Object System.Drawing.Point(165,50)
$checkbox2.Width = 180
$checkbox2.Height = 30
$checkbox2.Text = "Подключаться к сеансам RDP"
$MainForm.Controls.Add($checkbox2)

$label1 = New-Object System.Windows.Forms.Label
$label1.Text = ""
$label1.Location = New-Object System.Drawing.Point(0,20)
$label1.Width = 165
$label1.Height = 90
$MainForm.Controls.Add($label1)

$listbox1 = New-Object System.Windows.Forms.ListBox
$listbox1.Location  = New-Object System.Drawing.Point(0,110)
$listbox1.Width = 345
$listbox1.Height = 200
$listbox1.Add_Click({listbox1_SelectedIndexChanged})
$listbox1.Add_KeyUp({listbox1_KeyUp})
$MainForm.Controls.add($listbox1)

OnLoad
$MainForm.ShowDialog()

1 комментарий:

  1. Здравствуйте, скажите как подправить код чтобы подключаться к сессиям других компьютеров. В данном скрипте работает только подключение к сессиям с запускаемого сервера, при выборе любого другого "Невозможно иденцифицировать RDP-сессию"

    ОтветитьУдалить