如何在 PowerShell 中按上次写入时间/上次修改时间对注册表项进行排序

如何在 PowerShell 中按上次写入时间/上次修改时间对注册表项进行排序

我正在学习 PowerShell,我在 Windows 10 20H2 上使用 PSCore7.1,目前我可以这样做:

Get-ChildItem -Path "C:\" -Directory -Recurse -Depth 5 | Where-Object{$_.LastWriteTime.ToString("yyyy-MM-dd") -eq "2020-12-14"} | Sort-Object LastWriteTime

以递归方式获取指定目录(在本例中为 C:)的给定深度(在本例中为 5)内的子文件夹,然后查找在给定时间范围内(在本例中为今天或 2020 年 12 月 14 日)修改的对象,最后按时间戳对结果进行排序。

但是当我运行 get-childitem 来查看注册表时,如下所示:

Get-ChildItem -Path "HKLM:\SOFTWARE"

只有两个项目:名称和属性,没有时间戳,并且在 regedit.exe 中也没有时间戳,那么我如何才能像我上面发布的命令一样使用 PowerShell 按上次修改时间对注册表项进行排序?

编辑:我在超级用户中读到过,我可以将注册表项导出到注册表编辑器中的 txt 文件以查看它们的时间戳,虽然这很简单,但与这个问题无关,因为我想在控制台中按时间戳对注册表项进行排序。

重新编辑:

我已经运行了这个命令:

get-childitem -path "HKLM:\"  | Get-Member

结果如下:

   TypeName: Microsoft.Win32.RegistryKey

Name                      MemberType   Definition
----                      ----------   ----------
Close                     Method       void Close()
CreateSubKey              Method       Microsoft.Win32.RegistryKey CreateSubKey(string subkey), Microsoft.Win32.RegistryKey CreateSubKey(string subkey, bool writable…
DeleteSubKey              Method       void DeleteSubKey(string subkey), void DeleteSubKey(string subkey, bool throwOnMissingSubKey)
DeleteSubKeyTree          Method       void DeleteSubKeyTree(string subkey), void DeleteSubKeyTree(string subkey, bool throwOnMissingSubKey)
DeleteValue               Method       void DeleteValue(string name), void DeleteValue(string name, bool throwOnMissingValue)
Dispose                   Method       void Dispose(), void IDisposable.Dispose()
Equals                    Method       bool Equals(System.Object obj)
Flush                     Method       void Flush()
GetAccessControl          Method       System.Security.AccessControl.RegistrySecurity GetAccessControl(), System.Security.AccessControl.RegistrySecurity GetAccessCon…
GetHashCode               Method       int GetHashCode()
GetLifetimeService        Method       System.Object GetLifetimeService()
GetSubKeyNames            Method       string[] GetSubKeyNames()
GetType                   Method       type GetType()
GetValue                  Method       System.Object GetValue(string name), System.Object GetValue(string name, System.Object defaultValue), System.Object GetValue(s…
GetValueKind              Method       Microsoft.Win32.RegistryValueKind GetValueKind(string name)
GetValueNames             Method       string[] GetValueNames()
InitializeLifetimeService Method       System.Object InitializeLifetimeService()
OpenSubKey                Method       Microsoft.Win32.RegistryKey OpenSubKey(string name), Microsoft.Win32.RegistryKey OpenSubKey(string name, bool writable), Micro…
SetAccessControl          Method       void SetAccessControl(System.Security.AccessControl.RegistrySecurity registrySecurity)
SetValue                  Method       void SetValue(string name, System.Object value), void SetValue(string name, System.Object value, Microsoft.Win32.RegistryValue…
ToString                  Method       string ToString()
Property                  NoteProperty string[] Property=System.String[]
PSChildName               NoteProperty string PSChildName=BCD00000000
PSDrive                   NoteProperty PSDriveInfo PSDrive=HKLM
PSIsContainer             NoteProperty bool PSIsContainer=True
PSParentPath              NoteProperty string PSParentPath=Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE
PSPath                    NoteProperty string PSPath=Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\BCD00000000
PSProvider                NoteProperty ProviderInfo PSProvider=Microsoft.PowerShell.Core\Registry
Handle                    Property     Microsoft.Win32.SafeHandles.SafeRegistryHandle Handle {get;}
Name                      Property     string Name {get;}
SubKeyCount               Property     int SubKeyCount {get;}
ValueCount                Property     int ValueCount {get;}
View                      Property     Microsoft.Win32.RegistryView View {get;}

如您所见,没有时间戳......

引用:有没有办法查看 Windows 注册表项/值的更改日期?

证明:

Key Name:          HKEY_CLASSES_ROOT\._bsln140
Class Name:        <NO CLASS>
Last Write Time:   2020-12-11 - 14:54
Value 0
  Name:            <NO NAME>
  Type:            REG_SZ
  Data:            VisualStudio.Launcher._bsln140

答案1

不幸的是,由于 Windows 访问注册表项信息的方式,这可能会变得很复杂,但这是可能的。以下是 Dr Scripto 在 Microsoft devblog 上发布的一系列教程:

最终产品将如下所示,保存为 Add-RegKeyLastWriteTime.ps1:

#requires -version 3.0

function Add-RegKeyLastWriteTime {
[CmdletBinding()]
param(
    [Parameter(Mandatory, ParameterSetName="ByKey", Position=0, ValueFromPipeline)]
    # Registry key object returned from Get-ChildItem or Get-Item
    [Microsoft.Win32.RegistryKey] $RegistryKey,
    [Parameter(Mandatory, ParameterSetName="ByPath", Position=0)]
    # Path to a registry key
    [string] $Path
)

 begin {
    # Define the namespace (string array creates nested namespace):
    $Namespace = "HeyScriptingGuy"

    # Make sure type is loaded (this will only get loaded on first run):
    Add-Type @"
        using System;
        using System.Text;
        using System.Runtime.InteropServices;

        $($Namespace | ForEach-Object {
            "namespace $_ {"
        })
            public class advapi32 {
                [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
                public static extern Int32 RegQueryInfoKey(
                    Microsoft.Win32.SafeHandles.SafeRegistryHandle hKey,
                    StringBuilder lpClass,
                    [In, Out] ref UInt32 lpcbClass,
                    UInt32 lpReserved,
                    out UInt32 lpcSubKeys,
                    out UInt32 lpcbMaxSubKeyLen,
                    out UInt32 lpcbMaxClassLen,
                    out UInt32 lpcValues,
                    out UInt32 lpcbMaxValueNameLen,
                    out UInt32 lpcbMaxValueLen,
                    out UInt32 lpcbSecurityDescriptor,
                    out System.Runtime.InteropServices.ComTypes.FILETIME lpftLastWriteTime
                );
            }
        $($Namespace | ForEach-Object { "}" })
"@
   
    # Get a shortcut to the type:   
    $RegTools = ("{0}.advapi32" -f ($Namespace -join ".")) -as [type]
}
 process {
    switch ($PSCmdlet.ParameterSetName) {
        "ByKey" {
            # Already have the key, no more work to be done 

相关内容