如何使用C#编程更改本地系统的日期和时间?
这里是我找到答案的地方。我在这里重新发布它以提高阅读清晰度。
定义这个结构:
[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.
这里已经有很多好的观点和方法,但是有一些规范目前被忽略了,我感到这可能会使一些人出现问题并感到困惑。
SetSystemTime
函数,需要UAC提示框以获取必要的管理员权限。原因在于调用进程需要SE_SYSTEMTIME_NAME特权。SetSystemTime
函数期望以协调世界时(UTC)为基础的SYSTEMTIME
结构。否则它将无法按预期工作。根据你从哪里/如何获得你的DateTime
值,最好在设置相应值之前使用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);
你可以使用调用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);
}
使用此函数更改系统时间(在Windows 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();
}
}
例子: 在表单的load方法中调用 设置日期为"92年5月6日" 设置时间为"上午2点4分5秒"
两者都要求调用者已被授予SeSystemTimePrivilege权限并启用此权限。
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);
}
}
因为我在评论中提到了它,这里有一个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);
请注意!如果您从结构中删除未使用的属性,则会设置错误的时间。我因此失去了一天。我认为结构的顺序很重要。
这是正确的结构:
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;
};
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);
时间设置为:2019年10月15日 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);
运行相同的代码,但将时间设置为:2019年10月10日20:30
请注意SystemTime结构的顺序和所有字段。
Yusuf
SetSystemTime
函数需要一个具有精确字段的结构体。如果您传递一个具有不同字段的结构体(少字段,顺序不同,类型不同等),它将无法正常工作。如果您删除 DayOfWeek
字段,则 SetSystemTime
仍然期望该字段存在,因此从 Day
开始的字段都会被移位,最后一个字段也会丢失。 - user276648另一个选项(受this answer启发)是引用Microsoft.VisualBasic
程序集:
public bool isTimeCorrected;
public string errorMessage;
public void SetLocalClock(DateTime newLocalTime)
{
try
{
Microsoft.VisualBasic.DateAndTime.TimeOfDay = newLocalTime;
Microsoft.VisualBasic.DateAndTime.Today = newLocalTime;
isTimeCorrected = true;
}
catch (Exception e)
{
errorMessage = e.Message;
isTimeCorrected = false;
}
}
Microsoft.VisualBasic
的引用。<Reference Include="Microsoft.VisualBasic" />
proc.Arguments = "/C 日期:" + 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();
}
}