Noob here, I need to extract some data from a cim interrogation of a list of servers, however the csv output is just the same reiteration of the local server, with the sum total equaling the number of lines in the input file. I think I'm doing something wrong with the array but Ive been beating my head. Help?
$ErrorActionPreference = 'SilentlyContinue'
#Define Some Variables
$importpath = "c:\directory1"
$workingpath = "c:\directory2"
#Do Some Filtering
Import-CSV -Path "$importpath\somefile.csv" | where {$_.Powerstate -ne "PoweredOff"} | where Guest -notlike *somestring* | Export-Csv "$workingPath\PRODUCTION.csv" -NoTypeInformation
Import-csv -Path "$workingPath\PRODUCTION.csv" | Select-Object -Property Name | Export-Csv -Path "$workingpath\SERVERS.csv" -NoTypeInformation
#Create final input foreach routine
Import-CSV -Path "$workingpath\SERVERS.csv" | Out-file $workingpath\SERVERS.txt
$servers = Get-Content -path "$workingpath\SERVERS.txt"
$results = foreach ($server in $servers) {
Get-CimInstance -ClassName win32_OperatingSystem -ErrorAction SilentlyContinue | Select-Object *
}
$results | Export-Csv -Path "$workingPath\PRODUCTIONRESULTS.csv" -NoTypeInformation -Append
Try including the computername when you run the Get-CimInstance command
$results = foreach ($server in $servers) {
Get-CimInstance -ComputerName $server -ClassName win32_OperatingSystem -ErrorAction SilentlyContinue | Select-Object *
}
Related
I'm using this Powershell script to retrieve info of remote servers from a central server.
In this case, there are about 150 servers on Active Directory:
$Servers = Get-ADComputer -Filter 'Name -like "...*"' | Select-Object -ExpandProperty Name
foreach ($computer in $Servers)
{
try
{
$ping = Test-Connection -ComputerName $computer -count 1 -ErrorAction Stop
$IP = ($ping.IPV4Address).IPAddressToString
$hardware = Get-CimInstance -Class Win32_ComputerSystem -ComputerName $computer -ErrorAction Stop
$totalMemory = (Get-CimInstance Win32_PhysicalMemory -ComputerName $computer | Measure-Object -Property capacity -Sum).sum /1gb
$os = Get-CimInstance -Class Win32_OperatingSystem -ComputerName $computer
$cpu = Get-CimInstance -Class Win32_processor -ComputerName $computer | Group-Object -Property Name |
Select-Object -Property Name,
#{Name = 'TotalSockets'; Expression = {$_.Count}},
#{Name = 'TotalCores'; Expression = {($_.Group | Measure-Object -Property NumberOfCores -Sum).Sum}},
#{Name = 'TotalLogicalProcessors'; Expression = {($_.Group | Measure-Object -Property NumberOfLogicalProcessors -Sum).Sum}}
#$disks = Get-WmiObject Win32_Volume -ComputerName $computer -Filter "DriveType='3'" | Sort-Object Name
# create new custom object to keep adding store information to it
$Result = New-Object -TypeName PSCustomObject -Property #{
ComputerName = $computer.ToUpper()
IPAddress = $IP
Manufacturer = $hardware.Manufacturer
Model = $hardware.Model
ADDescription = (Get-ADComputer -Identity $computer -Properties Description).Description -join ';'
ProductName = $os.Caption
OSVersion = $os.version
BuildNumber = $os.BuildNumber
OSArchitecture = $os.OSArchitecture
Domain = $hardware.Domain
'RAM (GB)' = $totalMemory
CPU = $cpu.Name
CPUTotalSockets = $cpu.TotalSockets
CPUTotalCores = $cpu.TotalCores
CPUTotalLogicalProcessors = $cpu.TotalLogicalProcessors
CPUVirtualizationFirmwareEnabled = (Get-CimInstance -Class Win32_processor -ComputerName $computer).VirtualizationFirmwareEnabled -join ','
}
# Column ordering, re-order if you like
<#$colOrder = 'ComputerName', 'IPAddress', 'Manufacturer', 'Model', 'ADDescription',
'ProductName', 'OSVersion', 'BuildNumber', 'OSArchitecture',
'Domain', 'RAM (GB)', 'CPU', 'CPUTotalSockets', 'CPUTotalCores',
'CPUTotalLogicalProcessors', 'CPUVirtualizationFirmwareEnabled'#>
# Return all your results
#$Result | Select-Object -Property $colOrder
$Result | Select-Object "ComputerName", "IPAddress", "Manufacturer", "Model", "ADDescription", "ProductName", "OSVersion", "BuildNumber",
"OSArchitecture", "RAM (GB)", "CPU", "CPUTotalSockets", "CPUTotalCores", "CPUTotalLogicalProcessors", "CPUVirtualizationFirmwareEnabled", "Domain" |
Export-Csv -Path "C:\SQL\Get-Inventory.csv" -Delimiter '|' -Append -NoTypeInformation
#$disks | Format-Table DriveLetter, Label, #{Name='Size(GB)'; Expression={[decimal]('{0:N0}' -f($_.Capacity/1gb))}}, #{Name='FreeSpace(GB)'; Expression={[decimal]('{0:N0}' -f($_.FreeSpace/1gb))}}
}
catch
{ Write-Output "--- $computer ---" $Error[0] `n | Add-Content -Path C:\SQL\UnreachableServers.txt }
}
The Powershell's process uses an average of 50/75 Mb of RAM. It's possible to reduce the RAM usage?
I accept any kind of advice given my little experience on Powershell :)
Thanks in advance.
Alessandro
I'm trying to exclude two drives from a file search. I'm getting an error when running the code: "Get-ChildItem : Access to the path 'C:\Windows\system32\LogFiles...'". The search shouldn't touch C. Help!! What am I doing wrong? Code attached.
$Drives = Get-PSDrive -PSProvider FileSystem | where { -not ('c','u' -eq $_.name) }
$FS='(.*18)\.FOO'
$FPath=#(foreach($Drive in $drives) {
Get-ChildItem -Path $Drive.Root -Recurse | Where-Object {$_.Name -match $FS} -ErrorAction SilentlyContinue | %{$_.Name}
})
I think you are looking for
Get-PSDrive -PSProvider FileSystem |
Where-Object {"c","u" -notcontains $_.name} |
ForEach-Object{
Get-ChildItem -Path $_.Root -Recurse |
Where-Object {$_.Name -match '(.*18)\.FOO'} -ErrorAction SilentlyContinue |
select Name
}
Seems based on your comments you are still getting the error. Lets trouble shoot it a bit. Lets output the drive that it really seems to error on.
Get-PSDrive -PSProvider FileSystem |
Where-Object {"c","u" -notcontains $_.name} |
ForEach-Object{
$Drive = $_.Name
try{
Get-ChildItem -Path $_.Root -Recurse |
Where-Object {$_.Name -match '(.*18)\.FOO'} -ErrorAction SilentlyContinue |
Select Name
}catch{
#{
Drive = $Drive
}
}
}
I have an Inventory Powershell script that I am trying to output into a csv. My goal is to output each execution of the script in a separate row going down their columns.
I've tried Export-Csv, but since i'm using variables, the csv displays (i'g guessing) metadata.
$ComputerName = Get-WmiObject Win32_OperatingSystem | select -ExpandProperty CSName
$OS_Name = Get-WmiObject Win32_OperatingSystem | Select-Object -ExpandProperty Caption
$OS_Architecture = Get-WmiObject Win32_OperatingSystem | select -ExpandProperty OSArchitecture
$System_Manufacturer = Get-WmiObject win32_computersystem | select -ExpandProperty Manufacturer
$Model = Get-WmiObject win32_computersystem | select -ExpandProperty Model
$CPU_Manufacturer = Get-WmiObject Win32_Processor | select -ExpandProperty Name
$Disk_Size_GB = Get-WmiObject win32_diskDrive | Measure-Object -Property Size -Sum | % {[math]::round(($_.sum /1GB),2)}
$Physical_Memory_GB = Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB),2)}
$Version=(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ReleaseId).ReleaseId
$InstallDate= systeminfo | find /I “Install Date”
$Assettag=(Get-WmiObject -Class Win32_SystemEnclosure | Select-Object SMBiosAssetTag).SMBiosAssetTag
$SerialNumber = (Get-WmiObject -Class Win32_BIOS | Select-Object SerialNumber).SerialNumber
($Assettag, $ComputerName, $System_Manufacturer, $Model, $OS_Name, $Version, $SerialNumber | Format-Table | Out-File C:\Users\1\Desktop\Newinvent.csv )
I expect each row to be filled with each execution
Thanks
If you want to use Export-Csv, you need to have an object with properties that contain the names and values you want to export. One way to do this is to create a [PSCustomObject] with all of your properties defined in a hash table. You can pipe that custom object to the Export-Csv command.
[PSCustomObject]#{"ComputerName" = $ComputerName
"OS_Name" = $OS_Name
"OS_Architecture" = $OS_Architecture
"System_Manufacturer" = $System_Manufacturer
"Model" = $Model
"CPU_Manufacturer" = $CPU_Manufacturer
"Disk_Size_GB" = $Disk_Size_GB
"Physical_Memory_GB" = $Physical_Memory_GB
"Version" = $Version
"InstallDate" = $InstallDate
"Assettag" = $Assettag
"SerialNumber" = $SerialNumber
} | Export-Csv -Path file.csv -NoTypeInformation -Append
And try to look at the result from Get-ComputerInfo - most of your needs are satisfied there.
I'd avoid the time consuming Systeminfo
> (Measure-Command {$systeminfo=(systeminfo) 2>$NULL}).Totalseconds
3,0428012
As well as Get-ComputerInfo
$OldProgressPreference = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
(Measure-Command {$ComputerInfo = Get-ComputerInfo}).Totalseconds
3,1837208
$ProgressPreference = $OldProgressPreference
And use an optimized version of your script which gets/converts InstallDate from registry:
> (Measure-Command{Q:\Test\2019\06\03\SO_56429703.ps1}).TotalSeconds
1,635074
Get-Content file.csv
## Q:\Test\2019\06\03\SO_56429703.ps1
function RoundGB($Size){
[math]::round(($Size/1GB),2)
}
$Win32OS = Get-WmiObject Win32_OperatingSystem
$Win32CS = Get-WmiObject Win32_ComputerSystem
$CurrVer = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
$InstDate= [timezone]::CurrentTimeZone.ToLocalTime([datetime]'1/1/1970').AddSeconds(
(Get-ItemProperty $CurrVer).InstallDate)
$inventory = [PSCustomObject]#{
ComputerName = $Win32OS.CSName
OSName = $Win32OS.Caption
OSArchitecture = $Win32OS.OSArchitecture
SystemManufacturer= $Win32CS.Manufacturer
Model = $Win32CS.Model
CPUManufacturer = (Get-WmiObject Win32_Processor).Name
DiskSizeGB = RoundGB (Get-WmiObject Win32_DiskDrive | Measure-Object Size -Sum).Sum
PhysicalMemoryGB = RoundGB (Get-WMIObject Win32_PhysicalMemory | Measure-Object capacity -Sum).Sum
Version = (Get-ItemProperty -Path $CurrVer -Name ReleaseId).ReleaseId
InstallDate = $InstDate
Assettag = (Get-WmiObject Win32_SystemEnclosure).SMBiosAssetTag
SerialNumber = (Get-WmiObject Win32_BIOS).SerialNumber
}
$Inventory | Export-Csv -Path file.csv -NoTypeInformation -Append
I am trying to get all the list of KB installed on multiple servers and get the last reboot time of the system. My requirement is to get the result in csv or text format with column name "Hostname" , "KB Name" , "installed by" , "installed on" and "Last reboot". I have to execute 2 script to get this done and then i have to format it and i dont want other columns which i am receiving from code 1 only limited column are required.. Can some please help me to get the same format which i reuired?
Output required in below format :
"Source" "Description" "HotFixID" "InstalledBy" "InstalledOn" "Last Reboot"
Please find below 2 code.
FYI : I am new to powershell.
Code 1: This will list all KB installed patch.
$computers = Get-Content -path "C:\Users\joy\Desktop\Machine_List.txt"
$patches = Get-Content -path "C:\Users\joy\Desktop\KB_List.txt"
foreach ($computer in $computers){
foreach ($patch in $patches){
Get-HotFix -id $patch -ComputerName $computer | -OutVariable results -ErrorAction SilentlyContinue
if ($results -ne $null) {
$results | Out-File C:\Users\joy\Desktop\report1.txt -Append -Force
}
else {
Add-content "$Patch is not Present in $computer" -path "C:\Users\joy\Desktop\report2.txt"
}
}
Code 2: This will get the last reboot of the system.
$machines = Get-Content C:\Users\joy\Desktop\Machine_List.txt
$report = #()
$object = #()
foreach($machine in $machines)
{
$machine
$object = gwmi win32_operatingsystem -ComputerName $machine | select csname, #{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}
$report += $object
}
$report | Export-csv C:\Users\joy\Desktop\Reboot.csv
$computers = Get-Content C:\Users\XXXXXXXX\Desktop\Machine_List.txt
$patchlist = Get-Content C:\Users\XXXXXXXX\Desktop\KB_List.txt
foreach($computer in $computers)
{
Get-HotFix -ComputerName $computer -Id $patchlist | select
InstalledOn,InstalledBy,Description,HotFixID,__SERVER | Format-Table | Out-File
C:\Users\XXXXXXXX\Desktop\report1.txt
#Get-CimInstance -ClassName Win32_Operatingsystem | select csname, lastbootuptime |
Format-Table |Out-File C:\Users\XXXXXXXX\Desktop\report1.txt
gwmi win32_operatingsystem -ComputerName $computer | select csname,
#{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}} | Out-
File C:\Users\XXXXXXXX\Desktop\report1.txt -Append
}
Try this, This will allow you to get information what you are looking for. But this script only get installed patches information from the remote machines, If you want add one more loop to print the patches which are installed on another text file.
The code below makes an md5 and other metadata fingerprint, but crashes on files with unknown corruption (e.g., files, that can be copied, mostly even opened, but that can not be hashed or zipped up [to disguise their corruption]).
Question: How one makes this code to skip or ignore any problem files and just do the rest? Imagine 1 million files on 8 TB.
Get-childitem -recurse -file |
Select-object #{n="Hash";e={get-filehash -algorithm MD5 -path $_.FullName |
Select-object -expandproperty Hash}},lastwritetime,length,fullname |
Export-csv "$((Get-Date).ToString("yyyyMMdd_HHmmss"))_filelistcsv_MD5_LWT_size_path_file.csv" -notypeinformation
Try this:
$errLogPath = "$((Get-Date).ToString("yyyyMMdd_HHmmss"))_filelistcsv_MD5_LWT_size_path_file_ERROR.csv"
Get-childitem -recurse -file |
foreach-object {
$file = $_
try {
$hash = Get-FileHash -Algorithm MD5 -path $file.FullName -ErrorAction Stop
$file | Add-Member -MemberType NoteProperty -Name Hash -Value $hash.Hash -PassThru
} catch {
$file |
add-Member -MemberType NoteProperty -Name Exception -Value $_.Exception.Message -PassThru |
Select-Object -Property Name, FullName, Exception |
Export-Csv -Path $errLogPath -append -notypeinformation
}
} |
select-object -Property Hash, LastWriteTime, Length, FullName |
Export-csv "$((Get-Date).ToString("yyyyMMdd_HHmmss"))_filelistcsv_MD5_LWT_size_path_file.csv" -notypeinformation
Each file is processed through the foreach-object cmdlet. A try...catch is used to capture exceptions, and an -ErrorAction Stop parameter is added to get-FileHash to ensure Terminating errors are raised and will trigger the catch.
If an error is caught, the file name, path and exception message are output to a CSV file.
EDIT: Adding in the progress bar
$logPath = "$((Get-Date).ToString("yyyyMMdd_HHmmss"))_filelistcsv_MD5_LWT_size_path_file.csv"
$errLogPath = "$((Get-Date).ToString("yyyyMMdd_HHmmss"))_filelistcsv_MD5_LWT_size_path_file_ERROR.csv"
write-host "Counting files ..."
$maxFileCount = 0; get-childItem -recurse -file | % { $maxFileCount +=1 }
write-host "Hashing files ..."
$currFileCount = 0
Get-childitem -recurse -file |
foreach-object {
$file = $_
Write-Progress -Activity "Hashing Files" -Status ( "{0}/{1} - {2}" -f $currFileCount, $maxFileCount, $File.FullName ) -PercentComplete (($currFileCount++)/$maxFileCount*100)
try {
$hash = Get-FileHash -Algorithm MD5 -path $file.FullName -ErrorAction Stop
$file | Add-Member -MemberType NoteProperty -Name Hash -Value $hash.Hash -PassThru
} catch {
$file |
add-Member -MemberType NoteProperty -Name Exception -Value $_.Exception.Message -PassThru |
Select-Object -Property Name, FullName, Exception |
Export-Csv -Path $errLogPath -append -notypeinformation
}
} |
select-object -Property Hash, LastWriteTime, Length, FullName |
Export-csv -Path $logPath -notypeinformation