Converting Output to CSV and Out-Grid - powershell

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)
}``

Related

Powershell Hex, Int and Bit flag checking

I am trying to process a flag from the MECM command Get-CMTaskSequenceDeployment called 'AdvertFlags'.
The information from Microsoft in relation to this value is HERE
The value returned is designated as : Data type: UInt32
In the table of flags, the one I need to check is listed as :
Hexadecimal (Bit)
Description
0x00000020 (5)
IMMEDIATE. Announce the advertisement to the user immediately.
As part of my Powershell script I am trying to ascertain if this flag is set.
I can see by converting it to Binary that a particular bit gets set.
When the settings is enabled:
DRIVE:\> [convert]::ToString((Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags, 2)
100110010000000000100000
When the setting is disabled:
DRIVE:\> [convert]::ToString((Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags, 2)
100110010000000000000000
The 6th bit is changed. Great! So far though, I've been unable to find a way to check if this bit is set. I suspected something in the bitwise operators (-band -bor etc) would help me here but I've been unable to get it to work.
Any bitwise operation I try returns an error:
"System.UInt64". Error: "Value was either too large or too small for a UInt64."
I mean, I can compare the string literally, but other options may be changed at any point.
Any help greatly appreciated.
EDIT: Just as an example of the error I am seeing, I can see that the bit that is set is '32' and from my limited understanding I should be able to:
PS:\> '100110010000000000100000' -band '32'
Cannot convert value "100110010000000000100000" to type "System.UInt64". Error: "Value was either too large or too small for a UInt64."
At line:1 char:1
+ '100110010000000000100000' -band '32'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastIConvertible
But I just always return an error
To test bit6 in
$AdvertFlags = (Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags
Should simply be:
if ($AdvertFlags -band 32) { 'bit6 is set' } else { 'bit6 is not set' }
I do not have access to a deployment environment with Get-CMTaskSequenceDeployment cmdlet, nevertheless to confirm what I am stating:
$AdvertFlags = [Convert]::ToUInt32("100110010000000000100000", 2)
$AdvertFlags
10027040
if ($AdvertFlags -band 32) { 'bit6 is set' } else { 'bit6 is not set' }
bit6 is set
$AdvertFlags = [Convert]::ToUInt32("100110010000000000000000", 2)
$AdvertFlags
10027008
if ($AdvertFlags -band 32) { 'bit6 is set' } else { 'bit6 is not set' }
bit6 is not set
Your self-answer using [bigint]'100110010000000000100000' -band "32" to test for bit6 is merely a coincident that it returns the expected value:
10027035..10027045 |ForEach-Object {
$Binary = [convert]::ToString($_, 2)
[pscustomobject]#{
Binary = $Binary
bAnd = $_ -bAnd 32
Bigint = [bigint]$Binary -band "32"
}
}
Yields:
Binary bAnd Bigint
------ ---- ------
100110010000000000011011 0 0
100110010000000000011100 0 0
100110010000000000011101 0 0
100110010000000000011110 0 32 # ← incorrect
100110010000000000011111 0 32 # ← incorrect
100110010000000000100000 32 32
100110010000000000100001 32 32
100110010000000000100010 32 32
100110010000000000100011 32 32
100110010000000000100100 32 0 # ← incorrect
100110010000000000100101 32 0 # ← incorrect
enumerations as flags
But PowerShell has an even nicer way to test them by name:
[Flags()] enum AdvertFlags {
IMMEDIATE = 0x00000020 # Announce the advertisement to the user immediately.
ONSYSTEMSTARTUP = 0x00000100 # Announce the advertisement to the user on system startup.
ONUSERLOGON = 0x00000200 # Announce the advertisement to the user on logon.
ONUSERLOGOFF = 0x00000400 # Announce the advertisement to the user on logoff.
OPTIONALPREDOWNLOAD = 0x00001000 # If the selected architecture and language matches that of the client, the package content will be downloaded in advance
WINDOWS_CE = 0x00008000 # The advertisement is for a device client.
ENABLE_PEER_CACHING = 0x00010000 # This information applies to System Center 2012 Configuration Manager SP1 or later, and System Center 2012 R2 Configuration Manager or later.
DONOT_FALLBACK = 0x00020000 # Do not fall back to unprotected distribution points.
ENABLE_TS_FROM_CD_AND_PXE = 0x00040000 # The task sequence is available to removable media and the pre-boot execution environment (PXE) service point.
APTSINTRANETONLY = 0x00080000 #
OVERRIDE_SERVICE_WINDOWS = 0x00100000 # Override maintenance windows in announcing the advertisement to the user.
REBOOT_OUTSIDE_OF_SERVICE_WINDOWS = 0x00200000 # Reboot outside of maintenance windows.
WAKE_ON_LAN_ENABLED = 0x00400000 # Announce the advertisement to the user with Wake On LAN enabled.
SHOW_PROGRESS = 0x00800000 # Announce the advertisement to the user showing task sequence progress.
NO_DISPLAY = 0x02000000 # The user should not run programs independently of the assignment.
ONSLOWNET = 0x04000000 # Assignments are mandatory over a slow network connection.
TARGETTOWINPE = 0x10000000 # Target this deployment to WinPE only.
HIDDENINWINPE = 0x20000000 # Target this deployment to WinPE only but hide in WinPE. It can only be used by TS variable SMSTSPreferredAdvertID.
}
# $AdvertFlags = [AdvertFlags](Get-CMTaskSequenceDeployment -AdvertisementID ABC20723).AdvertFlags
$AdvertFlags = [AdvertFlags][Convert]::ToUInt32("100110010000000000100000", 2)
# or: $AdvertFlags = [AdvertFlags]('IMMEDIATE', 'ENABLE_PEER_CACHING', 'APTSINTRANETONLY', 'OVERRIDE_SERVICE_WINDOWS', 'SHOW_PROGRESS')
$AdvertFlags
IMMEDIATE, ENABLE_PEER_CACHING, APTSINTRANETONLY, OVERRIDE_SERVICE_WINDOWS, SHOW_PROGRESS
$AdvertFlags -bAnd [AdvertFlags]'IMMEDIATE'
IMMEDIATE
EDIT: My answer here is incorrect as noted above. Leaving here for prosperity!
As always I BELEIVE I found the answer minutes after posting (After spending a couple hours on this!).
By adjusting the type to [bigint] the comparison was able to complete and return the expected answer:
DRIVE:\> [bigint]'100110010000000000100000' -band "32"
32
So a simple:
If (([bigint]'100110010000000000100000' -band "32") -gt 0){$true}else{$false}
True
and:
If (([bigint]'100110010000000000000000' -band "32") -gt 0){$true}else{$false}
False
Solves my issue. Feel free to give any extra advice if this is not the ideal way to proceed.
I though PS would be smarted when auto defining types etc. This is targeting PS5 on Server 2012 R2 though.

Read in a *HUGE* CSV file, export specific columns based on column name in header, output comma delimited data

So, I know I can read in a csv file using import-csv like so:
$test = import-csv BPUSAUV20FARS-1000.csv
I found another stack overflow question which gave me some code to decipher column names, like so:
$columns = $test[0].psobject.properties.name
I found a reddit post that helped me find a way to extract multiple columns using select-object like so:
$properties = #('Index', 'Year', 'Day', 'Time', 'Line', 'Beam', 'Pos TPU', 'Depth TPU', 'Status')
$test |Select-Object $properties
But the output from the above command likes like this:
Index : 1
Year : EM2040-0073-1000-20200224-222235
Day : 25
Time : Accept
Line : 0.648
Beam : 24-FEB-2020:22:22:34.98
Pos TPU : 4.617
Depth TPU : 1124834.70
Status : 10247261.01
Index : 2
Year : EM2040-0073-1000-20200224-222235
Day : 26
Time : Accept
Line : 0.749
Beam : 24-FEB-2020:22:22:34.98
Pos TPU : 4.617
Depth TPU : 1124834.73
Status : 10247261.76
Index : 3
Year : EM2040-0073-1000-20200224-222235
Day : 27
Time : Accept
Line : 0.624
Beam : 24-FEB-2020:22:22:34.98
Pos TPU : 4.617
Depth TPU : 1124834.76
Status : 10247263.05
And what I need is this:
1,EM2040-0073-1000-20200224-222235,25,Accept,0.648,24-FEB-2020:22:22:34.98,4.617,1124834.70,10247261.01
I also need to be able to perform these actions on a few hundred files with several million lines each. The smallest file is about 2.4 million lines.
As for...
I also need to be able to perform these actions on a few hundred files
with several million lines each. The smallest file is about 2.4
million lines.
... dealing with large files in general --- (too long for just a comment)
As per MSDN
[IO.File]::OpenText and as noted in another Q&A
The Get-Content cmdlet does not perform as well as a StreamReader when
dealing with very large files. You can read a file line by line using
a StreamReader like this:
$path = 'C:\A-Very-Large-File.txt'
$r = [IO.File]::OpenText($path)
while ($r.Peek() -ge 0) {
$line = $r.ReadLine()
# Process $line here...
}
$r.Dispose()
Some performance comparisons:
Measure-Command {Get-Content .\512MB.txt > $null}
Total Seconds: 49.4742533
Measure-Command {
$r = [IO.File]::OpenText('512MB.txt')
while ($r.Peek() -ge 0) {
$r.ReadLine() > $null
}
$r.Dispose()
}
Total Seconds: 27.666803

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

inf2cat 22.9.10 error

I'm trying to sign old Hitachi driver that makes USB flash drive appear as fixed disk
(Quite useful when you have fast, large thumb drives)
Driver itself works fine but I constantly get same error when try to get it signed:
Errors:
22.9.10: cfadisk.sys in [cfadisk_copyfiles] is missing from [SourceDisksFiles] section in
\cfadisk.inf; driver may not sign correctly until this is resolved.
22.9.10: disk.sys in [gendisk_copyfiles] is missing from [SourceDisksFiles] section in
cfadisk.inf; driver may not sign correctly until this is resolved.
This is my .inf file:
[Version]
Signature="$Windows NT$"
Class=DiskDrive
ClassGuid={4D36E967-E325-11CE-BFC1-08002BE10318}
Provider=%HGST%
DriverVer=10/14/2012,9.9.9.9
CatalogFile=cfadisk.cat
[Manufacturer]
%HGST% = cfadisk_device,ntAMD64
[DestinationDirs]
cfadisk_copyfiles=12 ; %SystemRoot%\system32\drivers
gendisk_copyfiles=12 ; %SystemRoot%\system32\drivers
[cfadisk_copyfiles]
cfadisk.sys
[gendisk_copyfiles]
disk.sys
[cfadisk_device]
%Microdrive_devdesc% = cfadisk_install,USBSTOR\Disk&Ven_SanDisk&Prod_Extreme&Rev_0001
[cfadisk_device.NTamd64]
%Microdrive_devdesc% = cfadisk_install,USBSTOR\Disk&Ven_SanDisk&Prod_Extreme&Rev_0001
[cfadisk_addreg]
HKR,,"LowerFilters",0x00010008,"cfadisk"
[cfadisk_install]
CopyFiles=cfadisk_copyfiles,gendisk_copyfiles
[cfadisk_install.HW]
AddReg=cfadisk_addreg
[cfadisk_install.Services]
AddService=disk,2,gendisk_ServiceInstallSection
AddService=cfadisk,,cfadisk_ServiceInstallSection
[gendisk_ServiceInstallSection]
DisplayName = "Disk Driver"
ServiceType = 1
StartType = 0
ErrorControl = 1
ServiceBinary = %12%\disk.sys
LoadOrderGroup = SCSI Class
[cfadisk_ServiceInstallSection]
DisplayName = "CompactFlash Filter Driver"
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %12%\cfadisk.sys
LoadOrderGroup = Pnp Filter
; -----------------------
[Strings]
HGST = "Hitachi"
Microdrive_devdesc = "SanDisk Extreme"
I was using this tutorial as reference point:
http://www.deploymentresearch.com/Blog/tabid/62/EntryId/63/Sign-your-unsigned-drivers-Damn-It.aspx
cfadisk.inf and sys can be downloaded here:
link is at the beginning of first post
http://hardforum.com/showthread.php?t=1655684
Any help would be greatly appreciated
EDIT:
I just used chkinf utility on this .inf file
Here is the output:
C:\DriversCert\SanDisk\cfadisk.inf: FAILED
NTLOG REPORT--------------
Total Lines: 62 |
Total Errors: 1 |
Total Warnings: 4 |
--------------------------
Line 0: ERROR: (E22.1.1003) Section [SourceDisksNames] not defined.
Line 0: WARNING: (W22.1.2212) No Copyright information found.
Line 0: WARNING: (W22.1.2111) [SourceDisksFiles] section not defined - full CopyFiles checking not done.
Line 17: WARNING: (W22.1.2112) File "cfadisk.sys" is not listed in the [SourceDisksFiles].
Line 20: WARNING: (W22.1.2112) File "disk.sys" is not listed in the [SourceDisksFiles].
I'm really no programer so I really don't understand what does all this mean.
Strange thing is that driver does work, I just can't get i signed.
Thank you!
Best regards,
Walter
It means that some sections are missed. In your case they are [SourceDisksFiles] and [SourceDisksNames]
In this specific situation you just should add:
[SourceDisksFiles]
cfadisk.sys = 1
disk.sys = 1
[SourceDisksNames]
1 = %DiskName%, ,
and also add a record to [String] section in the bottom:
DiskName="Disk Drive"