Reputation: 51
Friendly hello to everyone! I've been working on this script this week. It works the way it should, but when querying the PCs in our network which are physically a substantial distance away from me (e.g., from Utah to Florida/Alaska) it's taking a VERY long time.
Querying PC's located in the office takes only ~15 seconds. Querying PC's located ~3000 miles away is taking sometimes more than 5 minutes.
I expect quite a bit of latency, but I was wondering if anyone had any advice on getting that time down at all using this script.
Any guidance for a PowerShell newbie would be appreciated.
Thanks!
## Ping Test to prevent errors when no PC is found
function PingTest {
$outputBox.text="Testing PC Connection. Please wait..."
$pingresults = Test-Connection $InputBox.text -count 2
if($pingresults.Count -gt 0)
{
GetComputerInfo
}
Else
{
$outputBox.text="**ERROR!**
The PC may either be off the network or the PC hostname you've entered is incorrect. Please try again."
}
}
## After successful ping, grabs PC info from ComputerInfoScript function and sents to the output box
function GetComputerInfo {
$outputBox.text = "Ping test successful. Gathering PC info. Please wait..."
$computerhostname = $InputBox.text;
$computerinfo = ComputerInfoScript | out-string;
$outputBox.text=$computerinfo #sends gathered computer information to output box
if ($Checkbox_AutoCopy.checked -eq $True) { # auto-copy
$outputBox.text | clip
}
}
## Commands to grab PC information
function ComputerInfoScript {
################################## Variables
$date = Get-Date
$computerSystem = get-wmiobject Win32_ComputerSystem -ComputerName $computerhostname
$computerBIOS = get-wmiobject Win32_BIOS -ComputerName $computerhostname
$computerOS = get-wmiobject Win32_OperatingSystem -ComputerName $computerhostname
$computerCPU = get-wmiobject Win32_Processor -ComputerName $computerhostname
$computerHDD = Get-WmiObject Win32_LogicalDisk -Filter drivetype=3 -ComputerName $computerhostname
$computerDefaultPrint = get-wmiobject win32_printer | %{if ($_.default) {$_}}
$computerPrint = Get-WmiObject Win32_Printer -ComputerName $computerhostname
$computerMonitors = Get-WMIObject Win32_DesktopMonitor -ComputerName $computerhostname
$computerOpticalDrive = Get-WmiObject Win32_CDROMDrive -ComputerName $computerhostname
$computerMappedDrives = Get-WmiObject -ComputerName $computerhostname -Class Win32_MappedLogicalDisk | select name,providername
$computerEventErrorsApp = Get-EventLog -ComputerName $computerhostname -LogName Application -EntryType Error -Newest 5 | select timegenerated,source,message
$computerEventErrorsSys = Get-EventLog -ComputerName $computerhostname -LogName System -EntryType Error -Newest 5 | select timegenerated,source,message
################################# System Info
"System Information for: " + $computerSystem.Name
"Captured on " + $date
"-------------------------------------"
"Distinguished Name: " + $computerOu.DistinguishedName
"Manufacturer: " + $computerSystem.Manufacturer
"Model: " + $computerSystem.Model
"Serial Number: " + $computerBIOS.SerialNumber
"CPU: " + $computerCPU.Name
"HDD Capacity: " + "{0:N2}" -f ($computerHDD.Size/1GB) + "GB"
"HDD Space: " + "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size) + " Free (" + "{0:N2}" -f ($computerHDD.FreeSpace/1GB) + "GB)"
"RAM: " + "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB) + "GB"
"Operating System: " + $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
"User logged In: " + $computerSystem.UserName
"Last Reboot: " + $computerOS.ConvertToDateTime($computerOS.LastBootUpTime)
################################# Share Drives
""
if ($Checkbox_MappedDrives.Checked -eq $true) {
"-------------------------------------"
"User's Mapped Network Drives"
"-------------------------------------"
foreach ($orca in $computerMappedDrives) {
$orca.name + " " + $orca.providername
}
}
################################# Printers
if ($Checkbox_InstalledPrinters.checked -eq $True) #checkbox for Installed Printers
{
""
"-------------------------------------"
"Installed Printers:"
"-------------------------------------"
"Default Printer: " + $computerDefaultPrint.name
""
foreach ($orca in $computerPrint) {
" " + $orca.name
}
}
################################# Errors
if ($Checkbox_Errors.Checked -eq $true) {
""
"-------------------------------------"
"Application Event Errors:"
"-------------------------------------"
foreach ($orca in $computerEventErrorsApp) {
"Date: " + $orca.timegenerated
"Source: " + $orca.source
"Message: "
" " + $orca.message
""
""
}
""
"-------------------------------------"
"System Event Errors:"
"-------------------------------------"
foreach ($orca in $computerEventErrorsSys) {
"Date: " + $orca.timegenerated
"Source: " + $orca.source
"Message: "
" " + $orca.message
""
""
}
}
}
## Clipboard Function
function ClipClip {
$outputBox.text | clip
}
###################################
# GUI #
###################################
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") #loading the necessary
################################# Main Window
$Form = New-Object System.Windows.Forms.Form #creating hte form (this will be the "Primary" window)
$Form.Size = New-Object System.Drawing.Size(590,315) #the size in px of the window length, height
$Form.Text = "Computer Info Tool v1.2"
$Form.MaximizeBox = $False
################################# INPUT; PC hostname/IP entry
$InputBox = New-Object System.Windows.Forms.TextBox
$InputBox.Location = New-Object System.Drawing.Size(5,250)
$InputBox.Size = New-Object System.Drawing.Size(485,20)
$Form.Controls.Add($InputBox)
################################# Information Output Box
$outputBox = New-Object System.Windows.Forms.TextBox #creating the text box
$outputBox.Location = New-Object System.Drawing.Size(5,40)
$outputBox.Size = New-Object System.Drawing.Size(565,200)
$outputBox.MultiLine = $True
$outputBox.AutoSize = $True
$outputBox.ScrollBars = "Vertical"
################################# COPY button
$CopyButton = New-Object System.Windows.Forms.Button
$CopyButton.Location = New-Object System.Drawing.Size (5,15)
$CopyButton.Size = New-Object System.Drawing.Size (110,20)
$CopyButton.Text = "Copy"
$CopyButton.Add_Click({ClipClip})
$Form.Controls.Add($CopyButton)
################################# Add'l Information Checkboxes
$Checkbox_AutoCopy = New-Object System.Windows.Forms.CheckBox #create the radio button
$Checkbox_AutoCopy.Location = new-object System.Drawing.Point(120,17) #location of the radio button(px) in relation to the group box's edges (length, height)
$Checkbox_AutoCopy.size = New-Object System.Drawing.Size(110,20) #the size in px of the radio button (length, height)
$Checkbox_AutoCopy.Checked = $false #is checked by default
$Checkbox_AutoCopy.Text = "Auto-Copy" #labeling the radio button
$Form.Controls.Add($Checkbox_AutoCopy) #activate the inside the group box
################################# GO button
$GoButton = New-Object System.Windows.Forms.Button
$GoButton.Location = New-Object System.Drawing.Size (495,250)
$GoButton.Size = New-Object System.Drawing.Size (60,20)
$GoButton.Text = "Go"
$GoButton.Add_Click({PingTest})
$Form.Controls.Add($GoButton)
$Form.AcceptButton = $GoButton
################################# Group Box
$groupBox = New-Object System.Windows.Forms.GroupBox #create the group box
$groupBox.Location = New-Object System.Drawing.Size(245,5) #location of the group box (px) in relation to the primary window's edges (length, height)
$groupBox.size = New-Object System.Drawing.Size(325,35) #the size in px of the group box (length, height)
$groupBox.text = "Additional Details" #labeling the box
$Form.Controls.Add($groupBox) #activate the group box
################################# Add'l Information Checkboxes
$Checkbox_InstalledPrinters = New-Object System.Windows.Forms.CheckBox #create the radio button
$Checkbox_InstalledPrinters.Location = new-object System.Drawing.Point(15,13) #location of the radio button(px) in relation to the group box's edges (length, height)
$Checkbox_InstalledPrinters.size = New-Object System.Drawing.Size(110,20) #the size in px of the radio button (length, height)
$Checkbox_InstalledPrinters.Checked = $false #is checked by default
$Checkbox_InstalledPrinters.Text = "Installed Printers" #labeling the radio button
$groupBox.Controls.Add($Checkbox_InstalledPrinters) #activate the inside the group box
$Checkbox_MappedDrives = New-Object System.Windows.Forms.CheckBox #create the radio button
$Checkbox_MappedDrives.Location = new-object System.Drawing.Point(125,13) #location of the radio button(px) in relation to the group box's edges (length, height)
$Checkbox_MappedDrives.size = New-Object System.Drawing.Size(100,20) #the size in px of the radio button (length, height)
$Checkbox_MappedDrives.Checked = $false #is checked by default
$Checkbox_MappedDrives.Text = "Mapped Drives" #labeling the radio button
$groupBox.Controls.Add($Checkbox_MappedDrives) #activate the inside the group box
$Checkbox_Errors = New-Object System.Windows.Forms.CheckBox #create the radio button
$Checkbox_Errors.Location = new-object System.Drawing.Point(225,13) #location of the radio button(px) in relation to the group box's edges (length, height)
$Checkbox_Errors.size = New-Object System.Drawing.Size(87,20) #the size in px of the radio button (length, height)
$Checkbox_Errors.Checked = $false #is checked by default
$Checkbox_Errors.Text = "Event Errors" #labeling the radio button
$groupBox.Controls.Add($Checkbox_Errors) #activate the inside the group box
$Form.Controls.Add($outputBox)
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
Upvotes: 0
Views: 920
Reputation: 10107
Two very good, knowledgeable answers but there is a much simpler solution which will speed up the entire operation significantly:
RDP to one of your IT workstations at the far end and run the script from there.
Upvotes: 0
Reputation: 68273
Absent "fan out" remoting, you should be able to speed that up quite a bit if you use CIM, creating a persistent CIM session first and then using that same session for repeated WMI queries rather than repeated Get-WMIObject calls which will result in repeated session set-up and tear-down per call.
Upvotes: 1
Reputation: 36297
My suggestion would be to have the remote system do the work once, and then respond with all of the results, instead of creating a connection, asking it for WMI info, closing the connection, creating a connection, asking it for WMI info, closing the connection, repeat, repeat, repeat...
To do that I changed one function. I converted all of the WMI and Eventlog calls to exclude the -ComputerName argument, and converted them to be properties of a custom object. Then I wrapped that all up as a ScriptBlock, and assigned it to $Command
. Then I use Invoke-Command to run that command on the remote machine, and assign the results to $Data
.
Then any reference to any of the various variables that you had before are changed to $data.oldvariablename
.
function ComputerInfoScript {
################################## Variables
$date = Get-Date
$Command = {[PSCustomObject]@{
'computerSystem' = get-wmiobject Win32_ComputerSystem
'computerBIOS' = get-wmiobject Win32_BIOS
'computerOS' = get-wmiobject Win32_OperatingSystem
'computerCPU' = get-wmiobject Win32_Processor
'computerHDD' = Get-WmiObject Win32_LogicalDisk -Filter drivetype=3
'computerDefaultPrint' = get-wmiobject win32_printer | %{if ($_.default) {$_}}
'computerPrint' = Get-WmiObject Win32_Printer
'computerMonitors' = Get-WMIObject Win32_DesktopMonitor
'computerOpticalDrive' = Get-WmiObject Win32_CDROMDrive
'computerMappedDrives' = Get-WmiObject -Class Win32_MappedLogicalDisk | select name,providername
'computerEventErrorsApp' = Get-EventLog -LogName Application -EntryType Error -Newest 5 | select timegenerated,source,message
'computerEventErrorsSys' = Get-EventLog -LogName System -EntryType Error -Newest 5 | select timegenerated,source,message
}}
$Data = Invoke-Command -ComputerName $computerhostname -ScriptBlock $Command
################################# System Info
"System Information for: " + $Data.computerSystem.Name
"Captured on " + $date
"-------------------------------------"
"Distinguished Name: " + $data.computerOu.DistinguishedName
"Manufacturer: " + $data.computerSystem.Manufacturer
"Model: " + $data.computerSystem.Model
"Serial Number: " + $data.computerBIOS.SerialNumber
"CPU: " + $data.computerCPU.Name
"HDD Capacity: " + "{0:N2}" -f ($data.computerHDD.Size/1GB) + "GB"
"HDD Space: " + "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size) + " Free (" + "{0:N2}" -f ($data.computerHDD.FreeSpace/1GB) + "GB)"
"RAM: " + "{0:N2}" -f ($data.computerSystem.TotalPhysicalMemory/1GB) + "GB"
"Operating System: " + $data.computerOS.caption + ", Service Pack: " + $data.computerOS.ServicePackMajorVersion
"User logged In: " + $data.computerSystem.UserName
"Last Reboot: " + $data.computerOS.ConvertToDateTime($data.computerOS.LastBootUpTime)
################################# Share Drives
""
if ($Checkbox_MappedDrives.Checked -eq $true) {
"-------------------------------------"
"User's Mapped Network Drives"
"-------------------------------------"
foreach ($orca in $data.computerMappedDrives) {
$orca.name + " " + $orca.providername
}
}
################################# Printers
if ($Checkbox_InstalledPrinters.checked -eq $True) #checkbox for Installed Printers
{
""
"-------------------------------------"
"Installed Printers:"
"-------------------------------------"
"Default Printer: " + $data.computerDefaultPrint.name
""
foreach ($orca in $data.computerPrint) {
" " + $orca.name
}
}
################################# Errors
if ($Checkbox_Errors.Checked -eq $true) {
""
"-------------------------------------"
"Application Event Errors:"
"-------------------------------------"
foreach ($orca in $data.computerEventErrorsApp) {
"Date: " + $orca.timegenerated
"Source: " + $orca.source
"Message: "
" " + $orca.message
""
""
}
""
"-------------------------------------"
"System Event Errors:"
"-------------------------------------"
foreach ($orca in $data.computerEventErrorsSys) {
"Date: " + $orca.timegenerated
"Source: " + $orca.source
"Message: "
" " + $orca.message
""
""
}
}
}
Upvotes: 2