PowerShell - Get Average Memory Usage of Server - powershell

I am running an instance of Windows Server 2012 R2 and would like to get the average memory usage of my server.
To get the CPU usage, I use
Get-WmiObject win32_processor | select LoadPercentage |fl
and to get the average CPU usage, I have
Get-WmiObject win32_processor | Measure-Object -property LoadPercentage -Average | Select Average
How do I do the same thing with memory usage?

You want the Win32_OperatingSystem namespace, and it's TotalVisibleMemorySize (physical memory), FreePhysicalMemory, TotalVirtualMemorySize, and FreeVirtualMemory properties.
Get-WmiObject win32_OperatingSystem |%{"Total Physical Memory: {0}KB`nFree Physical Memory : {1}KB`nTotal Virtual Memory : {2}KB`nFree Virtual Memory : {3}KB" -f $_.totalvisiblememorysize, $_.freephysicalmemory, $_.totalvirtualmemorysize, $_.freevirtualmemory}
That will spit back:
Total Physical Memory: 4079572KB
Free Physical Memory : 994468KB
Total Virtual Memory : 8157280KB
Free Virtual Memory : 3448916KB
I'm sure you can do the math if you want to get Used instead of Free.
Edit: Your CPULoad Average isn't really an average of anything. Case in point:
For($a=1;$a -lt 30;$a++){
Get-WmiObject win32_processor|ForEach{
[pscustomobject][ordered]#{
'Average' = $_ | Measure-Object -property LoadPercentage -Average | Select -expand Average
'Current' = $_ | select -expand LoadPercentage
}
}
Start-Sleep -Milliseconds 50
}
Results:
Average CPU Load
------- --------
2 2
1 1
1 1
1 1
1 1
5 5
1 1
1 1
0 0
1 1
1 1
1 1
2 2
4 4
0
1 1
7 7
24 24
1 1

If you want an average over a period of time you could use performance counters
### Get available memory in MB ###
$interval = 1 #seconds
$maxsamples = 5
$memorycounter = (Get-Counter "\Memory\Available MBytes" -maxsamples $maxsamples -sampleinterval $interval |
select -expand countersamples | measure cookedvalue -average).average
### Memory Average Formatting ###
$freememavg = "{0:N0}" -f $memorycounter
### Get total Physical Memory & Calculate Percentage ###
$physicalmemory = (Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).Sum / 1mb
$physicalmemory - $freememavg

Function Get-ADtop {
[CmdletBinding()]
param(
[String]$ComputerName,
[String]$Sort = "none",
[String]$BaseDN = "OU=systems,DC=domain,DC=com", # Edit Default Base DN
[String]$SampleTime = 2
)
If ($ComputerName) {
$Computers = $ComputerName
} else {
$Computers = Get-ADComputer -Filter * -Properties * -SearchBase $BaseDN -EA SilentlyContinue | % {$_.Name}
}
$DataSet = #()
$Targets = #()
ForEach ($Comp in $Computers) {
If (Test-Connection -ComputerName $Comp -Count 1 -Quiet -TimeToLive 1 -EA SilentlyContinue) {
If (!(Get-WmiObject -ComputerName $Comp win32_OperatingSystem -EA SilentlyContinue)) { break }
$Targets += $Comp
}
}
$CompCount = $Computers | Measure-Object | % {$_.Count}
$DeadCount = $CompCount - ($Targets | Measure-Object | % {$_.Count})
If (!($DeadCount -eq 0)) {
Write-Host "`n$DeadCount unavailable computers removed"
}
Write-Host "`nGathering realtime CPU/MEM/DISK Usage data from $CompCount computers..."
ForEach ($Comp in $Targets) {
$proc = (Get-WmiObject -ComputerName $Comp -class win32_processor -EA SilentlyContinue | Measure-Object -property LoadPercentage -Average | Select Average | % {$_.Average / 100}).ToString("P")
$mem = Get-WmiObject -ComputerName $Comp win32_OperatingSystem -EA SilentlyContinue
$mem = (($mem.TotalVisibleMemorySize - $mem.FreePhysicalMemory) / $mem.TotalVisibleMemorySize).ToString("P")
$disk = Get-WmiObject -ComputerName $Comp -class Win32_LogicalDisk -filter "DriveType=3" -EA SilentlyContinue
$disk = (($disk.Size - $disk.FreeSpace) / $disk.Size).ToString("P")
$Info = [pscustomobject]#{
'Computer' = $Comp
'CPU Usage' = $proc
'MEM Usage' = $mem
'Disk Usage' = $disk
}
$DataSet += Add-Member -InputObject $Info -TypeName Computers.CPU.Usage -PassThru
}
Switch ($Sort) {
"none" { $DataSet }
"CPU" { $DataSet | Sort-Object -Property "CPU Usage" -Descending }
"MEM" { $DataSet | Sort-Object -Property "MEM Usage" -Descending }
"DISK" { $DataSet | Sort-Object -Property "DISK Usage" -Descending }
}
}
More info here GitHub Gist Link

Related

Problem with the proper functioning of the script

I have a request if anyone could help find a bug in setting the virtual memory by the script, if you have less than 8GB of ram, the script instead of setting 8GB goes to setting the variant for 16GB of operating memory
$Result = (Get-CimInstance -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1GB
$DriveLetter = (Get-CimInstance -ClassName Win32_Volume | Where-Object -FilterScript {$_.PageFilePresent}).DriveLetter[0]
switch ($Result)
{
{$PSItem -le 7}
{
Write-Verbose "Masz $($PSItem) GB pamięci! Zmiana pliku stronicowania na poczatkowy: 8 GB - maks .: 8 GB" -Verbose
Start-Sleep -Seconds 5
Get-CimInstance -ClassName Win32_ComputerSystem | Set-CimInstance -Property #{AutomaticManagedPageFile = $false}
Get-CimInstance -ClassName Win32_PageFileSetting | Where-Object -FilterScript {$_.SettingID -eq "pagefile.sys # $($DriveLetter):"} | Set-CimInstance -Property #{
InitialSize = 8192
MaximumSize = 8192
}
}
{$PSItem -le 31}
{
Write-Verbose "Masz $($PSItem) GB pamięci! Zmiana pliku stronicowania na poczatkowy: 16 GB - Max 16 GB" -Verbose
Start-Sleep -Seconds 5
Get-CimInstance -ClassName Win32_ComputerSystem | Set-CimInstance -Property #{AutomaticManagedPageFile = $false}
Get-CimInstance -ClassName Win32_PageFileSetting | Where-Object -FilterScript {$_.SettingID -eq "pagefile.sys # $($DriveLetter):"} | Set-CimInstance -Property #{
InitialSize = 16384
MaximumSize = 16384
}
}
{$PSItem -ge 32}
{
Write-Verbose "Masz $($PSItem) GB pamięci! Zmiana pliku stronicowania na poczatkowy: 8 GB - Max 8 GB" -Verbose
Start-Sleep -Seconds 5
Get-CimInstance -ClassName Win32_ComputerSystem | Set-CimInstance -Property #{AutomaticManagedPageFile = $false}
Get-CimInstance -ClassName Win32_PageFileSetting | Where-Object -FilterScript {$_.SettingID -eq "pagefile.sys # $($DriveLetter):"} | Set-CimInstance -Property #{
InitialSize = 8192
MaximumSize = 8192
}
}
}
I don't see any break on your switch statement, all possibilities are being evaluated without a break. By the way, you say lower than 8 yet in your statement I see lower or equal to 7. In any case, suppose you have 4Gb of RAM, with your statement you would enter into the first condition because 4 is lower or equal to 7 and you would also enter into the second condition because 4 is lower or equal to 31.
When working with switch just remember, it's very important to use breaks if you don't want to keep evaluating the following conditions.
Try the code below with and without break and see what happens:
$eval=4
switch($eval)
{
{$_ -le 7}
{
"$_ is lower or equal to 7"
break
}
{$_ -le 31}
{
"$_ is lower or equal to 31"
break
}
Default
{
"$_ is higher than 31"
}
}

Listing processes by CPU usage percentage in powershell

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

Remove white spaces between commands output in powershell

I've got an script and I want to remove the white spaces that powershell puts by default in the output result. Is there any way of doing it?
=======Computer1=======
Microsoft Windows 8.1 Pro
Name : Computer1
Model : Vostro 200
Manufacturer : Dell Inc.
SerialNumber : 012345
This is what I want:
=======Computer1=======
Microsoft Windows 8.1 Pro
Name : Computer1
Model : Vostro 200
Manufacturer : Dell Inc.
SerialNumber : 012345
This is my script:
$Computers=Import-Csv C:\Powershell\test.csv
$ResultsPath="C:\Powershell\test.txt"
foreach ($i in $Computers.Name) {
"="*7 + $i + "="*7
if (Test-Connection $i -quiet) {
(Get-WmiObject -class Win32_OperatingSystem -ComputerName $i).Caption
Get-WmiObject -class Win32_Computersystem -ComputerName $i | Select-Object Name, Model, Manufacturer | Format-List
Get-WmiObject win32_SystemEnclosure -ComputerName $i | Select-Object SerialNumber | Format-List }
else { "nothing" }
}
While Trim will do what you need, this is not a PowerShell way. Here is revised script, that works with objects internally and writes output the way you want.
$Computers = Import-Csv 'C:\Powershell\test.csv'
$ResultsPath = 'C:\Powershell\test.txt'
foreach ($i in $Computers.Name) {
$Header = '='*7 + $i + '='*7
Write-Output $Header
if (Test-Connection $i -quiet)
{
$Os = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $i | Select-Object -ExpandProperty Caption
$Info = Get-WmiObject -Class Win32_Computersystem -ComputerName $i | Select-Object Name, Model, Manufacturer
$Sn = Get-WmiObject -Class Win32_SystemEnclosure -ComputerName $i | Select-Object -ExpandProperty SerialNumber
$PC = New-Object -TypeName psobject -Property #{
OperatingSystem = $Os
Name = $Info.Name
Model = $Info.Model
Manufacturer = $Info.Manufacturer
SerialNumber = $Sn
} | Select-Object OperatingSystem, Name, Model, Manufacturer, SerialNumber
Write-Output ($PC | Format-List | Out-String).Trim()
}
else
{
Write-Output 'nothing'
}
}
Convert output to string and trim it:
"="*7 + $i + "="*7
if (Test-Connection $i -quiet) {
(Get-WmiObject -class Win32_OperatingSystem -ComputerName $i).Caption
(Get-WmiObject -class Win32_Computersystem -ComputerName $i | Select-Object Name, Model, Manufacturer | Format-List | Out-String).Trim()
(Get-WmiObject win32_SystemEnclosure -ComputerName $i | Select-Object SerialNumber | Format-List | Out-String).Trim() }
else { "nothing" }

Powershell - helping with our CMDB Issue - Opinions?

recently I took it upon myself to learn Powershell. It was a rough 2 weeks and a lot of reading but I'm getting better and better. I had some pressure at work to help with correcting our CMDB. We are about 7 months away from having a true Depolyment/Asset Management system in place. We have many reasons for relying on Powershell right now and we're trying to clean up a mess before we get the management system in. Anyway, I created a script that gets a lot of information for us. We have about 3000 objects/pcs and we need as much info as possible. Anyway, I created a script. So far it works well but I wanted some opinions from the experts or any advice. I feel like I did a decent job putting this together with only 2 weeks experiance but I really want to know what others think.
One thing I noticed: Windows 7 Boxes with IE9 and Up do not return a value for IE Version. Anyone know why?
Please see my code below:
Set-QADPSSnapinSettings -defaultSizeLimit 0
$FullPCList = (Get-QADComputer -SearchRoot $ou | Sort Name | select -expand name)
foreach ($computer in $FullPCList) {
ping -n 2 $computer >$null
if($lastexitcode -eq 0) { $Online = "Yes" } else { $Online = "No" }
$PCInfo = (Get-WmiObject -ComputerName $computer -Class Win32_ComputerSystem -ErrorAction SilentlyContinue)
$WinInfo = (Get-WmiObject -ComputerName $computer -Class Win32_OperatingSystem -ErrorAction SilentlyContinue)
$ram = ((Get-WmiObject -ComputerName $computer -Class Win32_PhysicalMemory -ErrorAction SilentlyContinue | Measure-Object Capacity -Sum).Sum / 1MB)
$bios = (Get-WmiObject -ComputerName $computer -Class Win32_Bios -ErrorAction SilentlyContinue)
$ie = (Get-Wmiobject -ComputerName $computer -namespace “root\CIMV2\Applications\MicrosoftIE” -query “select version from MicrosoftIE_Summary” -ErrorAction SilentlyContinue)
$freespace = ((Get-WmiObject -ComputerName $computer -Class Win32_LogicalDisk | Select Freespace | Measure-object Freespace -Sum).Sum / 1GB)
#Start uptime check
$LastBootUpTime = $WinInfo.ConvertToDateTime($WinInfo.LastBootUpTime)
$Time = (Get-Date) - $LastBootUpTime
$formattime = '{0:00}:{1:00}:{2:00}' -f $Time.Days, $Time.Hours, $Time.Minutes
#End Uptime Check
if ($WinInfo.Caption -match "Windows 7") {
$name = (Get-ChildItem -Path "\\$Computer\C$\Users" -Exclude "*Service*","*admin*","*Public*","*ffodero*","*jgalli*","*jwalters*","*frochet*" | Sort-Object LastAccessTime -Descending | Select-Object Name -First 1).Name
$loggedintime = (Get-ChildItem -Path "\\$Computer\C$\Users" -Exclude "*Service*","*admin*","*Public*","*ffodero*","*jgalli*" | Sort-Object LastAccessTime -Descending | Select-Object LastAccessTime -First 1).LastAccessTime
}
if ($WinInfo.Caption -match "Windows XP") {
$name = (Get-ChildItem -Path "\\$Computer\C$\Documents and Settings" -Exclude "*Service*","*admin*","*Public*" | Sort-Object LastAccessTime -Descending | Select-Object Name -First 1).Name
$loggedintime = (Get-ChildItem -Path "\\$Computer\C$\Documents and Settings" -Exclude "*Service*","*admin*","*Public*" | Sort-Object LastAccessTime -Descending | Select-Object LastAccessTime -First 1).LastAccessTime
}
$table = #{
Model = $PCInfo.Model
IEVersion = $ie.Version
Serial = $Bios.SerialNumber
Memory = $ram
DriveFreeSpaceGB = $freespace
Manufacturer = $PCInfo.Manufacturer
OSName = $WinInfo.Caption
Computer = $computer
Uptime = $formattime
LastloggedinUser = $name
LastLoggedinDate = $loggedintime
LoggedOnDuringScan = $PCInfo.Username
ServicePack = $WinInfo.ServicePackMajorVersion
Online = $Online
}
New-Object PSObject -Property $table | Export-Csv C:\logs\mother.csv -NoTypeInformation -Append
}
The namespace root\CIMV2\Applications\MicrosoftIE has been removed starting with Windows Vista (see note at the end of the blog post). You should be able to read the version number from the registry, though:
$hive = [UInt32]'0x80000002'
$key = 'SOFTWARE\Microsoft\Internet Explorer'
$reg = [WMIClass]"\\$computer\root\default:StdRegProv"
$ieVersion = $reg.GetStringValue($hive, $key, 'Version').sValue

Error in foreach function in powershell

Below is the code snippet i tried but having an error because of it can anyone helpme in editing this one
$colItems4 = Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum |
foreach ($objItem4 in $colItems4 )
{
write-host "Total Physical Ram : " $objItem4.Sum
}
You already had it. You just added too much.
Gwmi win32_PhysicalMemory | Measure-Object -Property Capacity -Sum
And if you wanted to show only the sum then:
Gwmi win32_physcialmemory | measure-object -property Capacity -sum | select sum
$colItems4 = Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum
foreach ($objItem4 in $colItems4 )
{
write-host "Total Physical Ram : " $objItem4.Sum
}
Your code works fine. You just have an extra pipe at the end of your gwmi cmdlet.
$colItems4 = Get-WMIObject -class Win32_PhysicalMemory -computername $strComputer
$colItems5=$colItems4 | Measure-Object -Property capacity -Sum
foreach ($objItem4 in $colItems5)
{
write-host "Memory : " $colItems5.Sum
}
Will solve the problem :D