2011-03-14 48 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

相關問題