返回列表 发帖

[问题求助] PowerShell怎么调用api[已解决]

本帖最后由 czjt1234 于 2024-4-12 20:25 编辑

DosDateTimeToFileTime
https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime

FileTimeToSystemTime
https://learn.microsoft.com/zh-cn/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime

我想调用这两个api处理dos格式的时间,请问应该怎么写

QQ 20147578

dos格式时间怎么得到的呢,什么格式

TOP

本帖最后由 czjt1234 于 2024-4-12 19:35 编辑

回复 2# went


是一个64位无符号整数
比如 0x5C8A688A

纠正:32位

QQ 20147578

TOP

https://learn.microsoft.com/zh-c ... sdatetimetofiletime
根据这里按二进制逐位分析,可以得到年月日时分秒,但一来麻烦,二来秒的处理结果有问题

QQ 20147578

TOP

回复 3# czjt1234


    64位数,怎么得出MSDN里描述的wFatDate和wFatTime? API里面需要这两个参数

TOP

给出一个反向转换的示例
使用API,当前时间转MS-DOS时间
cls
$code=@'
    using System;
    using System.Runtime.InteropServices;
    public static class WinApi{
        public struct FILETIME {
            public uint dwLowDateTime;
            public uint dwHighDateTime;
        };
        public struct SYSTEMTIME {
            public short wYear;
            public short wMonth;
            public short wDayOfWeek;
            public short wDay;
            public short wHour;
            public short wMinute;
            public short wSecond;
            public short wMilliseconds;
        };
        [DllImport("kernel32.dll")]
        public static extern bool DosDateTimeToFileTime(short wFatDate, short wFatTime, ref FILETIME lpFileTime);
        [DllImport("kernel32.dll")]
        public static extern bool FileTimeToDosDateTime(ref FILETIME lpFileTime, ref short wFatDate, ref short wFatTime);
        [DllImport("kernel32.dll")]
        public static extern bool FileTimeToSystemTime(ref FILETIME lpFileTime,ref SYSTEMTIME lpSystemTime);
        [DllImport("kernel32.dll")]
        public static extern bool SystemTimeToFileTime(ref SYSTEMTIME lpSystemTime, ref FILETIME lpFileTime);
        [DllImport("kernel32.dll")]
        public static extern void GetLocalTime(ref SYSTEMTIME lpSystemTime);
    }
'@
Add-Type -TypeDefinition $code
$st_file_time = New-Object 'WinApi+FILETIME'
$st_system_time = New-Object 'WinApi+SYSTEMTIME'
$wFatDate = New-Object 'uint16'
$wFatTime = New-Object 'uint16'
[WinApi]::GetLocalTime([ref]$st_system_time)
[WinApi]::SystemTimeToFileTime([ref]$st_system_time,[ref]$st_file_time)
[WinApi]::FileTimeToDosDateTime([ref]$st_file_time,[ref]$wFatDate,[ref]$wFatTime)
'当前时间 {0:d4}/{1:d2}/{2:d2} {3:d2}:{4:d2}:{5:d2}' -f $st_system_time.wYear,$st_system_time.wMonth,$st_system_time.wDay,$st_system_time.wHour,$st_system_time.wMinute,$st_system_time.wSecond
'MS-DOS wFatDate:{0:X4} wFatTime:{1:X4}' -f $wFatDate,$wFatTimeCOPY

TOP

这个自己不能转吗

TOP

.net支持的语言(如C#)的平台调用
或者
基于反射的动态平台调用

不管那种都挺麻烦的(尤其是后者)

不如convert成字符串 , 然后截取手动解析

TOP

如果32位数0x5C8A688A高16位是wFatDate,低16位是wFatTime,使用以下代码转换
$st_file_time = New-Object 'WinApi+FILETIME'
$st_system_time = New-Object 'WinApi+SYSTEMTIME'
$ms_dos_time = 0x5C8A688A
$wFatDate = $ms_dos_time -shr 16
$wFatTime = $ms_dos_time -band 0xffff
[WinApi]::DosDateTimeToFileTime($wFatDate,$wFatTime,[ref]$st_file_time)
[WinApi]::FileTimeToSystemTime([ref]$st_file_time,[ref]$st_system_time)
'MS-DOS wFatDate:{0:X4} wFatTime:{1:X4}' -f $wFatDate,$wFatTime
'系统时间 {0:d4}/{1:d2}/{2:d2} {3:d2}:{4:d2}:{5:d2}' -f $st_system_time.wYear,$st_system_time.wMonth,$st_system_time.wDay,$st_system_time.wHour,$st_system_time.wMinute,$st_system_time.wSecondCOPY

TOP

直接转换
cls
$ms_dos_time = 0x5C8A688A
$wFatDate = $ms_dos_time -shr 16
$wFatTime = $ms_dos_time -band 0xffff
$day = $wFatDate -band 0x1f
$month = ($wFatDate -shr 5) -band 0x0f
$year = (($wFatDate -shr 9) -band 0x7f)+1980
$second = ($wFatTime -band 0x1f)*2
$minute = ($wFatTime -shr 5) -band 0x3f
$hour = ($wFatTime -shr 11) -band 0x1f
'MS-DOS wFatDate:{0:X4} wFatTime:{1:X4}' -f $wFatDate,$wFatTime
'系统时间 {0:d4}/{1:d2}/{2:d2} {3:d2}:{4:d2}:{5:d2}' -f $year,$month,$day,$hour,$minute,$secondCOPY

TOP

回复 7# terse


可以转的,年月日时分都没问题
但是秒要除以2
我就纳闷4秒和5秒怎么区分,还是就不能区分
所以想用API对比一下计算结果

QQ 20147578

TOP

本帖最后由 czjt1234 于 2024-4-12 19:49 编辑

回复 9# went

用6楼的换算
当前时间 2024/04/12 19:39:57
MS-DOS wFatDate:588C wFatTime:9CFD

但是用9楼的计算0x588C9CFD报错
无法将“DosDateTimeToFileTime”的参数“wFatTime”(其值为“40189”)转换为类型“System.Int16”:“无法将值“40189”转换为
类型“System.Int16”。错误:“值对于 Int16 太大或太小。””
所在位置 行:44 字符: 1
+ [WinApi]:osDateTimeToFileTime($wFatDate,$wFatTime,[ref]$st_file_tim ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: ( [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

QQ 20147578

TOP

回复 10# went

这个代码可以运行,不过我的纠结是秒的准确数,因为这样没有单数的秒了

还有小细节,这个时间是UTC时间,转换为系统时间要+8小时

QQ 20147578

TOP

本帖最后由 went 于 2024-4-12 20:09 编辑

回复 13# czjt1234


    上面报错需要把函数声明short改为ushort
api转换的时间也是把秒缩放的,2个相近的秒时间会生成同个ms-dos时间

TOP

回复 14# went


    非常感谢

QQ 20147578

TOP

返回列表