when attempting to run my script then I got the following output. So Computer Name is duplicating.
I am getting {192.168.1.11, 192.168.1.12, $null} in DNS.
Script :
$Result=Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'" -Property DNSServerSearchOrder,DNSHostname
$output = new-object PSObject
$output | add-member NoteProperty "ComputerName" $Result.DNSHostname
$output | add-member NoteProperty "DNSServerSearchOrder" $Result.DNSServerSearchOrder
$output
Output :
ComputerName DNSServerSearchOrder
------------ --------------------
{srv01, srv01} {192.168.1.11, 192.168.1.12, $null}
Use Select-Object when piping multiple results, like:
$Result | Select-Object -Property DNSHostname,DNSServerSearchOrder
DNSHostName DNSServerSearchOrder
----------- --------------------
srv01 {192.168.1.11, 192.168.1.12}
srv01 {$null}
The reason there are two results is you have two enabled adapters. The second has no DNS servers set
I'm working on a quick string of code that allows me to search a specific print server and also its contents such as printers. What I want for it to do is once getting the printer information to be able to find a specific printer using the port name which in this case is an IP address not quite sure if is possible but I haven't found a command that lets me define a search using those values.
Get-Printer -computerName "server01"|select-object -Property Name, PortName
Name PortName
Printer01 X.XX.XXX.X
Prnter02 X.XX.XX.XX
is there a way to be able to find a printer using the Get-Printer commandlet and utilizing the port name to find the specific printer?
I'm just explaining in more detail #JeffZeitlin very correct answer.
Get-Printer - The Get-Printer cmdlet retrieves a list of printers installed on a computer. You can also use Get-Printer to retrieve the properties of a single printer, and then use that information as input into other cmdlets.
Get-Printer | Get-Member - The Get-Member cmdlet gets the members, the properties and methods, of objects.
Get-Printer | get-member
Get-Printer | Select-Object - The Select-Object cmdlet selects specified properties of an object or set of objects. It can also select unique objects, a specified number of objects, or objects in a specified position in an array.
Get-Printer | select-object -Property Name, PortName
Get-Printer | Select-Object | Where-Object - The Where-Object cmdlet selects objects that have particular property values from the collection of objects that are passed to it. For example, you can use the Where-Object cmdlet to select files that were created after a certain date, events with a particular ID, or computers that use a particular version of Windows.
Get-Printer | select-object -Property Name, PortName | where PortName -eq "PORTPROMPT:"
Get-Printer -ComputerName
Get-Printer -ComputerName $env:Computername | select-object -Property Name, PortName | where PortName -eq "PORTPROMPT:"
Scripting Example Get-Printer
$server = "$env:Computername"
$printersportnames = Get-Printer -ComputerName $server | select-object -ExpandProperty PortName
#Write-Host $printersportnames
$results = New-Object System.Collections.ArrayList # Empty Array
ForEach ($printerportname in $printersportnames) {
$printerportname = $printerportname.ToString()
#Write-Host $printerportname
$output = Get-Printer -ComputerName $server | where-object {$_.PortName -eq $printerportname}
$x = $output.Name
$y = $output.PortName
$z = $output.CommunicationStatus
$a = $output.OperatingStatus
$Object = New-Object PSObject
$Object | Add-Member -Name 'Name' -MemberType Noteproperty -Value $x
$Object | Add-Member -Name 'PortName' -MemberType Noteproperty -Value $y
$Object | Add-Member -Name 'CommStatus' -MemberType Noteproperty -Value $z
$Object | Add-Member -Name 'OperStatus' -MemberType Noteproperty -Value $a
$results += $object
}
$results
How does one lists the processes using CPU > 1% by piping the output from Get-Process to Where-Object?
Complete beginner to powershell all i can think is something like this
Get-Process | Where-Object { CPU_Usage -gt 1% }
If you want CPU percentage, you can use Get-Counter to get the performance counter and Get-Counter can be run for all processes. So, to list processes that use greater than say 5% of CPU use:
(Get-Counter '\Process(*)\% Processor Time').CounterSamples | Where-Object {$_.CookedValue -gt 5}
This will list the processes that was using >5% of CPU at the instance the sample was taken. Hope this helps!
There are several points to note here:
first, you have to use the $_ variable to refer to the object currently coming from the pipe.
second, Powershell does not use % to express percentage -- instead, % represents the modulus operator. So, when ou want percentage, you have to transform your number by yourself by simply multiplying it by 0.01.
third, the Get-Process cmdlet does not have a field CPU_Usage; a summary on its output can be found here. About the field CPU is says: "The amount of processor time that the process has used on all processors, in seconds." So be clear on what you can expect from the numbers.
Summarizing the command can be written as
Get-Process | Where-Object { $_.CPU -gt 100 }
This gives you the processes which have used more than 100 seconds of CPU time.
If you want something like a relative statement, you first have to sum up all used times, and later divide the actual times by the total time. You can get the total CPU time e.g. by
Get-Process | Select-Object -expand CPU | Measure-Object -Sum | Select-Object -expand Sum
Try to stack it together with the previous command.
Further improving earlier answers by adding dynamic detection of the number of logic cores so the percentage can be adjusted back to what us common mortals expect to see, where 100% means all of the CPU bandwidth of the machine, and there is no value greater than 100%. Includes a filter set at 10%, which one can adjust as appropriate. The assumption is that people will be interested in finding processes with high overload processor usage and not want to list the numerous idle processes of the machine.
$NumberOfLogicalProcessors=(Get-WmiObject -class Win32_processor | Measure-Object -Sum NumberOfLogicalProcessors).Sum
(Get-Counter '\Process(*)\% Processor Time').Countersamples | Where cookedvalue -gt ($NumberOfLogicalProcessors*10) | Sort cookedvalue -Desc | ft -a instancename, #{Name='CPU %';Expr={[Math]::Round($_.CookedValue / $NumberOfLogicalProcessors)}}
Sample output:
InstanceName CPU %
------------ -----
_total 100
idle 100
I was looking for a solution to get cpu, mem utilization by process. All solutions I tried where I would get the cpu but those numbers were not matching with taskmanager. So I wrote my own. Following will provide accurate cpu utilization by each process. I tested this on a I7 laptop.
$Cores = (Get-WmiObject -class win32_processor -Property numberOfCores).numberOfCores;
$LogicalProcessors = (Get-WmiObject –class Win32_processor -Property NumberOfLogicalProcessors).NumberOfLogicalProcessors;
$TotalMemory = (get-ciminstance -class "cim_physicalmemory" | % {$_.Capacity})
$DATA=get-process -IncludeUserName | select #{Name="Time"; Expression={(get-date(get-date).ToUniversalTime() -uformat "%s")}},`
ID, StartTime, Handles,WorkingSet, PeakPagedMemorySize, PrivateMemorySize, VirtualMemorySize,`
#{Name="Total_RAM"; Expression={ ($TotalMemory )}},`
CPU,
#{Name='CPU_Usage'; Expression = { $TotalSec = (New-TimeSpan -Start $_.StartTime).TotalSeconds
[Math]::Round( ($_.CPU * 100 / $TotalSec) /$LogicalProcessors, 2) }},`
#{Name="Cores"; Expression={ ($Cores )}},`
#{Name="Logical_Cores"; Expression={ ($LogicalProcessors )}},`
UserName, ProcessName, Path | ConvertTo-Csv
Or as [pscustomobject]:
$cpu = Get-WmiObject –class Win32_processor -Property NumberOfCores, NumberOfLogicalProcessors
$mem = (Get-CimInstance -class cim_physicalmemory | measure capacity -sum).sum
$epoch = get-date(get-date).ToUniversalTime() -uformat "%s"
get-process -IncludeUserName |
% {
if ($_.starttime -gt 0) {
$ts = (New-TimeSpan -Start $_.StartTime -ea si).TotalSeconds
$cpuusage = [Math]::Round( $_.CPU * 100 / $ts / $cpu.numberoflogicalprocessors, 2)
} else {
$cpuusage = 0
}
[pscustomobject] #{
"Time" = $epoch
"Total_RAM" = $mem
"CPU_Usage" = $cpuusage
"Cores" = $cpu.numberofcores
"Logical Cores" = $cpu.numberoflogicalprocessors
"UserName" = $_.username
"ProcessName" = $_.processname
"Path" = $_.path
"CPU" = $_.CPU
"ID" = $_.ID
"StartTime" = $_.StartTime
"Handles" = $_.Handles
"WorkingSet" = $_.WorkingSet
"PeakPagedMemorySize" = $_.PeakPagedMemorySize
"PrivateMemorySize" = $_.PrivateMemorySize
"VirtualMemorySize" = $_.VirtualMemorySize
}
}
In addition to Get-Counter, you can also use Get-WmiObect to list and filter processes.
powershell "gwmi Win32_PerfFormattedData_PerfProc_Process -filter 'PercentProcessorTime > 1' | Sort PercentProcessorTime -desc | ft Name, PercentProcessorTime"
Alternatively, for Get-Counter, here is an example showing number format conversion to get rid of the annoying decimal places of the CookedValue.
In addition to filtering, this example also illustrates sorting, limiting columns, and output formatting:
powershell "(Get-Counter '\Process(*)\% Processor Time').Countersamples | Where cookedvalue -gt 3 | Sort cookedvalue -Desc | ft -a instancename, #{Name='CPU %';Expr={[Math]::Round($_.CookedValue)}}"
Get-Process is not the right cmdlet as it doesn't provide instantaneous CPU utilization.
You can also get the total load for all processors:
powershell "gwmi win32_processor | Measure-Object LoadPercentage -Average | ft -h Average"
Or,
typeperf -sc 4 "\Processor(_Total)\% Processor Time"
I'd like to Add my version of code just to assist anyone that is having trouble with the same issues.
I needed one that gave me the CPU and Memory and this my take on the subject. It can export over time if you setup a scheduled task in windows, and it appends to a CSV file output and you can get multiple processes.
$Cores = (Get-WmiObject -class win32_processor -Property numberOfCores).numberOfCores;
$LogicalProcessors = (Get-WmiObject –class Win32_processor -Property NumberOfLogicalProcessors).NumberOfLogicalProcessors;
$TotalMemory = (get-ciminstance -class "cim_physicalmemory" | % {$_.Capacity})
#EDIT the PATH for the CSV output to be located
$PATH = "C:\temp"
#You can add more processes here as variables or just CommaSeperate them like below
$Process1 = 'explorer'
$Process2 = 'chrome'
Get-Process -Name $Process1,$Process2 | select #{N="TimeStamp";E={Get-Date -Format 'dd/MM/yyyy HH:mm:ss.fff'}},
ID,
name,
Handles,
PeakPagedMemorySize,
PrivateMemorySize,
VirtualMemorySize,
#{Name="Memory_MB"; Expression = {[Math]::Round(($_.workingSet / 1mb),2)}},
#{Name='CPU_Usage'; Expression = { $TotalSec = (New-TimeSpan -Start $_.StartTime).TotalSeconds [Math]::Round( ($_.CPU * 100 / $TotalSec) /$LogicalProcessors, 2) }},
#{Name="Cores"; Expression={ ($Cores )}},
#{Name="Logical_Cores"; Expression={ ($LogicalProcessors )}},
Path | Export-Csv -Path "$PATH\CPU_MEMORY_$env:COMPUTERNAME.csv" -NoTypeInformation -Append
I know this is above the OP's question and goes a bit further but I hope this helps!
To invoke vs. multible servers in parallel, and return process, cpu usage, servername, and corecount the following works well.
It will take 10 samples over 10sec and average the value. You can change this with the MaxSamples parameter.
I reckon its a less elegant version of what Emrah Saglam is doing, i just get scared and confused by all his pipes :)
$allServers = "server1", "PC001", "server2"
#Change value of MaxSamples to the number of samples to take. Samples are taken in 1sec intervals
$CPUUsage = Invoke-Command -ComputerName $allServers -ScriptBlock {
$counters = (Get-Counter "\Process(*)\% Processor Time" -MaxSamples 10).CounterSamples | Sort-Object -Property CookedValue -Descending
[int]$coreCount = (Get-WMIObject Win32_ComputerSystem).NumberOfLogicalProcessors
$counters | ForEach-Object {
Add-Member -MemberType NoteProperty -Name "CPU_PCT" -Value ([math]::Round($_.CookedValue / $coreCount))[0] -InputObject $_
Add-Member -MemberType NoteProperty -Name "Host" -Value ($_.Path -replace "^\\\\|\\process.*$","") -InputObject $_
Add-Member -MemberType NoteProperty -Name "CoreCount" -Value $coreCount -InputObject $_
}
$counters | Select-Object InstanceName,CPU_PCT,Host,Path,CoreCount
}
#Unhash to see all samples:
#$CPUUsage | Sort-Object -Property Host,CPU_PCT -Descending | Select-Object -Property Host,InstanceName,CPU_PCT,Path,CoreCount | Out-GridView -Title "CPU Usage"
#Group samples, add wanted values and take average. Add values to new object
$CPUUsageGrouped = $CPUUsage | Group-Object -Property InstanceName,Host
$CPUUsageGrouped | ForEach-Object {
Add-Member -MemberType NoteProperty -Name "CPUavg" -Value (($_.Group.CPU_PCT | Measure-Object -Sum).Sum / $_.Count) -InputObject $_
Add-Member -MemberType NoteProperty -Name "CPUmin" -Value ($_.Group.CPU_PCT | Sort-Object)[0] -InputObject $_
Add-Member -MemberType NoteProperty -Name "CPUmax" -Value ($_.Group.CPU_PCT | Sort-Object)[$_.Count -1] -InputObject $_
Add-Member -MemberType NoteProperty -Name "Host" -Value $_.Group.Host[0] -InputObject $_
Add-Member -MemberType NoteProperty -Name "CoreCount" -Value $_.Group.CoreCount[0] -InputObject $_
Add-Member -MemberType NoteProperty -Name "InstanceName" -Value $_.Group.InstanceName[0] -InputObject $_
}
#Sort the grid view with the build in search functions
$CPUUsageGrouped | Sort-Object -Property Host,CPUavg -Descending | Select-Object -Property Host,InstanceName,CPUavg,CoreCount,CPUmin,CPUmax | Out-GridView -Title "CPU Usage"
How about this for one process?
$sleepseconds = 1
$numcores = 4
$id = 5244
while($true) {
$cpu1 = (get-process -Id $id).cpu
sleep $sleepseconds
$cpu2 = (get-process -Id $id).cpu
[int](($cpu2 - $cpu1)/($numcores*$sleepseconds) * 100)
}
$Result = Invoke-Command -ComputerName $ServerName -ScriptBlock {
Get-Counter "\Process(*)\% Processor Time" -ErrorAction SilentlyContinue `
| Select-Object -ExpandProperty CounterSamples `
| Where-Object {$_.Status -eq 0 -and $_.instancename -notin "_total", "idle", "" -and $_.CookedValue/$env:NUMBER_OF_PROCESSORS -gt 0} `
| Sort-Object CookedValue -Descending `
| Select-Object #{N="ServerName";E={$env:COMPUTERNAME}},
#{N="ProcessName";E={
$friendlyName = $_.InstanceName
try {
$procId = [System.Diagnostics.Process]::GetProcessesByName($_.InstanceName)[0].Id
$proc = Get-WmiObject -Query "SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId =$procId"
$procPath = ($proc | where { $_.ExecutablePath } | select -First 1).ExecutablePath
$friendlyName = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription
} catch { }
$friendlyName
}},
#{N="CPU_Percent";E={[System.Math]::Round(($_.CookedValue/$env:NUMBER_OF_PROCESSORS), 2)}},
#{N="TimeStamp";E={Get-Date -Format 'dd/MM/yyyy HH:mm:ss.fff'}} -First 10 `
$Result
}
# If you want to export result to your SQL Server table you can use DbaTools Powershell Modules.
$Result | Select -Property ServerName, ProcessName, CPU_Percent, TimeStamp | ConvertTo-DbaDataTable | Write-DbaDbTableData -SqlInstance $OutInstance -Database $OutDB -Schema dbo -Table WindowsTopCPUProcesses
Could someone provide a PowerShell script to join two function results based on common key columns.
Example:
Result1 and Result2 has common field 'Name'. I want to join both the results and fetch the below informations.
$Result1 = get-wmiobject -ComputerName localhost -Class win32_service
$Result2 = get-service
Result
Name : wuauserv
DisplayName : Windows Update
Status : Running
StartMode : Manual
ProcessId : 400
Use below PowerShell script to join both the results based on common key column (Name).
$Result1=get-wmiobject -ComputerName localhost -Class win32_service
$Result2=get-service
$Result=#()
for($i=0;$i -lt $Result2.count;$i++)
{
$startmode=($Result1 | where{$_.Name -eq $Result2[$i].Name})|Select StartMode,ProcessId
$tempObj=new-object PSObject
$tempObj | Add-member noteproperty Name $Result2[$i].Name
$tempObj | Add-member noteproperty DisplayName $Result2[$i].DisplayName
$tempObj | Add-member noteproperty Status $Result2[$i].Status
$tempObj | Add-member noteproperty StartMode $startmode.StartMode
$tempObj | Add-member noteproperty ProcessId $startmode.ProcessId
$Result += $tempObj
}
$Result
No need to combine the output of the two commands. All of the properties are already out from the Get-WMIObject. (Personally I like using the CIM cmdlets instead of WMI wherever possible too)
Get-CimInstance Win32_Service | select Name, DisplayName, State, StartMode, ProcessId
Edit: The output of State from gcim is the Status property of Get-Service (Here's a calculated property to fix that, if that's an issue)
Get-CimInstance Win32_Service | select Name, DisplayName, #{Name="Status";Expression={$_.State}}, StartMode, ProcessId
try this
$result=get-wmiobject -ComputerName localhost -Class win32_service | %{ New-Object psobject -Property #{ objectwmi=$_; objectgetservice=(get-service | where name -eq $_.Name | select -first 1)} }
I'd like to take specific output of four objects and put them into a CSV.
$obj1 = get-wmiobject win32_computersystem | select-object name,manufacturer,model,totalphysicalram
$obj2 = get-wmiobject win32_processor | select-object deviceid,name,maxclockspeed,numberofcores
$obj3 = get-wmiobject win32_bios | select-object serialnumber
$obj4 = get-wmiobject win32_operatingsystem | select-object osarchitecture
I'd like to combine all of those into the same output row in a csv.
How can I do this with powershell? Should I build an array of objects?
I don't fault you for not having a start on this, I wouldn't have had any idea where to go with code a year ago myself. Try this out and see how it strikes you...
$obj1 = get-wmiobject win32_computersystem | select-object name,manufacturer,model,TotalPhysicalMemory
$obj2 = get-wmiobject win32_processor | select-object deviceid,#{l="Proc";e={$_.name}},maxclockspeed,numberofcores
$obj3 = get-wmiobject win32_bios | select-object serialnumber
$obj4 = get-wmiobject win32_operatingsystem | select-object osarchitecture
$Combined = New-Object -Type PSObject
$obj1,$obj2,$obj3,$obj4|%{$CurObj = $_;$_|gm|?{$_.MemberType -match "NoteProperty"}|%{$NewMember = $_.Name;$Combined|Add-Member -MemberType NoteProperty -Name $NewMember -Value $CurObj.$NewMember}}
I fixed TotalPhysicalMemory (not totalphysicalram), and changed the proc query so it renamed the Name property to Proc, that way you don't have 2 properties with the same name. Then I fed all 4 objects into a ForEach loop, and for each object I got it's members and filtered for the NoteProperty members (getting rid of Methods and what not). For each one I took the member's name and created a property in a new PSCustomObject that I had created with that same name, and assigned the value from the original object associated with that property. I hope that makes sense, I found it a little hard to follow and I wrote the thing...
Edit: Dur... I didn't answer the original question, I just got all the prep work done. Here's how you output it:
$Combined|Export-CSV -Path C:\SomeFolder\MachineSpecs.CSV -NoTypeInfo
I tried running TheMadTechnician's answer on PSv3 and it didn't like the Out-CSV cmdlet. So I replaced it with Export-CSV and it worked fine.
$obj1 = get-wmiobject win32_computersystem | select-object name,manufacturer,model,TotalPhysicalMemory
$obj2 = get-wmiobject win32_processor | select-object deviceid,#{l="Proc";e={$_.name}},maxclockspeed,numberofcores
$obj3 = get-wmiobject win32_bios | select-object serialnumber
$obj4 = get-wmiobject win32_operatingsystem | select-object osarchitecture
$Combined = New-Object -Type PSObject
$obj1,$obj2,$obj3,$obj4|%{$CurObj = $_;$_|gm|?{$_.MemberType -match "NoteProperty"}|%{$NewMember = $_.Name;$Combined|Add-Member -MemberType NoteProperty -Name $NewMember -Value $CurObj.$NewMember}}
$Combined | Export-CSV -Path H:\MachineSpecs.CSV -NoTypeInfo
Gives the output of:
"manufacturer","model","name","TotalPhysicalMemory","deviceid","maxclockspeed","numberofcores","Proc","serialnumber","osarchitecture"
"Hewlett-Packard","HP EliteBook 8760w","LAUCA-44A135","8537874432","CPU0","2201","4","Intel(R) Core(TM) i7-2670QM CPU # 2.20GHz","USH244A135","64-bit"
Here's a readable syntax I like for this task, hope this helps. This creates a hashtable of properties and adds it to a PSObject, then adds that to an array. You can do as you wish with the resulting array. I typically run this in a foreach loop against a list of remote computers. You can glom together all kinds of disparate data for reporting very easily this way.
$Results = #()
$obj1 = get-wmiobject win32_computersystem
$obj2 = get-wmiobject win32_processor
$obj3 = get-wmiobject win32_bios
$obj4 = get-wmiobject win32_operatingsystem
$Obj = new-object psobject -property#{
PropertyName = $Obj2.Property
SomeOtherPropertName = $obj1.Property
SerialNumber = $obj3.SerialNumber
DateCollected = (get-date).DateTime
OSArchitecture = $obj4.OsArchitecture
}
$Results+=$obj