【问题标题】:Change system date programmatically以编程方式更改系统日期
【发布时间】:2010-10-13 15:28:58
【问题描述】:

如何使用 C# 以编程方式更改本地系统的日期和时间?

【问题讨论】:

  • 有趣的是,像这样的一些问题是如何得到回答的,而其他问题却是“你试过什么?” ...奇怪...

标签: c# datetime date time system


【解决方案1】:

Here is where I found the answer.;我已在此处重新发布以提高清晰度。

定义这个结构:

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

将以下extern 方法添加到您的类中:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetSystemTime(ref SYSTEMTIME st);

然后用你的结构实例调用方法,如下所示:

SYSTEMTIME st = new SYSTEMTIME();
st.wYear = 2009; // must be short
st.wMonth = 1;
st.wDay = 1;
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;

SetSystemTime(ref st); // invoke this method.

【讨论】:

  • 编写自定义 C++/CLI 包装器并引入另一个程序集比编写 ~9 行结构更容易??
  • 只是不要让 Marc Gravell 看到你的结构! ;-)
  • 由于某种原因,我对答案的编辑被拒绝了,但至少对于 Win 7,我发现我需要以管理员身份运行程序才能使其正常工作。见:stackoverflow.com/questions/2818179/…
  • 可以说这个方法设置了UTC时间。因此,如果您通过 Datetime.Now 获取本地时间,那么它将设置错误的时间。遇到这个,搞了半天不明白是什么问题……
  • 值得一提的是,该程序需要管理员权限才能运行...
【解决方案2】:

这里已经有很多很棒的观点和方法,但是这里有一些目前被遗漏的规范,我觉得它们可能会让一些人感到困惑。

  1. Windows Vista、7、8 操作系统上,这将需要一个 UAC 提示,以获得成功执行 SetSystemTime 函数所需的管理权限。原因是调用进程需要SE_SYSTEMTIME_NAME权限。
  2. SetSystemTime 函数在协调世界时 (UTC) 中期待 SYSTEMTIME 结构。否则它将无法按预期工作。

根据您获取DateTime 值的位置/方式,在设置SYSTEMTIME 结构中的相应值之前,最好谨慎行事并使用ToUniversalTime()

代码示例:

DateTime tempDateTime = GetDateTimeFromSomeService();
DateTime dateTime = tempDateTime.ToUniversalTime();

SYSTEMTIME st = new SYSTEMTIME();
// All of these must be short
st.wYear = (short)dateTime.Year;
st.wMonth = (short)dateTime.Month;
st.wDay = (short)dateTime.Day;
st.wHour = (short)dateTime.Hour;
st.wMinute = (short)dateTime.Minute;
st.wSecond = (short)dateTime.Second;

// invoke the SetSystemTime method now
SetSystemTime(ref st); 

【讨论】:

  • 我不能使用这个直接改变系统时间
  • 我已经在多个项目中成功使用了这段代码。您是否以管理员身份运行可执行文件?否则这段代码肯定行不通。
  • 哇,这个解决了我的问题。问题是您当地时间的时区妨碍了获取正确时间,因此“DateTime dateTime = tempDateTime.ToUniversalTime();”行解决了一切。
【解决方案3】:

您可以使用对 DOS 命令的调用,但在 windows dll 中调用该函数是一种更好的方法。

public struct SystemTime
{
    public ushort Year;
    public ushort Month;
    public ushort DayOfWeek;
    public ushort Day;
    public ushort Hour;
    public ushort Minute;
    public ushort Second;
    public ushort Millisecond;
};

[DllImport("kernel32.dll", EntryPoint = "GetSystemTime", SetLastError = true)]
public extern static void Win32GetSystemTime(ref SystemTime sysTime);

[DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)]
public extern static bool Win32SetSystemTime(ref SystemTime sysTime);

private void button1_Click(object sender, EventArgs e)
{
    // Set system date and time
    SystemTime updatedTime = new SystemTime();
    updatedTime.Year = (ushort)2009;
    updatedTime.Month = (ushort)3;
    updatedTime.Day = (ushort)16;
    updatedTime.Hour = (ushort)10;
    updatedTime.Minute = (ushort)0;
    updatedTime.Second = (ushort)0;
    // Call the unmanaged function that sets the new date and time instantly
    Win32SetSystemTime(ref updatedTime);
}  

【讨论】:

    【解决方案4】:

    使用此功能更改系统时间(在window 8中测试)

     void setDate(string dateInYourSystemFormat)
        {
            var proc = new System.Diagnostics.ProcessStartInfo();
            proc.UseShellExecute = true;
            proc.WorkingDirectory = @"C:\Windows\System32";
            proc.CreateNoWindow = true;
            proc.FileName = @"C:\Windows\System32\cmd.exe";
            proc.Verb = "runas";
            proc.Arguments = "/C date " + dateInYourSystemFormat;
            try
            {
                System.Diagnostics.Process.Start(proc);
            }
            catch
            {
                MessageBox.Show("Error to change time of your system");
                Application.ExitThread();
            }
        }
    void setTime(string timeInYourSystemFormat)
        {
            var proc = new System.Diagnostics.ProcessStartInfo();
            proc.UseShellExecute = true;
            proc.WorkingDirectory = @"C:\Windows\System32";
            proc.CreateNoWindow = true;
            proc.FileName = @"C:\Windows\System32\cmd.exe";
            proc.Verb = "runas";
            proc.Arguments = "/C time " + timeInYourSystemFormat;
            try
            {
                System.Diagnostics.Process.Start(proc);
            }
            catch
            {
                MessageBox.Show("Error to change time of your system");
                Application.ExitThread();
            }
        }
    

    示例: 调用表单的加载方法 setDate("5-6-92"); setTime("2:4:5 AM");

    【讨论】:

    【解决方案5】:
    1. PInvoke 调用 Win32 API SetSystemTime,(example)
    2. System.Management 类与 WMI 类 Win32_OperatingSystem 并在该类上调用 SetDateTime。

    两者都要求调用者已被授予 SeSystemTimePrivilege 并启用此权限。

    【讨论】:

      【解决方案6】:

      由于我在评论中提到过,这里是一个 C++/CLI 包装器:

      #include <windows.h>
      namespace JDanielSmith
      {
          public ref class Utilities abstract sealed /* abstract sealed = static */
          {
          public:
              CA_SUPPRESS_MESSAGE("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")
              static void SetSystemTime(System::DateTime dateTime) {
                  LARGE_INTEGER largeInteger;
                  largeInteger.QuadPart = dateTime.ToFileTimeUtc(); // "If your compiler has built-in support for 64-bit integers, use the QuadPart member to store the 64-bit integer."
      
      
                  FILETIME fileTime; // "...copy the LowPart and HighPart members [of LARGE_INTEGER] into the FILETIME structure."
                  fileTime.dwHighDateTime = largeInteger.HighPart;
                  fileTime.dwLowDateTime = largeInteger.LowPart;
      
      
                  SYSTEMTIME systemTime;
                  if (FileTimeToSystemTime(&fileTime, &systemTime))
                  {
                      if (::SetSystemTime(&systemTime))
                          return;
                  }
      
      
                  HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
                  throw System::Runtime::InteropServices::Marshal::GetExceptionForHR(hr);
              }
          };
      }
      

      C# 客户端代码现在非常简单:

      JDanielSmith.Utilities.SetSystemTime(DateTime.Now);
      

      【讨论】:

      【解决方案7】:

      为正在寻找的其他人提供的复制/粘贴课程

      using System;
      using System.ComponentModel;
      using System.Runtime.InteropServices;
      
      public static class SystemDateTime
      {
          [DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)]
          private static extern bool Win32SetSystemTime(ref SystemTime sysTime);
      
          [StructLayout(LayoutKind.Sequential)]
          public struct SystemTime
          {
              public ushort Year;
              public ushort Month;
              public ushort DayOfWeek;
              public ushort Day;
              public ushort Hour;
              public ushort Minute;
              public ushort Second;
              public ushort Millisecond;
          };
      
          public static void SetSystemDateTime(int year, int month, int day, int hour,
              int minute, int second, int millisecond)
          {
              SystemTime updatedTime = new SystemTime
              {
                  Year = (ushort) year,
                  Month = (ushort) month,
                  Day = (ushort) day,
                  Hour = (ushort) hour,
                  Minute = (ushort) minute,
                  Second = (ushort) second,
                  Millisecond = (ushort) millisecond
              };
      
              // If this returns false, then the problem is most likely that you don't have the 
              // admin privileges required to set the system clock
              if (!Win32SetSystemTime(ref updatedTime))
              {
                  throw new Win32Exception(Marshal.GetLastWin32Error());
              }
          }
      
          public static void SetSystemDateTime(DateTime dateTime)
          {
              SetSystemDateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute,
                  dateTime.Second, dateTime.Millisecond);
          }
      }
      

      【讨论】:

      • 效果很好
      【解决方案8】:

      小心! 如果您从结构中删除未使用的属性,则会设置错误的时间。我因此失去了 1 天。我认为结构的顺序很重要。

      这是正确的结构:

      public struct SystemTime
              {
                  public ushort Year;
                  public ushort Month;
                  public ushort DayOfWeek;
                  public ushort Day;
                  public ushort Hour;
                  public ushort Minute;
                  public ushort Second;
                  public ushort Millisecond;
      
              };
      

      如果您运行 SetSystemTime(),它会按预期工作。 对于测试,我将时间设置如下;

      SystemTime st = new SystemTime();
      st.Year = 2019;
      st.Month = 10;
      st.Day = 15;
      st.Hour = 10;
      st.Minute = 20;
      st.Second = 30;
      
      SetSystemTime(ref st);
      

      时间设置:15.10.2019 10:20,没关系。

      但我删除了未使用的 DayOfWeek 属性;

      public struct SystemTime
                  {
                      public ushort Year;
                      public ushort Month;
                      public ushort Day;
                      public ushort Hour;
                      public ushort Minute;
                      public ushort Second;
                      public ushort Millisecond;
      
                  };
      
      SystemTime st = new SystemTime();
          st.Year = 2019;
          st.Month = 10;
          st.Day = 15;
          st.Hour = 10;
          st.Minute = 20;
          st.Second = 30;
      
          SetSystemTime(ref st);
      

      运行相同的代码,但时间设置为:10.10.2019 20:30

      请注意 SystemTime 结构的顺序和所有字段。 优素福

      【讨论】:

      • SetSystemTime 期望具有这些确切字段的结构。如果您传递具有不同字段的结构(更少的字段,不同的顺序,不同的类型,......),它将无法工作。如果你删除了DayOfWeekSetSystemTime 仍然期望它,所以你从Day 开始的字段都被转移了,最后一个字段丢失了。
      【解决方案9】:

      proc.Arguments = "/C Date:" + dateInYourSystemFormat;

      这是工作函数:

      void setDate(string dateInYourSystemFormat)
      {
          var proc = new System.Diagnostics.ProcessStartInfo();
          proc.UseShellExecute = true;
          proc.WorkingDirectory = @"C:\Windows\System32";
          proc.CreateNoWindow = true;
          proc.FileName = @"C:\Windows\System32\cmd.exe";
          proc.Verb = "runas";
          proc.Arguments = "/C Date:" + dateInYourSystemFormat;
          try
          {
              System.Diagnostics.Process.Start(proc);
          }
          catch
          {
              MessageBox.Show("Error to change time of your system");
              Application.ExitThread();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-29
        • 2016-04-20
        • 2013-08-21
        • 1970-01-01
        • 2020-03-22
        • 2013-07-16
        • 2018-11-20
        相关资源
        最近更新 更多