I saw this one:
Identify open User sessions on all domain serversAs I worked on the request I had to hit the boards a few times, but, I eventually cobbled together this to drag out all logged on users:
Geistvolf
Check domain Servers daily for open user sessions. Computer Management:System tools>Shared Folders>sessions takes a long time. We must identify open user sessions and choose sessions we need to terminate.
function Get-LoggedOnUser {
[CmdletBinding()]
param(
[Parameter(
Mandatory=$true
)]
$computerName
)
Get-WmiObject -ComputerName $computerName -Class Win32_LoggedOnUser | `
Select-Object @{Expression={$_.__SERVER}; Name="Server"}, `
@{Expression={$_.Antecedent.ToString().Split("=")[2].Replace("`"","")};Name="User"};
}This raw function uses the Get-WmiObject cmdlet to access the Win32_LoggedOnUser. I tried this location at first by omitting the -ComputerName parameter, but, found I needed it as I attempted to solve the second portion of the request: "sessions on ALL domain servers". Some of the biggest issues I had revolved around:- machine accessibility and RPC issues
- stale AD entries
Server User
-------- --------
MyMachine WillBy combing this basic logic with the Scripting Guys post I arrived at this final script:<#
.AUTHOR
Will Steele (wlsteele@gmail.com)
.DEPENDENCIES
n/a
.DESCRIPTION
This script searches the current domain and returns all currently logged in
users for the machines with a valid RPC (port 135) connection. If a
connection cannot be formed, the machine name will be returned with an error
message.
.EXAMPLE
n/a
.EXTERNALHELP
None.
.FORWARDHELPTARGETNAME
None.
.INPUTS
System.Object
.LINK
http://technet.microsoft.com/en-us/library/ff730959.aspx.
.NAME
Get-UsersLoggedOnDomain
.NOTES
If stale entries exist in AD or the local machine cache the script will error
when it encounters these machine, but, the script will continue processing.
.OUTPUTS
System.Array
.SYNOPSIS
Returns a list of logged on user sessions for the current domain.
#>
#region functions
function Get-LoggedOnUsers {
[CmdletBinding()]
param(
[Parameter(
Mandatory=$true
)]
$computerName
)
Try {
Get-WmiObject -ComputerName $computerName -Class Win32_LoggedOnUser | Select-Object @{Expression={$_.__SERVER}; Name="Server"}, @{Expression={$_.Antecedent.ToString().Split("=")[2].Replace("`"","")};Name="User"} -ErrorAction Stop;
}
Catch {
Write-Output "$computerName was not accessible.";
}
}
function Get-PingStatus {
[Cmdletbinding()]
param (
[Parameter(
Mandatory=$false,
Position=0,
ValueFromPipeline=$true
)]
[System.String] $computerName = $env:COMPUTERNAME
)
$ping = Get-WmiObject -Query "SELECT * FROM Win32_PingStatus WHERE Address='$computerName'"
if ($ping.StatusCode -eq 0) {
return $true;
} else {
return $false;
}
}
function Test-Port {
Param(
[string] $srv,
$port=135,
$timeout=3000,
[switch]$verbose
)
# Test-Port.ps1
# Does a TCP connection on specified port (135 by default)
$ErrorActionPreference = "SilentlyContinue"
# Create TCP Client
$tcpclient = new-Object system.Net.Sockets.TcpClient
# Tell TCP Client to connect to machine on Port
$iar = $tcpclient.BeginConnect($srv,$port,$null,$null)
# Set the wait time
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
# Check to see if the connection is done
if(!$wait)
{
# Close the connection and report timeout
$tcpclient.Close()
if($verbose){Write-Host "Connection Timeout"}
Return $false
}
else
{
# Close the connection and report the error if there is one
$error.Clear()
$tcpclient.EndConnect($iar) | out-Null
if(!$?){if($verbose){write-host $error[0]};$failed = $true}
$tcpclient.Close()
}
# Return $true if connection Establish else $False
if($failed){
return $false
} else {
return $true
}
}
#endregion functions
#region script body
$strFilter = "computer"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.SearchScope = "Subtree"
$objSearcher.PageSize = 1000
$objSearcher.Filter = "(objectCategory=$strFilter)"
$colResults = $objSearcher.FindAll()
# Create empty arrays for storing results
$errored = $results = $null;
# Return logged on users based on computer name
foreach ($i in $colResults) {
Write-Output "Processing $($i.GetDirectoryEntry().Name)";
if((Test-Port -srv $i.GetDirectoryEntry().Name) -and (Get-PingStatus -computerName $i.GetDirectoryEntry().Name)) {
Try {
$results += Get-LoggedOnUsers -computerName $i.GetDirectoryEntry().Name;
}
Catch {
Write-Output "$($i.GetDirectoryEntry().Name) was not accessible.";
}
} else {
Write-Output "$($i.GetDirectoryEntry().Name) cannot be accessed over port 135.";
}
}
# Output results.
Write-Output "Successfully processed machines:"
return $results;
#endregion script bodyI added it to the Technet repository:http://gallery.technet.microsoft.com/scriptcenter/Get-LoggedOnDomainUsersps1-f6775285
0 comments:
Post a Comment