I am trying to delete registry string that contains value “Palo Alto Networks”
Path: HKEY_USERS\S-1-5-21-484763869-1659004503-1644491937-15773\Software\Microsoft\Windows\CurrentVersion\UFH\SHC
String: 61
Value: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Palo Alto Networks\GlobalProtect\GlobalProtect.lnk
C:\Program Files\Palo Alto Networks\GlobalProtect\PanGPA.exe
/noshrink
I want the script to delete string “61” if it detects value “Palo Alto Networks” in it.
This is the code that I think close to what I aim.
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
} |
Remove-ItemProperty -Name $RegKeyValueName
However, $RegKeyValueName is random. It could be other than 61.
My aim is if $RegKeyValueDataPattern match, it will delete the $RegKeyValueName
OK I'm not completely sure what exactly you like to delete. It might help you for the next time when you take a look at the following Info: Structure of the Registry.
If you like to get the registry key values and you know the name you can use following syntax:
$SearchBase = 'REGISTRY::HKEY_USERS\S-1-5-21-484763869-1659004503-1644491937-15773\Software\Microsoft\Windows\CurrentVersion\UFH\SHC'
$RegKeyValueName = '61'
$RegKeyValueDataPattern = 'Palo Alto Networks'
Get-ItemProperty -Path $SearchBase
If you're looking for a specific value you can either specify the name ...
Get-ItemProperty -Path $SearchBase -Name $RegKeyValueName
... or filter the output with a Where-Object ...
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
}
If you like to delete only the data of the value you can use Set-ItemProperty and provide an empty string ...
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
} |
Set-ItemProperty -Name $RegKeyValueName -Value ''
.... or if you like to delete the complete value you can use Remove-ItemProperty ...
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
} |
Remove-ItemProperty -Name $RegKeyValueName
.... and if you don't know the name of the value you like to delete you can use the following code scnippet:
Get-Item -Path $SearchBase |
Select-Object -ExpandProperty Property |
Where-Object {
(Get-ItemProperty -Path $SearchBase -Name $_ ) -match $RegKeyValueDataPattern
} |
ForEach-Object {
Remove-ItemProperty -Path $SearchBase -Name $_
}
Related
I am trying to check for presence of a particular folder "appdata\Local\Packages\ActiveSync" in each of the profile folders that are returned for each of the computer by the below script.Searching through various forums I got the script below and need further assistance to eventually output it to a file with results of Test-Path against each computer name and corresponding profile path.
e.g. \\Computer1\C:\users\John\appdata\Local\packages\ActiveSync False
Invoke-Command -Computer (get-content c:\temp\servers.txt) -ScriptBlock {
Get-childItem 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' |
% {Get-ItemProperty $_.pspath }} | Select pscomputername,profileimagepath |
Where-Object { $_.ProfileImagePath -like "C:\users*" } | Out-File c:\temp\profiles.csv
For this, I think I would use a loop to go through all user path strings like below:
Invoke-Command -ComputerName (Get-Content -Path 'c:\temp\servers.txt') -ScriptBlock {
$regPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*'
Get-ItemPropertyValue -Path $regPath -Name 'ProfileImagePath' -ErrorAction SilentlyContinue |
Where-Object { $_ -like 'C:\Users*' } | ForEach-Object {
# combine the value with the rest of the path to form a LOCAL path
$path = Join-Path -Path $_ -ChildPath 'AppData\Local\Packages\ActiveSync'
[PsCustomObject]#{
ComputerName = $env:COMPUTERNAME
Path = '\\{0}\{1}' -f $env:COMPUTERNAME, ($path.Replace(":", "$")) # UNC format
Exists = Test-Path -Path $path -PathType Container
}
}
} | Export-Csv -Path 'c:\temp\profiles.csv' -NoTypeInformation
Please note that if the output should be a structured CSV file, you need to use Export-Csv on the resulting objects instead of Out-File.
Also you may need to append parameter -Credential to the Invoke-Command call where you can give it administrative credentials.
I am trying to copy machines names to a text file if the programs are found in the user installations
machines are copying over to text file however it is getting machines that are not installed as well
$computers = Get-Content C:\temp\MY_TEST.txt | ForEach-Object {$_.trim()}
foreach($computer in $computers) {
Invoke-command -computername $computer {
$UserHives = Get-ChildItem Registry::HKEY_USERS\ | Where-Object {$_.Name -match '^HKEY_USERS\\S-1-5-[\d\-]+$'}
foreach($Hive in $UserHives)
{
# Construct path from base key
$Path = Join-Path $Hive.PSPath "Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
# Attempt to retrieve Item property
$one = Get-ItemProperty -Path $Path -ErrorAction SilentlyContinue | Where-Object {$_.displayname -eq 'ABC'}
$two = Get-ItemProperty -Path $Path -ErrorAction SilentlyContinue | Where-Object {$_.displayname -eq 'DEF'}
$three = Get-ItemProperty -Path $Path -ErrorAction SilentlyContinue | Where-Object {$_.displayname -eq '123'}
if($one -or $two -or $three){
$computer | Out-File C:\temp\MY.txt -Append
}
} #end foreach
}
#only copies here outside of loop
#$computer | Out-File C:\temp\MY.txt -Append
} #end main foreach loop
I expect only machines found in my registry hive to be copied to text file
I have a code that let me query one file version at the time.How can I query all file version inside of this registry key or if I just want to query specific files including firefox, chrome, etc.?
(Get-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\App Paths\communicator.exe').'(Default)' | ForEach-Object {
Get-ChildItem -Path $_ | Select-Object -ExpandProperty VersionInfo | Select FileDescription,ProductVersion
} | Format-Table -AutoSize
Instead of providing a literal path you should run Get-ChildItem on the "folder" the registry keys are contained in you are interested in. The result of this you pipe to your piece of code ... like this:
$Path = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\App Paths'
Get-ChildItem -Path $Path |
ForEach-Object {
Get-ItemProperty -Path $_.PSPath |
Select-Object -ExpandProperty '(default)' -ErrorAction SilentlyContinue |
ForEach-Object {
Get-Item -Path $_ -ErrorAction SilentlyContinue |
Select-Object FullName -ExpandProperty VersionInfo
}
} |
Format-Table -AutoSize
I have separate Powershell commands I run, one gets me a list of all folders at a specific level, the other list all folders and associated ACLs. I'd like to combine then to list only "level 3" folders, and their associated ACLs. Command for level 3 folders is:
Get-ChildItem "I:" -Recurse -Directory | Where-Object {$_.FullName.split("\").count -le 4} | ForEach-Object FullName
Command for folder ACLs is:
Get-ChildItem j:\ -Recurse | where-object {($_.PsIsContainer)} | Get-ACL | Format-List
I tried:
Get-ChildItem I:\ -Recurse | where-object {($_.PsIsContainer)} | Where-Object {$_.FullName.split("\").count -le 4} Get-ACL | Format-List
But got error Where-Object : A positional parameter cannot be found that accepts argument 'Get-ACL'.
Thanks in advance for any help! Using PS 5.1, btw.
You can accomplish this by using the pipeline. Simply pipe the output of your first set of commands directly into the Get-ACL cmdlet, like so.
$path = "I:\"
Get-ChildItem -Path $path -Recurse -Directory | `
Where-Object {$_.FullName.split('\').count -le 4} | `
Select-Object -ExpandProperty FullName | `
Get-ACL | `
Format-List
I think you're missing a pipe character (|) after Where-Object.
This worked:
dir "I:" -Recurse -ea silentlycontinue | where { $_.PsIsContainer -and $_.FullName.split("\").count -le 5} | % { $path1 = $_.fullname; Get-Acl $_.Fullname | % { $_.access | where { !$_.IsInherited } | Add-Member -MemberType NoteProperty -name "Path" -Value $path1 -passthru }}
Thanks for the responses!
There must be a more efficient way to import multiple CSV files from a directory where the name of the file contains Services_Results*.csv into one variable with unique entries. I'm thinking of looping through all the files in the directory that match the file name with a wildcard then just importing the lines where Success is on the field.
$Success0 = Import-Csv -Path "\\FILE05\Users\USER001\+Projects\Chrome\Services_Results.csv" | Where-Object {$_.Status -eq "Success"}
$Success1 = Import-Csv -Path "\\FILE05\Users\USER001\+Projects\Chrome\Services_Results_150601.csv" | Where-Object {$_.Status -eq "Success"}
$Success2 = Import-Csv -Path "\\FILE05\Users\USER001\+Projects\Chrome\Services_Results_150602.csv" | Where-Object {$_.Status -eq "Success"}
$Success3 = Import-Csv -Path "\\FILE05\Users\USER001\+Projects\Chrome\Services_Results_150602_b.csv" | Where-Object {$_.Status -eq "Success"}
$Success4 = Import-Csv -Path "\\FILE05\Users\USER001\+Projects\Chrome\Services_Results_150602_c.csv" | Where-Object {$_.Status -eq "Success"}
$Success5 = Import-Csv -Path "\\FILE05\Users\USER001\+Projects\Chrome\Services_Results_150603_a.csv" | Where-Object {$_.Status -eq "Success"}
$PCList = $Success0 + $Success1 + $Success2 + $Success3 + $Success4 + $Success5
$PCList = $PCList.PC | sort -Unique
Write-host "PCList" $PCList.count
From Get-Help Import-CSV:
-Path <String[]>
Specifies the path to the CSV file to import. You can also pipe a path to Import-Csv.
Required? false
Position? 1
Default value None
Accept pipeline input? true (ByValue)
Accept wildcard characters? false
So Import-CSV will accept multiple values for -Path from the pipeline:
$PCList =
Get-ChildItem '\\FILE05\Users\USER001\+Projects\Chrome\Services_Results*.csv' |
Select -ExpandProperty FullName |
Import-CSV |
Where-Object {$_.Status -eq "Success"}
How about using PowerShell Background Jobs to speed up the process? I haven't tested this code, but try to read an understand the pattern. I think you'll appreciate how much it can speed up the process, if you're importing large CSV files.
### Create an empty array to hold Background Jobs.
$JobList = #();
### Get a list of CSV files.
$FileList = Get-ChildItem -Path \\FILE05\Users\USER001\+Projects\Chrome\*Services_Results*.csv;
foreach ($File in $FileList) {
### Start a new Background Job for each file
$JobList += Start-Job -ScriptBlock { Import-Csv -Path $args[0] | Where-Object -FilterScript { $PSItem.Status -eq 'Success'; } } -ArgumentList $File.FullName -Name $File.Name;
}
### Wait for all the jobs to complete.
Wait-Job -Job $JobList;
### Receive the results of the jobs.
$ResultList = Receive-Job -Job $JobList;
I think you can do what you want quite neatly with the way you're already doing it, but using a wildcard and a ForEach loop:
$files = Get-ChildItem "\\FILE05\Users\USER001\+Projects\Chrome\*.csv"
$PCList = $files | ForEach { (Import-Csv $_ | Where Status -eq "Success") }
$PCList = $PCList | sort -Unique -Property PC
Write-Output $PCList
Write-Output $PCList.Count