Advice on how to compare string in a text file - powershell

Could anyone offer any advice how to compare string from a text file to the info pulled from wmi.
$GCard = (Get-WmiObject "Win32_Videocontroller").Name
$DriverModel = Get-Content -Path "C:\temp\Quadro473.81.txt"
foreach ($Line in $DriverModel)
{
if($Line -like "*$MyCard*")
{
write-host "Quadro"
}
}
The text file (Quadro473.81.txt) is as following.
UDA Package name: QuadroWeb Public Disk1
{"NSD":{"State":"0"},"DCH":{"State":"1"}}
nv_disp.inf:
DEV_0FF3 "NVIDIA Quadro K420"
DEV_0FF9 "NVIDIA Quadro K2000D"
DEV_0FFA "NVIDIA Quadro K600"
DEV_0FFD "NVIDIA NVS 510"
DEV_0FFE "NVIDIA Quadro K2000"
DEV_0FFF "NVIDIA Quadro 410"
DEV_1021 "NVIDIA Tesla K20Xm"
DEV_1022 "NVIDIA Tesla K20c"
DEV_1023 "NVIDIA Tesla K40m"
DEV_1024 "NVIDIA Tesla K40c"
DEV_1026 "NVIDIA Tesla K20s"
DEV_1027 "NVIDIA Tesla K40st"
DEV_1028 "NVIDIA Tesla K20m"
DEV_1029 "NVIDIA Tesla K40s"
The card in the machine report back as NVIDIA Quadro K420
I am trying to work out how to match the string from the video controller name to the list from the drivermodels and have it output the word quadro if it matches.
I would just need to match the model that appears in quotes.
Any help would be appriciated.

You can use -match to search through the array of strings returned by Get-Content and have it output "Quadro" when found inside your if statement.
$GCard = (Get-WmiObject "Win32_Videocontroller").Name
$DriverModel = Get-Content -Path "C:\temp\Quadro473.81.txt"
foreach ($GCName in $GCard)
{
if ($DriverModel -match $GCName)
{
Write-Host -Object "Quadro"
}
}
Few things to cover when using -match comparison operator.
When used against an array, it will act as a filter and return the line that was matched against $GCard.
It's underlying search pattern it uses are regular expressions.
So, if your call to (Get-WmiObject "Win32_Videocontroller").Name returned a value that has special characters, they would have to be escaped.
Since it returns the line it matches, it will evaluate the condition to "true" executing your block of code.
EDIT: Given that there could be multiple return values in $GCard, using a loop you can compare each line with $DriverModel.

Related

Powershell script to get the metadata field "writing application"

I am using a modified version of the GetMetaData script originally written by Ed Wilson at Microsoft (https://devblogs.microsoft.com/scripting/hey-scripting-guy-how-can-i-find-files-metadata/) and then modified by user wOxxOm here https://stackoverflow.com/a/42933461/5061596 . I'm trying to analyze all my DVD and BluRay rips and see what tool was used to create them. Mainly I want to check which ones I compressed with Handbrake and which ones came directly from MakeMKV. The problem is I can't find this field.
If I use the "stock" scrip and change the number of properties it looks for from 0 - 266 up to 0 - 330 I find the extra file info like movie length, resolution, etc. But I can't find the tool used. For example here is what the MediaInfo Lite tool reports:
But looking through the meta data I get something like this with no "Writing application" property:
Name : Ad Astra (2019).mkv
Size : 44.1 GB
Title : Ad Astra
Length : 02:03:02
Frame height : 2160
Frame rate : ‎23.98 frames/second
Frame width : 3840
Total bitrate : ‎51415kbps
Audio tracks : TrueHD S24 7.1 [Eng]
Contains chapters : Yes
Subtitle tracks : PGS [Eng], PGS [Eng]
Video tracks : HEVC (H265 Main 10 #L5.1)
How do I go about finding that property or is it not something that I can pull through PowerShell?
Edit: The info I'm looking for IS in Windows Explorer looking at the properties of the file and the details tab so if Explorer can see it I would think I should be able to:
edit: actually, this seems more reliable. So far any file that mediainfo can read, this also works with.
$FILE = "C:\test.mkv"
$content = (Get-Content -Path $FILE -First 100) + (Get-Content -Path $FILE -Tail 100)
if(($content -match '\*data')[0] -match '\*data\W*([\w\n\s\.]*)'){
write-host "Writing Application:" $Matches[1]
exit
}elseif(($content -match 'M€.*WA(.*)s¤')[0] -match 'M€.*WA(.*)s¤'){
write-host "Writing Application:" $Matches[1]
}
It looks like the last bytes in the file after *data that specify the writer, so try this:
(Get-Content -Path "c:\video.mkv" -Tail 1) -match '\*data\W*(.*)$' | out-null
write-host "Writing Application:" $Matches[1]
On my test file that resulted in "HandBrake 1.5.1 2022011000"
I'm not sure what standard specifies this sorry. There's also a host of useful info on the first line of data in the file as well, e.g:
ftypmp42 mp42iso2avc1mp41 free6dÊmdat ôÿÿðÜEé½æÙH·–,Ø Ù#îïx264 - core 164 r3065 ae03d92 - H.264/MPEG-4 AVC codec - Copyleft 2003-2021 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x1:0x111 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadz
one=21,11 fast_pskip=1 chroma_qp_offset=0 threads=18 lookahead_threads=5 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin
=0 qpmax=69 qpstep=4 vbv_maxrate=14000 vbv_bufsize=14000 crf_max=0.0 nal_hrd=none filler=0 ip_ratio=1.40 aq=1:1.00
I couldn't replicate your success viewing the info with Windows Explorer, the field is invisible for me even though I can view it with MediaInfo etc

Converting Output to CSV and Out-Grid

I have a file as below.
I want it to convert it to CSV and want to have the out grid view of it for items Drives,Drive Type,Total Space, Current allocation and Remaining space only.
PS C:\> echo $fileSys
Storage system address: 127.0.0.1
Storage system port: 443
HTTPS connection
1: Name = Extreme Performance
Drives = 46 x 3.8T SAS Flash 4
Drive type = SAS Flash
RAID level = 5
Stripe length = 13
Total space = 149464056594432 (135.9T)
Current allocation = 108824270733312 (98.9T)
Remaining space = 40639785861120 (36.9T)
I am new to Powershell but I have tried below code for two of things but it's not even getting me desired output.
$filesys | ForEach-Object {
if ($_ -match '^.+?(?<Total space>[0-9A-F]{4}\.[0-9A-F]{4}\.[0-9A-F]{4}).+?(?<Current allocation>\d+)$') {
[PsCustomObject]#{
'Total space' = $matches['Total space']
'Current allocation' = $matches['Current allocation']
}
}
}
First and foremost, the named capture groups cannot contain spaces.
From the documentation
Named Matched Subexpressions
where name is a valid group name, and subexpression is any valid
regular expression pattern. name must not contain any punctuation
characters and cannot begin with a number.
Assuming this is a single string since your pattern attempts to grab info from multiple lines, you can forego the loop. However, even with that corrected, your pattern does not appear to match the data. It's not clear to me what you are trying to match or your desired output. Hopefully this will get you on the right track.
$filesys = #'
Storage system address: 127.0.0.1
Storage system port: 443
HTTPS connection
1: Name = Extreme Performance
Drives = 46 x 3.8T SAS Flash 4
Drive type = SAS Flash
RAID level = 5
Stripe length = 13
Total space = 149464056594432 (135.9T)
Current allocation = 108824270733312 (98.9T)
Remaining space = 40639785861120 (36.9T)
'#
if($filesys -match '(?s).+total space\s+=\s(?<totalspace>.+?)(?=\r?\n).+allocation\s+=\s(?<currentallocation>.+?)(?=\r?\n)')
{
[PsCustomObject]#{
'Total space' = $matches['totalspace']
'Current allocation' = $matches['currentallocation']
}
}
Total space Current allocation
----------- ------------------
149464056594432 (135.9T) 108824270733312 (98.9T)
Edit
If you just want the values in the parenthesis, modifying to this will achieve it.
if($filesys -match '(?s).+total space.+\((?<totalspace>.+?)(?=\)).+allocation.+\((?<currentallocation>.+?)(?=\))')
{
[PsCustomObject]#{
'Total space' = $matches['totalspace']
'Current allocation' = $matches['currentallocation']
}
}
Total space Current allocation
----------- ------------------
135.9T 36.9T
$unity=[Regex]::Matches($filesys, "\(([^)]*)\)") -replace '[(\)]','' -replace "T",""
$UnityCapacity = [pscustomobject][ordered] #{
Name = "$Display"
"Total" =$unity[0]
"Used" = $unity[1]
"Free" = $unity[2]
'Used %' = [math]::Round(($unity[1] / $unity[0])*100,2)
}``

Windows api for identifying NVMe drive

Is there any windows api which returns if the drive is of nvme type? In powershell, when I do
Get-PhysicalDisk | select Friendlyname, BusType, MediaType
it gives the MediaType as SSD and the BusType as RAID. Ealier, I was using the STORAGE_BUS_TYPE win32 for checking NVMe by using the BusType, but I have an SSD Nvme device which has BusType as RAID.
Thanks.
I know I'm a little late but have recently been working on a project and have come up with this which may help:
$bustype_table = #{ #bus type table taken from Microsofts webiste
'0' = 'The bus type is unknown.'
'1' = 'SCSI'
'2' = 'ATAPI'
'3' = 'ATA'
'4' = 'IEEE 1394'
'5' = 'SSA'
'6' = 'Fibre Channel'
'7' = 'USB'
'8' = 'RAID'
'9' = 'iSCSI'
'10' = 'Serial Attached SCSI (SAS)'
'11' = 'Serial ATA (SATA)'
'12' = 'Secure Digital (SD)'
'13' = 'Multimedia Card (MMC)'
'14' = 'This value is reserved for system use (Virtual)'
'15' = 'File-Backed Virtual'
'16' = 'Storage spaces'
'17' = 'NVMe'
}
try
{
$windows_version = (Get-WmiObject Win32_OperatingSystem).Version #Gets windows version.
if($windows_version -gt 10.0.00000) #has to be windows 10.0 or higher. wont work on 7 or 8.
{
$bustype = wmic /namespace:\\root\microsoft\windows\storage path msft_disk get BusType #,Model
$bustype_value = $bustype[2].Trim() #trims whitespace from the bustype value.
$drive_connection = $bustype_table[$bustype_value] #calls the table.
Write-Host "The C drive is connected via: $drive_connection `r`n"
}
}
catch
{
$_.Exception.Message #windows version is pre windows 10. Script wont work.
}
Specifically, this is what you want I think:
wmic /namespace:\\root\microsoft\windows\storage path msft_disk get Model,BusType
Although, this may not work as you have stated that your NVMe drives are in raid so it may pick it up as '8' (RAID).
Let me know how it goes.

powershell listing Ram information

I am trying to find out what type of RAM is in a computer. I'd like to know whether the modules are UDIMM, RDIMM, LRDIMM or any other type. This would be very useful so I can plan what modules are going into what servers at the data center.
This is what I have so far:
Get-WmiObject Win32_PhysicalMemory |
Select-Object PSComputerName, DeviceLocator, Manufacturer, PartNumber,
#{ label = "Size/GB"; expression = { $_.Capacity / 1GB } },
Speed, Datawidth, TotalWidth |
Format-Table -AutoSize
This is useful information but I'd like a column that tells me the type (UDIMM, RDIMM, LRDIMM) and a way to list the DIMMS that are empty as it will make it easier to see what DIMM is full/empty (but this isn't a huge problem).
this is not a duplicate as i am looking for the type of Ram that is stored on the servers so i know what Ram to buy and put in without having to travel a long way to find out i got the wrong type
The Win32_PhysicalMemory class documentation contains a reference for translating the MemoryType value to the type of memory module. Turn it into a hashtable for easy access:
$MemoryTypeMap = #{
"0" = 'Unknown'
"1" = 'Other'
"2" = 'DRAM'
"3" = 'Synchronous DRAM'
"4" = 'Cache DRAM'
"5" = 'EDO'
"6" = 'EDRAM'
"7" = 'VRAM'
"8" = 'SRAM'
"9" = 'RAM'
"10" = 'ROM'
"11" = 'Flash'
"12" = 'EEPROM'
"13" = 'FEPROM'
"14" = 'EPROM'
"15" = 'CDRAM'
"16" = '3DRAM'
"17" = 'SDRAM'
"18" = 'SGRAM'
"19" = 'RDRAM'
"20" = 'DDR'
"21" = 'DDR2'
"22" = 'DDR2 FB-DIMM'
"24" = 'DDR3'
"25" = 'FBD2'
}
Get-WmiObject Win32_PhysicalMemory |Select #{Label = 'Type';Expression = {$MemoryTypeMap["$($_.MemoryType)"]}}
You can see which memory devices are in which slots by using the WMI class of CIM_PhyicalMemoryArray and CIM_MemoryDeviceLocation. I've used WBEMTest and Get-CimInstance, however, and it doesn't seem that Windows reports on which memory slots are open on the motherboard.
My best guess? You'll need to use the Win32_Baseboard class to report on the model of the motherboard, and do some legwork manually to see how many slots each model has. You can then use the data from CIM_MemoryDeviceLocation to determine how many slots are open.
An approach to do so might look like this.
$memorySlots = Get-CimInstance Win32_MemoryDeviceLocation
$motherBoard = Get-CimInstance win32_baseboard
switch ($motherBoard.Product){
#find the motherboard models for the most common models and populate manually w/ count of ram slots
"0TM99H" {$Totalslots = 2}
Default {$Totalslots = 4}
}
Get-WmiObject Win32_PhysicalMemory |
Select-Object PSComputerName, DeviceLocator, Manufacturer, PartNumber,
#{ label = "Size/GB"; expression = { $_.Capacity / 1GB } },
Speed, Datawidth, TotalWidth, #{ label ="FreeSlots";exp={$Totalslots-$memorySlots.Count}}
It would look something like this:
PSComputerName : SLVER
DeviceLocator : DIMM A
Manufacturer : Elpida
PartNumber : 8KTS51264HDZ-1G6E1
Size/GB : 4
Speed : 1600
Datawidth : 64
TotalWidth : 64
FreeSlots : 0
PSComputerName : SLVER
DeviceLocator : DIMM B
Manufacturer : Elpida
PartNumber : 8KTS51264HDZ-1G6E1
Size/GB : 4
Speed : 1600
Datawidth : 64
TotalWidth : 64
FreeSlots : 0
Finally, you asked about memory type present, that also doesn't seem to be info that we know of, from a WMI perspective. Or rather, if WMI does know about it, I couldn't find it anywhere.
I think you'll need to do some manual work too there, gathering the memory part number, then manually research to determine what type of RAM it is, then finally add that info to the output by adding another Switch statement, as shown.
switch ($memorySpecs.PartNumber){
"8KTS51264HDZ-1G6E1" {$RAMType='SoDimm'}
Default {$RAMType="Unknown, research $($memorySpecs.PartNumber)"}
}
Update
Mathias provided an excellent method to look up RAM if the BIOS on that PC reports it to Windows. I've tested on a few systems, some report their RAM Type while others don't. For those that don't, you can reference the partNumber property as I've demoed above to manually look it up. After a few iterations, you should be able to gather the data and program your own exceptions, and wrap up this task.

Matching 'Network Location' icons

I am using the following code to create a Network Location, but the result is not exactly the same as when doing it manually. The icon from shell32.dll is smaller, lower res and has a frame, as seen here on the left. Is there any way to match the "native" look with PowerShell?
$linkFolder = New-Item -name:$location.name -path:"$nethoodPath\$($location.name)" -type:Directory -errorAction:stop
# Create the ini file
$desktopIniContent = (
'[.ShellClassInfo]',
'CLSID2={0AFACED1-E828-11D1-9187-B532F1E9575D}',
'Flags=2',
'ConfirmFileOp=1'
) -join "`r`n"
$desktopIniContent | Out-File -filePath:"$nethoodPath\$($location.name)\Desktop.ini"
# Create the shortcut file
$link = $shell.Createshortcut("$nethoodPath\$($location.name)\target.lnk")
$link.TargetPath = $location.value
$link.IconLocation = "%SystemRoot%\system32\SHELL32.DLL, 275"
$link.Description = $location.value
$link.WorkingDirectory = $location.value
$link.Save()
# Set attributes on the files & folders
Set-ItemProperty "$nethoodPath\$($location.name)\Desktop.ini" -name:Attributes -value:([IO.FileAttributes]::System -bxor [IO.FileAttributes]::Hidden) -errorAction:stop
Set-ItemProperty "$nethoodPath\$($location.name)" -name:Attributes -value:([IO.FileAttributes]::ReadOnly) -errorAction:stop
The icon on the right hand side can be found in imageres.dll (the Windows image resource library), icon 138 (index 137):
$link.IconLocation = "%SystemRoot%\system32\imageres,137"
It would seem that the horrible resolution of the shell32.dll,275 version is a bug/blunder that has been fixed by Microsoft subsequently:
Windows 7:
The shell32.dll version scales horribly
Windows 10:
On Windows 10, shell32.dll,275 scales to "Extra Large Icons"-size perfectly fine