powershell 如何转换WMI返回的该日期值

gjmwrych  于 2022-11-10  发布在  Shell
关注(0)|答案(2)|浏览(154)

我运行此PowerShell脚本以查询绑定到SQL服务器的证书:

Get-WmiObject -Namespace 'ROOT\Microsoft\SqlServer\ComputerManagement14' -Class SecurityCertificate | select name,expirationdate

它正确地将证书的主题和到期日期返回为:

name                        expirationdate
----                        --------------
servername.domain.com       31052014

但是,我不知道该日期是什么格式,因为证书将过期显示为‎Thursday, ‎August ‎17, ‎2023 2:34:27 AM
我在谷歌上搜索了一下,但没有找到返回的适当类型的日期以及如何转换为[DateTime]的结果。我如何才能理解这一点,以便我可以转换它并将其用于比较?

piah890a

piah890a1#

31052014表示日期+时间2023-08-15T19:08:23

TL;DR:运行这个交互的JS代码片段,将WMI SecurityCertificateuint32值转换为人类可读的日期时间:

1.点击下面的[显示代码片段]。
1.向下滚动到蓝色的大“运行代码片段”按钮,然后点击它。
1.然后在出现的输入框中输入数字(例如31052014),然后点击按钮进行转换。

function convertSqlServerCertificateExpirationToDateTime( value ) {

     //debugger;

      if( typeof value !== 'number' || value < 0 ) throw new Error( "Invalid `value` argument. Should be an integer number somewhere around ~30000000." );

     const epoch = new Date( /*y:*/ 1601, /*m:*/ 0, /*d:*/ 1, /*h:*/ 0, /*m:*/ 0, /*s:*/ 0, /*ms:*/ 0 ); // JS uses 0 for January instead of 1.

     const unitsPerDay   = 0.004970966;
     const days          = value * unitsPerDay;
     const secondsPerDay = 86400;
     const addSeconds    = days * secondsPerDay;

//   const secondsSinceEpoch = value * 430;

     const t = new Date( epoch.getTime() );
     t.setSeconds( t.getSeconds() + addSeconds );

     console.log( "Value %o corresponds to %o", value, t );

     return t;
 }

 function doConvert() {

     const inputValue = document.getElementById('wmiDateTime').valueAsNumber;

     console.log( 'inputValue: %o', inputValue );

     const dt = convertSqlServerCertificateExpirationToDateTime( inputValue );

     document.getElementById('output1').textContent = dt.toLocaleString();
     document.getElementById('output2').textContent = dt.toISOString();
 }
output {
    font-weight: bold;
    color: purple;
    display: block;
    margin: 1em 0; }

label { display: block; }
<fieldset>
    <legend>WMI uint32 datetime converter</legend>

    <label>
        <span>Integer value:</span>
        <input type="number" min="0" id="wmiDateTime" />
    </label>

    <div>
        <button type="button" onclick="doConvert()">Convert</button>
    </div>

    <output id="output1"></output>
    <output id="output2"></output>

</fieldset>

背景故事

这让我很感兴趣,所以我创建了一个新的自签名证书,并跳过了这些困难,使其能够与SQL Server2022一起工作。

  • 用于SQL Server 2022的SQL Server配置管理器现在可以显示到期日期(但不显示时间,而且它是本地时间,不是UTC,Gah)。
  • 但是,使用WMI CIM浏览器工具(如wmiexplorer)会显示您所描述的uint32值:

  • 我生成的证书有以下字段(如证书.msc和certutil所示):
  • NotBefore
  • 2022-10-07 18:59:44
  • 30988985
  • NotAfter
  • 2023-04-07 19:09:44
  • 31025599
  • 这两个整数值之间的差值是36614
  • 这两个日期之间的差异是182天零0小时10分钟。
  • 182d + 0h + (10/1440)m182.00694天。
  • 36614 / 182.00694 == 201.168,因此1天(即24小时)==201.168神秘单位
  • 现在让我们寻找大纪元:
  • 30988985 / 201.168 == 154,045.3
  • 30988985是纪元后的154,045天。
  • 由于309889852022-10-07 18:59:44,因此纪元是该日期+时间减去154,045.3天。
  • 时间1601-01-02 11:47:44
  • 呵呵*那个日期看起来有点眼熟……1601-01-01 00:00is the Win32 clock epoch!-所以让我们将多出来的一天归因于舍入误差。
  • 此外,182.00694 / 36614 == 0.00497
  • expirationdate中的每个增量整数值对应于0.00497天-或430秒(约)。
  • 因此转换函数(在JavaScript中)为:
function convertSqlServerCertificateExpirationToDateTime( value ) {
     if( typeof value !== 'number' || value < 0 ) throw new Error( "Invalid `value` argument. Should be an integer number somewhere around ~30000000." );

     const epoch = new Date( /*y:*/ 1601, /*m:*/ 0, /*d:*/ 1, /*h:*/ 0, /*m:*/ 0, /*s:*/ 0, /*ms:*/ 0 ); // JS uses 0 for January instead of 1.

     const unitsPerDay   = 0.004970966;
     const days          = value * unitsPerDay;
     const secondsPerDay = 86400;
     const addSeconds    = days * secondsPerDay;

     const t = new Date( epoch.getTime() );
     t.setSeconds( t.getSeconds() + addSeconds );
     return t;
}

痛苦……

PS C:\Users\Administrator> $selfSignedRootCA = New-SelfSignedCertificate -DnsName sql2022.corp.example.com -notafter (Get-Date).AddMonths(6) -CertStoreLocation Cert:\LocalMachine\My\ -KeyExportPolicy Exportable -KeyUsage CertSign,CRLSign,DigitalSignature -KeySpec KeyExchange -KeyLength 2048 -KeyUsageProperty All -KeyAlgorithm 'RSA' -HashAlgorithm 'SHA256' -Provider 'Microsoft Enhanced RSA and AES Cryptographic Provider'
  • -KeySpec KeyExchange选项非常重要
  • 使用-DnsName而不是-Subject,并使用FQDN名称。
x6h2sr28

x6h2sr282#

它看起来像64 bit win32 filetime的高32位字
下面是将其转换为正常值的示例js:

function fromHighW32(value) {
  let bv = BigInt(value);
  bv = bv << 32n;
  bv = bv - 116444736000000000n; // start of unix epoch
  bv = bv / 10000n; // convert from 100n to millis
  return new Date(parseInt(bv.toString(), 10));
}

console.log(fromHighW32(31052014).toUTCString());
console.log(fromHighW32(30988985).toUTCString());
console.log(fromHighW32(31025599).toUTCString());

尽管确切的数字与您的输出和@DAI Answer的输出略有不同,但这是因为我们没有看到低位字,所以值是+/-429.5秒(~7分钟)

相关问题