【问题标题】:Is there a way to verify if the User's time and date is correct in microsoft access vba?有没有办法验证用户的时间和日期在 microsoft access vba 中是否正确?
【发布时间】:2021-06-27 09:17:37
【问题描述】:

我正在创建一个数据库,它会根据用户的当前日期自动更新所有信息。
但是有一个问题,这意味着如果用户设置了错误的日期,则意味着整个系统都受到了威胁。我想到的唯一解决方案是获取用户的区域设置和用户的时区,并使用它来确定时间和日期是否错误,这样数据库就不会更新。但到目前为止,我发现没有办法使用 microsoft access 获取用户的时区和区域设置。有人能帮助我吗? 我发现没有任何功能或方法可以在 Access 中获取用户的这些设置。我最接近的是 Application.LanguageSettings 。我真的迷路了。

【问题讨论】:

  • 这里有问题。所有用户的“用户当前日期”必须相同。所以没有“用户当前日期”,只有一个“当前日期”。
  • 但是如果当前用户的系统日期和时间可以不同,那么你需要both下面的解决方案来检查:get UTC to check against the系统并使用时区信息将任何本地时间调整为 UTC。 UTC 是时间的黄金标准。
  • 它不会添加任何真实信息来检查机器的当前时区,因为用户可以轻松调整。
  • 哇。确实有效。我只是使用 wscript.shell 来检查时区。该软件只需要与一个用户一起使用。所以如果时区设置不正确,它应该提示用户并且只以读取模式打开软件。够酷吗?

标签: vba database datetime ms-access ms-access-2016


【解决方案1】:

您可以从远程 API 检索 UTC 时间:

' Retrieves the current UTC date and time from a remote source.
' Split seconds (milliseconds) are rounded to the second like VBA.Now does.
'
' Documentation:
'   http://worldtimeapi.org/
'
' 2018-09-11. Gustav Brock. Cactus Data ApS, CPH.
'
Public Function DateUtcNow() As Date

    ' ServiceUrl for time service.
    Const ServiceUrl        As String = "http://worldtimeapi.org/api/timezone/etc/utc.txt"
    
    ' Fixed constants.
    Const Async             As Boolean = False
    Const StatusOk          As Integer = 200
    Const UtcSeparator      As String = "datetime: "
    Const IsoSeparator      As String = "T"
    
    ' Engine to communicate with the service.
    Dim XmlHttp             As XMLHTTP60
    
    Dim ResponseText        As String
    Dim UtcTimePart         As String
    Dim DateTimePart        As String
    Dim SplitSeconds        As Double
    Dim CurrentUtcTime      As Date
  
    On Error GoTo Err_DateUtcNow
    
    Set XmlHttp = New XMLHTTP60
    
    XmlHttp.Open "GET", ServiceUrl, Async

    XmlHttp.send

    ResponseText = XmlHttp.ResponseText
    If XmlHttp.status = StatusOk Then
        UtcTimePart = Split(ResponseText, UtcSeparator)(1)
        DateTimePart = Replace(Left(UtcTimePart, 19), IsoSeparator, " ")
        SplitSeconds = Val(Mid(UtcTimePart, 20, 7))
        CurrentUtcTime = DateAdd("s", SplitSeconds + 0.5, CDate(DateTimePart))
    End If
    
    DateUtcNow = CurrentUtcTime

Exit_DateUtcNow:
    Set XmlHttp = Nothing
    Exit Function

Err_DateUtcNow:
    MsgBox "Error" & Str(Err.Number) & ": " & Err.Description, vbCritical + vbOKOnly, "Web Service Error"
    Resume Exit_DateUtcNow

End Function

然后检查Now() 的日期/时间是否在此之后的 +/- 12 小时内。

这需要引用Microsoft XML, v6.0

【讨论】:

    【解决方案2】:

    您可以从注册表中读取区域设置。

    VBA中从注册表读取的方式有很多,我比较喜欢用WScript.Shell,但也有人用WinAPI(比较复杂,但是可以屏蔽WScript.Shell)

    CreateObject("WScript.Shell").RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\TimeZoneKeyName")
    

    更详细的时区信息,可以使用WinAPI。

    Public Type SYSTEMTIME
        wYear As Integer
        wMonth As Integer
        wDayOfWeek As Integer
        wDay As Integer
        wHour As Integer
        wMinute As Integer
        wSecond As Integer
        wMilliseconds As Integer
    End Type
    
    
    Public Type TIME_ZONE_INFORMATION
        Bias As Long
        StandardName(64) As Byte
        StandardDate As SYSTEMTIME
        StandardBias As Long
        DaylightName(64) As Byte
        DaylightDate As SYSTEMTIME
        DaylightBias As Long
    End Type
    
    Const TIME_ZONE_ID_STANDARD = 1
    Const TIME_ZONE_ID_DAYLIGHT = 2
    
    Public Declare PtrSafe Function GetTimeZoneInformation Lib "Kernel32.dll" (ByRef lpTimezoneInformation As TIME_ZONE_INFORMATION) As Long
    
    Public Function GetBiasInHours() As Long
        Dim tzi As TIME_ZONE_INFORMATION
        Dim IsDST As Long
        IsDST = GetTimeZoneInformation(tzi)
        Dim Bias As Long
        If IsDST = TIME_ZONE_ID_DAYLIGHT Then
            Bias = tzi.DaylightBias / 60
        Else
            Bias = tzi.Bias / 60
        End If
        GetBiasInHours = Bias
    End Function
    

    偏差可用于计算时间到 UTC 时间。 the documentation on the type 中描述了如何进行这些计算。当然,您也可以使用 StandardName 和 DaylightName 来检查时区是否按预期设置。您可以使用以下代码将它们转换为字符串:

    Dim StandardNameString As String
    StandardNameString = tzi.StandardName
    StandardNameString = Left(StandardNameString, InStr(StandardNameString & vbNullChar, vbNullChar) - 1)
    

    【讨论】:

    • 天啊!我什至不知道这甚至一开始就存在。我什至不理解你放在那里的一半 WinAPI 代码。我唯一可以使用的真正有效的是 "WScript.Shell" 。非常感谢你!但我希望我能理解 WinAPI 是如何工作的。你是怎么做到这一点的?老实说,这真是太神奇了。太谢谢你了!!!
    • 不幸的是,学习 WinAPI 很困难。如果你有 C 的背景或开始学习 C,它会很有帮助,因为 WinAPI 是 VBA 可以调用的 C API。如果你会写 C,并且知道 VBA 类型如何转换为 C 类型,那并不难,但这些必要条件都非常具有挑战性。
    猜你喜欢
    • 2019-04-10
    • 2016-07-29
    • 1970-01-01
    • 2012-08-13
    • 2011-11-07
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多