Search code examples
c#timesystemtime

Change system time programmaticaly using datetimepeaker


I am trying to change system date and time using the following C# code. But the result is no change is occuring in systemdate(no error is thrown either). I tried by uncommenting the commented portion of the code too. But no effect. :( Afterward I tried to change time from command prompt.(not using c#) Then it showed "A required privilage is not held by the client." I know this message may not have any connection with the code, but I am adding it to make my situation clearer.

   [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;
     }
    /*
            [DllImport("kernel32.dll", EntryPoint = "GetSystemTime", SetLastError = true)]
            [return: MarshalAsAttribute(UnmanagedType.Bool)]
            public static extern bool Win32GetSystemTime([InAttribute]ref Systemtime sysTime);
     */
    [DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)]
    [return: MarshalAsAttribute(UnmanagedType.Bool)]
    public static extern bool Win32SetSystemTime([InAttribute]ref Systemtime sysTime);

    private void DateTimeSelectedButton_Click(object sender, EventArgs e)
    {
        //var neededtime = MonthChangePhenomenonDateTimePicker.Value - TimeSpan.FromHours(5)-TimeSpan.FromMinutes(30);
        // Set system date and time

        Systemtime updatedTime = new Systemtime();
        updatedTime.Year = (ushort)MonthChangePhenomenonDateTimePicker.Value.Year;
        updatedTime.Month = (ushort)MonthChangePhenomenonDateTimePicker.Value.Month;
        updatedTime.Day = (ushort)MonthChangePhenomenonDateTimePicker.Value.Day;

        // UTC time; it will be modified according to the regional settings of the target computer so the actual hour might differ
        updatedTime.Hour = (ushort)MonthChangePhenomenonDateTimePicker.Value.Hour;
        updatedTime.Minute = (ushort)MonthChangePhenomenonDateTimePicker.Value.Minute;
        updatedTime.Second = (ushort)MonthChangePhenomenonDateTimePicker.Value.Second;
        // Call the unmanaged function that sets the new date and time instantly
        Win32SetSystemTime(ref updatedTime);

        MessageBox.Show(@"You Have Current System Time: " + updatedTime);
    }

Please help me to know what is going wrong. Thanks in advance. :)


Solution

  • Hereafter is a C# Console Application to raise the SE_SYSTEMTIME_NAME based on the post "C# – How to enable SeDebugPrivilege?" of Tri Nguyen's Blog and tested on my Windows 7 64bits Laptop. Please don't forget to post a comment on this blog.

    using System;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern IntPtr GetCurrentProcess();
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern bool CloseHandle(IntPtr hHandle);
    
            [StructLayout(LayoutKind.Sequential)]
            public struct LUID
            {
                public UInt32 LowPart;
                public Int32 HighPart;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct TOKEN_PRIVILEGES
            {
                public UInt32 PrivilegeCount;
                public LUID Luid;
                public UInt32 Attributes;
            }
    
            [DllImport("advapi32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool OpenProcessToken(IntPtr ProcessHandle,
                UInt32 DesiredAccess, out IntPtr TokenHandle);
    
            [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool LookupPrivilegeValue(string lpSystemName, string lpName,
                out LUID lpLuid);
    
            // Use this signature if you do not want the previous state
            [DllImport("advapi32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
               [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
               ref TOKEN_PRIVILEGES NewState,
               UInt32 Zero,
               IntPtr Null1,
               IntPtr Null2);
    
            private static uint TOKEN_QUERY = 0x0008;
            private static uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
    
            public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
    
            public const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege";
    
            static void Main(string[] args)
            {
                IntPtr hToken;
                string sSEPrivilegeName = SE_SYSTEMTIME_NAME;
                LUID luidSEPrivilegeNameValue;
                TOKEN_PRIVILEGES tkpPrivileges;
    
                if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken))
                {
                    Console.WriteLine("OpenProcessToken() failed, error = {0}. {1} is not available", Marshal.GetLastWin32Error(), sSEPrivilegeName);
                    return;
                }
                else
                {
                    Console.WriteLine("OpenProcessToken() successfully");
                }
    
                if (!LookupPrivilegeValue(null, SE_SYSTEMTIME_NAME, out luidSEPrivilegeNameValue))
                {
                    Console.WriteLine("LookupPrivilegeValue() failed, error = {0}. {1} is not available", Marshal.GetLastWin32Error(), sSEPrivilegeName);
                    CloseHandle(hToken);
                    return;
                }
                else
                {
                    Console.WriteLine("LookupPrivilegeValue() successfully");
                }
    
                tkpPrivileges.PrivilegeCount = 1;
                tkpPrivileges.Luid = luidSEPrivilegeNameValue;
                tkpPrivileges.Attributes = SE_PRIVILEGE_ENABLED;
    
                if (!AdjustTokenPrivileges(hToken, false, ref tkpPrivileges, 0, IntPtr.Zero, IntPtr.Zero))
                {
                    Console.WriteLine("LookupPrivilegeValue() failed, error = {0}. {1} is not available", Marshal.GetLastWin32Error(), sSEPrivilegeName);
                }
                else
                {
                    Console.WriteLine("{0} is now available", sSEPrivilegeName);
                }
                CloseHandle(hToken);
                Console.ReadLine();
            }
        }
    }