2011-03-14 19 views
0

我已经在一个应用程序中编写了一个小实用程序,它将时间服务器与使用Windows API函数GetSystemTimeSetSystemTime的时间服务器进行同步。这是所有工作正常,但现在我每次打电话Get/SetSystemTime时候,我得到一个错误:调用GetSystemTime/SetSystemTime时发生FatalExecutionEngineError

FatalExecutionEngineError was detected 
Message: 
The runtime has encountered a fatal error. 
The address of the error was at 0x792bee10, on thread 0x48c. 
The error code is 0xc0000005. This error may be a bug in the CLR 
or in the unsafe or non-verifiable portions of user code. 
Common sources of this bug include user marshaling errors for COM-interop 
or PInvoke, which may corrupt the stack. 

现在,作为唯一的不安全的代码是对Win32函数的调用(是,即使是不安全的?)好像它不能在我的代码 - 这并没有改变anythig,因为它实际上正在工作...

任何想法可能会发生什么吗?

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

编辑:

Win32的调用都是使用由现在非常相同的代码(未修改)是给我一个AccessViolation ???

Attempted to read or write protected memory. 
This is often an indication that other memory is corrupt. 
+0

您使用GetSystemTime的P/Invoke签名? – Mormegil 2011-03-14 10:53:41

+0

请注意,通常使用http://pinvoke.net/中的P/Invoke定义是最好的选择。 (至少作为一个起点。) – Mormegil 2011-03-18 23:44:53

回答

1

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

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

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

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

个人而言,我会将其更改为结构体。

+0

我会尝试这个,但它不解释3完全不同的行为从不变的代码-1)工作正常,然后2)FataException然后3)AccessViolation?肯定还有更多... ...? – 2011-03-17 03:30:14

+0

访问指针指针时,系统将尝试在指向的位置读取或写入数据。这可能是受保护的内存,在这种情况下,您将得到一个AccessViolation,或者它可能会损坏.Net运行时使用的内存,在这种情况下,您将得到一个FatalExecutionEngineError,或者甚至更糟糕,它可能会默默地损坏一个值在不知不觉中使用后,这一切都取决于SystemTime结构的前4个(或8个)字节中的内容。至于它以前的工作,我认为你必须改变一些东西,因为如果书面它不应该正常工作。 – 2011-03-17 16:07:25

1

基于从MSDN的功能thesignatures,该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); 

您是否使用不同的东西?

+0

编辑我的原始问题,包括我使用的代码。认为它是无关紧要的,因为它之前工作正常。 – 2011-03-15 06:26:05

+0

@Aaron:有两件事:(a)方法名不以'Win32'开始,(b)'SetSystemTime'返回一个'uint',而不是'bool'。 – Jon 2011-03-15 08:48:13

+0

这里应该返回类型的问题吗?它被解释为一个布尔没有?而且我实际上忽略了代码中的返回值......?另外,我使用前缀'Win32'来替代我所有的Win32调用。它没有区别,如果你指定的dll入口点的功能,因为我有上面... – 2011-03-15 22:12:08

相关问题