Quem lembra do net send do Windows XP, pois bem, chegou a hora de aposentar ele.
Bem-vindo msg.exe!
O msg.exe envia uma mensagem para um usuário. Este usuário deve estar conectado como usuário de domínio (Perfil de Domínio). O que significa que o seguinte funciona apenas em um ambiente de domínio. Para técnicos de rede: msg usa a porta 445 (SMB / CIFS). Se você enviar uma mensagem para um usuário, precisará fornecer um nome de computador e um nome de usuário. Ou você pode tentar enviar uma mensagem para si mesmo:
1 |
msg * "Olá, este é um teste!" |
* significa que a mensagem é enviada a todos os usuários conectados. Lembre-se de que o Windows é um sistema operacional multiusuário. Não esqueça os outros!
Imagine a seguinte situação, você precisa enviar uma mensagem a todos os computadores clientes que estejam armazenados em um OU (Unidade Organizacional) específica, denominada Desktops. Você deseja informar a todos usuários conectados a esses computadores. Vamos usar o comando Invoke-Command. Verifique se os computadores clientes aceitam comandos do Remote PowerShell. Você pode executar o Enable-PSRemoting em cada um deles. Ou você pode configurar o WinRM usando diretivas de grupo, conforme demostrei neste artigo aqui.
Pré requisitos
- Todos os computadores devem residir no mesmo domínio.
- O WinRM deve ser ativado nos computadores clientes executando Enable-PSRemoting ou configurando através de Diretivas de Grupo, conforme descrito no link acima. Observe que, nos sistemas operacionais Windows Server 2012/2016, o WinRM é ativado por padrão, mas não nos sistemas Windows Client.
- Abrir a porta 445 no firewall.
Powershell e msg.exe em Ação
Primeiro execute o Powershell como administrador.
Vamos aprender agora enviar uma mensagem a todos os usuários conectados nas estações de trabalho que estão na OU (Unidade Organizacional) com o nome Desktops, com a seguinte mensagem: “Feche todos os arquivos abertos. O servidor será desligado em 5 minutos.”.
1 |
(Get-ADComputer -SearchBase "OU=Desktops,DC=contoso,DC=local" -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * "Feche todos os arquivos abertos. O servidor será desligado em 5 minutos."}} |
Agora vamos aprender a enviar a mesma mensagem, mas com um diferencial, vamos ter um time, a mensagem vai ficar 15 minutos ou até a hora que usuário ler e clicar em OK na mensagem enviada.
1 |
(Get-ADComputer -SearchBase "OU=Desktops,DC=contoso,DC=local" -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * /time:900 "Feche todos os arquivos abertos. O servidor será desligado em 15 minutos."}} |
Observação: O parâmetro time será contado em segundos. 900 é o que equivalente a 15 minutos.
Um outro parâmetro que podemos adicionar um usuário específico, neste exemplo será o carlos.luiz, o comando fica assim:
1 |
(Get-ADComputer -SearchBase "OU=Desktops,DC=contoso,DC=local" -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg carlos.luiz "Feche todos os arquivos abertos. O servidor será desligado em 5 minutos."}} |
Observação: O usuário deve estar conectado no momento.
Agora vamos usar o msg.exe sem o Powershell.
Primeiro execute o CMD (Prompt de Comando) como administrador.
Podemos enviar mensagens para um computador e usuários, ambos devem estar conectados. Para isso usamos o seguinte comando:
1 |
msg /server:DESKTOP-6KHKKLM gabriel.luiz Feche todos os arquivos abertos. O servidor será desligado em 5 minutos. |
Observação: o parâmetro server é o hostname do computador no qual queremos enviar a mensagem que é o DESKTOP-6KHKKLM, também devemos colocar o usuário que estar conectado, neste exemplo será o usuário gabriel.luiz.
Referências
https://docs.microsoft.com/pt-br/windows-server/administration/windows-commands/msg
https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adcomputer?view=win10-ps
Inscreva-se no meu canal do YouTube!
Há 10 anos atuo na área de TI focado em suporte e administração de infraestrutura, especializado em plataformas Microsoft. Tenho grande experiência em troubleshooting, implantação, configuração e administração de funções e recursos de tecnologia Microsoft. Formado em Redes de Computadores pela faculdade Estácio de Sá de Belo Horizonte.
Comecei a compartilhar o meu conhecimento no ano de 2012, fazendo artigos e vídeos para o meu Blog. Em 2017 comecei a escrever artigos para o portal Cooperati.
Sou apaixonado em compartilhar o meu conhecimento. Meu lema é: um conhecimento só é válido quando compartilhado.
25 Responses
Boa tarde estou executando do comando através do Windows 10 Pro, e o comandao Get-ADComputer não é reconhecido. Eu preciso habilitar algo além das configurações acima citadas?
Bom dia. Muito obrigado por prestigiar o meu trabalho. O comando Get-ADComputer deve ser executado no seu controlador de domínio ou você deve instalar o RSAT do AD LDS que incluem ferramentas de linha de comando do AD no seu Windows 10.
http://gabrielluiz.com/2020/04/rsat-windows-10-versao-1809
Boa tarde Gabriel Luiz,
Obrigado pelo post, muito útil, fiquei com duvidas somente em dois pontos.
Na linha de comando que você enviou com o timer de 15 minutos, ficou identica a primeira, entao nao consegui entender as variaveis para o tempo, se puder mandar por favor, ambas estão assim:
(Get-ADComputer -SearchBase “OU=Desktops,DC=contoso,DC=local” -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * “Feche todos os arquivos abertos. O servidor será desligado em 5 minutos.”}}
Outra coisa é que o nome do dominio por aqui é task.local então eu precisaria colocar DC=task, DC=local?
Bom dia. Muito obrigado por prestigiar o meu trabalho.
Foi apenas um erro de digitação, já fiz a correção. Correto DC=task, DC=local se seu domínio for igual a task.local. Mas são se esqueça de colocar o caminho da OU, onde encontra-se os objetos de computadores do seu AD.
Boa tarde. Quando ou o comando: (Get-ADComputer -SearchBase “OU=Computadores,DC=cetamsede,DC=local” -Filter *).Name |Foreach-Object {Invoke-Command -ComputerName $_ {msg * “Mensagem de teste”}}
Tenho essa msg de erro: Não é possivel validar o argumento no parametro “ComputerName” . O argumento é nulo ou vazio.
Alguma ideia doq possa ser?
Estou usando windows server 2008 R2
Boa noite! Muito obrigado por prestigiar o meu trabalho. Windows server 2008 R2 é um sistema operacional antigo, alguma coisas não pode funcionar bem mais.
Recomendo atualizar o Powershell dele para uma versão mais nova.
Todo o processo de atualização esta neste artigo https://cooperati.com.br/2017/11/como-atualizar-o-powershell-em-versoes-mais-antigas-do-windows-server-e-windows-cliente/
Depois me informe se deu certo.
Olá, boa tarde, ao tentar executar o comando para todos recebo a seguinte mensagem,
Get-ADComputer : O distinguishedName fornecido deve pertencer a uma das seguintes partições: ‘DC=sell,DC=local ,
CN=Configuration,DC=sell,DC=local , CN=Schema,CN=Configuration,DC=sell,DC=local , DC=DomainDnsZones,DC=sell,DC=local ,
DC=ForestDnsZones,DC=sell,DC=local’.
No linha:1 caractere:2
+ (Get-ADComputer -SearchBase “OU=Desktops,DC=task,DC=local” -Filter *) …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADComputer], ArgumentException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Comm
ands.GetADComputer
Boa noite. Muito obrigador por prestigiar o meu trabalho.
Você deve esta informando o distinguishedName “OU=Desktops,DC=contoso,DC=local” de forma errada para informar a OU aonde contém os objetos computadores do AD.
(Get-ADComputer -SearchBase “OU=Desktops,DC=contoso,DC=local” -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * “Feche todos os arquivos abertos. O servidor será desligado em 5 minutos.”}}
Olá Gabriel, parabéns pelo conteúdo!
Existe alguma maneira prática de enviar uma mensagem programada (por exemplo, de 2 em 2 horas) para todos os PCs da rede?
Gostaria de enviar um alerta para todos os usuários, conforme abaixo:
“Está na hora de beber água! Pare por alguns minutos e se hidrate, a seu corpo e a sua saúde agradecem!”
Bom dia. Muito obrigado por prestigiar o meu trabalho. Existe sim. Bastar criar um bat no servidor e agendar a tarefa usando o agendador de tarefas do Windows para o horário que deseja executar.
Boa noite Gabriel, tudo bem ? Primeiramente obrigado por partilhar esse conteúdo. Vê se consegue me ajudar por gentileza.
Estou tendo a seguinte dificuldade: Quanto tiro do comando OU=Computadores e deixo somente o domínio DC=gpmmhmg,DC=local dá certo.
COMANDO:
PS C:\Windows\system32> (Get-ADComputer -SearchBase “OU=Computadores,DC=gpmmhmg,DC=local” -Filter *).Name | Foreach-Object
{Invoke-Command -ComputerName $_ {msg * “Essa e uma mensagem de teste.”}}
ERRO:
Get-ADComputer : Directory object not found
At line:1 char:2
+ (Get-ADComputer -SearchBase “OU=Computers,DC=gpmmhmg,DC=local” -Filte …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-ADComputer], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,M
icrosoft.ActiveDirectory.Management.Commands.GetADComputer
Boa tarde. Muito obrigado por prestigiar o meu trabalho. Seu erro é um erro clássico que acontece. Bem provável que em seu domínio você esteja armazenando os objetos computadores (Computers) no Contêiner. Lembre-se contêiner e não OU (unidade organizacional) por isto acontece o erro, você mandou procurar em Get-ADComputer -SearchBase “OU=Computadores,DC=gpmmhmg,DC=local” “OU=Computadores”.
O que eu recomendo, crie uma OU na raiz do seu domínio gpmmhmg.local chamada Estações de trabalho e altere o comando para Get-ADComputer -SearchBase “OU=Estações de trabalho,DC=gpmmhmg,DC=local
Depois manda o feedback aqui.
Fala Gabriel, boa noite! É exatamente isso cara, deu certo. Só fiquei na dúvida porque eu tinha criado a OU, e ela estava dentro de outra OU (Ex: OU Empresas – OU Computadores), ai não funcionou. Quando puxei para raiz como vc disse, funcionou. Obrigado mais uma vez.
Boa noite. Fico feliz que funcionou.
Boa tarde Gabriel, tranquilo ?
Me tira uma dúvida por gentileza, o ad aqui está estruturado, exemplo tem o diretório Empresas – Empresa x – Setor ADM – Usuários – Computadores. Ai cada setor tem suas sub OUs Computadores, usuários, grupos, etc. Ai segue tbm para Financeiro – Computadores – MKT – Computadores…etc.
Quando coloco a OU principal (Ex: Empresas) que está na raiz e que engloba todas essas outras abaixo que incluiu computadores de todos setores, a msg não vai. Funciona apenas se eu tiver uma OU na raiz e colocar todas as contas de computadores nela ?
Obrigado.
Bom dia. Muito obrigado por prestigiar o meu trabalho.
Agora vamos a sua dúvida. Utilize o atributo distinguishedName para localizar o caminho completo da OU no qual o objeto computadores estão inseridos.
Exemplo: Se você tem uma OU Computadores dentro da OU Financeiro, que está dentro da OU Setores, que por sua vez está dentro do domínio contoso.local. O caminho seria: OU=Computadores,OU=Financeiro,OU=Setores,DC=contoso,DC=local
O caminho completo da OU aparece no atributo distinguishedName, em Editor de Atributo. Você pode acessar ele através de Usuários e Computadores do Active Directory, para visualizar está aba necessário ir em Exibir, logo depois clicar em Recursos avançados.
Após colocar o atributo distinguishedNamem, basta colocar no comando, conforme demostra o exemplo abaixo:
(Get-ADComputer -SearchBase “OU=Computadores,OU=Financeiro,OU=Setores,DC=contoso,DC=local” -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * “Feche todos os arquivos abertos. O servidor será desligado em 5 minutos.”}}
Bom dia Gabriel,
Maravilha…obrigado pelo retorno, vou fazer os testes aqui, deve funcionar.
Abraços!
Olá bom dia, pode me tirar uma duvida a respeito do AD? gostaria de replicar um comando de exclusao de arquivos temporarios, cache, como conseguiria? qual comando usaria?
Boa tarde. Muito obrigado por prestigiar o meu trabalho. Tudo depender que tipo de comando deseja utilizar, scripts CMD, VBS, Powershell. Para isto basta configurar um script de logon.
Existe uma maneira mais moderna de fazer isto, Sensor de Armazenamento do Windows 10. http://gabrielluiz.com/2021/07/deploy-gpo-storage-sensor-windows10/
Olá amigo tudo bem, conteúdo muito bom. To com uma duvida no comando Get-ADComputer.. na rede em qual trabalho nosso dominio é dr.gov, os computdaores estão na Unidade Organizacionao DR e dentro outra como Computadores. Minha dúvida coloco assim: “(Get-ADComputer -SearchBase “OU=DR,OU=Computadores,DC=dr,DC=gov” -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg r.teixeira “Feche todos os arquivos abertos. O servidor será desligado em 5 minutos.”}} “, caso eu queira mandar pra um user só? E se ao invés de um user especifico eu quisesse mandar pra uma maquina especifica q pode ser usada por várias pessoas como ficaria?
Boa tarde. Muito obrigado por prestigiar o meu trabalho. Isto é demostrado também no artigo. Leia o artigo com calma.
Um outro parâmetro que podemos adicionar um usuário específico, neste exemplo será o carlos.luiz, o comando fica assim:
(Get-ADComputer -SearchBase “OU=Desktops,DC=contoso,DC=local” -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg carlos.luiz “Feche todos os arquivos abertos. O servidor será desligado em 5 minutos.”}}
Boa tarde.
Muito obrigado pelo tutorial.
Algumas máquinas estão com erro WinRm, como solucionar o erro?
PS C:\Users\Administrador> (Get-ADComputer -SearchBase “OU=Computadores,DC=hvm,DC=local” -Filter *).Name | Foreach-Object {Invoke-Command -ComputerName $_ {msg * “TESTE – TI”}}
[DESKTOP-EGAS9M4] Falha ao conectar ao servidor remoto DESKTOP-EGAS9M4 com a seguinte mensagem de erro: O WinRM não
pode concluir a operação. Verifique se o nome do computador especificado é válido, se o computador está acessível
pela rede e se uma exceção de firewall para o WinRM está habilitada e permite acesso desse computador. Por padrão, a
exceção de firewall do WinRM para perfis públicos limita o acesso a computadores remotos na mesma sub-rede local. Para
obter mais informações, consulte o tópico da Ajuda about_Remote_Troubleshooting.
+ CategoryInfo : OpenError: (DESKTOP-EGAS9M4:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : WinRMOperationTimeout,PSSessionStateBroken
[HVM-100] Falha ao conectar ao servidor remoto HVM-100 com a seguinte mensagem de erro: O WinRM não pode concluir a
operação. Verifique se o nome do computador especificado é válido, se o computador está acessível pela rede e se uma
exceção de firewall para o WinRM está habilitada e permite acesso desse computador. Por padrão, a exceção de firewall
do WinRM para perfis públicos limita o acesso a computadores remotos na mesma sub-rede local. Para obter mais
informações, consulte o tópico da Ajuda about_Remote_Troubleshooting.
+ CategoryInfo : OpenError: (HVM-100:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : WinRMOperationTimeout,PSSessionStateBroken
[HVM-87] Falha ao conectar ao servidor remoto HVM-87 com a seguinte mensagem de erro: O WinRM não pode concluir a
operação. Verifique se o nome do computador especificado é válido, se o computador está acessível pela rede e se uma
exceção de firewall para o WinRM está habilitada e permite acesso desse computador. Por padrão, a exceção de firewall
do WinRM para perfis públicos limita o acesso a computadores remotos na mesma sub-rede local. Para obter mais
informações, consulte o tópico da Ajuda about_Remote_Troubleshooting.
+ CategoryInfo : OpenError: (HVM-87:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : WinRMOperationTimeout,PSSessionStateBroken
[HVM-134-2] Falha ao conectar ao servidor remoto HVM-134-2 com a seguinte mensagem de erro: O WinRM não pode concluir
a operação. Verifique se o nome do computador especificado é válido, se o computador está acessível pela rede e se
uma exceção de firewall para o WinRM está habilitada e permite acesso desse computador. Por padrão, a exceção de
firewall do WinRM para perfis públicos limita o acesso a computadores remotos na mesma sub-rede local. Para obter mais
informações, consulte o tópico da Ajuda about_Remote_Troubleshooting.
+ CategoryInfo : OpenError: (HVM-134-2:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : WinRMOperationTimeout,PSSessionStateBroken
Bom dia.
Muito obrigado por prestigiar o meu trabalho. Parece que o seu firewall estar barrando a comunicação.
Você verificou os requisitos para utilização?
Se deseja explanar melhor o meu problema com imagens ou vídeo, entre no mue grupo do Telegram https://t.me/gabrielluizbrasil
ATENÇÃO: AO ENTRAR NO GRUPO DO TELEGRAM, RESPONDA RÁPIDO AS DUAS PERGUNTAS DE SEGURANÇA OU SERÁ BANIDO PELO ROBÔ.
#MVPBuzz
Apenas um Adendo o comando só vai funcionar se tiver comunicação com o WINRM habilitado nas máquinas.
Para habilitar usar o comando (Bem porcamente resumido)” Enable-PSRemoting -Force ” ira habilitar tudo e aceitar tudo, o que pode ser habilitado pela GPO também.
Boa noite. Muito obrigado por prestigiar o meu trabalho. Fico feliz com seu comentário, pois pode ajudar mais pessoas.
#MVPBuzz