I want my PowerShell script to go out to remote servers, gather hotfix data, and export that data to Excel for each server or one Excel sheet per server.
Currently when I run the script it does go out to each server listed in a .txt file and gathers the hotfix data. But it exports that data to one Excel file with a name of all the servers. It's a very long name!
Here's the script:
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$Server_Name = Get-Content $dir\computers.txt
Get-HotFix -computername $Server_Name | Export-Csv -Path "$dir\$Server_Name HotFixData.csv" -notype
Get-Content $dir\computers.txt | Foreach-Object {
Get-HotFix -ComputerName $_ | Export-Csv -Path "$dir\$($_)_HotFixData.csv" -notype
}
Related
I am fairly new at PowerShell. I am trying to retrieve the directory Names & Mode at depth 2 from a list of servers using the Get-ChildItem command.
$serverList = import-csv -Path C:\Users\J\Desktop\servers.csv
ForEach ($server in $serverList)
{
Get-ChildItem -path $_.server -Recurse -depth 2 `
| where { $_.PsIsContainer -eq $true} `
|select name, mode -Unique | export-csv -Path "C:\Users\J\Desktop\output.csv"
}
When I run the script, PowerShell retrieves the directories for my local machine instead of the remote servers. Could someone help me modify my script to get the desired result?
This is a screenshot of the server.csv file
I am trying to use power shell to determine whether a server has a particular patch installed based on the KB and if not append the name to a csv. my input file has system names so I want to export that system name if it does not find the patch installed.
here is what i have so far. The export to csv part does not seem to work.
forEach-Object{
try{
$status = wmic /node:#sys.csv qfe list full /format:table | findstr /i $kb_number
if(!$status){
$output_file = New-Item C:\temp\$kb_number.csv -ItemType File
export-csv $output_file -append -Force
}
else{
write-output $status
}
}
catch{
$error_message = $_.Exception.Message
#write-output "the error message is" $error_message
write-output "Could not find any system with this patch installed."
}
}
Why your code might be failing
We don't see where you're setting the values of #sys.csv or $kb_number in the code you shared. Either of those could be throwing you off.
But the real issue is Export-Csv. For one, you're making a new CSV with every iteration of the loop. And for two, you have to pass in some item for the cmdlet to export as a CSV. Right now, you're only providing these values.
$output_file = New-Item C:\temp\$kb_number.csv -ItemType File
Export-csv -Path $output_file -append -Force
Export-Csv requires an input object. You're not giving it one now.
What do you want to export? If you just want a list of computers without a patch, do this instead.
if(-not(Test-path C:\temp\$kb_number.csv)){
#if file doesn't exist, make it
$output_file = New-Item C:\temp\$kb_number.txt -ItemType File
}
#adds computer name if it doesn't have the patch
Add-Content -Path $output_file -Value $computer
General Suggestions
Instead of using ForEach-Object, you might find it's easier to debug if you use a ForEach loop like this.
$computers = Get-Content C:\pathTo\Your\ComputerList.txt
ForEach($computer in $computers){
}
One additional source of trouble is that your code is using older dos commands in WMIC and then tries to use PowerShell to store the records. You don't need to do this and can make it easier on yourself if you swap out the calls to wmic for Get-WmiObject or Get-CimInstance, the PowerShell native versions of the commands.
To do that, change this line:
wmic /node:#sys.csv qfe list full /format:table | findstr /i $kb_number
translates into
$kb_number = "KB4576484"
Get-CimInstance Win32_QuickFixEngineering -Filter "HotfixID = '$kb_number'" -ComputerName $computer
Source Description HotFixID InstalledBy InstalledOn
------ ----------- -------- ----------- -----------
Update KB4576484 NT AUTHORITY\SYSTEM 9/14/2020 12:00:00 AM
You can store the output of that in a variable and then call Export-Csv on it and that should work.
When in doubt, remove the filter part and just get it working to export all patches to a csv. Then add complexity by adding back the filtering statements.
So far I have created a PowerShell script to find the specific files from multiple servers and dump the output to excel file.
For some reason my script only dumps the output for 1 server (last one to the list) out of 50. Not sure what I'm missing.
$server = get-content "C:\temp\servers.txt"
Foreach ($srv in $server)
{
Get-ChildItem -Path "\\$srv\d$\temp\" -include "java_pid*" -Recurse -ErrorAction silentlycontinue | export-csv c:\temp\results.csv
}
When run the script it will go thru all the servers and dump the export to excel file.
Use the -Append tag this will append each of the server results pipeline into one long results.csv. Right now you are overwriting the output csv for each server.
$server = get-content "C:\temp\servers.txt" Foreach ($srv in $server) { Get-ChildItem -Path "\$srv\d$\temp\" -include "java_pid*" -Recurse -ErrorAction silentlycontinue | export-csv c:\temp\results.csv -Append}
I currently have this script working but only able to get it to run locally, I would like to have it read a text file that would be stored on c:\List_of_PCs.txt that would have computer names that it would also run the same script on. That way I can update the text file instead of modify the code.
Set-ExecutionPolicy RemoteSigned
# Get all users
$users = Get-ChildItem -Path "C:\Users"
# Loop through users and delete the Teams file
$users | ForEach-Object {
Remove-Item -Path "C:\Users\$($_.Name)\AppData\Roaming\Microsoft\Teams\Cache\f*" -Force
Remove-Item -Path "C:\Users\$($_.Name)\AppData\Roaming\Microsoft\Teams\Application Cache\Cache\f*" -Force
}
Any help on this I've tried multiple things every which way, I'm sure this is something simple but I'm still very new to PowerShell.
Try something like this...
Requires PowerShell remoting to be enabled and using an account that is an admin on the remote computer
$ComputerList = Import-Csv -Path 'c:\List_of_PCs.txt'
$ComputerList | % {
Invoke-Command -ComputerName $_ -ScriptBlock {
# Set-ExecutionPolicy RemoteSigned # this is something that should be set via GPO for all systems, not your script, so that it is centrally controlled and monitored.
# Get all users
$users = Get-ChildItem -Path "C:\Users"
# Loop through users and delete the Teams file
$users | ForEach-Object {
Remove-Item -Path "C:\Users\$($_.Name)\AppData\Roaming\Microsoft\Teams\Cache\f*" -Force
Remove-Item -Path "C:\Users\$($_.Name)\AppData\Roaming\Microsoft\Teams\Application Cache\Cache\f*" -Force
}
}
}
My script does (somewhat) what it's supposed to do if I need the information from the local PC. I have it reaching to a txt file for a list of computers. The script will read the list and show "Processing:..." for the list of computers but the export only shows the local system. Even if I remove my local PC from the txt file, the export to csv still only shows the local system. It does create the correct columns and populates accordingly. I just need it to pull the data from remote systems as well. Since the script will be used by multiple people, the variables allow the txt file and output file to be on their systems.
Function Export-InstalledSoftware {
Process {
if (Test-Connection -ComputerName $_ -count 1 -quiet)
{
echo "Processing: $env:COMPUTERNAME"
Get-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*,HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* `
| Select-object #{n='ComputerName';e={$env:COMPUTERNAME}},#{n='DisplayName';e={$_.displayName}},#{n='Publisher';e={$_.Publisher}},#{n='DisplayVersion';e={$_.DisplayVersion}} `
| Sort displayName `
| Export-CSV C:\Users\$(get-content env:username)\Desktop\"SoftwareQuery_"$(get-date -f yyyy-MM-dd)".csv" -NoTypeInformation -Encoding ASCII
}
}
}
Get-Content "C:\Users\$(get-content env:username)\Desktop\systems.txt" -readcount 1 | Export-InstalledSoftware