Powershell not storing foreach loop info in Variable - powershell

I am trying to collect a list of the viewers installed on a set of servers. I am trying to loop through that list and run a wmi query and store the results and export a table with with the wmi result and server name next to it.
I am running this on server 2012
$computers = Get-Content C:\computers.txt
$WMIQuery = foreach ($computer in $computers){Get-WmiObject -Class
Win32_Product | where-object {$_.name -match "Microsoft Viewer*"}}
$WMIQuery
$WMIQuery | Out-File c:\Viewers.txt
Desired Results
Server Name Object1 Object2
Server1 Microsoft Excel Viewer Microsoft Visio Viewer
I output the file and get a blank txt file.

foreach ($computer in (Get-Content -Path "C:\computers.txt")) {
Get-WMIObject -ComputerName $computer -Class Win32_Product |
Where-Object {$_.name -match "Microsoft Viewer" } |
Out-File -Append -Path "C:\viewers.txt"
}
Your original code wasn't identifying the computer to perform Get-WMIObject against, so it was looking at only the computer that you were running the script on.
If there are many products on the remote computer, you may want to consider filtering on the remote computer instead of locally, so as to avoid transferring large amounts of data over what may be a slower-than-ideal network:
foreach ($computer in (Get-Content -Path "C:\computers.txt")) {
Get-WMIObject -ComputerName $computer -Class Win32_Product -Filter "Name LIKE '*Microsoft Viewer*'"|
Out-File -Append -Path "C:\viewers.txt"
}
(I think I have the filter syntax correct; I seem to have to hack at it every time I write a new filter...)

I don't have enough rep to add a comment, but Jeff is correct. However, there are still issues with the original poster's query. The following piece of code will yield no results based on the examples provided by the poster:
{$_.name -match "Microsoft Viewer*"}
That needs to either be changed to
{$_.name -like "*Microsoft*Viewer*"}
or
{$_.name -match "Microsoft.*?Viewer"}

Related

Get-ChildItem on Multiple Computers, Performance Issues

I'm wanting to improve on my script to be able to accomplish the following:
Scan servers based on get-adcomputer on specific OUs.
Scan each server based on whatever drive letter it has.
Scan each server for log4j.
Export all results to a CSV that identifies the folder path, name of file, and the server that the file was found on.
I have been using the following code to start with:
$Servers = Get-ADComputer -Filter * -SearchBase "OU=..." | Select -ExpandProperty Name
foreach ($server in $Servers){
Invoke-Command -ComputerName $Server -ScriptBlock {
$Drives = (Get-PSDrive -PSProvider FileSystem).Root
foreach ($drive in $Drives){
Get-ChildItem -Path $drive -Force -Filter *log4j* -ErrorAction SilentlyContinue | '
foreach{
$Item = $_
$Type = $_.Extension
$Path = $_.FullName
$Folder = $_.PSIsContainer
$Age = $_.CreationTime
$Path | Select-Object `
#{n="Name";e={$Item}}, `
#{n="Created";e={$Age}},`
#{n="FilePath";e={$Path}},`
#{n="Extension";e={if($Folder){"Folder"}else{$Type}}}`
} | Export-Csv C:\Results.csv -NoType
}
}
I am having the following issues and would like to address them to learn.
How would I be able to get the CSV to appear the way I want, but have it collect the information and store it on my machine instead of having it on each local server?
I have noticed extreme performance issues on the remote hosts when running this. WinRM takes 100% of the processor while it is running. I have tried -Include first, then -Filter, but to no avail. How can this be improved so that at worst, it's solely my workstation that's eating the performance hit?
What exactly do the ` marks do?
I agree with #SantiagoSquarzon - that's going to be a performance hit.
Consider using writing a function to run Get-ChildItem recursively with the -MaxDepth parameter, including a Start-Sleep command to pause occasionally. Also, you may want to note this link
You'd also want to Export-CSV to a shared network drive to collect all the machines' results.
The backticks indicate a continuation of the line, like \ in bash.
Finally, consider using a Scheduled Task or start a powershell sub-process with a lowered process priority, maybe that will help?

How do I get a list of the servers as well as respective application and version of that very same app to be exported properly into excel?

With this script, I am able to find a specific application on a list of multiple remote devices and determine the version number of the application on their corresponding host system. This is outputted beautifully in the PS window. However, I am having trouble exporting the results properly into excel, that is, I want each property (Name, Version, PSComputerName) to be in a separate column vs all in one column. So far, I've tried the following
$list = Get-Content -Path C:\Users\bob\AppList.txt
$Servers = Get-Content -Path C:\Users\bob\ServerList.txt
foreach ($Serv in $Servers) {
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Product -ComputerName $Serv |
Select-Object -Property Name, Version, PSComputerName |
Where-Object -FilterScript { $_.Name -like "*$list*" } |
Export-Csv -Path C:\Users\bob\ServerListResults.csv
}
This resulted in simply just one device's information being extracted while every other cell was empty
I added -append at the very end! Thank you anyways!

Powershell ForEach-Object {Start-Job -Scriptblock} not populating variables

Here is my code, it works and creates a job for each computer in the OU but does not populate the $Computer variable in my script block causing this to fail.
I am sure I am missing something small since I have never created jobs before in Powershell but after working on this for an hour or two I have been unable to figure out what I am missing.
#Gets all workstations that need to have software installed, if you don't want to uninstall all of the software from you will need to use a text document and Get-Content
$computers = Get-ADComputer -Filter * -SearchBase "OU=Workstation Test,OU=Workstations,OU=Workstations,DC=CONTOSO,DC=COM" | Select DNSHostName -ExpandProperty DNSHostname
$Computer
#Use Get-WMIObject to find the IdentifyingNumber
$Computers | ForEach-Object {Start-Job -Name "$Uninstall" -ScriptBlock {(Get-WmiObject -Class Win32_product -ComputerName $Computer -Filter {IdentifyingNumber LIKE '{CD95F661-A5C4-44F5-A6AA-ECDD91C2410B}'}).uninstall()}}
Instead of $computer you need to use $_.
$_ represents the current item in the pipeline.
Alternatively you could do:
ForEach ($Computer in $Computers) { Invoke-Command -ComputerName $Computer -ScriptBlock {(Get-WmiObject -Class Win32_product -Filter {IdentifyingNumber LIKE '{CD95F661-A5C4-44F5-A6AA-ECDD91C2410B}'}).uninstall()} }
Here you continue to use $Computer inside the foreach as it now gets populated with each item in the collection.
Also FYI your $computer line above the ForEach-Object is currently unnecessary (it's just outputting an empty variable, unless you've already populated it elsewhere).
Edit: per comments I also noticed that the start-job seemed redundant as -computername was being used on the wmi cmdlet. Invoke-command is preferred as it uses winrm, so I've modified it as such in my code above.

Outputing contents to CSV with Powershell

I use this site alot while learning Powershell. Its been a great help so far!
Here is my issue:
I am trying to write a script that will take workstation names, pull the workstation description from WMI and output both the workstation name and description found into a new .csv file.
Here is what I have so far:
Get-Content -Path "workstation_names.csv" | Select-Object Workstations |
Foreach-Object { Get-WmiObject -Class Win32_OperatingSystem -ComputerName $workstations | Select Workstations, Description | Export-CSV -Path "results.csv" -NoTypeInformation }
The workstation_names.csv has a column named "Workstations" and under it each cell has a single workstation name in it. Currently my script will create an output file that will have two columns in it. One called "Workstations" and the other called "Description". The Workstation column is empty, and the Description column only has the results for the first workstation description in it (even though I have 10 workstation names listed in the workstation_names.csv file).
I am sitting here scratching my head with my n00bish knowledge of Powershell. I know I PROBABLY need to so something with the array that is created from the first .csv file but I am not sure how to code what I need. Any help??
Probably something like this should do the trick:
$inFile = "workstation_names.csv"
$results = #()
Import-CSV -path $inFile -header Workstations |
% {$results += Get-WmiObject -Class Win32_OperatingSystem `
-ComputerName $_.Workstations | Select PSComputerName, Description}
$results | Export-Csv -Path "results.csv" -NoTypeInformation
So to elaborate on this, you aren't really importing the CSV, you are importing the raw text file, which is confusing, since I don't really understand how anything works for you in that case. Here the script will create an array to store the results, import file as CSV, loop through the valuables and output results to the CSV.
4c74356b41's script will fail for several reasons
It's -header not -headers
there is a typo %_ instead of $_
select Workstations won't work as that's no property of gwmi
This only slightly reworked script should do.
$inFile = "workstation_names.csv"
$results = #()
Import-CSV -path $inFile -header Workstations |
% {$results += Get-WmiObject -Class Win32_OperatingSystem `
-ComputerName $_.Workstations | Select PSComputerName, Description}
$results | Export-Csv -Path "results.csv" -NoTypeInformation
To see which properties are available see the following output
GWmi -Class Win32_OperatingSystem -ComputerName localhost|gm|out-gridview

Using Powershell to build a list of computer model numbers in our Domain?

As the title states, I am trying to determine every computer model used in our domain. I am new to the company, and have been placed in charge of producing a new encryption solution for all end point devices. By knowing the computer models in our domain, I will be able to determine which machines have a TPM 1.2 chip, and which ones don't (almost 15k devices). I do not need anything to look pretty, but I'm open for ideas. I more or less want a list (text or csv for sorting purposes) so I can quantify models and research.
Here's what I have so far:
Get-ADComputer -Filter {Name -like 'ML*'} | select -expand name |
ForEach {
If (Test-Connection $_ -count 1 -quiet)
{Get-WmiObject -Class Win32_ComputerSystem -ComputerName $_} Select-Object -Property model | Export-Csv "c:\scripts\Models.csv"}
Else { Add-Content -value $_ c:\scripts\not.responding.txt}
I know there are problems with this. Right now I'm having trouble querying AD and passing the computer name variable only. Because of this, the ping test fails, and everything exports to the failed text file. The failed text file indicates that the variable includes a lot more than just the computer name. If I can pull the variable correctly, I'm not sure if the rest would work, but I think it should. Any help would be greatly appreciated.
$ComputerNames = Get-ADComputer -Filter {Name -like 'ML*'} | select -expand name
foreach ($computername in $ComputerNames){
If (Test-Connection $computername -count 1 -quiet){
Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computername | Select-Object -Property model | Export-Csv "c:\scripts\Models.csv"
}
else{
Add-Content -value $computername c:\scripts\not.responding.txt
}
}
there you go.