2009-02-06 9 views
8

Sto cercando di aggiornare il mio tempo di sistema utilizzando il seguente:Come aggiornare la data e/o l'ora del sistema utilizzando .NET

[StructLayout(LayoutKind.Sequential)] 
private struct SYSTEMTIME 
{ 
    public ushort wYear; 
    public ushort wMonth; 
    public ushort wDayOfWeek; 
    public ushort wDay; 
    public ushort wHour; 
    public ushort wMinute; 
    public ushort wSecond; 
    public ushort wMilliseconds; 
} 

[DllImport("kernel32.dll", EntryPoint = "GetSystemTime", SetLastError = true)] 
private extern static void Win32GetSystemTime(ref SYSTEMTIME lpSystemTime); 

[DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)] 
private extern static bool Win32SetSystemTime(ref SYSTEMTIME lpSystemTime); 

public void SetTime() 
{ 
    TimeSystem correctTime = new TimeSystem(); 
    DateTime sysTime = correctTime.GetSystemTime(); 
    // Call the native GetSystemTime method 
    // with the defined structure. 
    SYSTEMTIME systime = new SYSTEMTIME(); 
    Win32GetSystemTime(ref systime); 

    // Set the system clock ahead one hour. 
    systime.wYear = (ushort)sysTime.Year; 
    systime.wMonth = (ushort)sysTime.Month; 
    systime.wDayOfWeek = (ushort)sysTime.DayOfWeek; 
    systime.wDay = (ushort)sysTime.Day; 
    systime.wHour = (ushort)sysTime.Hour; 
    systime.wMinute = (ushort)sysTime.Minute; 
    systime.wSecond = (ushort)sysTime.Second; 
    systime.wMilliseconds = (ushort)sysTime.Millisecond; 

    Win32SetSystemTime(ref systime); 
} 

Quando metto a punto tutto sembra a posto e tutti i valori sono corretti, ma quando si chiama Win32SetSystemTime (ref systime) l'ora effettiva del sistema (tempo di visualizzazione) non cambia e rimane invariata. La parte strana è che quando chiamo Win32GetSystemTime (ref systime) mi dà il nuovo tempo aggiornato. Qualcuno può darmi un aiuto su questo?

+0

come la vedo io, TimeSystem è non dalla classe sistema di base, sei sicuro che TimeSystem non cambiano il tempo? prova a commentare Win32SetSystemTime (ref systime); line – Avram

risposta

4

In base al codice che hai proprio lì, non stai aumentando l'ora. Sembra che tu abbia impostato l'ora del tuo sistema esattamente nello stesso istante in cui si trovava quando hai chiamato Win32GetSystemTime.

Prova:

systime.wHour = (ushort)(sysTime.Hour + 1); 
+0

Ma non voglio aumentare l'ora. Voglio impostarlo in un altro momento. – user62958

+0

Il commento di codice nel codice specifica "imposta l'orologio del sistema in anticipo di un'ora". Non stai cambiando il tuo tempo di sistema semplicemente perché non lo stai cambiando. Per impostarlo su un altro momento, devi impostare la struttura che stai inviando nel metodo a un orario diverso dall'ora corrente. –

6

Parte del problema è che avete un paio di firme PInvoke non corretti. Il più importante SetSystemTime dovrebbe avere un valore di ritorno non vuoto. Ecco la firma corretta

/// Return Type: BOOL->int 
    ///lpSystemTime: SYSTEMTIME* 
    [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint="SetSystemTime")] 
    [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] 
public static extern bool SetSystemTime([InAttribute()] ref SYSTEMTIME lpSystemTime) ; 

Il mio sospetto è che il blocco di un valore di ritorno incasinato lo stack e la funzione SetSystemTime essenzialmente finito con dati non corretti.

2
 

TimeSpan diffLocalTime = DateTime.Now - DateTime.UtcNow; 
SystemTime systemTime = new SystemTime(); 
systemTime.Second = ... 
systemTime.Minute =.... 
systemTime.Hour -= (ushort)(diffLocalTime.Hours + 1); // 00:59:59 I rounded as 1 hour 
bool result = SetSystemTime(ref systemTime); 
 

Questo utilizzo funziona correttamente per il fuso orario locale.

1
[DllImport("Kernel32.dll")] 
public static extern bool SetLocalTime(ref StractData.Datetime.SYSTEMTIME Time); 
0

Hai solo un problema di privilegi, quando si esegue il programma senza privilegi, does'nt cambia la data, ma se lo faccio fare clic destro sul programma e fare clic su Esegui come amministratore, funziona!

2

Non c'è bisogno di P/Invoke - c'è un modo più semplice (ma non ben noto) disponibile dall'assembly Microsoft.VisualBasic. Se sei in C#, ricorda di aggiungere un riferimento ad esso.

È possibile utilizzare la classe Microsoft.VisualBasic.DateAndTime per ottenere e modificare la data o l'ora. Le proprietà Today e TimeOfDay hanno setter che apporteranno le modifiche alla data o all'ora.

Sono ancora necessari i privilegi pertinenti: fare riferimento al collegamento alla documentazione MSDN riportato di seguito.

Ecco un esempio arbitrario per modificare l'ora:

public static void SetTimeToPast() 
{ 
    Microsoft.VisualBasic.DateAndTime.TimeOfDay = DateTime.Now.AddMinutes(-2); 
} 

di riferimento su MSDN: http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.dateandtime(v=vs.110).aspx

+0

Per me, la modifica della data di sistema Microsoft.VisualBasic.DateAndTime.TimeOfDay.Today = [nuova data] ha funzionato. Molte grazie. Questa è finora la soluzione più semplice e pulita. – FrenkyB

+0

L'utilizzo di Win32SetSystemTime funziona per me, ma sfortunatamente no. – Matt

Problemi correlati