我无法使用 C# 和 Interop (P/Invoke) 让 SetSystemTime 在 Windows Vista 中工作

发布于 2024-08-25 13:16:44 字数 3301 浏览 2 评论 0原文

我很难让 SetSystemTime 在我的 C# 代码中工作。 SetSystemtime 是一个 kernel32.dll 函数。我使用 P/invoke(互操作)来调用它。 SetSystemtime 返回 false,错误为“无效参数”。我已经发布了下面的代码。我强调 GetSystemTime 工作得很好。我已经在 Vista 和 Windows 7 上对此进行了测试。根据我看到的一些新闻组帖子,我已经关闭了 UAC。没有区别。我已经做了一些搜索这个问题。我找到了这个链接: http://groups.google。 com.tw/group/microsoft.public.dotnet.framework.interop/browse_thread/thread/805fa8603b00c267

报告了问题,但似乎没有找到解决方案。请注意,还提到了 UAC,但我不确定这就是问题所在。另请注意,这位先生没有得到实际的 Win32Error。

  1. 有人可以在 XP 上试试我的代码吗?
  2. 有人可以告诉我我做错了什么以及如何解决它。如果答案是以某种方式以编程方式更改权限设置,我需要一个示例。我本以为关闭 UAC 应该可以解决这个问题。
  3. 我不需要使用这种特殊的方式(SetSystemTime)。我只是想引入一些“时钟漂移”来对某些东西进行压力测试。如果还有其他方法可以做到,请告诉我。坦率地说,我很惊讶我需要使用 Interop 来更改系统时间。我本以为有一个 .NET 方法。

非常感谢您的任何帮助或想法。 安德鲁

代码:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

她如夕阳 2024-09-01 13:16:44

.Net有一个设置时间的方法;它只是默认在 C# 中不可用。如果您将 Microsoft.VisualBasic 的引用添加到您的项目中,那么您可以编写:

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

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);
掩饰不了的爱 2024-09-01 13:16:44

您不能只在秒字段中添加 3000。您需要指定 0 到 60 之间的秒数。您需要调整秒、分钟、小时等字段,使它们都在有效范围内。

编辑
最简单的方法实际上是调用 SystemTimeToFileTime 然后将 numSeconds * 10000 添加到它返回的值中,然后调用 FileTimeToSystemTime 转换回系统时间。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文