1

I want optimize a simple task: pull server OS version into a neat table. However, some servers in our environment have Powershell disabled. Below you fill find my script, which works! However, it takes about 20 seconds or so per server, since it waits for the server to return the results of the invoked command before moving onto the next server in the list. I know there's a way to asynchronously pull the results from a PS command, but is this possible when I need to resort to cmd line syntax for servers that can't handle PS, as shown in the catch statement?

$referencefile = "ps_servers_to_query.csv" $export_location = "ps_server_os_export.csv" $Array = @() $servers = get-content $referencefile foreach ($server in $servers){ #attempt to query the server with Powershell. try{ $os_version = invoke-command -ComputerName $server -ScriptBlock {Get-ComputerInfo -Property WindowsProductName} -ErrorAction stop $os_version = $os_version.WindowsProductName } # If server doesnt have PS installed/or is disabled, then we will resort to CMD Prompt, this takes longer however.. also we will need to convert a string to an object. catch { $os_version = invoke-command -ComputerName $server -ScriptBlock {systeminfo | find "OS Name:"} # this returns a string that represents the datetime of reboot $os_version = $os_version.replace('OS Name: ', '') # Remove the leading text $os_version = $os_version.replace(' ','') # Remove leading spaces $os_version = $os_version.replace('Microsoft ','') # Removes Microsoft for data standardization } # Output each iteration of the loop into an array $Row = "" | Select ServerName, OSVersion $Row.ServerName = $Server $Row.OSVersion = $os_version $Array += $Row } # Export results to csv. $Array | Export-Csv -Path $export_location -Force 

Edit: Here's what I'd like to accomplish. Send the command out to all the servers (less than 30) at once, and have them all process the command at the same time rather than doing it one-by-one. I know I can do this if they all could take PowerShell commands, but since they can't I'm struggling. This script takes about 6 minutes to run in total.

Thank you in advance!

5
  • 2
    You may consider using Get-Ciminstance instead. And you don't need a loop. The cmdlet can take an array of computernames. Commented Feb 4, 2022 at 23:25
  • @Olaf Wow, that works very well! Unfortunately I ran into some permissions issues for a few of these servers, but I think I'll have script use Get-Cimeinstance first, then if that fails, try these slower methods. Great suggestion! Commented Feb 4, 2022 at 23:33
  • @Olaf since my account is new, I dont have the sufficient "reputation points" to upvote you. However, I basically took your recommendation and ran with it a bit to include some error-handling. The script went from taking 6 minutes to about 25 seconds. I'll upvote you once I have sufficient reputation points. Thanks a lot! Commented Feb 5, 2022 at 5:03
  • I'm glad it helped. ;-) Commented Feb 5, 2022 at 7:00
  • @Theo good call! Commented Feb 6, 2022 at 6:46

1 Answer 1

1

If I got it right something like this should be all you need:

$referencefile = "ps_servers_to_query.csv" $export_location = "ps_server_os_export.csv" $ComputerName = Get-Content -Path $referencefile $Result = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName $ComputerName | Select-Object -Property Caption,PSComputerName $Result | Export-Csv -Path $export_location -NoTypeInformation 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.