【问题标题】:How to change system date in c# [duplicate]如何在c#中更改系统日期[重复]
【发布时间】:2013-07-06 01:18:33
【问题描述】:

我的程序需要能够更改机器上的 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;
}

【问题讨论】:

  • 如果抛出异常,它说明了什么?
  • 您是否以管理员身份运行 Visual Studio?
  • @RubensMariuzzo 我不太确定,它还没有抛出异常。
  • @keyboardP 是的,我也在以管理员身份运行程序。
  • 正如@keyboardP 所说,您可能需要以管理员身份运行您的应用程序。只有管​​理员 AFAIK 才允许更改本地系统日期。

标签: c# winapi date datetime time


【解决方案1】:

以管理员身份运行它,因为它对我有用。代码来自SetSystemTimePinvoke.net 文档,尽管我在设置时间后添加了一个额外的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();

【讨论】:

  • 这段代码有效,所以我将重构我的代码以使其看起来/行为更像这个代码。谢谢。
【解决方案2】:

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

如今,这并不意味着什么,许多用户使用管理员帐户登录 Windows。重要的是您运行此代码提升。这需要带有“requireAdministrator”属性的a manifest,以便用户获得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();
}

【讨论】:

  • 如果我在清单中添加,是否会因为 Windows Server 2003 上没有 UAC 而在我的虚拟机(运行 Windows Server 2003 R2)上运行应用程序?
  • 不,它只会忽略它不理解的清单中的条目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 2019-08-28
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多