Olá a todos!
Neste post mostro como juntei a ideia dos scripts que postei recentemente Definindo permissão de horário dos colaboradores no Active Directory e Forçar shutdown das estações de trabalho. E assim além de setar via powershell os atributos do Active Diretory para determinar o horário de login e da mesma maneira, via script, enviar um comando de desligando, neste post mostro como podemos incrementar um pouco mais, como por exemplo enviar uma mensagem para o usuário informando que o logoff da estação ocorrerá em X minutos, além de tratar em paralelo tanto as contas de usuário quanto as estações de trabalho.
- O primeiro passo aqui foi definir alguns parâmetros que vou precisar utilizar mais adiante no laço onde trato a mensagem que será enviada para o usuário.
- Sempre inicio os scripts definindo o arquivo de log, assim posso acompanhar o que está acontecendo, no PowerShell venho utilizando o “Start-Transcript” e tem me atendido bem.
- Gero uma variável com a lista de usuários não possuem limitação de acesso por horário e ajusto o atribito logonHours deles. Lembrando que por padrão defini que todo e qualquer novo usuário possui restrição de horário.
- Após isso trato a exceção de estações, comparando com as estações ativas (lista gerada pelo DHCP + checagem via ping, por exemplo) e ao final tenho a lista de máquinas para onde será enviado o comendo de logoff.
- E por último temos o logoff propriamente dito, onde através de um “while” envio mensagens a cada 5 min para o usuário informando que a máquina sofrerá o logoff, nesse exemplo começo a enviar as mensagens 15 min antes do horário definido para o logoff em si. E esse passo só foi possível por encontrei um script brilhante que tratava essa contagem regressiva e me ajudou demais a concluir esse script, no final do post deixei os links de referência.
param([int]$timeleft = 15)
Start-Transcript -path “D:\ScriptsAD\Logs\logoff_connected_users.log”
############### Ajusta do logon hours da lista de exceção de usuários ###############
$UsersReleased = get-content “D:\ScriptsAD\LogoffDiario\usuarios_liberados.txt”
foreach($User in $UsersReleased)
{
### Sem restrição de horário
$logonHours = @{“logonHours” = [byte[]]$hours=@(255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255)}
Set-ADUser $User -Replace $logonHours}
############### Lista de máquinas via DHCP e faz comparação com as máquinas liberadas ###############
Clear-Content “D:\ScriptsAD\logoff_pcs.txt”
$ClientReleased = get-content “D:\ScriptsAD\LogoffDiario\pcs_liberados.txt”
$dhcplist = Get-DhcpServerv4Lease -ComputerName “ad.dominio.local” -ScopeId 192.168.0.0 |Select-Object -property HostName
$logofflist = New-object System.Collections.ArrayList
foreach ($dhcpclient in $dhcplist)
{
$achou = 0foreach ($Client in $ClientReleased)
{
if ($dhcpclient -match $Client){$achou = 1}
}
if ( $achou -eq 0) {$logofflist.Add($dhcpclient)}
}
$logofflist = $logofflist -replace ‘@{HostName=’,”
$logofflist = $logofflist -replace ‘}’,”
$logofflist = $logofflist -replace ‘\s’,”“Flushing DNS”
ipconfig /flushdns | out-null“Registering DNS”
ipconfig /registerdns | out-null$logofflistping = New-object System.Collections.ArrayList
Foreach($Clientping in $logofflist) {
if (!(Test-Connection -Cn $Clientping -BufferSize 16 -Count 1 -ea 0 -quiet))
{
$ping = 1
“Cliente $Clientping inacessível”
}Else
{$ping = 0}
if ($ping -eq 0)
{
$logofflistping.Add($Clientping)
“Incluindo cliente $Clientping na lista de estacoes ativas”
}}
$logofflistping | Out-File “D:\GERENCIAS\COTEC\ScriptsAD\logoff_pcs.txt”
############### Logoff de estações ###############
Write-Output “Iniciando contador em $(Get-Date -format g)”
[System.Reflection.Assembly]::LoadWithPartialName(“System.Diagnostics”)
$countdowntimer = new-object system.diagnostics.stopwatch
while($timeleft -gt 0)
{
“Acompanhando o Timeleft $timeleft e o Countdowntimer $Countdowntimer”
$countdowntimer.start()
foreach ($_ in get-content “D:\ScriptsAD\logoff_pcs.txt”) {msg * /SERVER:$_ “Sua sessão será finalizada em $timeleft minutos. Salve seus arquivos e encerre os programas.”}
while ($countdowntimer.elapsed.minutes -lt 5) {write-progress -activity “Elapsed Time” -status $countdowntimer.elapsed}
$countdowntimer.reset()
$timeleft -= 5
}
Write-Output “Iniciando o logoff das estações $(Get-Date -format g)”
foreach ($_ in get-content “D:\ScriptsAD\logoff_pcs.txt”) {(gwmi Win32_OperatingSystem -ComputerName $_).Win32Shutdown(4)}
Stop-Transcript
# Lista de códigos para o uso do Win32Shutdown( )
# 0 – logoff
# 4 – logoff forçado
# 1 – desligamento
# 5 – desligamento forçado
# 2 – reiniciar
# 6 – reinicialização forçada
# 8 – desligar
# 12 – desligamento forçado
Fontes de pesquisa:
https://www.resdevops.com/2012/09/12/remote-logoff-all-windows-users-with-powershell
https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32shutdown-method-in-class-win32-operatingsystem
https://docs.microsoft.com/en-us/powershell/module/dhcpserver/get-dhcpserverv4lease?view=win10-ps