Wie erhalte ich den Wert eines Registrierungsschlüssels und NUR den Wert mit Powershell?

73

Kann mir jemand helfen, den Wert eines Registrierungsschlüssels abzurufen und in eine Variable in PowerShell einzufügen? Bisher habe ich verwendet Get-ItemPropertyund reg queryund obwohl beide den Wert ziehen, fügen beide auch zusätzlichen Text hinzu. Ich brauche nur den Zeichenfolgentext aus dem Registrierungsschlüssel und NUR den Zeichenfolgentext aus dem Schlüssel. Ich bin sicher, ich könnte eine Funktion erstellen, um den zusätzlichen Text zu entfernen, aber wenn sich etwas ändert (z. B. der Name der Reg-Taste), könnte dies Auswirkungen haben.

Alan Anderson
quelle
Es ist eine gute Frage, aber beachten Sie, dass Get-ItemPropertykein zusätzlicher Text hinzugefügt wird . Stattdessen wird ein Objekt zurückgegeben, dessen Eigenschaften die gewünschten Daten enthalten. Der zusätzliche Text stammt aus der Standardausgabeformatierung des zurückgegebenen Objekts (eine Darstellung der Objektstruktur).
mklement0

Antworten:

113
$key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
(Get-ItemProperty -Path $key -Name ProgramFilesDir).ProgramFilesDir

Ich habe noch nie gemocht, wie dieser Anbieter so implementiert wurde: /

Grundsätzlich macht es jeden Registrierungswert ein PSCustomObjectObjekt mit PsPath, PsParentPath, PsChildname, PSDriveund PSProviderEigenschaften und dann eine Eigenschaft für den tatsächlichen Wert. Obwohl Sie nach dem Namen des Elements gefragt haben, müssen Sie den Namen erneut verwenden, um seinen Wert zu erhalten.

Andy Arismendi
quelle
8
Hi @Andy: Warum nicht einfach (Get-ItemProperty -Path $key).ProgramFilesDirRedundanz vermeiden? Das ist für mich in Ordnung; aber sind es einige Fälle, in denen es nicht ...?
Michael Sorens
3
@msorens Siehe die Antworten von charleswj81 auf M Jeremy Carter.
Andy Arismendi
26

KEINE dieser Antworten funktioniert in Situationen, in denen der Wertname Leerzeichen, Punkte oder andere Zeichen enthält, die in PowerShell reserviert sind. In diesem Fall müssen Sie den Namen gemäß http://blog.danskingdom.com/accessing-powershell-variables-with-periods-in-the-name/ in doppelte Anführungszeichen setzen - zum Beispiel:

PS> Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7

14.0         : C:\Program Files (x86)\Microsoft Visual Studio 14.0\
12.0         : C:\Program Files (x86)\Microsoft Visual Studio 12.0\
11.0         : C:\Program Files (x86)\Microsoft Visual Studio 11.0\
15.0         : C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\V
               S7
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS
PSChildName  : VS7
PSProvider   : Microsoft.PowerShell.Core\Registry

Wenn Sie auf einen der Werte 14.0, 12.0, 11.0, 15.0 zugreifen möchten, funktioniert die Lösung aus der akzeptierten Antwort nicht - Sie erhalten keine Ausgabe:

PS> (Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7 -Name 15.0).15.0
PS>

Was funktioniert, ist das Zitieren des Wertnamens, was Sie aus Sicherheitsgründen wahrscheinlich sowieso tun sollten:

PS> (Get-ItemProperty "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7" -Name "15.0")."15.0"
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PS> 

Daher sollte die akzeptierte Antwort als solche geändert werden:

PS> $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"
PS> $value = "15.0"
PS> (Get-ItemProperty -Path $key -Name $value).$value
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PS> 

Dies funktioniert in PowerShell 2.0 bis 5.0 (obwohl Sie es wahrscheinlich Get-ItemPropertyValuein Version 5 verwenden sollten).

Ian Kemp
quelle
Um Zeit zu sparen, können Sie den Eigenschaftsnamen in eine Variable einfügen und wie folgt referenzieren:
Justin
21

Harry Martyrossian erwähnt in einem Kommentar zu seiner eigenen Antwort, dass das
Cmdlet Get-ItemPropertyValue in Powershell v5 eingeführt wurde , wodurch das Problem gelöst wird:

PS> Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion' 'ProgramFilesDir'
C:\Program Files

Alternativen für PowerShell v4- :

Hier ist ein Versuch, die Effizienz beizubehalten und gleichzeitig die Notwendigkeit der Wiederholung des Wertnamens zu beseitigen, was jedoch immer noch etwas umständlich ist:

& { (Get-ItemProperty `
      -LiteralPath HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion `
      -Name $args `
    ).$args } 'ProgramFilesDir'

Mithilfe eines Skriptblocks kann der Wertname einmal als Parameter übergeben werden, und die Parametervariable ( $args) kann dann einfach zweimal innerhalb des Blocks verwendet werden.

Alternativ kann eine einfache Hilfsfunktion die Schmerzen lindern:

function Get-RegValue([String] $KeyPath, [String] $ValueName) {
  (Get-ItemProperty -LiteralPath $KeyPath -Name $ValueName).$ValueName
}

Hinweis: Alle oben genannten Lösungen umgehen das in Ian Kemps Antwort beschriebene Problem - die Notwendigkeit, explizite Anführungszeichen für bestimmte Wertnamen zu verwenden, wenn diese als Eigenschaftsnamen verwendet werden; zB .'15.0'- weil die Wertnamen als Parameter übergeben werden und der Eigenschaftszugriff über eine Variable erfolgt ; z.B,.$ValueName


Wie für die anderen Antworten:

mklement0
quelle
6

Ich bin nicht sicher, ob dies geändert wurde oder ob es etwas mit der von Ihnen verwendeten PS-Version zu tun hat, aber anhand von Andys Beispiel kann ich den Parameter -Name entfernen und erhalte trotzdem den Wert des Registrierungselements ::

PS C:\> $key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
PS C:\> (Get-ItemProperty -Path $key).ProgramFilesDir
C:\Program Files


PS C:\> $psversiontable.psversion

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1
M Jeremy Carter
quelle
6
Dies ist und war schon immer so. An Ihrem Ansatz ist technisch nichts auszusetzen, er ist jedoch weniger effizient als die Angabe der spezifischen Eigenschaften, die zurückgegeben werden sollen. Ihre Methode fragt alle Eigenschaften ab und filtert sie dann heraus, bevor sie zurückkehrt.
Charleswj81
5
Zur Veranschaulichung sehen Sie den Unterschied in der Zeit, die die folgenden zwei PowerShell-Einzeiler measure-command{1..10|%{[void]( Get-ItemProperty HKLM:\software\microsoft\windows\currentversion\installer\Folders -Name 'C:\Windows\PCHEALTH\' )}}measure-command{1..10|%{[void]( Get-ItemProperty HKLM:\software\microsoft\windows\currentversion\installer\Folders )}}
benötigen
3

Gegeben ein Schlüssel \SQLmit zwei Eigenschaften:

Geben Sie hier die Bildbeschreibung ein

Ich würde mir den "MSSQLSERVER" mit den folgenden Fällen schnappen, in denen ich nicht sicher war, wie der Eigenschaftsname für die Punktnotation lauten würde:

$regkey_property_name = 'MSSQLSERVER'
$regkey = get-item -Path 'HKLM:\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL'
$regkey.GetValue($regkey_property_name)
Adam
quelle
2

Nun, Sie müssen hier genau sein. Soweit ich weiß, ist der Schlüssel in einer Registrierung ein "Ordner" mit Eigenschaften. Meinten Sie also den Wert einer Immobilie? Wenn ja, versuchen Sie Folgendes:

(Get-ItemProperty HKLM:\Software\Microsoft\PowerShell\1\PowerShellEngine -Name PowerShellVersion).PowerShellVersion

Zuerst erhalten wir ein Objekt, das die Eigenschaft enthält, die wir benötigen, Get-ItemPropertyund dann erhalten wir den Wert von für die Eigenschaft, die wir von diesem Objekt benötigen. Dadurch wird der Wert der Eigenschaft als Zeichenfolge zurückgegeben. Das obige Beispiel gibt Ihnen die PS-Version für "Legacy" / Compatibility-Mdoe Powershell (1.0 oder 2.0).

Frode F.
quelle
1

Der folgende Code listet alle Werte für einen bestimmten Registrierungsschlüssel auf, sortiert sie und gibt den durch Doppelpunkt (:) getrennten Wertnamen: Wertepaare zurück:

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework';

Get-Item -Path $path | Select-Object -ExpandProperty Property | Sort | % {
    $command = [String]::Format('(Get-ItemProperty -Path "{0}" -Name "{1}")."{1}"', $path, $_);
    $value = Invoke-Expression -Command $command;
    $_ + ' : ' + $value; };

So was:

DbgJITDebugLaunchSetting: 16

DbgManagedDebugger: "C: \ Windows \ system32 \ vsjitdebugger.exe" PID% d APPDOM% d EXTEXT "% s" EVTHDL% d

InstallRoot: C: \ Windows \ Microsoft.NET \ Framework \

Harry Martyrossian
quelle
Bei der Frage ging es darum, die Daten eines bestimmten Werts ohne zusätzliche Informationen abzurufen. Abgesehen davon stützt sich Ihr Code auf .NET-Methodenaufrufe, damit Dinge, die einfacher in PowerShell ausgeführt werden können, nativ ausgeführt werden können.
mklement0
1
Für PowerShell v. 5.0 und höher verwenden Sie bitte das neue Cmdlet - Get-ItemPropertyValue: $value = Get-ItemPropertyValue -Path $regKeyPath -Name $valueName;
Harry Martyrossian
1
Die Verwendung von v5 + Get-ItemPropertyValueist ein großartiger Tipp, danke. Seitdem haben Sie Ihre Antwort etwas PowerShell-ähnlicher gemacht, aber sie beantwortet immer noch eine Frage, die nicht gestellt wurde, und die Antwort, die Sie geben, ist noch lange nicht PowerShell-idiomatisch. Eine idiomatischere Version wäre : (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\.NETFramework').psobject.properties | ? Name -notlike 'PS*' | Sort-Object Name | Select-Object Name, Value. Wenn Sie nicht mehrere Anweisungen in eine Zeile einfügen möchten, gibt es keinen Grund, Anweisungen mit zu beenden ;.
mklement0
1

Sie sind sich nicht sicher, bei welcher Version diese Funktion verfügbar ist, aber Sie können so etwas verwenden, um alle Eigenschaften mehrerer untergeordneter Registrierungseinträge in einem Array zurückzugeben:

$InstalledSoftware = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object {Get-ItemProperty "Registry::$_"}

Ich habe dies nur hinzugefügt, als Google mich aus einem relevanten Grund hierher gebracht hat, und ich habe schließlich den oben genannten Einzeiler für das Ausbaggern der Registrierung gefunden.

Unbekannte Variable
quelle
0

Wenn Sie ein Objekt erstellen, erhalten Sie eine besser lesbare Ausgabe und erhalten ein Objekt mit Eigenschaften, auf die Sie zugreifen können:

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework'
$obj  = New-Object -TypeName psobject

Get-Item -Path $path | Select-Object -ExpandProperty Property | Sort | % {
$command = [String]::Format('(Get-ItemProperty -Path "{0}" -Name "{1}")."{1}"', $path, $_)
$value = Invoke-Expression -Command $command
$obj | Add-Member -MemberType NoteProperty -Name $_ -Value $value}

Write-Output $obj | fl

Beispielausgabe: InstallRoot: C: \ Windows \ Microsoft.NET \ Framework \

Und das Objekt: $ obj.InstallRoot = C: \ Windows \ Microsoft.NET \ Framework \

Die Wahrheit ist, dass dies viel komplizierter ist, als es sein muss. Hier ist ein viel besseres und viel einfacheres Beispiel:

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework'
$objReg = Get-ItemProperty -Path $path | Select -Property *

$ objReg ist jetzt ein benutzerdefiniertes Objekt, bei dem jeder Registrierungseintrag ein Eigenschaftsname ist. Sie können die formatierte Liste anzeigen über:

write-output $objReg

InstallRoot        : C:\Windows\Microsoft.NET\Framework\
DbgManagedDebugger : "C:\windows\system32\vsjitdebugger.exe"

Und Sie haben Zugriff auf das Objekt selbst:

$objReg.InstallRoot
C:\Windows\Microsoft.NET\Framework\
Steve Fellwock
quelle