Closed smru closed 4 years ago
What version are you running? And what do you mean by "wrong results"?
Hi Bryan,
I'm running Windows 10 Enterprise, Version 1809 (OS Build 17763.134). plink.exe: Version 0.70.0.0, 2017-12-11 14:18, 617048 bytes. ssh.exe: Version 7.7.2.1, 2018-09-15 16:07, 882688 bytes. OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
The PowerShell scripts and results are in the attachments.
I use the following two statements to easily toggle between using plink.exe or ssh.exe.
$OpenSSH = $False $OpenSSH = $True
The Remote-Good.ps1 script always succeeds. See Good.txt. The Remote-Fail.ps1 script always fails when probing more than say 10 computers. See Fail.txt. However, the Remote-Fail.ps1 script always succeeds when probing just 1 computer. See One.txt. The Remote-Fail.ps1 script sometimes succeeds and sometimes fails when probing 4 computers. See Four.txt.
Best regards, Douwe.
On 2018-12-05 10:47, Bryan Berns wrote:
What version are you running? And what do you mean by "wrong results"?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/PowerShell/Win32-OpenSSH/issues/1301#issuecomment-444348707, or mute the thread https://github.com/notifications/unsubscribe-auth/ALGi4somGj59wXJp6aNTQ8AJWpC2-Ngeks5u10HYgaJpZM4Y9NyT.
################################################################################
################################################################################
function Add-Colors{
param([Parameter(Mandatory = $True)] $Status)
$Field = $Status -split "\t+"
if ($Field[0].Length -lt 0) { $Field[1] += "t" } if ($Field[1].Length -lt 8) { $Field[1] += "
t" }
if ($Field[2].Length -lt 8) { $Field[2] += "t" } if ($Field[3].Length -lt 8) { $Field[3] += "
t" }
if ($Field[3].Length -lt 16) { $Field[3] += "t" } if ($Field[4].Length -lt 8) { $Field[4] += "
t" }
if ($Field[5].Length -lt 0) { $Field[5] += "t" } if ($Field[6].Length -lt 8) { $Field[6] += "
t" }
if ($Field[6].Length -lt 16) { $Field[6] += "t" } if ($Field[6].Length -lt 24) { $Field[6] += "
t" }
if ($Field[7].Length -lt 0) { $Field[7] += "`t" }
if ($Field.Count -gt 8) {
if ($Field[8].Length -lt 8) { $Field[8] += "`t" }
if ($Field[8].Length -lt 16) { $Field[8] += "`t" }
}
if ($Field.Count -gt 9) {
if ($Field[9].Length -lt 8) { $Field[9] += "`t" }
if ($Field[9].Length -lt 16) { $Field[9] += "`t" }
if ($Field[9].Length -lt 24) { $Field[9] += "`t" }
if ($Field[9].Length -lt 32) { $Field[9] += "`t" }
}
# Start writing status line with all fields.
if ($Field[7] -match "Bitvise") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Dns") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Key") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Locked") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Offline") { Write-Host -ForegroundColor Cyan -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Online") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Passwrd") { Write-Host -ForegroundColor Magenta -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Plink") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Refused") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Ssh") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Timeout") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Unknown") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[0])`t" }
Write-Host -ForegroundColor Green -NoNewLine "$($Field[1])`t"
if ($Field[2] -match "SMRU") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[2])`t" }
if ($Field[2] -notmatch "SMRU") { Write-Host -ForegroundColor Yellow -NoNewLine "$($Field[2])`t" }
Write-Host -ForegroundColor Green -NoNewLine "$($Field[3])`t"
Write-Host -ForegroundColor Green -NoNewLine "$($Field[4])`t"
if ($Field[5] -match "32-bit") { Write-Host -ForegroundColor Yellow -NoNewLine "$($Field[5])`t" }
if ($Field[5] -notmatch "32-bit") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[5])`t" }
Write-Host -ForegroundColor Green -NoNewLine "$($Field[6])`t"
if ($Field[7] -match "Bitvise") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Dns") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Key") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Locked") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Offline") { Write-Host -ForegroundColor Cyan -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Online") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Passwrd") { Write-Host -ForegroundColor Magenta -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Plink") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Refused") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Ssh") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Timeout") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Unknown") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[7])`t" }
if ($Field.Count -gt 8) {
Write-Host -ForegroundColor Green -NoNewLine "$($Field[8])`t"
}
if ($Field.Count -gt 9) {
Write-Host -ForegroundColor Green -NoNewLine "$($Field[9])"
}
Write-Host
}
function Get-Inventory { param([Parameter(Mandatory = $True)] $File) $Chassis = "???" $Domain = "???" $Location = "???" $User = "???" $OSArch = "???" $OSName = "???" $OSVersion = "???" if (Test-Path -Path $File) { $Lines = Get-Content "$File" foreach ($Line in $Lines) { $Field = $Line -split "\t+" if ($Field) { if ($Field[0] -match "Chassis Type:") { $Chassis = $Field[1] } if ($Field[0] -match "Domain:") { $Domain = $Field[1] } if ($Field[0] -match "Location:") { $Location = $Field[1] } if ($Field[0] -match "User:") { $User = $Field[1] } if ($Field[0] -match "OS Architecture:") { $OSArch = $Field[1] } if ($Field[0] -match "OS Name:") { $OSName = $Field[1] } if ($Field[0] -match "OS Version:") { $OSVersion = $Field[1] } } } } else { Write-Host -ForegroundColor Magenta "File $File does not exist." } if ($OSVersion -ne "") { $OSName += " $OSVersion" }
if ($Chassis -eq "") { $Chassis = " " }
if ($Domain -eq "") { $Domain = " " }
if ($Location -eq "") { $Location = " " }
if ($User -eq "") { $User = " " }
if ($OSArch -eq "") { $OSArch = " " }
if ($OSName -eq "") { $OSName = " " }
if ($OSVersion -eq "") { $OSVersion = " " }
# Todo: Remove next 2 lines in next version.
if ($Domain -eq "smru.shoklo-unit.com") { $Domain = "SMRU" }
if ($Domain -eq "SMRU (smru.shoklo-unit.com)") { $Domain = "SMRU" }
if ($Domain.Length -lt 8) { $Domain += "`t" }
if ($Location.Length -lt 8) { $Location += "`t" }
if ($Location.Length -lt 16) { $Location += "`t" }
if ($User.Length -lt 8) { $User += "`t" }
$OSName = $OSName -replace " release", ""
if ($OsName.Length -lt 8) { $OSName += "`t" }
if ($OSName.Length -lt 16) { $OSName += "`t" }
if ($OSName.Length -lt 24) { $OSName += "`t" }
return @{
Chassis = $Chassis
Domain = $Domain
Location = $Location
User = $User
OSArch = $OSArch
OSName = $OSName
OSVersion = $OSVersion
# Create one or more consecutive tabs separated summary.
Summary = "$Domain`t$Location`t$User`t$OSArch`t$OSName"
}
}
function Get-RunspaceData { $OpenSSH = $True $OpenSSH = $False foreach($Runspace in $Runspaces) {
if ($Runspace.Runspace.IsCompleted) {
$Result = $Runspace.Powershell.EndInvoke($Runspace.Runspace)
Add-Colors $Result
} elseif ($Runspace.Runspace -ne $Null) {
$Computer = $Runspace.Computer
$Folder = $Runspace.Folder
$Info = Get-Inventory "O:\Inventory\$Folder\$Computer.log"
$Summary = $Info.Summary
if ($OpenSSH) {
$Result = "$Computer`t `t`t$Summary`tSsh"
} else {
$Result = "$Computer`t `t`t$Summary`tPlink"
}
Add-Colors $Result
}
$Runspace.Powershell.Dispose()
$Runspace.Runspace = $Null
$Runspace.Powershell = $Null
}
# Clean out unused runspace jobs.
$temphash = $Runspaces.Clone()
$temphash | Where-Object { $_.Runspace -eq $Null } | ForEach-Object { $Runspaces.Remove($_) }
}
$ScriptBlock = { param($Computer, $Folder, $Info)
$OpenSSH = $True
$OpenSSH = $False
# Function: Send command to remote computer using plink.exe.
# Parameters: The 1st parameter contains the command.
# Remarks: Cannot use "<dos command> *> $Null" in PowerShell 2.0. Instead
# use "cmd /c "<dos command> > nul 2>&1"". Any double quotes in
# the <dos command> need to be escaped with the backtick character.
# Remarks: Possible replies:
# The server's host key does not match the one PuTTY has cached.
# The server's host key is not cached in the registry.
# Remarks: It is possible that plink.exe does not return due to some issue
# on the remote computer.
# See https://powershell.org/forums/topic/timeout-for-runspace
# Returns: ???
function Send-PlinkCommand {
param([Parameter(Mandatory = $True)] $Computer,
[Parameter(Mandatory = $True)] $Command)
$Command = "plink.exe -batch -i `"$Env:UserProfile\id_rsa-auto.ppk`" `"Administrator@$Computer`" `"$Command`" 2>&1"
$Reply = Invoke-Expression $Command
if ($Reply -match "The server's host key ") {
# Update server's host key in PuTTY's cache if it does not match
# or add server's host key to PuTTY's cache if it is not cached.
# Putty's cache is HKCU:\Software\SimonTatham\PuTTY\SshHostKeys.
# Use "(echo y)" to output a yes followed by Enter.
$Cmd = "cmd /c `"(echo y) | $Command`""
$Cmd = $Cmd -replace " -batch", ""
$Null = Invoke-Expression $Cmd
# Try again.
$Reply = Invoke-Expression $Command
}
$Status = "Online"
if ($Reply -match "FATAL ERROR: ") { $Status = "Bitvise" }
if ($Reply -match "FATAL ERROR: Network error: Connection refused") { $Status = "Refused" }
if ($Reply -match "FATAL ERROR: Network error: Connection timed out") { $Status = "Timeout" }
if ($Reply -match "FATAL ERROR: Server unexpectedly closed network connection") { $Status = "Locked" }
if ($Reply -match "Server refused our key") { $Status = "Passwrd" }
if ($Reply -match "Unable to load key file") { $Status = "Key" }
if ($Reply -match "Unable to use key file") { $Status = "Key" }
return @{
Reply = $Reply
Status = $Status
}
}
# Function: Send command to remote computer using ssh.exe.
# Parameters: The 1st parameter contains the command.
# Remarks: Cannot use "<dos command> *> $Null" in PowerShell 2.0. Instead
# use "cmd /c "<dos command> > nul 2>&1"". Any double quotes in
# the <dos command> need to be escaped with the backtick character.
# Remarks: Possible replies:
# The server's host key does not match the one in known hosts.
# The server's host key is not listed in known hosts.
# Remarks: It is possible that ssh.exe does not return due to some issue
# on the remote computer.
# See https://powershell.org/forums/topic/timeout-for-runspace
# Returns: ???
function Send-SshCommand {
param([Parameter(Mandatory = $True)] $Computer,
[Parameter(Mandatory = $True)] $Command)
$Command = "ssh.exe -i `"$Env:UserProfile\id_rsa-auto`" -o `"BatchMode=yes`" `"Administrator@$Computer`" `"$Command`" 2>&1"
$Reply = Invoke-Expression $Command
if ($Reply -match "bad permissions") {
msg.exe * "Permissions for 'C:\\Users\\Administrator\\id_rsa-auto' are too open."
}
if ($Reply -match "Host key verification failed") {
# Update server's host key in list of known hosts if it does not match
# or add server's host key to list of known hosts if it is not present.
# List of OpenSSH known hosts is at C:\Users\<User>\.ssh\known_hosts.
$Cmd = $Command -replace " -o `"BatchMode=yes`"", " -o `"BatchMode=yes`" -o `"StrictHostKeyChecking=no`""
$Null = Invoke-Expression $Cmd
# Try again.
$Reply = Invoke-Expression $Command
}
$Status = "Online"
if ($Reply -match "Connection timed out") { $Status = "Timeout" }
if ($Reply -match "Connection closed by remote host") { $Status = "Locked" }
if ($Reply -match "Load key") { $Status = "Key" }
if ($Reply -match "No matching host key type found") { $Status = "Key" }
if ($Reply -match "password") { $Status = "Passwrd" }
return @{
Reply = $Reply
Status = $Status
}
}
# Function: Get online status (Bitvise/Dns/Key/Locked/Offline/Online/
# Passwrd/Plink/Refused/Ssh/Timeout/Unknown).
# Parameters: The 1st parameter contains the computer name.
# The 2nd parameter contains the inventory subfolder name.
# The 3rd parameter contains the inventory information.
# Remarks: When pinging a computer name it is possible that the DNS server
# returns an outdated IP address. To ensure that the IP address
# is correct, execute a remote command to tell its computer name
# or check that the MAC address in the arp table matches the one
# in the inventory.
# Remarks: Information about the various statuses returned:
# Bitvise Bitvise SSH Server fatal error.
# Locked Remote computer is locked out due to too many logon attempts.
# Offline Ping of remote computer failed.
# Dns Out of date DNS record.
# Key Private key file issue.
# Online Public key authentication works.
# Passwrd Public key authentication failed.
# Plink plink.exe command timed out.
# Refused Connection refused.
# Ssh ssh.exe command timed out.
# Timeout Bitvise SSH Server is not installed or not started.
# Unknown The computer name is not known by the DNS server.
# Returns: The Status variable.
function Get-Status {
param([Parameter(Mandatory = $True)] $Computer,
[Parameter(Mandatory = $True)] $Folder,
[Parameter(Mandatory = $True)] $Info)
$Addr = " `t"
$Count = 2
$Summary = $Info.Summary
$Ping = ping.exe -4 -n $Count -w 2500 $Computer
if ($Ping -is [array]) {
$Addr = $Ping[1] -replace '^.*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*?$', '$1'
$Unfixed = $Addr
if ($Computer -eq $Env:ComputerName) {
# Fix possible incorrect IP address due to VirtualBox.
$Addr = nslookup.exe $Env:ComputerName | Where-Object { $_ -match "^Address:" } |
Select-Object -Last 1
$Addr = $Addr -replace "^Address:\s+", ""
}
}
if ($Ping -match "Ping request could not find host") { return "$Computer`t$Addr`t$Summary`tUnknown" }
if ($Ping -match "Destination host unreachable") { return "$Computer`t$Addr`t$Summary`tOffline" }
if (($Ping -match "Request timed out").Count -eq $Count) { return "$Computer`t$Addr`t$Summary`tOffline" }
if (($Ping -match "Reply from $Unfixed").Count -eq 0) { return "$Computer`t$Addr`t$Summary`tOffline" }
# Do not send commands to linux computers and windows servers.
if ($Folder -eq "_Servers") {
if ($Info.Chassis -match "Virtual") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
}
if ($Info.OSName -match "Debian") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
if ($Info.OSName -match "Endian") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
if ($Info.OSName -match "Server") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
$Users = " "
# Get computer name from remote computer.
$Command = "set ComputerName"
if ($OpenSSH) {
$Answer = Send-SshCommand $Computer $Command
} else {
$Answer = Send-PlinkCommand $Computer $Command
}
if ($Answer.Status -ne "Online") { return "$Computer`t$Addr`t$Summary`t$($Answer.Status)`t$Users`t$($Answer.Reply)" }
if ($Answer.Reply) {
$RemoteName = $Answer.Reply.Split('=')[1]
# Check if out of date DNS entry.
if ($Computer -ne $RemoteName) { return "$Computer`t `t`t$Summary`tDns`t$Users`t$($Answer.Reply)" }
}
# Get logged on user names on remote computer.
$Command = "query.exe user"
if ($OpenSSH) {
$Answer = Send-SshCommand $Computer $Command
} else {
$Answer = Send-PlinkCommand $Computer $Command
}
if ($Answer.Status -ne "Online") { return "$Computer`t$Addr`t$Summary`t$($Answer.Status)`t$Users`t$($Answer.Reply)" }
# Maximum length of user name is 20 characters.
$Users = ((($Answer.Reply | Select-Object -Skip 1) -replace '^.(.{1,20}).*$', '$1').Trim() | Sort-Object) -join ", "
# Get Windows version on remote computer.
$Version = ""
$Command = "ver"
if ($OpenSSH) {
$Answer = Send-SshCommand $Computer $Command
} else {
$Answer = Send-PlinkCommand $Computer $Command
}
if ($Answer.Status -ne "Online") { return "$Computer`t$Addr`t$Summary`t$($Answer.Status)`t$Users`t$($Answer.Reply)" }
if ($Answer.Reply -match "10240") { $Version = "1507" }
if ($Answer.Reply -match "10586") { $Version = "1511" }
if ($Answer.Reply -match "14393") { $Version = "1607" }
if ($Answer.Reply -match "15063") { $Version = "1703" }
if ($Answer.Reply -match "16299") { $Version = "1709" }
if ($Answer.Reply -match "17134") { $Version = "1803" }
if ($Answer.Reply -match "17763") { $Version = "1809" }
# Find Windows 10 computers where inventory and current version do not match.
if ($Summary -notmatch $Version) {
$Summary = $Summary -replace "^(.*)($($Info.OSVersion))(.*)$", "`$1`$2/$Version`$3"
}
return "$Computer`t$Addr`t$Summary`tOnline`t$Users`t$($Answer.Reply)"
}
Get-Status $Computer $Folder $Info
}
function Show-Status { param([Parameter(Mandatory = $False)] $Site = "MST") $OpenSSH = $True $OpenSSH = $False if ($OpenSSH) {
$Null = Remove-Item -ErrorAction SilentlyContinue -Force -Path "$Env:UserProfile\.ssh\known_hosts"
}
$Throttle = 15
$Path = "O:\Inventory"
$File = "$Path\Computers3.txt"
if (Test-Path -Path $File) {
$Header =
"Computer" + "`t" +
"IP Address" + "`t" +
"Domain" + "`t`t" +
"Location" + "`t`t" +
"User" + "`t`t" +
"OS Arch" + "`t" +
"OS Name" + "`t`t`t`t" +
"Status" + "`t" +
"Logged on users" + "`t`t" +
"Reply" + "`t`t`t`t"
$Separator =
"-" * 15 + "`t" +
"-" * 15 + "`t" +
"-" * 15 + "`t" +
"-" * 23 + "`t" +
"-" * 15 + "`t" +
"-" * 7 + "`t" +
"-" * 31 + "`t" +
"-" * 7 + "`t" +
"-" * 23 + "`t" +
"-" * 31
Write-Host -Foregroundcolor Green $Header
Write-Host -Foregroundcolor Green $Separator
# Create runspace pool and session states.
$SessionState = [system.management.automation.runspaces.initialsessionState]::CreateDefault()
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $SessionState, $Host)
$RunspacePool.Open()
# Create empty collection to hold runspace jobs.
$Script:Runspaces = New-Object System.Collections.ArrayList
# Total number of run spaces.
$Total = 0
# One or more consecutive tabs separated file.
# Field 0: Hostname
# Field 1: Folder
# Field 2: Site
# Field 3: Address
# Field 4: Location
# Field 5: Remark
$Lines = Get-Content "$File"
foreach ($Line in $Lines) {
$Field = $Line -split "\t+"
# Do not show servers at MST.
if (($Field) -and
($Field[0] -match "SMRU") -and
($Field[2] -eq $Site) -and
(($Field[2] -ne "MST") -and ($Field[1] -eq "_Servers") -or ($Field[1] -notmatch "_")) -and
(($Field[2] -ne "MST") -or ($Field[3] -eq " ")))
{
$Total++
$Info = Get-Inventory "$Path\$($Field[1])\$($Field[0]).log"
# Create powershell instance and supply scriptblock with other parameters.
$PowerShell = [powershell]::Create().AddScript($ScriptBlock).AddArgument($Field[0]).AddArgument($Field[1]).AddArgument($Info)
# Add runspace into powershell instance.
$PowerShell.RunspacePool = $RunspacePool
# Create temporary collection for each runspace.
$Temp = "" | Select-Object Computer, Folder, PowerShell, Runspace
$Temp.Computer = $Field[0]
$Temp.Folder = $Field[1]
$Temp.PowerShell = $PowerShell
# Save handle output when calling BeginInvoke() that will be used later to end runspace.
$Temp.Runspace = $PowerShell.BeginInvoke()
$Null = $Runspaces.Add($Temp)
}
}
if ($Runspaces) {
# Reset progress indicator.
$BlankLine = " " * ([Console]::BufferWidth - 1)
# Wait for all runspaces to have completed.
$Loops = 0
while (($Runspaces.Runspace.IsCompleted -contains $False) -and ($Loops -lt 35)) {
$Loops++
# Use @() to make sure it always returns an array that has the Count property.
# See answer to question 2 at https://www.red-gate.com/simple-talk/sysadmin/powershell/a-plethora-of-powershell-pitfalls
$Tasks = @($Runspaces | Where-Object { $_.Runspace.IsCompleted -eq $False })
$Completed = $Total - $Tasks.Count
# See https://stackoverflow.com/questions/4998173/how-do-i-write-to-standard-error-in-powershell
# Show progress line using standard error output.
if ($Tasks.Count -lt 9) {
# Get list of computers that have not yet finished.
$Computers = ""
foreach ($Task in $Tasks) { $Computers += ", $($Task.Computer)" }
$Computers = $Computers -replace "^, ", ""
[Console]::Error.Write("$BlankLine`r$Completed out of $Total tasks completed. Still waiting for: $Computers`r")
} else {
[Console]::Error.Write("$BlankLine`r$Completed out of $Total tasks completed.`r")
}
Start-Sleep -Seconds 1
}
# Clear progress line.
[Console]::Error.Write("$BlankLine`r")
# Finish processing the runspace jobs.
Get-RunspaceData
# Close runspace pool.
$RunspacePool.Close()
}
} else {
Write-Host -ForegroundColor Magenta "File '$File' is not available, aborting..."
}
}
$Command = "" if ($Args) { for ($i = 0; $i -lt $Args.Count; $i++) { $Command += "$($Args[$i]) " } Invoke-Expression -Command $Command }
################################################################################
################################################################################
function Add-Colors{
param([Parameter(Mandatory = $True)] $Status)
$Field = $Status -split "\t+"
if ($Field[0].Length -lt 0) { $Field[1] += "t" } if ($Field[1].Length -lt 8) { $Field[1] += "
t" }
if ($Field[2].Length -lt 8) { $Field[2] += "t" } if ($Field[3].Length -lt 8) { $Field[3] += "
t" }
if ($Field[3].Length -lt 16) { $Field[3] += "t" } if ($Field[4].Length -lt 8) { $Field[4] += "
t" }
if ($Field[5].Length -lt 0) { $Field[5] += "t" } if ($Field[6].Length -lt 8) { $Field[6] += "
t" }
if ($Field[6].Length -lt 16) { $Field[6] += "t" } if ($Field[6].Length -lt 24) { $Field[6] += "
t" }
if ($Field[7].Length -lt 0) { $Field[7] += "`t" }
if ($Field.Count -gt 8) {
if ($Field[8].Length -lt 8) { $Field[8] += "`t" }
if ($Field[8].Length -lt 16) { $Field[8] += "`t" }
}
if ($Field.Count -gt 9) {
if ($Field[9].Length -lt 8) { $Field[9] += "`t" }
if ($Field[9].Length -lt 16) { $Field[9] += "`t" }
if ($Field[9].Length -lt 24) { $Field[9] += "`t" }
if ($Field[9].Length -lt 32) { $Field[9] += "`t" }
}
# Start writing status line with all fields.
if ($Field[7] -match "Bitvise") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Dns") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Key") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Locked") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Offline") { Write-Host -ForegroundColor Cyan -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Online") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Passwrd") { Write-Host -ForegroundColor Magenta -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Plink") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Refused") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Ssh") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Timeout") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[0])`t" }
if ($Field[7] -match "Unknown") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[0])`t" }
Write-Host -ForegroundColor Green -NoNewLine "$($Field[1])`t"
if ($Field[2] -match "SMRU") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[2])`t" }
if ($Field[2] -notmatch "SMRU") { Write-Host -ForegroundColor Yellow -NoNewLine "$($Field[2])`t" }
Write-Host -ForegroundColor Green -NoNewLine "$($Field[3])`t"
Write-Host -ForegroundColor Green -NoNewLine "$($Field[4])`t"
if ($Field[5] -match "32-bit") { Write-Host -ForegroundColor Yellow -NoNewLine "$($Field[5])`t" }
if ($Field[5] -notmatch "32-bit") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[5])`t" }
Write-Host -ForegroundColor Green -NoNewLine "$($Field[6])`t"
if ($Field[7] -match "Bitvise") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Dns") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Key") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Locked") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Offline") { Write-Host -ForegroundColor Cyan -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Online") { Write-Host -ForegroundColor Green -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Passwrd") { Write-Host -ForegroundColor Magenta -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Plink") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Refused") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Ssh") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Timeout") { Write-Host -ForegroundColor Red -NoNewLine "$($Field[7])`t" }
if ($Field[7] -match "Unknown") { Write-Host -ForegroundColor Gray -NoNewLine "$($Field[7])`t" }
if ($Field.Count -gt 8) {
Write-Host -ForegroundColor Green -NoNewLine "$($Field[8])`t"
}
if ($Field.Count -gt 9) {
Write-Host -ForegroundColor Green -NoNewLine "$($Field[9])"
}
Write-Host
}
function Get-Inventory { param([Parameter(Mandatory = $True)] $File) $Chassis = "???" $Domain = "???" $Location = "???" $User = "???" $OSArch = "???" $OSName = "???" $OSVersion = "???" if (Test-Path -Path $File) { $Lines = Get-Content "$File" foreach ($Line in $Lines) { $Field = $Line -split "\t+" if ($Field) { if ($Field[0] -match "Chassis Type:") { $Chassis = $Field[1] } if ($Field[0] -match "Domain:") { $Domain = $Field[1] } if ($Field[0] -match "Location:") { $Location = $Field[1] } if ($Field[0] -match "User:") { $User = $Field[1] } if ($Field[0] -match "OS Architecture:") { $OSArch = $Field[1] } if ($Field[0] -match "OS Name:") { $OSName = $Field[1] } if ($Field[0] -match "OS Version:") { $OSVersion = $Field[1] } } } } else { Write-Host -ForegroundColor Magenta "File $File does not exist." } if ($OSVersion -ne "") { $OSName += " $OSVersion" }
if ($Chassis -eq "") { $Chassis = " " }
if ($Domain -eq "") { $Domain = " " }
if ($Location -eq "") { $Location = " " }
if ($User -eq "") { $User = " " }
if ($OSArch -eq "") { $OSArch = " " }
if ($OSName -eq "") { $OSName = " " }
if ($OSVersion -eq "") { $OSVersion = " " }
# Todo: Remove next 2 lines in next version.
if ($Domain -eq "smru.shoklo-unit.com") { $Domain = "SMRU" }
if ($Domain -eq "SMRU (smru.shoklo-unit.com)") { $Domain = "SMRU" }
if ($Domain.Length -lt 8) { $Domain += "`t" }
if ($Location.Length -lt 8) { $Location += "`t" }
if ($Location.Length -lt 16) { $Location += "`t" }
if ($User.Length -lt 8) { $User += "`t" }
$OSName = $OSName -replace " release", ""
if ($OsName.Length -lt 8) { $OSName += "`t" }
if ($OSName.Length -lt 16) { $OSName += "`t" }
if ($OSName.Length -lt 24) { $OSName += "`t" }
return @{
Chassis = $Chassis
Domain = $Domain
Location = $Location
User = $User
OSArch = $OSArch
OSName = $OSName
OSVersion = $OSVersion
# Create one or more consecutive tabs separated summary.
Summary = "$Domain`t$Location`t$User`t$OSArch`t$OSName"
}
}
function Get-RunspaceData { $OpenSSH = $False $OpenSSH = $True foreach($Runspace in $Runspaces) {
if ($Runspace.Runspace.IsCompleted) {
$Result = $Runspace.Powershell.EndInvoke($Runspace.Runspace)
Add-Colors $Result
} elseif ($Runspace.Runspace -ne $Null) {
$Computer = $Runspace.Computer
$Folder = $Runspace.Folder
$Info = Get-Inventory "O:\Inventory\$Folder\$Computer.log"
$Summary = $Info.Summary
if ($OpenSSH) {
$Result = "$Computer`t `t`t$Summary`tSsh"
} else {
$Result = "$Computer`t `t`t$Summary`tPlink"
}
Add-Colors $Result
}
$Runspace.Powershell.Dispose()
$Runspace.Runspace = $Null
$Runspace.Powershell = $Null
}
# Clean out unused runspace jobs.
$temphash = $Runspaces.Clone()
$temphash | Where-Object { $_.Runspace -eq $Null } | ForEach-Object { $Runspaces.Remove($_) }
}
$ScriptBlock = { param($Computer, $Folder, $Info)
$OpenSSH = $False
$OpenSSH = $True
# Function: Send command to remote computer using plink.exe.
# Parameters: The 1st parameter contains the command.
# Remarks: Cannot use "<dos command> *> $Null" in PowerShell 2.0. Instead
# use "cmd /c "<dos command> > nul 2>&1"". Any double quotes in
# the <dos command> need to be escaped with the backtick character.
# Remarks: Possible replies:
# The server's host key does not match the one PuTTY has cached.
# The server's host key is not cached in the registry.
# Remarks: It is possible that plink.exe does not return due to some issue
# on the remote computer.
# See https://powershell.org/forums/topic/timeout-for-runspace
# Returns: ???
function Send-PlinkCommand {
param([Parameter(Mandatory = $True)] $Computer,
[Parameter(Mandatory = $True)] $Command)
$Command = "plink.exe -batch -i `"$Env:UserProfile\id_rsa-auto.ppk`" `"Administrator@$Computer`" `"$Command`" 2>&1"
$Reply = Invoke-Expression $Command
if ($Reply -match "The server's host key ") {
# Update server's host key in PuTTY's cache if it does not match
# or add server's host key to PuTTY's cache if it is not cached.
# Putty's cache is HKCU:\Software\SimonTatham\PuTTY\SshHostKeys.
# Use "(echo y)" to output a yes followed by Enter.
$Cmd = "cmd /c `"(echo y) | $Command`""
$Cmd = $Cmd -replace " -batch", ""
$Null = Invoke-Expression $Cmd
# Try again.
$Reply = Invoke-Expression $Command
}
$Status = "Online"
if ($Reply -match "FATAL ERROR: ") { $Status = "Bitvise" }
if ($Reply -match "FATAL ERROR: Network error: Connection refused") { $Status = "Refused" }
if ($Reply -match "FATAL ERROR: Network error: Connection timed out") { $Status = "Timeout" }
if ($Reply -match "FATAL ERROR: Server unexpectedly closed network connection") { $Status = "Locked" }
if ($Reply -match "Server refused our key") { $Status = "Passwrd" }
if ($Reply -match "Unable to load key file") { $Status = "Key" }
if ($Reply -match "Unable to use key file") { $Status = "Key" }
return @{
Reply = $Reply
Status = $Status
}
}
# Function: Send command to remote computer using ssh.exe.
# Parameters: The 1st parameter contains the command.
# Remarks: Cannot use "<dos command> *> $Null" in PowerShell 2.0. Instead
# use "cmd /c "<dos command> > nul 2>&1"". Any double quotes in
# the <dos command> need to be escaped with the backtick character.
# Remarks: Possible replies:
# The server's host key does not match the one in known hosts.
# The server's host key is not listed in known hosts.
# Remarks: It is possible that ssh.exe does not return due to some issue
# on the remote computer.
# See https://powershell.org/forums/topic/timeout-for-runspace
# Returns: ???
function Send-SshCommand {
param([Parameter(Mandatory = $True)] $Computer,
[Parameter(Mandatory = $True)] $Command)
$Command = "ssh.exe -i `"$Env:UserProfile\id_rsa-auto`" -o `"BatchMode=yes`" `"Administrator@$Computer`" `"$Command`" 2>&1"
$Reply = Invoke-Expression $Command
if ($Reply -match "bad permissions") {
msg.exe * "Permissions for 'C:\\Users\\Administrator\\id_rsa-auto' are too open."
}
if ($Reply -match "Host key verification failed") {
# Update server's host key in list of known hosts if it does not match
# or add server's host key to list of known hosts if it is not present.
# List of OpenSSH known hosts is at C:\Users\<User>\.ssh\known_hosts.
$Cmd = $Command -replace " -o `"BatchMode=yes`"", " -o `"BatchMode=yes`" -o `"StrictHostKeyChecking=no`""
$Null = Invoke-Expression $Cmd
# Try again.
$Reply = Invoke-Expression $Command
}
$Status = "Online"
if ($Reply -match "Connection timed out") { $Status = "Timeout" }
if ($Reply -match "Connection closed by remote host") { $Status = "Locked" }
if ($Reply -match "Load key") { $Status = "Key" }
if ($Reply -match "No matching host key type found") { $Status = "Key" }
if ($Reply -match "password") { $Status = "Passwrd" }
return @{
Reply = $Reply
Status = $Status
}
}
# Function: Get online status (Bitvise/Dns/Key/Locked/Offline/Online/
# Passwrd/Plink/Refused/Ssh/Timeout/Unknown).
# Parameters: The 1st parameter contains the computer name.
# The 2nd parameter contains the inventory subfolder name.
# The 3rd parameter contains the inventory information.
# Remarks: When pinging a computer name it is possible that the DNS server
# returns an outdated IP address. To ensure that the IP address
# is correct, execute a remote command to tell its computer name
# or check that the MAC address in the arp table matches the one
# in the inventory.
# Remarks: Information about the various statuses returned:
# Bitvise Bitvise SSH Server fatal error.
# Locked Remote computer is locked out due to too many logon attempts.
# Offline Ping of remote computer failed.
# Dns Out of date DNS record.
# Key Private key file issue.
# Online Public key authentication works.
# Passwrd Public key authentication failed.
# Plink plink.exe command timed out.
# Refused Connection refused.
# Ssh ssh.exe command timed out.
# Timeout Bitvise SSH Server is not installed or not started.
# Unknown The computer name is not known by the DNS server.
# Returns: The Status variable.
function Get-Status {
param([Parameter(Mandatory = $True)] $Computer,
[Parameter(Mandatory = $True)] $Folder,
[Parameter(Mandatory = $True)] $Info)
$Addr = " `t"
$Count = 2
$Summary = $Info.Summary
$Ping = ping.exe -4 -n $Count -w 2500 $Computer
if ($Ping -is [array]) {
$Addr = $Ping[1] -replace '^.*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*?$', '$1'
$Unfixed = $Addr
if ($Computer -eq $Env:ComputerName) {
# Fix possible incorrect IP address due to VirtualBox.
$Addr = nslookup.exe $Env:ComputerName | Where-Object { $_ -match "^Address:" } |
Select-Object -Last 1
$Addr = $Addr -replace "^Address:\s+", ""
}
}
if ($Ping -match "Ping request could not find host") { return "$Computer`t$Addr`t$Summary`tUnknown" }
if ($Ping -match "Destination host unreachable") { return "$Computer`t$Addr`t$Summary`tOffline" }
if (($Ping -match "Request timed out").Count -eq $Count) { return "$Computer`t$Addr`t$Summary`tOffline" }
if (($Ping -match "Reply from $Unfixed").Count -eq 0) { return "$Computer`t$Addr`t$Summary`tOffline" }
# Do not send commands to linux computers and windows servers.
if ($Folder -eq "_Servers") {
if ($Info.Chassis -match "Virtual") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
}
if ($Info.OSName -match "Debian") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
if ($Info.OSName -match "Endian") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
if ($Info.OSName -match "Server") { return "$Computer`t$Addr`t$Summary`tOnline`t-" }
$Users = " "
# Get computer name from remote computer.
$Command = "set ComputerName"
if ($OpenSSH) {
$Answer = Send-SshCommand $Computer $Command
} else {
$Answer = Send-PlinkCommand $Computer $Command
}
if ($Answer.Status -ne "Online") { return "$Computer`t$Addr`t$Summary`t$($Answer.Status)`t$Users`t$($Answer.Reply)" }
if ($Answer.Reply) {
$RemoteName = $Answer.Reply.Split('=')[1]
# Check if out of date DNS entry.
if ($Computer -ne $RemoteName) { return "$Computer`t `t`t$Summary`tDns`t$Users`t$($Answer.Reply)" }
}
# Get logged on user names on remote computer.
$Command = "query.exe user"
if ($OpenSSH) {
$Answer = Send-SshCommand $Computer $Command
} else {
$Answer = Send-PlinkCommand $Computer $Command
}
if ($Answer.Status -ne "Online") { return "$Computer`t$Addr`t$Summary`t$($Answer.Status)`t$Users`t$($Answer.Reply)" }
# Maximum length of user name is 20 characters.
$Users = ((($Answer.Reply | Select-Object -Skip 1) -replace '^.(.{1,20}).*$', '$1').Trim() | Sort-Object) -join ", "
# Get Windows version on remote computer.
$Version = ""
$Command = "ver"
if ($OpenSSH) {
$Answer = Send-SshCommand $Computer $Command
} else {
$Answer = Send-PlinkCommand $Computer $Command
}
if ($Answer.Status -ne "Online") { return "$Computer`t$Addr`t$Summary`t$($Answer.Status)`t$Users`t$($Answer.Reply)" }
if ($Answer.Reply -match "10240") { $Version = "1507" }
if ($Answer.Reply -match "10586") { $Version = "1511" }
if ($Answer.Reply -match "14393") { $Version = "1607" }
if ($Answer.Reply -match "15063") { $Version = "1703" }
if ($Answer.Reply -match "16299") { $Version = "1709" }
if ($Answer.Reply -match "17134") { $Version = "1803" }
if ($Answer.Reply -match "17763") { $Version = "1809" }
# Find Windows 10 computers where inventory and current version do not match.
if ($Summary -notmatch $Version) {
$Summary = $Summary -replace "^(.*)($($Info.OSVersion))(.*)$", "`$1`$2/$Version`$3"
}
return "$Computer`t$Addr`t$Summary`tOnline`t$Users`t$($Answer.Reply)"
}
Get-Status $Computer $Folder $Info
}
function Show-Status { param([Parameter(Mandatory = $False)] $Site = "MST") $OpenSSH = $False $OpenSSH = $True if ($OpenSSH) {
$Null = Remove-Item -ErrorAction SilentlyContinue -Force -Path "$Env:UserProfile\.ssh\known_hosts"
}
$Throttle = 15
$Path = "O:\Inventory"
$File = "$Path\Computers3.txt"
if (Test-Path -Path $File) {
$Header =
"Computer" + "`t" +
"IP Address" + "`t" +
"Domain" + "`t`t" +
"Location" + "`t`t" +
"User" + "`t`t" +
"OS Arch" + "`t" +
"OS Name" + "`t`t`t`t" +
"Status" + "`t" +
"Logged on users" + "`t`t" +
"Reply" + "`t`t`t`t"
$Separator =
"-" * 15 + "`t" +
"-" * 15 + "`t" +
"-" * 15 + "`t" +
"-" * 23 + "`t" +
"-" * 15 + "`t" +
"-" * 7 + "`t" +
"-" * 31 + "`t" +
"-" * 7 + "`t" +
"-" * 23 + "`t" +
"-" * 31
Write-Host -Foregroundcolor Green $Header
Write-Host -Foregroundcolor Green $Separator
# Create runspace pool and session states.
$SessionState = [system.management.automation.runspaces.initialsessionState]::CreateDefault()
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $SessionState, $Host)
$RunspacePool.Open()
# Create empty collection to hold runspace jobs.
$Script:Runspaces = New-Object System.Collections.ArrayList
# Total number of run spaces.
$Total = 0
# One or more consecutive tabs separated file.
# Field 0: Hostname
# Field 1: Folder
# Field 2: Site
# Field 3: Address
# Field 4: Location
# Field 5: Remark
$Lines = Get-Content "$File"
foreach ($Line in $Lines) {
$Field = $Line -split "\t+"
# Do not show servers at MST.
if (($Field) -and
($Field[0] -match "SMRU") -and
($Field[2] -eq $Site) -and
(($Field[2] -ne "MST") -and ($Field[1] -eq "_Servers") -or ($Field[1] -notmatch "_")) -and
(($Field[2] -ne "MST") -or ($Field[3] -eq " ")))
{
$Total++
$Info = Get-Inventory "$Path\$($Field[1])\$($Field[0]).log"
# Create powershell instance and supply scriptblock with other parameters.
$PowerShell = [powershell]::Create().AddScript($ScriptBlock).AddArgument($Field[0]).AddArgument($Field[1]).AddArgument($Info)
# Add runspace into powershell instance.
$PowerShell.RunspacePool = $RunspacePool
# Create temporary collection for each runspace.
$Temp = "" | Select-Object Computer, Folder, PowerShell, Runspace
$Temp.Computer = $Field[0]
$Temp.Folder = $Field[1]
$Temp.PowerShell = $PowerShell
# Save handle output when calling BeginInvoke() that will be used later to end runspace.
$Temp.Runspace = $PowerShell.BeginInvoke()
$Null = $Runspaces.Add($Temp)
}
}
if ($Runspaces) {
# Reset progress indicator.
$BlankLine = " " * ([Console]::BufferWidth - 1)
# Wait for all runspaces to have completed.
$Loops = 0
while (($Runspaces.Runspace.IsCompleted -contains $False) -and ($Loops -lt 35)) {
$Loops++
# Use @() to make sure it always returns an array that has the Count property.
# See answer to question 2 at https://www.red-gate.com/simple-talk/sysadmin/powershell/a-plethora-of-powershell-pitfalls
$Tasks = @($Runspaces | Where-Object { $_.Runspace.IsCompleted -eq $False })
$Completed = $Total - $Tasks.Count
# See https://stackoverflow.com/questions/4998173/how-do-i-write-to-standard-error-in-powershell
# Show progress line using standard error output.
if ($Tasks.Count -lt 9) {
# Get list of computers that have not yet finished.
$Computers = ""
foreach ($Task in $Tasks) { $Computers += ", $($Task.Computer)" }
$Computers = $Computers -replace "^, ", ""
[Console]::Error.Write("$BlankLine`r$Completed out of $Total tasks completed. Still waiting for: $Computers`r")
} else {
[Console]::Error.Write("$BlankLine`r$Completed out of $Total tasks completed.`r")
}
Start-Sleep -Seconds 1
}
# Clear progress line.
[Console]::Error.Write("$BlankLine`r")
# Finish processing the runspace jobs.
Get-RunspaceData
# Close runspace pool.
$RunspacePool.Close()
}
} else {
Write-Host -ForegroundColor Magenta "File '$File' is not available, aborting..."
}
}
$Command = "" if ($Args) { for ($i = 0; $i -lt $Args.Count; $i++) { $Command += "$($Args[$i]) " } Invoke-Expression -Command $Command }
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Good.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD01 10.10.1.79 SMRU ANC office Mookhopaw 64-bit Windows 10 Enterprise 1809 Offline SMRUWS-AD04 10.10.1.80 SMRU Data office Miasa 64-bit Windows 7 Professional Online miasa Microsoft Windows [Version 6.1.7601] SMRUWS-AD05 10.10.1.75 SMRU Finance office Amorn 64-bit Windows 7 Professional Offline SMRUWS-AD06 10.10.1.109 SMRU Finance office Kee 64-bit Windows 7 Professional Offline SMRUWS-AD07 10.10.1.122 SMRU Admin office Sittipong 64-bit Windows 7 Professional Offline SMRUWS-AD11 SMRU METF office 2 Micho 64-bit Windows 10 Enterprise 1809 Unknown SMRUWS-AD12 10.10.1.78 SMRU Pharmacy room Carela 64-bit Windows 7 Professional Online carela Microsoft Windows [Version 6.1.7601] SMRUWS-AD14 SMRU Finance office Jeerawan.w 64-bit Windows 7 Professional Unknown SMRUWS-AD15 10.10.1.84 SMRU Logistics Siam 64-bit Windows 7 Professional Online siam Microsoft Windows [Version 6.1.7601] SMRUWS-AD17 10.10.1.70 SMRU Finance office Janjira 64-bit Windows 7 Professional Online janjira Microsoft Windows [Version 6.1.7601] SMRUWS-AD18 10.10.1.147 SMRU Staff office Sangrawee 64-bit Windows 7 Professional Online Microsoft Windows [Version 6.1.7601] SMRUWS-AD19 10.10.1.136 SMRU HR Suchadas 64-bit Windows 8.1 Enterprise Online suchadas Microsoft Windows [Version 6.3.9600] SMRUWS-AD20 10.10.1.181 SMRU Grant Phaitoon 64-bit Windows 8.1 Enterprise Online phaitoon Microsoft Windows [Version 6.3.9600] SMRUWS-AD21 10.10.1.108 SMRU Finance office Wararat 64-bit Windows 10 Enterprise 1809 Online oh Microsoft Windows [Version 10.0.17763.107] SMRUWS-AD22 10.10.1.152 SMRU Meeting room SMRU 64-bit Windows 10 Enterprise 1809 Online Microsoft Windows [Version 10.0.17763.107]
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Fail.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD01 10.10.1.79 SMRU ANC office Mookhopaw 64-bit Windows 10 Enterprise 1809 Offline SMRUWS-AD04 SMRU Data office Miasa 64-bit Windows 7 Professional Ssh SMRUWS-AD05 10.10.1.75 SMRU Finance office Amorn 64-bit Windows 7 Professional Offline SMRUWS-AD06 10.10.1.109 SMRU Finance office Kee 64-bit Windows 7 Professional Offline SMRUWS-AD07 10.10.1.122 SMRU Admin office Sittipong 64-bit Windows 7 Professional Offline SMRUWS-AD11 SMRU METF office 2 Micho 64-bit Windows 10 Enterprise 1809 Unknown SMRUWS-AD12 SMRU Pharmacy room Carela 64-bit Windows 7 Professional Ssh SMRUWS-AD14 SMRU Finance office Jeerawan.w 64-bit Windows 7 Professional Unknown SMRUWS-AD15 SMRU Logistics Siam 64-bit Windows 7 Professional Ssh SMRUWS-AD17 SMRU Finance office Janjira 64-bit Windows 7 Professional Ssh SMRUWS-AD18 SMRU Staff office Sangrawee 64-bit Windows 7 Professional Ssh SMRUWS-AD19 SMRU HR Suchadas 64-bit Windows 8.1 Enterprise Ssh SMRUWS-AD20 SMRU Grant Phaitoon 64-bit Windows 8.1 Enterprise Ssh SMRUWS-AD21 SMRU Finance office Wararat 64-bit Windows 10 Enterprise 1809 Ssh SMRUWS-AD22 SMRU Meeting room SMRU 64-bit Windows 10 Enterprise 1809 Ssh
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Fail.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD04 10.10.1.80 SMRU Data office Miasa 64-bit Windows 7 Professional Online miasa Microsoft Windows [Version 6.1.7601]
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Fail.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD04 SMRU Data office Miasa 64-bit Windows 7 Professional Dns Host key verification failed. SMRUWS-AD15 SMRU Logistics Siam 64-bit Windows 7 Professional Dns Host key verification failed. SMRUWS-AD21 SMRU Finance office Wararat 64-bit Windows 10 Enterprise 1809 Ssh SMRUWS-AD22 SMRU Meeting room SMRU 64-bit Windows 10 Enterprise 1809 Dns Host key verification failed.
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Fail.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD04 SMRU Data office Miasa 64-bit Windows 7 Professional Ssh SMRUWS-AD15 SMRU Logistics Siam 64-bit Windows 7 Professional Ssh SMRUWS-AD21 SMRU Finance office Wararat 64-bit Windows 10 Enterprise 1809 Ssh SMRUWS-AD22 SMRU Meeting room SMRU 64-bit Windows 10 Enterprise 1809 Ssh
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Fail.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD04 10.10.1.80 SMRU Data office Miasa 64-bit Windows 7 Professional Online miasa Microsoft Windows [Version 6.1.7601] SMRUWS-AD15 10.10.1.84 SMRU Logistics Siam 64-bit Windows 7 Professional Online siam Microsoft Windows [Version 6.1.7601] SMRUWS-AD21 10.10.1.108 SMRU Finance office Wararat 64-bit Windows 10 Enterprise 1809 Online oh Microsoft Windows [Version 10.0.17763.107] SMRUWS-AD22 10.10.1.152 SMRU Meeting room SMRU 64-bit Windows 10 Enterprise 1809 Online Microsoft Windows [Version 10.0.17763.107]
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Fail.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD04 10.10.1.80 SMRU Data office Miasa 64-bit Windows 7 Professional Online miasa Microsoft Windows [Version 6.1.7601] SMRUWS-AD15 10.10.1.84 SMRU Logistics Siam 64-bit Windows 7 Professional Online siam Microsoft Windows [Version 6.1.7601] SMRUWS-AD21 10.10.1.108 SMRU Finance office Wararat 64-bit Windows 10 Enterprise 1809 Online oh Microsoft Windows [Version 10.0.17763.107] SMRUWS-AD22 10.10.1.152 SMRU Meeting room SMRU 64-bit Windows 10 Enterprise 1809 Online Microsoft Windows [Version 10.0.17763.107]
SMRUWS-IT10\Administrator C:\Users\Administrator# powershell -ExecutionPolicy Bypass -File "C:\Tmp\Remote-Fail.ps1" Show-Status Computer IP Address Domain Location User OS Arch OS Name Status Logged on users Reply
SMRUWS-AD04 SMRU Data office Miasa 64-bit Windows 7 Professional Ssh SMRUWS-AD15 SMRU Logistics Siam 64-bit Windows 7 Professional Ssh SMRUWS-AD21 SMRU Finance office Wararat 64-bit Windows 10 Enterprise 1809 Ssh SMRUWS-AD22 SMRU Meeting room SMRU 64-bit Windows 10 Enterprise 1809 Ssh
Dear fellow coders,
I have a PowerShell script to check what Windows computers are online and who is logged on. I have Bitvise SSH server installed on all Windows computers and I use ping.exe and plink.exe (from PuTTY 0.70). The script uses runspaces to send the ping.exe and plink.exe commands to all computers in parallel. The network has a maximum of 250 computers. The following line is used to get any user(s) logged on.
plink.exe -batch -i
"$Env:UserProfile\id_rsa-auto.ppk
""Administrator@<IP Address>
""query.exe user
"Everything is working fine. However, when I replace plink.exe by ssh.exe on my Windows 10 1809 computer it works only for a small amount of computers. When there are too many computers to be queried I do get wrong results. I suspect there may be an issue with the re-entry code of ssh.exe.
ssh.exe -i
"$Env:UserProfile\id_rsa-auto
" -o"BatchMode=yes
""Administrator@<IP Address>
""$Command
"I'm not sure the back ticks will show up correctly online on Github. See attachment for exact PowerShell code.
Best regards,
Douwe Kiestra Status.txt