The estimated reading time 3 minutes
RDSMessenger.ps1
UPDATE 11/09/2019: If you like this script as module or EXE see my new post
In RDServer (Remote Desktop) environmets (also know with the legacy name terminalservices) you need to notify all active users, because there is a maintenace or anything else. I searched a while to find a thin solution for that, but did not find any proper solution. So I decided to write a short powershell script to do this task.
With Windows Server 2012 a new cmdlet was introduced
https://docs.microsoft.com/en-us/powershell/module/remotedesktop/send-rdusermessage?view=win10-ps
Send-RDUserMessage
The goal:
Link to my github repository:
https://github.com/blog-it-koehler-com/rdsmessenger
You can use this cmdlet after importing on the server where you want so send the notification. This message is also displayed in remoteapps so it can be used in mixed environments with desktop and remoteapps. (WIN2012/R2, WIN2016 and WIN2019 include this module by default).
NOTE: how to find the RD-Broker? If you don’t know which server is the broker, please open your ServerManager and connect all server which are part of the collection (ServerManager tells you which one is missing)
After importing all server in ServerManager you can see the configuration and also the broker
As mentioned there is one cmdlet which generates the message for one user. The heart of my script are these few lines:
Import-Module RemoteDesktop $broker = "FQDN of the Broker" $userids = Get-RDUserSession -ConnectionBroker "$broker" | sort Username foreach($uid in $userids){ $id = (($uid).UnifiedSessionID) Send-RDUserMessage -HostServer $($uid.HostServer) -UnifiedSessionID $id -MessageTitle "messagetitel" -MessageBody "text in your messagebox" }
With the following script you see some output when you execute the script.
Import-Module RemoteDesktop #fill message $msgtitel = Read-Host "Type message titel" $msg = Read-Host "Type message..." $broker = Read-Host "Type FQDN of rd broker server" #getting all user ids $userids = Get-RDUserSession -ConnectionBroker "$broker" | Sort-Object Username $sessions = ($userids | Select-Object UserName,UnifiedSessionId)|Out-String Write-host "Getting all active sessions on rd broker $broker" -ForegroundColor Yellow Write-host "$sessions" -ForegroundColor Yellow #send message to all user ids foreach($uid in $userids){ $id = (($uid).UnifiedSessionID) $user = (($uid).UserName) Send-RDUserMessage -HostServer $($uid.HostServer) -UnifiedSessionID $id -MessageTitle "$msgtitel" -MessageBody "$msg" Write-Host "Sending message to user: $user with titel: $msgtitel" -ForegroundColor Green } pause
here my script in action.
After this short introduction, see some tips to handle my ps script from github with parameters:
EXAMPLE 1 simple execution:
EXAMPLE 2 execution with parameters
.\rdmessenger.ps1 -rdbroker rds02.demo01.it-koehler.com -messagetitel “admin message” -message “message to display” -Verbose
EXAMPLE 3 execution with parameter -rdsessionhost
.\rdmessenger.ps1 -rdbroker rds02.demo01.it-koehler.com -messagetitel “admin message” -message “message to display” -rdsessionhost rds02.demo01.it-koehler.com
Features of this script:
- checks modules required
- imports modules required
- waiting 10 seconds before notification is send to all users
- see what it does with verbose command
Also have a look at my comments inside script if you want to know what it does.
If you have any further questions please leave me a message. If you like the tool click on helpful. Have fun sending messages to your users.
Was this article helpful?
YesNo
Do you remember the net send command? And do you remember the security concerns? Last week I played with msg.exe. Msg is the “new” net send. I tried to send a message to all users and computers in my domain. Why? I wanted to instruct all users to close all open programs. And now I want to keep and share this knowledge in form of this blog post.
Introduction (msg.exe)
Msg sends a message to a user. This user must be logged in as a domain user (Domain Profile). Which means that the following only works in a domain environment. For network technicans: msg uses Port 445 (SMB/CIFS). If you send a message to a user you have to provide a computername and a username. Or you can try sending a message to yourself:
msg * "Hallo, this is a test!"
* means, that the message is send to all logged on users. Keep in mind that Windows is a multi-user operating system. Don’t forget the others! 😉
Prerequisites
The headline is somewhat misleading. Yes, we are going to send messages to all users, but actually to all computers. Suppose all your client computers are stored in specific Organizational Unit called Workstations. You want to inform all users logged on to this computers. I am going to use Invoke-Command. Make sure, your client computers accepts Remote PowerShell commands. You can run Enable-PSRemoting on each of them. Or you could configure WinRM by using Group Policies:
Group Policies: Enabling WinRM for Windows Client Operating Systems (Windows 10, Windows 8, Windows 7)
Summary
- All Computers must reside in the same domain
- WinRM has to be enabled on the client computers by running Enable-PSRemoting or by configuring via Group Policies, as described in the link above. Note that on Windows Server 2012/2016 operating systems WinRM is enabled by default, but not on Windows Client systems.
Sending Messages to all Users: PowerShell and Msg.exe in Action
The following One-Liner gets all the computernames of the OU Workstations in the domain sid-500.com. Afterwards msg is executed for each computer in the OU Workstations. The message is send to all users which are currently logged on.
(Get-ADComputer -SearchBase "OU=Workstations,DC=sid-500,DC=com" -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * "Please close all open files. The Server will be shut down in 5 Minutes"}}
Client01 is a member of the OU Workstation. Client01 receives the message.
Have fun playing with msg!
See also
For more remote actions see also:
PowerShell: Enable Remote Desktop on multiple Servers remotely (Bulk)
PowerShell: Using Restart-Computer to restart your Computer and Remote Computers
Published by Patrick Gruenauer
Microsoft MVP on PowerShell [2018-2025], IT-Trainer, IT-Consultant, MCSE: Cloud Platform and Infrastructure, Cisco Certified Academy Instructor.
View all posts by Patrick Gruenauer
Частенько возникает необходимость предупредить пользователей терминального сервера о перезагрузке или технических работах. Проще всего это сделать сообщением, которое отображается по центру экрана в RDP-сессии. В Windows Server 2003/2008 R2 сообщение можно было отправить прямо из диспетчера задач, что на мой взгляд было весьма удобно. В следующих версиях Windows Server эту возможность убрали, но оставили консольную утилиту msg, которая вполне справляется с этой задачей.
1. С помощью диспетчера задач. Подходит для Windows Server 2003/2008 R2.
Диспетчер задач —> Вкладка Пользователи —> ПКМ —> Отправить сообщение.
2. Консольной утилитой msg. Подходит для любой версии Windows Server.
Утилита msg имеет достаточно большой функционал, но лично я обычно пользуюсь всего тремя командами.
Сообщение всем пользователям текущего сервера:
msg * «Сообщение»
Сообщение конкретному пользователю:
msg ИмяПользователя «Сообщение»
Сообщение пользователю другого сервера в локальной сети:
msg /server:ИмяСервера ИмяПользователя «Сообщение»
По умолчанию сообщение висит 1 минуту. Изменить время ожидания можно ключом /time:времявсекундах. Пример:
msg * /time:3200 «Сообщение»
Содержание
- Постановка задачи
- Методы отправки сообщения на RDS ферме
- Как отправить предупреждение пользователям RDS через диспетчер задач
- Использование утилиты MSG
- Третий метод отправки сообщения пользователям RDS через Send-RDUserMessage
Добрый день! Уважаемые читатели и гости IT блога Pyatilistnik.org. В прошлый раз мы с вами научились устанавливать библиотеку VCRUNTIME140.dll в операционных системах Windows. Сегодня я переключу наше внимание с клиентских ОС на серверные. Наверняка многие из обычных людей , а тем более системные администраторы знают, что такое терминальные службы, RDS ферма или удаленный стол (Удаленка). Это уже неотъемлемая часть бизнес процессов, для многих организаций. Бывают ситуации, что вам необходимо оповестить всех пользователей терминального сервера, о необходимости в его обслуживании. По мимо корпоративной почты вы можете, это делать и средствами Windows и сегодня я покажу, как отправить сообщение всем пользователям RDS фермы.
Постановка задачи
Необходимо научиться отправлять сообщение на терминальный стол всем пользователям, кто на нем работает, иметь возможность вводить текст сообщения. Данный функционал, очень полезен, когда у вас зависают пользовательские сессии и вам необходимо перезагрузить сервер, для его восстановления, но так как на нем есть активные сессии, то желательно бы предупредить сотрудников, чтобы они сохранили все свои данные.
Методы отправки сообщения на RDS ферме
- Отправка сообщение, через диспетчер задач
- Отправка сообщения через утилиту командной строки msg
- Отправка сообщения через командлеты PowerShell
Как отправить предупреждение пользователям RDS через диспетчер задач
Во времена терминальных служб на Windows Server 2008 R2, была замечательная возможность массовой отправки сообщений для всех пользователей фермы и делалось, это штатно из диспетчера задач. В 2008R2, когда вы запустите диспетчер задач и перейдете на вкладку «Пользователи», то у вас была возможность выделить их всех, щелкнуть правой кнопкой мыши и из контекстного меню выбрать пункт «Отправить сообщение».
У вас откроется окно «Отправка сообщений», где вы можете задать заголовок сообщения и его текст. После чего нажмите кнопку «Ок».
В результате все пользователи данного удаленного стола, получат вот такое сообщение в виде всплывающего окна.
Точно так же в Windows Server 2008 R2 вы могли произвести отправку оповещений, через оснастку «Диспетчер служб удаленных рабочих столов»
К сожалению начиная с Windows Server 2012 R2, данную возможность для массовой рассылки из диспетчера задач убрали, вы теперь не можете выделить всех пользователей.
Использование утилиты MSG
Есть такая замечательная утилита командной строки msg. Что хорошо, вы ей можете пользоваться на любом компьютере, хоть на Windows 8.1. Откройте cmd, желательно от имени администратора и просто введите:
У вас появится справка по утилите. Конструкция команды будет такой MSG {<пользователь> | <имя сеанса> | <ID сеанса> | @<имя файла> | *} [/SERVER:<сервер>] [/TIME:<секунд>] [/V] [/W] [<сообщение>]
- <пользователь> Имя пользователя.
- <имя сеанса> Имя сеанса. Удобно если нужно отправить конкретному сеансу.
- <ID сеанса> Идентификатор сеанса.
- @<имя файла> Файл, содержащий список имен пользователей, сеансов или идентификаторов сеансов, которым отправляется сообщение.
- * Отправить сообщение всем сеансам на указанном сервере.
- /SERVER:<сервер> Сервер (по умолчанию — текущий).
- /TIME:<секунд> Интервал ожидания подтверждения от получателя.
- /V Отображение информации о выполненных действиях.
- /W Ожидание ответа от пользователя, полезно вместе с /V.
- <сообщение> Отправляемое сообщение. Если не указано, выдается запрос или принимается ввод из STDIN.
Если нужно отправить сообщение всем людям локально с того же сервера, где они работают, то просто введите:
msg * Пожалуйста сохраните все свои файлы и завершите корректно ваши сессии в программах. Сервер будет перезагружен, через 5 минут С уважением, отдел технической поддержки
Вот так, например в Windows Server 2019 выглядит подобное оповещение на RDS ферме.
Для отправки оповещения на удаленный сервер вы должны использовать вот такую конструкцию:
msg * /server:svt2019s01 Пожалуйста сохраните все свои файлы и завершите корректно ваши сессии в программах. Сервер будет перезагружен, через 5 минут С уважением, отдел технической поддержки
Для отправки на несколько серверов, можно использовать вот такое построение команды:
invoke-command -computername computer1, computer2 -scriptblock {msg * «Ваш текст сообщения»}
Использование связки PowerShell и msg
(Get-ADComputer -SearchBase «OU=Workstations,DC=root,DC=pyatilistnik,DC=org» -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * «Текст сообщения»}
Если у вас выскакивает ошибка «Ошибка 1726 при получении имен сеанса» и сообщение не отправляется, то тут вся загвоздка в том, что у той учетной записи от имени которой открыта командная строка, просто не хватает прав. Вам нужно открыть cmd от имени пользователя у кого есть права на тот сервер.
Третий метод отправки сообщения пользователям RDS через Send-RDUserMessage
Безусловно самым популярным и универсальным методом отправки оповещений пользователям удаленного рабочего стола, являются командлеты PowerShell. Одним из таких командлетов выступает Send-RDUser
Справка по командлеты Send-RDUser
Запускаем PowerShell от имени администратора или нужного пользователя. Синтаксис будет такой:
Send-RDUserMessage -HostServer «svt2019s01.root.pyatilistnik.org» -UnifiedSessionID 1 -MessageTitle «От отдела технической поддержки» -MessageBody «Сообщение отправлено через Send-RDUser
- HostServer — Имя RDS сервера
- -UnifiedSessionID — идентификатор сеанса, к сожалению сразу нельзя выбрать всех, обязательно указывать число (Как определить номер сеанса пользователя, читайте по ссылке)
- -MessageTitle — Текст самого сообщения
Еще есть скрипт от Microsoft инженера https://gallery.technet.microsoft.com/scriptcenter/Send-NetMessage-Net-Send-0459d235
Еще есть возможность воспользоваться скриптом гуляющем по интернету:
- 1 скрипт
$Sessions = Get-TerminalSession -ComputerName «Имя сервера»
ForEach ($Session in $Sessions) {
Send-RDUserMessage -HostServer $Session.ServerName -UnifiedSessionID $Session.UnifiedSessionID -MessageTitle $MessageTitle -MessageBody $MessageText
}
- 2 скрипт
# $ConnectionBroker - Активный сервер RDCB. Если не указан, будет произведена попытка выявить его автоматически (для этого обязательно чтобы скрипт выполнялся на одном из серверов фермы RDS) # $SessionHostCollection – Имя RD-коллекции в которой нужно вывести сообщение.$ConnectionBroker = «»
$SessionHostCollection = «Терминал»$MessageTitle = «От кого)) «
$MessageText = «Текст «If ($ConnectionBroker -eq «») {
$HAFarm = Get-RDConnectionBrokerHighAvailability
$ConnectionBroker = $HAFarm.ActiveManagementServer
}$Sessions = Get-RDUserSession -ConnectionBroker $ConnectionBroker -CollectionName $SessionHostCollection
ForEach ($Session in $Sessions) {
Send-RDUserMessage -HostServer $Session.ServerName -UnifiedSessionID $Session.UnifiedSessionID -MessageTitle $MessageTitle -MessageBody $MessageText
}
Подробнее на https://blog.it-kb.ru/2013/11/15/remote-desktop-services-send-message-to-all-active-rds-farm-users-via-powershell
Кстати если вы неправильно развернули RDS ферму, то при выполнении скрипта получите сообщение
Get-RDUserSession : На svt2019s01.root.pyatilistnik.org не развернуты службы удаленных рабочих столов. Эту операцию можно выполнить после их развертывания. Для получения дополнительных сведений.
На этом у меня все. Мы рассмотрели несколько методов по массовой отправке сообщений пользователям удаленных рабочих столов. С вами был Иван Семин, автор и создатель IT портала Pyatilistnik.org.
Например, требуется срочно перегрузить терминальный сервер. Как быстро оповестить залогиненых пользователей о необходимости сохранить свои данные и корректно закрыть программы?
От имени Администратор запустим командную строку ( cmd.exe ).
msg.exe * /SERVER:<Имя сервера> "Текст сообщения"
вместо <Имя сервера> укажите имя терминального сервера к которому подключены пользователи.
Как отослать сообщение всем пользователям терминального сервера?
Метки: msg windows terminal
- ← Для чего нужен файл fstab?
- Как конвертировать файлы изображений и Microsoft Office в PDF в Windows 10 / Windows Server 2016 →
Добавить комментарий
Ваш адрес email не будет опубликован. Обязательные поля помечены *
Комментарий *
Имя *
Email *
Сайт
Сохранить моё имя, email и адрес сайта в этом браузере для последующих моих комментариев.