Powershell - массовые рассылки сообщений на доменные ПК в AD

 

Всем привет

Навеяно не очень давним сбоем одного известного почтовика...)

И так, начнем

Когда падает почтовый сервис, будь он сторонним, либо на своем железе, то резко возникает потребность предупредить пользователей о его недоступности на некоторое время, что для этого нужно?

  • Развернутая в сети AD DC
  • Развернутый WinRM на доменных ПК
  • Скрипт Powershell'a

1. В интернете море инструкций как реализовать это дело, можно на Win-серверах, можно на линуксовой самбе, оно работает и там и там, как вводить ПК в домен - надеюсь, все знают :)

2. Как развернуть WinRM - есть куча способов, самый удобный, где не приходится бегать до компов юзеров - это через доменные политики. Напомню, что при создании этой политики необходимо сделать запуск службы WinRM (WS-Remote Manager) автоматическим, в "брандмауэре Windows в режиме повышенной безопасности" открыть 5985/5986 порты (желательно только для одного IP-адреса для повышения безопасности), и, напоследок, разрешить, собственно, само удаленное управление - Административные шаблоны/Компоненты Windows/Удаленное управление Windows/Служба удаленного управления Windows "Разрешить удаленное администрирование сервера средствами WinRM", а в соседнем пункте настройки политики "Удаленная оболочка Windows" включить "Разрешить доступ к удаленной оболочке".

Сохраняем политику, ждем, пока они применятся - это зависит от настроек, по-умолчанию - 90 минут +- полчаса, либо при включении ПК и залогинивании пользователя, на Wi-Fi, допустим на Win7 политики цепляются не всегда сразу.

На случай, если политика не применилась - можно использовать

gpupdate /force

в командной строке cmd или Powershell'а

3. Вариаций отправки сообщений существует несколько, я пользуюсь двумя

3.1

$name = (Get-ADComputer -SearchBase "DC=TSPC,DC=RU" -Filter *).Name
$message = read-host "Введите ваше сообщение"
$computers | ForEach {Invoke-Command -Computer $name -scriptblock {param ($message) msg * "$message"} -args $message}

При желании - туда можно прикрутить окно

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Сообщение всем'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,120)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,120)
$cancelButton.Size = New-Object System.Drawing.Size(75,23)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'Введи сообщение'
$form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(260,70)
$textbox.Multiline = $true
$form.Controls.Add($textBox)
$form.Topmost = $true
$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{ $message = $textBox.Text
$message
$name = (Get-ADComputer -SearchBase "DC=TSPC,DC=RU" -Filter *).Name
$computers | ForEach {Invoke-Command -Computer $name -scriptblock {param ($message) msg * "$message"} -args $message}}
GUI скрипта массовой рассылки
GUI скрипта массовой рассылки

3.2 WMI-Метод массовой рассылки.

Ничего принципиального в скрипте не меняется кроме строки

$computers | ForEach {Invoke-Command -Computer $name -scriptblock {param ($message) msg * "$message"} -args $message}}

Она заменяется на

$computers | ForEach {Invoke-WmiMethod -Path Win32_Process -Name Create -ArgumentList "msg * $msg" -ComputerName $name}

к этому так же можно прикрутить оконный интерфейс

3й способ - вызвать сообщение на доменном ПК через управление планировщиком задач - но он избыточен для данной задачи массовой рассылки

Кто осилил - всем спасибо за внимание, дополняйте в комментах недочеты