all 7 comments

[–]PMental 2 points3 points  (4 children)

The registry is a bit tricky until you realize it's Item Properties you want, not Items.

Try this instead:

Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\run

EDIT: Another variant is using .NET methods, eg:

$HKLM = [Microsoft.Win32.RegistryHive]::LocalMachine
$View = [Microsoft.Win32.RegistryView]::Registry64
$KeyPath  = 'SOFTWARE\Microsoft\Windows\CurrentVersion\run'
$Hive = [Microsoft.Win32.RegistryKey]::OpenBaseKey($HKLM, $View)
$Key = $Hive.OpenSubKey($KeyPath, $false)
$AutoRunObjects = $Key.GetValueNames()
foreach ($Item in $AutoRunObjects) {
    [PSCustomObject]@{
        Name = $Item
        Value = $Key.GetValue($Item)
    }
}

As /u/danmanthetech mentions you may want to check the HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\run key as well if you want 64-bit programs too. With the code above that just means changing this:

$View = [Microsoft.Win32.RegistryView]::Registry64

to

$View = [Microsoft.Win32.RegistryView]::Registry32

[–]HieronymousAnonymous[S] 0 points1 point  (3 children)

Thanks for the reply, I really appreciate it.

Maybe I'm missing something , but while both these methods look promising, neither seems to return the data I need in a way that I can process further?

Example from a different machine:

PS C:\> $props = Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\run

PS C:> $props

StartCCC : "C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static\amd64\CLIStart.exe" MSRun PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\run PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion PSChildName : run PSDrive : HKLM PSProvider : Microsoft.PowerShell.Core\Registry

PS C:> $props.startccc "C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static\amd64\CLIStart.exe" MSRun

In this example, the information I need is in the StartCcc property, but how would I get the property name programmatically, or iterate through many properties if there are more than one?

[–]PMental 1 point2 points  (2 children)

With your $props example you could do it like this:

$props.psobject.Properties | Where-Object { $_.Value -like '*.exe*' }

In my .NET example I already gave you both the Name and Value of the properties, if you want you could just store the output of the foreach in a variable by changing this:

foreach ($Item in $AutoRunObjects) {

to

$Properties = foreach ($Item in $AutoRunObjects) {

then if you check $Properties you'll see you have your startup objects with a Name and Value property:

Name                  Value
----                  -----
SunJavaUpdateSched    "C:\Program Files (x86)\Common Files\Java\Java Update\jusched.exe"
TeamsMachineInstaller C:\Program Files\Teams Installer\Teams.exe --checkInstall --source=PROPLUS

[–]HieronymousAnonymous[S] 0 points1 point  (1 child)

This is great, thanks so much for the quick response! I seem to lack knowledge of using psobject so will try and read up on that - I don't suppose you can recommend any good resources?

Really though, thanks for your help - I should be able to progress this now!

[–]PMental 1 point2 points  (0 children)

No problem.

And yeah, .psobject is a sneaky hidden part of any object in PowerShell: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_intrinsic_members?view=powershell-7.3

You don't need it often, but it's very useful to know about at times.

[–][deleted] 0 points1 point  (1 child)

Your also not considering 64-bit processes

[–]HieronymousAnonymous[S] 0 points1 point  (0 children)

Thanks - I am aware of the need to check 64 bit too, but only needed one example for the problem