How can I Change Local System DateTime Programatically with C# ?
A:
One of the many links found when you google "c# change system date".
Garry Shutler
2009-03-16 15:17:30
Sure, but anything can be found on google, why say this ?
MarmouCorp
2009-03-16 15:21:22
This is just negativity... The point of this site is to assimilate knowledge and expose it to rigorous "peer review". Sure, some blog might have an answer but this site can be a "collector" that provides an even better answer in one place than having to route around numerous Google results.
Andrew Flanagan
2009-03-16 16:19:03
Because the orignal question didn't indicate that a Google search had even been done. Why not start with "how can this approach be improved?" rather than nothing?
Dan
2009-03-16 16:41:12
+9
A:
Here is where I found the answer.
I have reposted it here to improve clarity.
Define this structure:
[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;
}
Add the following extern
method to your class:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetSystemTime(ref SYSTEMTIME st);
Then call the method with an instance of your struct like this:
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.
Andrew Hare
2009-03-16 15:17:56
This is about at the limit for a C++ struct I'd want to duplicate in C#; writing a custom wrapper in C++/CLI can be easier, even if it does introduce another assembly.
Dan
2009-03-16 15:29:23
writing a custom C++/CLI wrapper and introcuding another assembly is easier than writing an ~9-line struct??
Lucas
2009-03-16 17:50:24
A few lines for this struct, a few lines for another one; mix-in a [MarshalBy] for something slightly more complicated...C++/CLI looks even better.Plus a custom wrapper might make for a nicer API: does anybody really want to set wMillisconds? The API could take a System.DateTime argument.
Dan
2009-03-16 18:37:27
The Microsoft.VisualStudio.Shell.Interop namespace contains a definiton of the SYSTEMTIME struct; see http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.systemtime.aspx
Dan
2009-03-16 21:56:02
A:
You can use a call to a DOS command but the invoke of the function in the windows dll is a better way to do it.
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);
}
MarmouCorp
2009-03-16 15:28:20
A:
Since I mentioned it in a comment, here's a C++/CLI wrapper:
#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);
}
};
}
The C# client code is now very simple:
JDanielSmith.Utilities.SetSystemTime(DateTime.Now);
Dan
2009-03-16 22:29:55