将十六进制字符串转换为日期时间时遇到困难

本文关键字:遇到 时间 日期 十六进制 字符串 转换 | 更新日期: 2023-09-27 18:34:50

我正在尝试将通过其他应用程序提供的一些十六进制字符串转换为正确的日期时间值,但是无论我尝试什么,该值总是错误的。 十六进制字符串来自多个系统的 ShutdownTime 注册表项,在读取时由不同的应用程序转换为十六进制。

这是我尝试过的代码:

$shutdownkey = Get-ItemProperty -Path 'HKLM:'SYSTEM'CurrentControlSet'Control'Windows'' -Name ShutdownTime
$bitconverted = [DateTime]::FromFileTime([System.BitConverter]::ToInt64($shutdownkey.ShutdownTime, 0))
$hextime = "C11E6DF46024D101"
$test = [DateTime]::FromFileTime([Convert]::ToInt64($hextime, 16))

因此,例如,当我使用自己的 ShutdownTime 键时,前两行正常工作,但当我使用最后两行或以下任何一项时:

C9520B970A69D101

0A44A6EA3300D101

C11E6DF46024D101

它要么失败,要么给我一个不可能的时间戳。 但是,如果我使用像DCode这样的工具,它会成功地将其转换为"Windows:64位十六进制值 - 小端序"的解码格式。 从我在几个地方阅读的内容来看,.NET 使用的小端序,所以这应该不是编码的问题,但我怀疑它是。

谁能帮我弄清楚如何解决这个转换问题? 这让我很困扰,为什么我无法弄清楚这一点。

将十六进制字符串转换为日期时间时遇到困难

字节序是落后的。时代应该颠倒过来。例如:

C9520B970A69D101 should be 01D1690A970B52C9 
[DateTime]::FromFileTime(0x01D1690A970B52C9) gives (Tuesday, February 16, 2016 4:37:17 PM)

有时十六进制字符串日期可以是Unix时间戳,UTC时间戳等。这里有一些快速转换可以尝试。

$hexValue =0x61D75331
[datetimeoffset]::FromUnixTimeSeconds([Convert]::ToInt64($hexValue)).datetime
[datetime]::FromFileTime([Convert]::ToInt64($hexValue))
[datetime]::FromFileTimeUtc([Convert]::ToInt64($hexValue))
[datetime]::FromBinary([Convert]::ToInt64($hexValue))

January 6, 2022 20:38:09 #was what I needed
December 31, 1600 19:02:44
January 1, 1601 00:02:44
January 1, 0001 00:02:44

从读取寄存器值并转换为日期大卫·布拉班特评论

$regKey = Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE'System'CurrentControlSet'Control'Windows
$shutDown = $regKey.ShutdownTime
$Int64Value = [System.BitConverter]::ToInt64($shutDown, 0)
$date = [DateTime]::FromFileTime($Int64Value)
$date

和我的扩展

并非所有注册表项都直接转换为日期时间。有些数组是复合的。

压缩功能

function GetRegDate ($path, $key){
    function GVl ($ar){
        return [uint32]('0x'+(($ar|ForEach-Object ToString X2) -join ''))
    }
    $ar=Get-ItemPropertyValue $path $key
    [array]::reverse($ar)
    $time = New-Object DateTime (GVl $ar[14..15]),(GVl $ar[12..13]),(GVl $ar[8..9]),(GVl $ar[6..7]),(GVl $ar[4..5]),(GVl $ar[2..3]),(GVl $ar[0..1])
    return $time
}
$path='HKLM:'SOFTWARE'Microsoft'Windows NT'CurrentVersion'NetworkList'Profiles'{6CB1FEAE-02B2-4922-8D81-331219215E21}'
$key='DateLastConnected'
$DateLastConnected=GetRegDate $path $key
Get-Date $DateLastConnected -Format "ddd, dd.MM.yyyy HH:mm:ss,fff"

原始功能

# http://cfed-ttf.blogspot.com/2009/08/decoding-datecreated-and.html
$path='HKLM:'SOFTWARE'Microsoft'Windows NT'CurrentVersion'NetworkList'Profiles'{6CB1FEAE-02B2-4922-8D81-331219215E21}'
$key='DateLastConnected'
$dateArr=Get-ItemPropertyValue $path $key
[array]::reverse($dateArr)
$chank = '0x'+(($dateArr[0..1]|ForEach-Object ToString X2) -join '')
$mSeconds = [uint32]$chank
$chank = '0x'+(($dateArr[2..3]|ForEach-Object ToString X2) -join '')
$Seconds = [uint32]$chank
$chank = '0x'+(($dateArr[4..5]|ForEach-Object ToString X2) -join '')
$minutes = [uint32]$chank
$chank = '0x'+(($dateArr[6..7]|ForEach-Object ToString X2) -join '')
$hour = [uint32]$chank
$chank = '0x'+(($dateArr[8..9]|ForEach-Object ToString X2) -join '')
$date = [uint32]$chank
$chank = '0x'+(($dateArr[10..11]|ForEach-Object ToString X2) -join '')
$Weekday =[uint32]$chank
$WeekdayLong = (Get-UICulture).DateTimeFormat.GetDayName([uint32]$Weekday)
$chank = '0x'+(($dateArr[12..13]|ForEach-Object ToString X2) -join '')
$Month = [uint32]$chank
$LongMonth = (Get-UICulture).DateTimeFormat.GetMonthName([uint32]$Month)
$chank = '0x'+(($dateArr[14..15]|ForEach-Object ToString X2) -join '')
$Year = [uint32]$chank
$time = New-Object DateTime $Year, $Month, $date, $hour, $minutes, $Seconds, $mSeconds
Get-Date $time -Format "ddd, dd.MM.yyyy HH:mm:ss,fff"