.net 调用GetSystemTime/SetSystemTime时FATAlexecutionEngineer错误

.net 调用GetSystemTime/SetSystemTime时FATAlexecutionEngineer错误,.net,winapi,pinvoke,fatal-error,.net,Winapi,Pinvoke,Fatal Error,我在一个应用程序中编写了一个小的util,它使用Windows API函数GetSystemTime和SetSystemTime同步时间服务器上的时间。一切正常,但现在每次我调用Get/SetSystemTime时都会收到一个错误: 现在,由于唯一不安全的代码是对Win32函数的调用(这是不安全的吗??),它似乎不可能出现在我的代码中-这和我没有改变任何东西,因为它实际上正在工作 你知道这是怎么回事吗 Win32调用是通过以下方式进行的: public class SystemTime

我在一个应用程序中编写了一个小的util,它使用Windows API函数
GetSystemTime
SetSystemTime
同步时间服务器上的时间。一切正常,但现在每次我调用
Get/SetSystemTime
时都会收到一个错误:

现在,由于唯一不安全的代码是对Win32函数的调用(这是不安全的吗??),它似乎不可能出现在我的代码中-这和我没有改变任何东西,因为它实际上正在工作

你知道这是怎么回事吗

Win32调用是通过以下方式进行的:

public class 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;

            public static implicit operator SystemTime(DateTime dt)
            {
                SystemTime rval = new SystemTime();
                rval.Year = (ushort)dt.Year;
                rval.Month = (ushort)dt.Month;
                rval.Day = (ushort)dt.Day;
                rval.DayOfWeek = (ushort)dt.DayOfWeek;
                rval.Hour = (ushort)dt.Hour;
                rval.Minute = (ushort)dt.Minute;
                rval.Second = (ushort)dt.Second;
                rval.Millisecond = (ushort)dt.Millisecond;
                return rval;
            }

            public static implicit operator DateTime(SystemTime st)
            {
                return new DateTime(st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second, st.Millisecond);
            }
        }; 

        [DllImport("kernel32.dll", EntryPoint = "GetSystemTime")]
        public extern static void Win32GetSystemTime(ref SystemTime sysTime); 
        [DllImport("kernel32.dll", EntryPoint = "SetSystemTime")]
        public extern static bool Win32SetSystemTime(ref SystemTime sysTime);
编辑:现在同样的代码(未修改)给了我访问冲突

Attempted to read or write protected memory.  
This is often an indication that other memory is corrupt.
根据MSDN的功能,您应该使用的PInvoke签名包括:

[StructLayout(LayoutKind.Sequential)]
public class SYSTEMTIME
{
   public ushort Year;
   public ushort Month;
   public ushort DayOfWeek;
   public ushort Day;
   public ushort Hour;
   public ushort Minute;
   public ushort Second;
   public ushort Milliseconds;
}

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

[DllImport("kernel32.dll")]
public extern static uint SetSystemTime(ref SYSTEMTIME systemTime);

您使用的是不同的东西吗?

因为您将SYSTEMTIME定义为一个类,当您通过引用传递它时,实际上是在传递指向指针的指针,但在非托管端,它需要指向SYSTEMTIME结构的指针

或者将SYSTEMTIME的定义更改为结构,并像现在这样通过引用传递它。或者将其作为类保留,并将声明更改为:

[DllImport("kernel32.dll")]
static extern void GetSystemTime([Out] SYSTEMTIME systemTime);

[DllImport("kernel32.dll")]
public extern static uint SetSystemTime([In] SYSTEMTIME systemTime);

就我个人而言,我会将其更改为struct

您使用的GetSystemTime的p/Invoke签名是什么?请注意,通常使用中的p/Invoke定义是最好的选择。(至少作为一个起点。)编辑了我的原始问题,包括我正在使用的代码。Aaron:有两件事:(a)方法名不是以Win32开头的,并且(b)
SetSystemTime
返回一个
uint
,而不是
bool
。在这里返回类型是否重要?它被解释为一个布尔不?我实际上忽略了代码中的返回值。。。?此外,我用前缀“Win32”为所有Win32调用别名。如果您为函数指定dll入口点,这没有什么区别,正如我上面所说的……更改返回类型没有任何效果,但是我尝试了。我发现Win32前缀有助于在代码中分散时识别它们;-)@亚伦:我不知道。谢谢你提到它。我会试试这个,但它没有解释3种与未更改代码完全不同的行为-1)工作正常,2)FataException,然后3)AccessViolation??肯定还有其他事情在发生…?当访问指向指针的指针时,系统将尝试在指向的位置读取或写入。这将是受保护的内存,在这种情况下,您将获得访问冲突,或者它可能会损坏.Net运行时使用的内存,在这种情况下,您将获得FatalExecutionEngineError,或者更糟糕的是,它可能会默默地损坏您将在以后不知不觉中使用的值,这一切都取决于前4(或8)中的内容SystemTime结构的字节数。至于它以前的工作情况,我想你一定改变了一些东西,因为正如我写的那样,它永远不会正常工作。
[DllImport("kernel32.dll")]
static extern void GetSystemTime([Out] SYSTEMTIME systemTime);

[DllImport("kernel32.dll")]
public extern static uint SetSystemTime([In] SYSTEMTIME systemTime);