开发者

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

开发者 https://www.devze.com 2022-12-24 03:26 出处:网络
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 \"In

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)]
        //publ开发者_如何学编程ic 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);
            }
        }
    }
}


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);


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号