I can't get SetSystemTime to work in Windows Vista using C# with Interop (P/Invoke)

眉间皱痕 提交于 2019-12-01 12:41:58

问题


I'm having a hard time getting SetSystemTime working in my C# code. SetSystemtime is a kernel32.dll function. I'm using P/invoke (interop) to call it. SetSystemtime returns false and the error is "Invalid Parameter". I've posted the code below. I stress that GetSystemTime works just fine. I've tested this on Vista and Windows 7. Based on some newsgroup postings I've seen I have turned off UAC. No difference. I have done some searching for this problem. I found this link: http://groups.google.com.tw/group/microsoft.public.dotnet.framework.interop/browse_thread/thread/805fa8603b00c267

where the problem is reported but no resolution seems to be found. Notice that UAC is also mentioned but I'm not sure this is the problem. Also notice that this gentleman gets no actual Win32Error.

  1. Can someone try my code on XP?
  2. Can someone tell me what I'm doing wrong and how to fix it. If the answer is to somehow change permission settings programatically, I'd need an example. I would have thought turning off UAC should cover that though.
  3. I'm not required to use this particular way (SetSystemTime). I'm just trying to introduce some "clock drift" to stress test something. If there's another way to do it, please tell me. Frankly, I'm surprised I need to use Interop to change the system time. I would have thought there is a .NET method.

Thank you very much for any help or ideas. Andrew

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace SystemTimeInteropTest
{
    class Program
    {
        #region ClockDriftSetup
        [StructLayout(LayoutKind.Sequential)]
        public struct SystemTime
        {
            [MarshalAs(UnmanagedType.U2)]
            public short Year;
            [MarshalAs(UnmanagedType.U2)]
            public short Month;
            [MarshalAs(UnmanagedType.U2)]
            public short DayOfWeek;
            [MarshalAs(UnmanagedType.U2)]
            public short Day;
            [MarshalAs(UnmanagedType.U2)]
            public short Hour;
            [MarshalAs(UnmanagedType.U2)]
            public short Minute;
            [MarshalAs(UnmanagedType.U2)]
            public short Second;
            [MarshalAs(UnmanagedType.U2)]
            public short Milliseconds;
        }

        [DllImport("kernel32.dll")]
        public static extern void GetLocalTime(
        out SystemTime systemTime);

        [DllImport("kernel32.dll")]
        public static extern void GetSystemTime(
        out SystemTime systemTime);

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

        //[DllImport("kernel32.dll", SetLastError = true)]
        //public static extern bool SetLocalTime(
        //ref SystemTime systemTime);
        [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "SetLocalTime")]
        [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
        public static extern bool SetLocalTime([InAttribute()] ref SystemTime lpSystemTime);



        #endregion ClockDriftSetup
        static void Main(string[] args)
        {
            try
            {
            SystemTime sysTime;
             GetSystemTime(out sysTime);
                sysTime.Milliseconds += (short)80;
                sysTime.Second += (short)3000;
                bool bResult = SetSystemTime(ref sysTime);

                if (bResult == false)
                    throw new System.ComponentModel.Win32Exception();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Drift Error: " + ex.Message);
            }
        }
    }
}

回答1:


There is a .Net method to set the time; it's just not available in C# by default. If you add a reference to Microsoft.VisualBasic to your project then you can just write:

Microsoft.VisualBasic.DateAndTime.TimeOfDay = DateTime.Now.AddSeconds(3000).AddMilliseconds(80);



回答2:


You can't just add 3000 to the seconds field. You need to specify a number of seconds between 0 and 60. You need to adjust the seconds, minutes, hours, etc fields so that they are all within a valid range.

Edit The simplest way would actually be to call SystemTimeToFileTime then add numSeconds * 10000 to the value it gives back, and then call FileTimeToSystemTime to convert back to a SystemTime.



来源:https://stackoverflow.com/questions/2486125/i-cant-get-setsystemtime-to-work-in-windows-vista-using-c-sharp-with-interop-p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!