1

我的程序需要能够更改机器上的 SystemDate。环顾四周后,我找到了这段代码并实现了它,但它似乎根本没有改变日期。它运行的虚拟机关闭了时间同步,所以我知道问题不在于那里。我犯了一个小错误,还是有更简单的方法来更改系统日期?

[StructLayout(LayoutKind.Sequential)]
private 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;
}

// Return Type: BOOL
[System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "SetSystemTime")]
[return:System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
private static extern bool SetSystemTime([InAttribute()] ref SYSTEMTIME lpSystemTime);



public bool SetSystemDateTime(DateTime newDateTime)
{
    bool result = false;

    try
    {
        newDateTime = newDateTime.ToUniversalTime();

        SYSTEMTIME sysTime = new SYSTEMTIME() 
            { wYear = (short)newDateTime.Year /* must be short */, 
            wMonth = (short)newDateTime.Month, 
            wDayOfWeek = (short)newDateTime.DayOfWeek, 
            wDay = (short)newDateTime.Day, 
            wHour = (short)newDateTime.Hour, 
            wMinute = (short)newDateTime.Minute, 
            wSecond = (short)newDateTime.Second, 
            wMilliseconds = (short)newDateTime.Millisecond };

        result = SetSystemTime(ref sysTime);
    }
    catch (Exception)
    {
        result = false;
    }
    return result;
}
4

2 回答 2

2

以管理员身份运行它,因为它对我有用。代码来自Pinvoke.net文档SetSystemTime,尽管我Console.Read在设置时间后添加了一个额外的代码,以便可以看到系统时间在设置回原始时间之前已经更改。

public struct SYSTEMTIME
{
   public ushort wYear, wMonth, wDayOfWeek, wDay,
          wHour, wMinute, wSecond, wMilliseconds;
}

[DllImport("kernel32.dll")]
public extern static void GetSystemTime(ref SYSTEMTIME lpSystemTime);

[DllImport("kernel32.dll")]
public extern static uint SetSystemTime(ref SYSTEMTIME lpSystemTime);

Console.WriteLine(DateTime.Now.ToString());
SYSTEMTIME st = new SYSTEMTIME();
GetSystemTime(ref st);

Console.WriteLine("Adding 1 hour...");
st.wHour = (ushort)(st.wHour + 1 % 24);
if (SetSystemTime(ref st) == 0)
    Console.WriteLine("FAILURE: SetSystemTime failed");

Console.WriteLine(DateTime.Now.ToString());
Console.Read();

Console.WriteLine("Setting time back...");
st.wHour = (ushort)(st.wHour - 1 % 24);
SetSystemTime(ref st);
Console.WriteLine(DateTime.Now.ToString());
Console.WriteLine("Press Enter to exit");
Console.Read();
于 2013-07-08T16:16:49.310 回答
1

该应用程序正在以管理员身份运行

如今,这并不意味着什么,许多用户使用管理员帐户登录 Windows。重要的是您运行此代码提升。这需要具有“requireAdministrator”属性的清单,以便用户获得 UAC 提升提示。

代码中的重大缺陷是很容易忽略函数的返回值。也没有任何办法找出它返回错误的原因。[DllImport] 有缺陷,它没有将 SetLastError 属性设置为 true。在不生成诊断的情况下捕获异常是一个坏主意,请删除它。使固定:

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetSystemTime(ref SYSTEMTIME lpSystemTime);
...
if (!SetSystemTime(ref sysTime)) {
   throw new System.ComponentModel.Win32Exception();
}
于 2013-07-08T16:37:54.593 回答