Назначьте время последней записи/изменения ключа реестра рекурсивно с помощью PowerShell.

Ключ реестра Windows можно просмотреть, экспортировав его в формате TXT с помощью редактора реестра:

      Key Name:          HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Audio
Class Name:        <NO NAME>
Last Write Time:   16.5.22 - 14:05
Value 0
  Name:            EnableCaptureMonitor
  Type:            REG_DWORD
  Data:            0x1

Поскольку в PowerShell нет встроенных свойств для ключей (на момент$psversiontable.psversion5), нужно использовать (любезно собранные @Cpt.Whale из статей Dr Scripto 1, 2, , 34оригинальные сценарии ) для получения значения:

      #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 
        }
        "ByPath" {
            # We need a RegistryKey object (Get-Item should return that)
            $Item = Get-Item -Path $Path -ErrorAction Stop
 
            # Make sure this is of type [Microsoft.Win32.RegistryKey]
            if ($Item -isnot [Microsoft.Win32.RegistryKey]) {
                throw "'$Path' is not a path to a registry key!"
            }
            $RegistryKey = $Item
        }
    }
 
    # Initialize variables that will be populated:
    $ClassLength = 255 # Buffer size (class name is rarely used, and when it is, I've never seen
                        # it more than 8 characters. Buffer can be increased here, though.
    $ClassName = New-Object System.Text.StringBuilder $ClassLength  # Will hold the class name
    $LastWriteTime = New-Object System.Runtime.InteropServices.ComTypes.FILETIME 
           
    switch ($RegTools::RegQueryInfoKey($RegistryKey.Handle,
        $ClassName,
        [ref] $ClassLength,
        $null,  # Reserved
        [ref] $null, # SubKeyCount
        [ref] $null, # MaxSubKeyNameLength
        [ref] $null, # MaxClassLength
        [ref] $null, # ValueCount
        [ref] $null, # MaxValueNameLength
        [ref] $null, # MaxValueValueLength
        [ref] $null, # SecurityDescriptorSize
        [ref] $LastWriteTime
    )) {
         0 { # Success
            # Convert to DateTime object:
            $UnsignedLow = [System.BitConverter]::ToUInt32([System.BitConverter]::GetBytes($LastWriteTime.dwLowDateTime), 0)
            $UnsignedHigh = [System.BitConverter]::ToUInt32([System.BitConverter]::GetBytes($LastWriteTime.dwHighDateTime), 0)
            # Shift high part so it is most significant 32 bits, then copy low part into 64-bit int:
            $FileTimeInt64 = ([Int64] $UnsignedHigh -shl 32) -bor $UnsignedLow
            # Create datetime object
            $LastWriteTime = [datetime]::FromFileTime($FileTimeInt64)
 
            # Add properties to object and output them to pipeline
            $RegistryKey | Add-Member -NotePropertyMembers @{
                LastWriteTime = $LastWriteTime
                ClassName = $ClassName.ToString()
            } -PassThru -Force
        }
        122  { # ERROR_INSUFFICIENT_BUFFER (0x7a)
            throw "Class name buffer too small"
            # function could be recalled with a larger buffer, but for
            # now, just exit
        }
        default {
            throw "Unknown error encountered (error code $_)"
        }
    }
}
}

Пример использования Add-RegKeyLastWriteTime.ps1:

      Get-ChildItem HKCU:\ | Add-RegKeyLastWriteTime | Select Name,LastWriteTime
'
Name                                                         LastWriteTime         
----                                                         -------------         
HKEY_CURRENT_USER\AppEvents                                  7/6/2020 8:56:11 AM   
HKEY_CURRENT_USER\Console                                    7/6/2020 8:56:11 AM   
HKEY_CURRENT_USER\Control Panel                              7/6/2020 1:04:53 PM  
' 

Я хотел бы установитьLastWriteTimeсвойство ко всем ключам рекурсивно (т. е.2020/01/01 00:00:00 UTCна офлайн-изображении). Возможно ли этого добиться, используяAdd-RegKeyLastWriteTime.ps1методы?

PS Есть скрипт AutoIt SetRegTime , который делает это в Windows 7, но рекурсия не работает в Windows 10 (проверено в версиях 1607, 1809, 21H2 какTrustedInstaller,SystemиAdministratorучетные записи, так что это не проблема с разрешениями), а разработчик Йоаким Шихт, похоже, больше не активен. Если существует другое программное решение, которое может рекурсивно устанавливать время последней записи для ключей реестра Windows, дайте мне знать, поскольку я не смог его найти.

0 ответов

Другие вопросы по тегам