finding registry parent folder to add registry - powershell

I am stuck at how to actually find the parent folder to add a new registry key using powershell. The reason is because the device shows as a different value per computer. And the registry that I am trying to add will set the default over to the "internal mic"'s parents key.
Here is the code
$pathToIntMic = Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture | Where-Object { .Name -eq "internal mic"}
#$intMicParent = (Get-item $pathToIntMic).parent.Fullname
#write-host $intMicParent
The last two line are commented out but serve just to get the parent folder key name just under \Audio\Capture.
Thanks for any help!

Use the property PSParentPath:
$key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture'
$pathToIntMic = Get-ItemProperty "HKLM:\$key" | ? { $_.Name -eq "internal mic" }
Write-Host $pathToIntMic.PSParentPath
You can enumerate the properties and methods of an object by piping it into the Get-Member cmdlet:
$pathToIntMic | Get-Member

Related

Filter PowerShell command Output

I want to change a mapped drive remote path. but I'm unable to filter the remote path property. Is there any way I can filter all the mapped drives remote path only so, later on, I can run a foreach loop to change the values? Thanks.
Get-Item -Path HKCU:\Network | Where-Object -FilterScript {'RemotePath'}
Hive: HKEY_CURRENT_USER\Network
Name Property
---- --------
Z RemotePath : \\IAPC\Users\IA\Documents\10
UserName :
ProviderName : Microsoft Windows Network
ProviderType : 131072
ConnectionType : 1
ConnectFlags : 0
DeferFlags : 4
UseOptions : {68, 101, 102, 67...}
PS HKCU:\Network>
Only interested in name of the network drive with RemotePath (under Property column)
The following outputs [pscustomobject] instances representing the values of those registry subkeys of HKCU:\Network whose RemotePath value is non-empty:
Get-ItemProperty -Path HKCU:\Network\* | Where-Object RemotePath
To get just the drive-name-remote-path pairs:
Get-ItemProperty -Path HKCU:\Network\* | Where-Object RemotePath |
Select-Object PSChildName, RemotePath
Note: The PSChildName property contains the drive letter of each mapping (it is the name of the subkey whose values are being returned).
To loop over all mappings of interest and update them by replacing the server-name component:
$oldServer = '\\IAPC\'
$newServer = '\\localhost\'
# CAVEAT: This instantly updates your drive mappings.
# You can add -WhatIf to the Set-ItemProperty call,
# to *preview* the operation, but it will only show the
# target registry key and value, not the new data.
Get-ItemProperty -Path HKCU:\Network\* | Where-Object RemotePath | ForEach-Object {
$driveLetter, $remotePath = $_.PSChildName, $_.RemotePath
Set-ItemProperty -LiteralPath HKCU:\Network\$driveLetter RemotePath ($remotePath -replace [regex]::Escape($oldServer), $newServer)
}
As for what you tried:
Where-Object -FilterScript {'RemotePath'} is a no-op, because any input meets the criterion 'RemotePath', which, as a non-empty string literal is invariably $true when interpreted as a Boolean. To access a property on the current input object, you need to use automatic $_ variable: { $_.RemotePath }
It is only with the simplified syntax, shown above, which doesn't use a script block ({ ... }) that the string argument given is implicitly interpreted as the name of the property to access on the input object at hand.
Get-Item -Path HKCU:\Network only targets the root key of all network mappings itself, not the subkeys that define the actual mappings.
In your case you're also interested in the RemotePath value of each subkey, which Get-ItemProperty provides for all subkeys, targeted with a wildcard pattern, HKCU:\Network\*
Get-ItemProperty, when not given a property name, returns all properties - which in the case at hand are registry values - as a "property bag", in the form of a [pscustomobject] instance, with the name of the containing key reported in the .PSChildName property.
Unfortunately, working with PowerShell's registry provider is often not as straightforward as one would like.
#imtiaz Hey i am not sure if you are trying the same but here is how i have achieved recently.
$oldServer = "\\abc.local"
$newServer = "\abc.com"
$paths = REG QUERY HKCU\Network | where{$_ -ne ""}
foreach ($item in $paths)
{
$oldPath = REG QUERY $item /f RemotePath /t REG_SZ | Out-String
$oldPath1 = $oldPath.Split()[-12]
$updatedPath = $oldPath1 -replace $oldServer,$newServer
reg add $item /v RemotePath /t REG_SZ /d $updatedPath /f /reg:64
}
I tried before Get-ItemProperty and set-itemproperty was facing some issues. This might help you. I know this's not a "professional way" but this worked for me.

Get mapped network drives labels

Is there a way to get mapped network drives labels?
I know it's possible to get multiple properties through the
Get-Object Win32_MappedLogicalDisk
But none of them are labels (please do not misunderstand, I do not want Name i.e. K:, I want labels i.e. My Network drive)
You could use the Com Shell.Application object for this:
$shell = New-Object -ComObject Shell.Application
(Get-WmiObject -Class Win32_MappedLogicalDisk).DeviceID |
# or (Get-CimInstance -ClassName Win32_MappedLogicalDisk).DeviceID |
# or ([System.IO.DriveInfo]::GetDrives() | Where-Object { $_.DriveType -eq 'Network' }).Name |
Select-Object #{Name = 'Drive'; Expression = {$_}},
#{Name = 'Label'; Expression = {$shell.NameSpace("$_").Self.Name.Split("(")[0].Trim()}}
# when done, clear the com object from memory
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Output:
Drive Label
----- -----
X: MyCode
Some explanation for the above:
Using the COM object Shell.Application, you can drill down through its properties and methods.
.NameSpace create and return a Folder object for the specified folder
.Self gets a Read-Only duplicate System.Shell.Folder object
.Name from that we take the Name property like 'MyCode (X:)'
.Split this name we split on the opening bracket '(',
[0] take the first part of the splitted name and
.Trim() get rid of any extraneous whitespace characters
Another way is to go into the registry, but remember that after a mapped network folder is unmapped, the old registry value remains.
This is why below code still uses one of two methods to find active network mappings first:
# the registry key to search in
$regKey = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2'
# list the mapped network drives and loop through
# you can also use Get-CimInstance -ClassName Win32_MappedLogicalDisk
Get-WmiObject -Class Win32_MappedLogicalDisk | ForEach-Object {
# create the full registry key by replacing the backslashes in the network path with hash-symbols
$key = Join-Path -Path $regKey -ChildPath ($_.ProviderName -replace '\\', '#')
# return an object with the drive name (like 'X:') and the Label the user gave it
[PsCustomObject]#{
Drive = $_.DeviceID
Label = Get-ItemPropertyValue -Path $key -Name '_LabelFromReg' -ErrorAction SilentlyContinue
}
}
Output here also:
Drive Label
----- -----
X: MyCode
I am not aware of a cmdlet that will give you that info. I believe you can find it by looking at the registry with gci, but you would need to cleanup the output.
get-childitem "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2"

Cannot Get-ItemProperty in Group Policy registry

I need to locate a specific GPO to manually delete it from our machines, due to the pandemic they are at home and outside domain, so I thought about doing it remotely via PS with Intune.
I'm trying to create an script that looks for the DisplayName of the GPO and the deletes it, but it seems like the properties are protected or some other issue, because i cannot find any Property beyond the Group Policy registry.
If i try to do:
Get-ChildItem -Path 'Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Group Policy\History\'
I get something like:
Name Property
---- --------
{3537}
{42B5}
{4CFB}
It does not matter how deep I go beyond that point, it does not show me any Property. I just started with PS and I don't know if there's anything I'm doing wrong, with others registries i got no issue.
¿Any thoughts? :(
At the end I want to have something like:
$path = "Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Group Policy\History\"
$match = "GPO_1234"
Get-ChildItem -Path $path -recurse |
ForEach { Get-ItemProperty $_.PSPath } |
Where-Object { $_.DisplayName -match $match } | del
But if it cannot match with anything if the Properties cannot be iterated.
Thanks in advance
It's a bit hard without knowing what's in "Group Policy\History" exactly (I have a single DWORD there and that's it, no subkeys at all), but assuming "DisplayName" is the name of a property somewhere and "GPO_1234" is the value of that property, then something like this should work:
$RegPath = "Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Group Policy\History\"
$Pattern = "GPO_1234"
Get-ChildItem -Recurse $RegPath |
ForEach-Object { Get-ItemProperty $_.PsPath } |
Where-Object {
$_.psobject.Properties.Name -eq 'DisplayName' -and
$_.psobject.Properties.Value -eq $Pattern
}
If you get the matches you want just throw a final | Remove-Item -Force at the end, and if you have any questions about what's going on just ask!
As a sidenote, you should avoid using aliases like Foreach and del and instead use the real nammes (ie. Foreach-Object and Remove-Item). It will make your scripts easier to read and follow in the long run.
Especially important with Foreach since it exists with that exact spelling but a completely different syntax as well (foreach ($Item in $Collection) {}).

can't seem to match two values in registry

I am trying to get all the NICs on my system and then using that information to insert registry values of *TCPChecksumOffloadIPv4 etc. However, I am failing this task miserably!
I can get all the GUID's and want to match that to what is in this registry path: HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\*
I get all the GUID's by this:
$GuidSet = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\*" | select -ExpandProperty pschildname
Output:
{1FE01120-3866-437F-81FF-556B08999AA4}
{2533855F-2A59-485D-87A0-167E5DA39E45}
{2A6471FB-C1D6-47D2-A665-9F276D142D7C}
{306D2DED-18B5-45D8-858E-BB3F49E3BD6A}
{30EF50B2-E4B3-400D-9614-B590E37DE4D8}
{4A208C06-0D99-4DE4-9B2F-86285AEF864E}
{B7883140-E15B-4409-BA1B-96E37A45425C}
{D129DDA8-C64B-46A1-B99A-EA74FC4FAF81}
{D5C9183B-E542-4010-866F-4443AD55F28C}
This is where I am stuck now...how can I use this information to match what is in the registry path of "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\*" ?
I tried the below but I get access denied - I think this is because of the "Properties" registry key - how can I ignore that registry key?
$path1 = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\*" |?{$_.NetCfgInstanceId -match $guidset} | select -ExpandProperty pspath
Once that is done though then do I construct a foreach loop on each entry and then add in the registry keys I need?
ANSWER:
you know what...when your in a muddle and you have lots of scripts...take a break, open a new window and start from scrath! That's what I did and in 10min I figured it out...!
$aGUID_SET = #(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\*" | select -ExpandProperty pschildname)
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\*" -exclude "Properties" |
Where-Object {$aGUID_SET.Contains($_.NetCfgInstanceId)} |
ForEach-Object {
""
$_.DriverDesc
$_.NetCfgInstanceId
}
You are on the right track.
The Get-ItemProperty cmdlet will only get the properties of the items specified, not including any sub-items.
Since the registry values you are looking for are not actually properties of the registry key HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} but instead are properties of subkeys of that key, the first thing we need to do is list the subkeys: $path = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}"
We can then use Get-ChildItem $path to list the subkeys.
After formatting the paths properly (add Registry:: to the front), you can then input that to Get-ItemProperty. I would filter with something like: Where-Object {$guidset -contains $_.NetcfgInstanceID} | Select-Object -ExpandProperty PSPath.
Finally, you should have an array of paths to keys that matched $guidset, which
Set-ItemProperty can take.
EDIT: The error you are receiving is because permissions on those "Properties" subkeys is restricted. I would tack an -ErrorAction SilentlyContinue to Get-ChildItem because it is not a terminating error and does not actually affect the results.
You can do it like this
ForEach ($item in $(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\*" |?{$_.NetCfgInstanceId -match $guidset} | select -ExpandProperty pspath)) {
Try {
Write-Host $item
} Catch {
Write-Host "error..."
}
}

Variable referencing. How to create arrays getting their names from elements of another array

This is as simplified version of what I'd like to achieve... I think it's called 'variable referencing'
I have created an array containing the content of the folder 'foo'
$myDirectory(folder1, folder2)
Using the following code:
$myDirectory= Get-ChildItem ".\foo" | ForEach-Object {$_.BaseName}
I'd like to create 2 arrays named as each folders, with the contained files.
folder1(file1, file2)
folder2(file1, file2, file3)
I tried the following code:
foreach ($myFolder in $myDirectory) {
${myFolder} = Get-ChildItem ".\$myFolders" | forEach-Object {$_.BaseName}
}
But obviously didn't work.
In bash it's possible create an array giving it a variable's name like this:
"${myForder[#]}"
I tried to search on Google but I couldn't find how to do this in Powershell
$myDirectory = "c:\temp"
Get-ChildItem $myDirectory | Where-Object{$_.PSIsContainer} | ForEach-Object{
Remove-Variable -Name $_.BaseName
New-Variable -Name $_.BaseName -Value (Get-ChildItem $_.FullName | Where-Object{!$_.PSIsContainer} | Select -ExpandProperty Name)
}
I think what you are looking for is New-Variable. Cycle through all the folders under C:\temp. For each folder make a new variable. It would throw errors if the variable already exists. What you could do for that is remove a pre-exising variable. Populate the variable with the current folders contents in the pipeline using Get-ChildItem. The following is a small explanation of how the -Value of the new variable is generated. Caveat Remove-Variable has the potiential to delete unintended variables depending on your folder names. Not sure of the implications of that.
Get-ChildItem $_.FullName | Where-Object{!$_.PSIsContainer} | Select -ExpandProperty Name
The value of each custom variable is every file ( not folder ). Use -ExpandProperty to just gets the names as strings as supposed to a object with Names.
Aside
What do you plan on using this data for? It might just be easier to pipe the output from the Get-ChildItem into another cmdlet. Or perhaps create a custom object with the data you desire.
Update from comments
$myDirectory = "c:\temp"
Get-ChildItem $myDirectory | Where-Object{$_.PSIsContainer} | ForEach-Object{
[PSCustomObject] #{
Hotel = $_.BaseName
Rooms = (Get-ChildItem $_.FullName | Where-Object{!$_.PSIsContainer} | Select -ExpandProperty Name)
}
}
You need to have at least PowerShell 3.0 for the above to work. Changing it for 2.0 is easy if need be. Create and object with hotel names and "rooms" which are the file names from inside the folder. If you dont want the extension just use BaseName instead of Name in the select.
This is how I did it at the end:
# Create an array containing all the folder names
$ToursArray = Get-ChildItem -Directory '.\.src\panos' | Foreach-Object {$_.Name}
# For each folder...
$ToursArray | ForEach-Object {
# Remove any variable named as the folder's name. Check if it exists first to avoid errors
if(Test-Path variable:$_.BaseName){ Remove-Variable -Name $_.BaseName }
$SceneName=Get-ChildItem ".\.src\panos\$_\*.jpg"
# Create an array using the main folder's name, containing the names of all the jpg inside
New-Variable -Name $_ -Value ($SceneName | Select -ExpandProperty BaseName)
}
And here it goes some code to check the content of all the arrays:
# Print Tours information
Write-Verbose "Virtual tours list: ($($ToursArray.count))"
$ToursArray | ForEach-Object {
Write-Verbose " Name: $_"
Write-Verbose " Scenes: $($(Get-Variable $_).Value)"
}
Output:
VERBOSE: Name: tour1
VERBOSE: Scenes: scene1 scene2
VERBOSE: Name: tour2
VERBOSE: Scenes: scene1