tags:

views:

876

answers:

5

How can I Change Local System DateTime Programatically with C# ?

+5  A: 
  1. PInvoke to call Win32 API SetSystemTime,(example)
  2. System.Management classes with WMI class Win32_OperatingSystem and call SetDateTime on that class.

Both require that the caller has been granted SeSystemTimePrivilege and that this privilege is enabled.

Avram
A: 

One of the many links found when you google "c# change system date".

Garry Shutler
Sure, but anything can be found on google, why say this ?
MarmouCorp
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
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
+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
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
writing a custom C++/CLI wrapper and introcuding another assembly is easier than writing an ~9-line struct??
Lucas
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
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
Just don't let Marc Gravell see your struct! ;-)
Si
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
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