2010-03-21 44 views
0

我很難讓SetSystemTime在我的C#代碼中工作。 SetSystemtime是一個kernel32.dll函數。我使用P/invoke(interop)來調用它。 SetSystemtime返回false,錯誤是「Invalid Parameter」。我已經發布了下面的代碼。我強調GetSystemTime工作得很好。我已經在Vista和Windows 7上測試過了。基於我看到的一些新聞組帖子,我已經關閉了UAC。沒有不同。我已經做了一些搜索這個問題。我發現這個鏈接: http://groups.google.com.tw/group/microsoft.public.dotnet.framework.interop/browse_thread/thread/805fa8603b00c267我無法使SetSystemTime在Windows Vista中使用C#與Interop(P/Invoke)工作

問題被報告,但似乎沒有發現解決方案。請注意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); 
      } 
     } 
    } 
} 
+0

有一個小竅門,你可以使用編輯器中的101010按鈕格式化塊的代碼。 – itowlson 2010-03-21 06:04:48

+0

還有一個新手跟進問題。在成功推進時鐘之後的某個時刻(請參閱Gabe對如何執行此操作的響應),時鐘恢復到正確的時間。我仍在收集數據,等待這樣做的等待時間,但我的猜測是,它在某種程度上通過網絡或其他方式進行更新。任何人都知道是否有Windows程序/服務正在這樣做?有沒有辦法將其關閉以進行測試?或者正在從網絡上斷開首選方式? 非常感謝, 安德魯 – Dave 2010-03-22 14:27:50

回答

6

有一個.Net方法來設置時間;它在默認情況下僅在C#中不可用。如果你Microsoft.VisualBasic添加到您的項目的引用,那麼你可以這樣寫:

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

gabe,非常感謝你的回答。這對我有效! – Dave 2010-03-22 14:24:22

+0

還有一個新手跟進問題。在成功推進時鐘之後的某個時刻(請參閱Gabe對如何執行此操作的響應),時鐘恢復到正確的時間。我仍在收集數據,等待這樣做的等待時間,但我的猜測是,它在某種程度上通過網絡或其他方式進行更新。任何人都知道是否有Windows程序/服務正在這樣做?有沒有辦法將其關閉以進行測試?或者正在從網絡上斷開首選方式?很多謝謝,安德魯 – Dave 2010-03-22 16:51:52

+0

賠率是你需要停止'w32time'服務。 – Gabe 2010-03-23 21:07:48

0

你不能僅僅加上3000秒字段。您需要指定介於0和60之間的秒數。您需要調整秒,分鐘,小時等字段,以使它們全部位於有效範圍內。

編輯 最簡單的方法實際上是調用SystemTimeToFileTime再加入numSeconds * 10000到它給回值,然後調用FileTimeToSystemTime轉換回一個SYSTEMTIME。

+0

codeka,感謝您的迴應。我沒有發現有必要修改上面的代碼(請參閱Gabe的回答)。也就是說,我增加了3600秒,時鐘似乎提前了1個小時。我不確定我是否誤會了你... – Dave 2010-03-22 14:25:33

相關問題