unable to fetch system.int64 registry datavalue in powershell - powershell

Below powershell code is for exporting the complete registry hive to CSV file. But it gives error for exporting REG_Binary type data whose value is big as shown in the attached registry screenshot. Though I tried to convert it to string but no luck. Please suggest on how to fetch the REG_Binary data or how to convert it to string.
Function Get_Reg_Keys ($reg_key) {
$actualKey = Get-Item -Path Registry::$reg_key
#Write-Host $actualKey
ForEach ($name in $actualKey.GetValueNames()) {
# Write-Host $name
$name.Property | foreach {
$type = $actualKey.GetValue($name).GetType()
#Write-Host $type
Write-Host $actualKey.Name " | " $name " | " $actualKey.GetValue($name) " | " $type
If ( $type -eq [System.Byte[]] -Or $type -eq [System.Int64[]]) {
$a = [System.BitConverter]::ToString($actualKey.GetValue($name))
( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $a) |
Out-File "C:\Temp\Automation\HKCU.csv" -append -Encoding ascii -erroraction SilentlyContinue
}
Else {
( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $actualKey.GetValue($name)) |
Out-File "C:\Temp\Automation\HKCU.csv" -append -Encoding ascii -erroraction SilentlyContinue
}
}
}
$keyinfo = Get-ChildItem Registry::$reg_key
if ($keyinfo.count -gt 0) {
ForEach ($keyitem in $keyinfo) { Get_Reg_Keys ($keyitem) }
}
}
Then running: Get_Reg_Keys ("HKEY_CURRENT_USER\")
Gives the error:
Cannot convert argument "index", with value: "MRUListEx", for "GetValue" to type "System.Int64": "Cannot convert value "MRUListEx" to type "System.Int64". Error: "Input string was
not in a correct format.""
At C:\Temp\Automation\HKCUregistrynew.ps1:27 char:21
+ ( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $act ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Registry Key details:

To be honest, I'm having a tough time following your function. I'm not even sure how you're iterating over values in a key with that $name.properties | foreach... loop.
But, generally, this is pretty straight forward. For example, I've got a registry key HKCU:\Environment. I've created a property in that key named "thing", and I've stuffed it with some random binary data.
I'll take the guts of that property and output it to a file:
$reg_key = 'HKCU:\Environment'
$key_properties = Get-Item -Path $reg_key
[System.BitConverter]::ToString($key_properties.GetValue('thing')) | Out-File -FilePath .\Test.txt
cat .\Test.txt
Just to show there is nothing up my sleeve:
Good luck.

After making below changes I am able to export a registry hive to CSV file:
$actualKey = Get-Item -LiteralPath Registry::$reg_key
$keyinfo = Get-ChildItem -LiteralPath Registry::$reg_key

Related

how to append output to a CSV file

foreach ( $newfile in $file )
{
$b = Get-CMDeploymentStatus -PackageId $newfile -StatusType Any | select PackageID
Write-Output $b | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\list.csv"
}
I am giving input to this with an input file which has number of package names listed and then I want to process it in such a way that the output comes one after the other right now I am getting an error as
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null. At line:16 char:20 + Write-Output $b | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\lis ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand
Your code is assuming that you will have a result coming back from $b, if it does not though, you'll get an error because you're piping $b, which is null, into Export-CSV.
$null |export-csv c:\temp\1.csv
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At line:1 char:8
+ $null |export-csv c:\temp\1.csv
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCs
You should add a 'Guard Clause' before you try to export.
if ($null -ne $b){
Export-csv -Append -InputObject $b
}
At least this will continue executing. Now your next problem is to determine why $b would be empty...from my experience with CM, I bet you need to specify which property in your $file you need. Maybe that line should read:
$b = Get-CMDeploymentStatus -PackageId $newfile.PackageId -StatusType Any | select PackageID
Since you say "I am giving input to this with an input file which has number of package names listed", but your code uses PackageId..
It looks to me that this file contains a packageId, each on a single line.
Anyway, I don't see the code ever reading this file..
If my assumption about the text file is correct, try:
# read the content of the text file and loop through the lines
# collect the output from Get-CMDeploymentStatus in variable $result
$result = Get-Content -Path 'X:\TheFileWithPackageIds.txt' | ForEach-Object {
# inside the ForEach-Object, the $_ automatic variable represents a single line from the text file
Get-CMDeploymentStatus -PackageId $_ -StatusType Any | select PackageID
}
# output on screen
$result
# write to new CSV file
$result | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\list.csv" -NoTypeInformation

Cannot insert variable into path for Get-Item

I am trying to take a list of strings separated by a return and split them by the = symbol, both sides match a registry key which is queried by Get-Item. The first half always matches fine, but referencing the second half only matches for the last item in the list:
First half example:
[string[]]$Patch = (".accda=Access.ACCDAExtension.16
.accdb=Access.Application.16" -split "`n")
Foreach ($a in $Patch) {
$RegKey = ($a -split "=")[0]
$Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
echo $Result
}
This returns:
Name Property
---- --------
.accda (default) : Access.ACCDAExtension.16
Content Type : application/msaccess.addin
.accdb (default) : Access.Application.16
Content Type : application/msaccess
Second half example:
[string[]]$Patch = ("
.accda=Access.ACCDAExtension.16
.accdb=Access.Application.16
" -split "`n")
Foreach ($a in $Patch) {
$RegKey = ($a -split "=")[1]
$Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
}
This returns:
Get-Item : Cannot find path 'HKEY_CLASSES_ROOT\Access.ACCDAExtension.16' because it does not exist.
At line:6 char:15
+ $Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKEY_CLASSES_RO...DAExtension.16:String) [Get-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
Hive: HKEY_CLASSES_ROOT
Name Property
---- --------
Access.Application.16 (default) : Microsoft Access Database
However, that registry key does exist and if I run the command manually it finds it:
get-item Registry::HKEY_CLASSES_ROOT\Access.ACCDAExtension.16
Hive: HKEY_CLASSES_ROOT
Name Property
---- --------
Access.ACCDAExtension.16 (default) : Microsoft Access Add-in
I'm pretty sure it's caused by the return at the end of each line.
PowerShell version 5.1
I have resolved this my making my list a list of strings:
[string[]]$Patch = (".accda=Access.ACCDAExtension.16",
".accdb=Access.Application.16" -split "`n")
Foreach ($a in $Patch) {
$RegKey = ($a -split "=")[1]
$Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
}
The issue was probably caused by the return at the end of each line, maybe I could have also filtered it out of the command.
Change this:
[string[]]$Patch = ("
.accda=Access.ACCDAExtension.16
.accdb=Access.Application.16
" -split "`n")
to this
[string[]]$Patch = (-split "
.accda=Access.ACCDAExtension.16
.accdb=Access.Application.16
")
That way you don't have any whitespaces.
Here is some more background on the split operator

Why does this PowerShell script produce an error?

I have a file called Eric Clapton - Nothing But The Blues - Full Concert (1994) [HQ].URL in a directory C:\Hans\Hans4\.
Code to create this is below (though the error occurs regardless of file contents)
$fileContents = #"
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
URL=http://example.com/
IDList=
"#
New-Item -Path "C:\Hans\Hans4" `
-Name "Eric Clapton - Nothing But The Blues - Full Concert (1994) [HQ].URL" `
-ItemType "file" `
-Value $fileContents `
-Force
When I run the following I get an error
Get-ChildItem 'C:\Hans' -Recurse | Resolve-ShortcutFile > Output.txt
The code references the function below
function Resolve-ShortcutFile {
param(
[Parameter(
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position = 0)]
[Alias("FullName")]
[string]$fileName
)
process {
if ($fileName -like "*.url") {
Get-Content $fileName | Where-Object {
$_ -like "url=*"
} |
Select-Object #{
Name='ShortcutFile'
Expression = {Get-Item $fileName}
}, #{
Name='Url'
Expression = {$_.Substring($_.IndexOf("=") + 1 )}
}
}
}
}
This is the error message
Get-Content : An object at the specified path C:\Hans\Hans4\Eric Clapton - Nothing But
The Blues - Full Concert (1994) [HQ].URL does not exist, or has been filtered by
the -Include or -Exclude parameter.
At line:33 char:28
+ Get-Content $fileName | Where-Object {
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (System.String[]:String[]) [Get-Content], Exception
+ FullyQualifiedErrorId : ItemNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Why do I get this error?
The problem is the filename that is piped into the function and passed to Get-Content
C:\Hans\Hans4\Eric Clapton - Nothing But The Blues - Full Concert
(1994) [HQ].URL
You are encountering the problem described here.
It contains square brackets that are interpreted as a range operator with the set H and Q
So the pattern would mean that it attempts to read the contents of files with either of the following names...
Eric Clapton - Nothing But The Blues - Full Concert (1994) H.URL
Eric Clapton - Nothing But The Blues - Full Concert (1994) Q.URL
... but will not match the literal [HQ] in
Eric Clapton - Nothing But The Blues - Full Concert (1994) [HQ].URL
You can use the -literalPath parameter to avoid this problem and have the file name treated literally.
function Resolve-ShortcutFile {
param(
[Parameter(
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position = 0)]
[Alias("FullName")]
[string]$fileName
)
process {
if ($fileName -like "*.url") {
Get-Content -literalPath $fileName | Where-Object {
$_ -like "url=*"
} |
Select-Object #{
Name='ShortcutFile'
Expression = {Get-Item -literalPath $fileName}
}, #{
Name='Url'
Expression = {$_.Substring($_.IndexOf("=") + 1 )}
}
}
}
}

Powershell incorrect parameter

So I am trying to pass the file directory to the function convert at the bottom. When I run the script I receive the output:
Succes
C:\test 2\00000027627-00001\PROCESSING CHECKLIST
convert : Invalid Parameter - 2\00000027627-00001\PROCESSING
At C:\Users\pmanca\Desktop\msbxmlreader.ps1:35 char:13
+ convert([string]$hostdirectoryPlusLoanPlusDocType)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Invalid Paramet...0001\PROCESSING:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
It appears to be cutting off the file path after C:\test. Could the file path be too long? even so i wouldn't imagine getting the error at the function call and instead somewhere in the function when it couldn't resolve the path.
#? is a shortcut for where object and % is a shortcut for foreach-object
cls
#count 1 = Loan Number
#count 4 = Cust Num
#count 5 = Document Type
$hostdirectory = "C:\test 2"
$count = 0
$file = (Select-xml -Path "$hostdirectory\index.xml" -XPath / ).Node
$test = $file.ExportedResult.Docs.ExportedDoc.Doc.UdiValues.UdiValue.Value# | Select-Object {$_.UdiValue.Value.InnerXML} -Unique #|? {$_.UdiValue.Name -eq "Loan Number"}
$test | ForEach-Object{
$count++
# Write-Host $_.innerxml "----" $count
if($count -eq 1){
[string]$xmlHold = $_.InnerXML
$hostdirectoryPlusLoan = "$hostdirectory\$xmlHold"
if(!(test-path $hostdirectoryPlusLoan)){
New-Item $hostdirectoryPlusLoan -ItemType directory
}
}
if($count -eq 5){
[string]$xmlHold = $_.InnerXML
$hostdirectoryPlusLoanPlusDocType = "$hostdirectoryPlusLoan\$xmlHold"
if(!(test-path $hostdirectoryPlusLoanPlusDocType)){
New-Item $hostdirectoryPlusLoanPlusDocType -ItemType directory
}
if(Test-Path "$hostdirectory\$xmlhold.pdf"){
$check = Copy-Item "$hostdirectory\$xmlHold.pdf" -Destination $hostdirectoryPlusLoanPlusDocType -ErrorAction SilentlyContinue
if(-not $?) {write-warning "Copy Failed"; Write-Host $Error[0].exception.message}
else {write-host "Succes"}
Write-Host $hostdirectoryPlusLoanPlusDocType
convert([string]$hostdirectoryPlusLoanPlusDocType)
}
}
if($count -ge 8){
$count = 0
# Write-Host "-----------------------------------"
}
}
function convert([string]$inputDirectory){
write-host $inputDirectory
#Variable to hold current input directory
$InputPathFilter = $InputDirectory + '\*.pdf'
#Variable to hold the list of PDFs from the current input directory
$PDFList = #(gci $InputPathFilter | foreach {write-output $_.name})
#Loop through list of PDF files to convert to TIF image files.
for ($j=0; $j -lt $PDFList.count; $j++) {
#Each PDF will go into its own directory/batch
#Create a variable with only the file name
$FileName = $PDFList[$j] -replace(".pdf",'')
#Variable of the full path to the current PDF
$InputPath = $InputDirectory + '\' + $PDFList[$j]
#Variable to hold output path of each TIF file. Filename format is that used by batches in ScerIS (i.e. 00010001.tif, 00010002.tif, etc...)
$OutputFullDirectory = $inputlDirectory + '\' + $FileName + "_" + "{0:D4}" -f + '1' + '%04d.tif'
#Calls Ghostscript command line executable to process each PDF file into a group of single page TIF image files
&'C:\Program Files\gs\gs9.14\bin\gswin64c.exe' -sDEVICE=tiffg4 -dBATCH -dNOPAUSE -q -r600 "-sOutputFile=$OutputFullDirectory" "$InputPath"
#Increment the counter for the loop
$DocCounter = $j + 1
#Rename the current pdf so that it isn't processed again.
$RenamePath = $PdfList[$j] -replace("pdf", "pd_")
Rename-Item $InputPath $RenamePath -Force
}
}
First : In PowerShell, when you call a function you must not use parenthesis :
convert $hostdirectoryPlusLoanPlusDocType
or as suggested in comment
convert -inputDirectory $hostdirectoryPlusLoanPlusDocType
but not :
convert([string]$hostdirectoryPlusLoanPlusDocType)
Second : Your function should be declarated first and use after :
function toto ($var)
{
Write-Host $var
}
toto "voila"
and not
toto "voila"
function toto ($var)
{
Write-Host $var
}

OutOfMemoryException when running my PowerShell script

Here's the PowerShell script I am using to add "segment99" to the beginning of all the text files (one by one) within a folder:
Set Environmental Variables:
$PathData = '<<ESB_Data_Share_HSH>>\RwdPnP'
Go to each text file in the specified folder and add header to the file:
Get-ChildItem $PathData -filter 'test_export.txt'|%{
$content = '"segment99" ' + [io.file]::ReadAllText($_.FullName)
[io.file]::WriteAllText(($_.FullName -replace '\.txt$','_99.txt'),$content)
}
This is giving me the following error:
Error: Exception calling "ReadAllText" with "1" argument(s): "Exception of type 'Syste
Error: m.OutOfMemoryException' was thrown."
Error: At D:\apps\MVPSI\JAMS\Agent\Temp\JAMSTemp13142.ps1:17 char:51
Error: + $content = '"segment99" ' + [io.file]::ReadAllText <<<< ($_.FullName)
Error: + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
Error: + FullyQualifiedErrorId : DotNetMethodException
Error:
I am running this code on a folder that has 20 files, each over 2 GB.
How can I fix this?
Copying a header file + a large file to a new file will be less prone to outofmemory exceptions (for files of that size):
$header = '"segment99"'
$header | out-file header.txt -encoding ASCII
$pathdata = "."
Get-ChildItem $PathData -filter 'test_export.txt' | %{
$newName = "{0}{1}{2}" -f $_.basename,"_99",$_.extension
$newPath = join-path (split-path $_.fullname) $newname
cmd /c copy /b "header.txt"+"$($_.fullname)" "$newpath"
}
This is not optimal code but it solves the task without reading all text to memory: it adds the header to the first line and then outputs other lines. Also, note that it does nothing if the input file is empty.
Get-ChildItem $PathData -Filter 'test_export.txt' | %{
$header = $true
Get-Content $_.FullName | .{process{
if ($header) {
'"segment99" ' + $_
$header = $false
}
else {
$_
}
}} | Set-Content ($_.FullName -replace '\.txt$', '_99.txt')
}