i want to get just the model name of the gpu by searching for the "$deviceid".
So this is what i have at the moment:
Install-Module PSParseHtml
$deviceid = "0x1f02"
$Url = 'https://envytools.readthedocs.io/en/latest/hw/pciid.html#gpu'
$AllTables = ConvertFrom-HtmlTable -Url $Url
$AllTables | Where-Object {$_."device id" -match $deviceid}
My output is this:
device id product
--------- -------
0x1f02 TU106 [GeForce RTX 2070]
0x1f07 TU106 [GeForce RTX 2070]
0x1f08 TU106 [GeForce RTX 2060]
0x1f10 TU106 [GeForce RTX 2070 Mobile]
0x1f11 TU106 [GeForce RTX 2060 Mobile]
0x1f50 TU106 [GeForce RTX 2070 Mobile]
0x1f51 TU106 [GeForce RTX 2060 Mobile]
How can i get now as output only the gpu model name "GeForce RTX 2070" with the matching device id "0x1f02"
Thank you
Your question has two distinct aspects:
A question that is specific to the PSParseHTML module's ConvertFrom-HtmlTable cmdlet:
ConvertFrom-HtmlTable, outputs whole arrays in your case, so that $AllTables is in effect a nested array, whereas you want to filter by the individual elements of those nested arrays.
To force these nested arrays to be enumerated, so that Where-Object can act on individual objects, as usual, you can simply pipe to Write-Output:
# Thanks to Write-Output, outputs *only* the object (table row)
# with device ID $deviceID.
# Note the use of -eq instead of -match
# (-match is only needed for regex matching).
$AllTables |
Write-Output | # Enumerate arrays
Where-Object { $_.'device id' -eq $deviceid }
A general question about how to select and transform properties from given input objects - see below.
In order to select a subset of properties and/or transform the values of the properties of input objects, use Select-Object. In order to transform property values, use it with calculated properties. The result will be [pscustomobject] instances that have the desired properties and values.
$sampleInput = [pscustomobject] #{
'device id' = '0x1f02'
product = 'TU106 [GeForce RTX 2070]'
}
# Use a calculated property to select and transform the 'product' value,
# and select the 'device id' property as-is.
$sampleInput |
Select-Object #{
Name='product';
Expression={ ($_.product -split '[][]')[1] }
},
'device id'
The regex-based -split operator is used to split each product name by [ and ]; the 2nd element (index 1) of the resulting array contains the substring of interest. Alternatively, you could use the regex-based -replace operator: $_.product -replace '^.+\[(.+?)\]$', '$1'
Output:
product device id
------- ---------
GeForce RTX 2070 0x1f02
Note: If you don't actually need to construct new objects and are simply looking for the formatted display shown above, you can substitute Format-Table for Select-Object; however, note that such output is then truly only usable for display purposes.
Related
Generating a list of windows workstation computer names by reading the active directory and I need to find the highest number so that I can then assign a new device with the next available number - I am not having any success in doing this - how to do it? And as you can see from the list of names, I also have missing numbers in the sequence that ideally, I would like to fill in with new devices also...
The code I am using to get the list from AD is below.
((Get-ADComputer -Filter {operatingsystem -notlike "*server*" -and Name -like $NamingConvention -and enabled -eq "true"} -Credential $credential -server $ADServerIP).Name)
List of device names
PC01
PC28
PC29
PC30
PC31
PC32
PC33
PC34
PC35
PC36
PC37
PC38
PC40
PC41
PC42
PC43
PC44
PC45
PC46
PC47
PC27
PC48
PC26
PC24
PC179
PC18
PC180
PC181
PC182
PC183
PC184
PC185
PC186
PC187
PC188
PC189
PC19
PC190
PC191
PC192
PC21
PC22
PC23
PC25
PC178
PC49
PC51
PC77
PC78
PC79
PC80
PC81
PC83
PC84
PC85
PC87
PC88
PC89
PC90
PC91
PC92
PC93
PC94
PC95
PC96
PC97
PC76
PC50
PC75
PC72
PC52
PC53
PC54
PC55
PC56
PC57
PC59
PC60
PC61
PC62
PC63
PC64
PC65
PC66
PC67
PC68
PC69
PC70
PC71
PC73
PC98
PC177
PC175
PC115
PC116
PC117
PC118
PC119
PC12
PC120
PC121
PC122
PC123
PC124
PC125
PC126
PC127
PC128
PC129
PC13
PC130
PC131
PC114
PC132
PC113
PC111
PC02
PC03
PC04
PC06
PC08
PC09
PC10
PC100
PC101
PC102
PC103
PC104
PC105
PC106
PC107
PC108
PC109
PC11
PC110
PC112
PC176
PC133
PC135
PC158
PC159
PC16
PC160
PC161
PC162
PC163
PC164
PC165
PC166
PC167
PC168
PC169
PC17
PC170
PC171
PC172
PC173
PC174
PC157
PC134
PC156
PC154
PC136
PC137
PC138
PC139
PC14
PC140
PC141
PC142
PC143
PC144
PC145
PC146
PC147
PC148
PC149
PC150
PC151
PC152
PC153
PC155
PC99
Sort the pc names on their numeric values and select the last one:
$lastPC = (Get-ADComputer -Filter {operatingsystem -notlike "*server*" -and Name -like $NamingConvention -and enabled -eq "true"} -Credential $credential -server $ADServerIP).Name |
Sort-Object { [int]($_ -replace '\D+')} | Select-Object -Last 1
Here's a solution that will give you the highest number ($dataMax), the missing numbers ($dataMissing), and the next number to use ($dataNext). The next number to use will be either the 1st missing number, or if there are no missing numbers then it will be the highest number + 1
# load the computers list
$data = ((Get-ADComputer -Filter {operatingsystem -notlike "*server*" -and Name -like $NamingConvention -and enabled -eq "true"} -Credential $credential -server $ADServerIP).Name)
# create an array by splitting the data text using the "space" character as a delimiter
$data = $data.Split(" ")
# remove all the alpha characters ("PC"), leaving only the number values so it can be sorted easier
$dataCleaned = $data -replace "[^0-9]" , '' | sort { [int]$_ }
# after sorting the data, [-1] represents the last element in the array which will be the highest number
[int]$dataMax = $dataCleaned[-1]
# create a number range that represents all the numbers from 1 to the highest number
$range = 1..$dataMax | foreach-object { '{0:d2}' -f $_ }
# compare the created range against the numbers actually in the computer array to find the missing numbers
$dataMissing = #(compare $range $dataCleaned -PassThru)
# if there's a missing value, [0] represents the first element in the array of missing numbers
if ($dataMissing)
{
$dataNext = $dataMissing[0]
}
# if there's no missing values, the next value is the max value + 1
else
{
$dataMissing = "none"
$dataNext = $dataMax + 1
}
Write-Host "The highest number is:"('{0:d2}' -f $dataMax)
Write-Host "The missing numbers are: $dataMissing"
Write-Host "The next number to use is:" ('{0:d2}' -f $dataNext)
Assuming your list is exactly as it appears to be, then this appears to be one way to do it:
$List = 'PC01 PC28 PC29 PC30 PC31 PC32 PC33 PC34 PC35 PC36 PC37 PC38 PC40 PC41 PC42 PC43 PC44 PC45 PC46 PC47 PC27 PC48 PC26 PC24 PC179 PC18 PC180 PC181 PC182 PC183 PC184 PC185 PC186 PC187 PC188 PC189 PC19 PC190 PC191 PC192 PC21 PC22 PC23 PC25 PC178 PC49 PC51 PC77 PC78 PC79 PC80 PC81 PC83 PC84 PC85 PC87 PC88 PC89 PC90 PC91 PC92 PC93 PC94 PC95 PC96 PC97 PC76 PC50 PC75 PC72 PC52 PC53 PC54 PC55 PC56 PC57 PC59 PC60 PC61 PC62 PC63 PC64 PC65 PC66 PC67 PC68 PC69 PC70 PC71 PC73 PC98 PC177 PC175 PC115 PC116 PC117 PC118 PC119 PC12 PC120 PC121 PC122 PC123 PC124 PC125 PC126 PC127 PC128 PC129 PC13 PC130 PC131 PC114 PC132 PC113 PC111 PC02 PC03 PC04 PC06 PC08 PC09 PC10 PC100 PC101 PC102 PC103 PC104 PC105 PC106 PC107 PC108 PC109 PC11 PC110 PC112 PC176 PC133 PC135 PC158 PC159 PC16 PC160 PC161 PC162 PC163 PC164 PC165 PC166 PC167 PC168 PC169 PC17 PC170 PC171 PC172 PC173 PC174 PC157 PC134 PC156 PC154 PC136 PC137 PC138 PC139 PC14 PC140 PC141 PC142 PC143 PC144 PC145 PC146 PC147 PC148 PC149 PC150 PC151 PC152 PC153 PC155 PC99'
$NextNumber = ($List -split "\s" | ForEach-Object { if ($_ -match 'PC(?<Number>\d+)') { $Matches.Number } } | Measure-Object -Maximum).Maximum + 1
$NextNumber
"PC$NextNumber"
So i have the following code to generate the entire Windows Update History:
$Session = New-Object -ComObject "Microsoft.Update.Session"
$Searcher = $Session.CreateUpdateSearcher()
$historyCount = $Searcher.GetTotalHistoryCount()
$Searcher.QueryHistory(0, $historyCount) | Select-Object Title, Description, Date,
#{name="Operation"; expression={switch($_.operation){
1 {"Installation"}; 2 {"Uninstallation"}; 3 {"Other"}
}}}
My question is how can i search in this table for updates containing KB. So for instance i want to know if the update KB4052623 has been installed. How can i write a simple piece of code to tell me KB4052326 has been found in the output of above code? Thanks in advance.
You need to assign the array returned by QueryHistory to a variable, then loop through that array to get the objects. Probably easiest to use Regex to find the KB numbers.
This code just list the found KB numbers, but you should be able test it as needed. Also, you may want to check the Description for KB numbers as well, it may tell you that it replaces old KB numbers or other important info.
$Session = New-Object -ComObject "Microsoft.Update.Session"
$Searcher = $Session.CreateUpdateSearcher()
$historyCount = $Searcher.GetTotalHistoryCount()
$MSUpdateHistory = $Searcher.QueryHistory(0, $historyCount) | Select-Object Title, Description, Date,
#{name="Operation"; expression={switch($_.operation){
1 {"Installation"}; 2 {"Uninstallation"}; 3 {"Other"}
}}}
$MSUpdateHistory | ForEach-Object {
if ($_.Title -match '(?<KBNum>KB\d+)') {
Write-Host "Found $($Matches.KBNum)"
#$_.Description
#$_.Date
#$_.Operation
}
}
If I look in Task Manager, I can see "In Use" memory.
I know that I can grab performance information in PerfMon, but I do not know which counter in Perfmon retrieves this value.
I want to write a PowerShell script to find out average memory usage for the past day. PerfMon is the only option that I can think of. Is there a better way to do this in PowerShell?
Get-Counter -Counter is the way to get performance counters in PowerShell 2+. "In use" looks like it's the rounded value of Total Memory - Available:
[math]::Round(((((Get-Ciminstance Win32_OperatingSystem).TotalVisibleMemorySize * 1kb) - ((Get-Counter -Counter "\Memory\Available Bytes").CounterSamples.CookedValue)) / 1GB),1)
What I usually do is run the following to get the current:
The $UsedRAM variable is what you are looking for.
$SystemInfo = Get-WmiObject -Class Win32_OperatingSystem | Select-Object Name, TotalVisibleMemorySize, FreePhysicalMemory
$TotalRAM = $SystemInfo.TotalVisibleMemorySize/1MB
$FreeRAM = $SystemInfo.FreePhysicalMemory/1MB
$UsedRAM = $TotalRAM - $FreeRAM
$RAMPercentFree = ($FreeRAM / $TotalRAM) * 100
$TotalRAM = [Math]::Round($TotalRAM, 2)
$FreeRAM = [Math]::Round($FreeRAM, 2)
$UsedRAM = [Math]::Round($UsedRAM, 2)
$RAMPercentFree = [Math]::Round($RAMPercentFree, 2)
Now we know how to get the current/In Use memory, but getting the average takes some more code.
Using the Get-Counter we can setup a counter of the average, but note that this will only provide the average during the time of testing and doesn't go back in time.
To get a good understanding of the average, I do about 1000 counts. Note this will also consume memory. Depending on the language of the system the formatting can be wrong.
$interval = 1 #seconds
$maxsamples = 1000
$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 - $memorycounter
#$physicalmemory - $freememavg #Depending on the Formatting of your system
This can also be done with the CPU and DISK.
I have job to get the following ESXi host information, while I am coding the powercli, I need to get the consumed CPU Mhz, but there is no field to get the value directly, so I custom a field and write some formula to caculate it, Called "Host CPU - Mhz". However, the following information will write into the excel file, I have some confuse how to get the custom field in the powercli
here is my part of code
$hostState = "" | get-vm | where-object {$_.VMHost -match '10.0.0.100'} | select Name, PowerState, #{N="Host CPU - MHz";E={[Math]::Round(($_ | get-stat -stat cpu.usagemhz.average -Start (Get-Date).AddDays(-1) -IntervalMins 1440 | Measure-object Value -Average).Average,2)}}
$hName = $hostState.Name
$hPowerState = $hostState.PowerState
$hCPU = << how to do it?>>
kindly advice and help.
$hCPU = $hostState."Host CPU - MHz"
I am trying to check memory types on all PCs across company. My testing code is below based on info from here:
Get-WmiObject Win32_PhysicalMemory |
Select-Object -Property PSComputerName, DeviceLocator, Manufacturer, PartNumber, #{label = "Size/GB" ; Expression = {$_.capacity / 1GB}}, Speed, datawidth, totalwidth, #{label = "ECC" ; Expression = {
if ( $_.totalwidth > $_.datawidth ) {
"$($_.DeviceLocator) is ECC memory type"
}
else {
"$($_.DeviceLocator) is non-ECC Memory Type"
}
}
} | Out-GridView
The results showing me that memory type is non-ecc:
But if I use 3rd party tool like "HWiNFO64 v4.30" the result is ECC memory. See pic below. How can I get the same memory info like pic below by using PowerShell? Speciously "Memory type" "Speed" and "ECC"
Vikas could have some good points about the accuracy of the information which should be considered. The linked post eludes to other issues as well.
The issue you are running into with this code is your use of PowerShell Comparison Operators.
They are in the format of -gt and -lt for example which are greater than and less than respectively. Assuming your logic you should just have to update
if ( $_.totalwidth > $_.datawidth )
to
if ( $_.totalwidth -gt $_.datawidth )