2009-03-16 6 views

risposta

60

Here is where I found the answer.

ho ripubblicato qui per migliorare la chiarezza.

Definire questa struttura:

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

Aggiungere il extern seguente metodo alla classe:

[DllImport("kernel32.dll", SetLastError = true)] 
public static extern bool SetSystemTime(ref SYSTEMTIME st); 

quindi chiamare il metodo con un'istanza della struct come questo:

SYSTEMTIME st = new SYSTEMTIME(); 
st.wYear = 2009; // must be short 
st.wMonth = 1; 
st.wDay = 1; 
st.wHour = 0; 
st.wMinute = 0; 
st.wSecond = 0; 

SetSystemTime(ref st); // invoke this method. 
+4

scrivere un wrapper C++/CLI personalizzato e intromettersi in un altro assembly è più facile che scrivere una struct ~ 9-line ?? – Lucas

+4

Lo spazio dei nomi Microsoft.VisualStudio.Shell.Interop contiene una definizione della struttura SYSTEMTIME; vedi http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.systemtime.aspx –

+0

Non lasciare che Marc Gravell veda la tua struttura! ;-) – si618

7
  1. PInvoke per chiamare API Win32 SetSystemTime, (example)
  2. classi System.Management con classe WMI Win32_OperatingSystem e chiamare SetDateTime quella classe.

Entrambi richiedono che al chiamante sia stato assegnato SeSystemTimePrivilege e che questo privilegio sia abilitato.

14

È possibile utilizzare una chiamata a un comando DOS ma il richiamo della funzione nelle finestre dll è un modo migliore per farlo.

public struct 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; 
}; 

[DllImport("kernel32.dll", EntryPoint = "GetSystemTime", SetLastError = true)] 
public extern static void Win32GetSystemTime(ref SystemTime sysTime); 

[DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)] 
public extern static bool Win32SetSystemTime(ref SystemTime sysTime); 

private void button1_Click(object sender, EventArgs e) 
{ 
    // Set system date and time 
    SystemTime updatedTime = new SystemTime(); 
    updatedTime.Year = (ushort)2009; 
    updatedTime.Month = (ushort)3; 
    updatedTime.Day = (ushort)16; 
    updatedTime.Hour = (ushort)10; 
    updatedTime.Minute = (ushort)0; 
    updatedTime.Second = (ushort)0; 
    // Call the unmanaged function that sets the new date and time instantly 
    Win32SetSystemTime(ref updatedTime); 
} 
4

Dal momento che ho parlato in un commento, ecco un wrapper C++/CLI:

#include <windows.h> 
namespace JDanielSmith 
{ 
    public ref class Utilities abstract sealed /* abstract sealed = static */ 
    { 
    public: 
     CA_SUPPRESS_MESSAGE("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands") 
     static void SetSystemTime(System::DateTime dateTime) { 
      LARGE_INTEGER largeInteger; 
      largeInteger.QuadPart = dateTime.ToFileTimeUtc(); // "If your compiler has built-in support for 64-bit integers, use the QuadPart member to store the 64-bit integer." 


      FILETIME fileTime; // "...copy the LowPart and HighPart members [of LARGE_INTEGER] into the FILETIME structure." 
      fileTime.dwHighDateTime = largeInteger.HighPart; 
      fileTime.dwLowDateTime = largeInteger.LowPart; 


      SYSTEMTIME systemTime; 
      if (FileTimeToSystemTime(&fileTime, &systemTime)) 
      { 
       if (::SetSystemTime(&systemTime)) 
        return; 
      } 


      HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 
      throw System::Runtime::InteropServices::Marshal::GetExceptionForHR(hr); 
     } 
    }; 
} 

Il C# codice del client è ora molto semplice:

JDanielSmith.Utilities.SetSystemTime(DateTime.Now); 
+0

Ho provato il tuo codice, ma non sembra funzionare. https://gist.github.com/jtara1/07cfd5ebffab8296564f86000c50510e Ad ogni modo, ho trovato una soluzione a ciò che volevo e l'ho testato https://github.com/jtara1/MiscScripts/blob/00a5d330d784d7e423c0f8a83172ddfc31aad3fa/MiscScripts/UpdateOSTime.cs –

8

Un sacco di grandi punti di vista e gli approcci sono già qui, ma qui ci sono alcune specifiche che sono attualmente tralasciate e che ritengo possano far scattare e confondere alcune persone.

  1. Su Windows Vista, 7, 8 OS questo sarà richiederà un prompt UAC per ottenere i diritti amministrativi necessari per eseguire con successo la funzione SetSystemTime. Il motivo è che il processo di chiamata richiede il privilegio SE_SYSTEMTIME_NAME.
  2. La funzione SetSystemTime prevede una struttura SYSTEMTIME in tempo universale coordinato (UTC). Non funzionerà come desiderato altrimenti.

A seconda di dove/come hai trovato i tuoi DateTime valori, potrebbe essere meglio andare sul sicuro e usare ToUniversalTime() prima di impostare i valori corrispondenti nel SYSTEMTIME struct.

Codice esempio:

DateTime tempDateTime = GetDateTimeFromSomeService(); 
DateTime dateTime = tempDateTime.ToUniversalTime(); 

SYSTEMTIME st = new SYSTEMTIME(); 
// All of these must be short 
st.wYear = (short)dateTime.Year; 
st.wMonth = (short)dateTime.Month; 
st.wDay = (short)dateTime.Day; 
st.wHour = (short)dateTime.Hour; 
st.wMinute = (short)dateTime.Minute; 
st.wSecond = (short)dateTime.Second; 

// invoke the SetSystemTime method now 
SetSystemTime(ref st); 
+0

I Non posso cambiare direttamente il tempo di sistema usando questo –

+0

Ho usato questo codice su più progetti con successo. Stai eseguendo l'eseguibile come amministratore? Altrimenti questo codice non funzionerà sicuramente. –

+1

wow questo ha risolto il mio problema. Il problema è che il fuso orario per l'ora locale sta intralciando l'ora corretta in modo che la riga "DateTime dateTime = tempDateTime.ToUniversalTime();" risolto tutto –

5

Utilizzare questa funzione per modificare il tempo di sistema (testato in finestra 8)

void setDate(string dateInYourSystemFormat) 
    { 
     var proc = new System.Diagnostics.ProcessStartInfo(); 
     proc.UseShellExecute = true; 
     proc.WorkingDirectory = @"C:\Windows\System32"; 
     proc.CreateNoWindow = true; 
     proc.FileName = @"C:\Windows\System32\cmd.exe"; 
     proc.Verb = "runas"; 
     proc.Arguments = "/C date " + dateInYourSystemFormat; 
     try 
     { 
      System.Diagnostics.Process.Start(proc); 
     } 
     catch 
     { 
      MessageBox.Show("Error to change time of your system"); 
      Application.ExitThread(); 
     } 
    } 
void setTime(string timeInYourSystemFormat) 
    { 
     var proc = new System.Diagnostics.ProcessStartInfo(); 
     proc.UseShellExecute = true; 
     proc.WorkingDirectory = @"C:\Windows\System32"; 
     proc.CreateNoWindow = true; 
     proc.FileName = @"C:\Windows\System32\cmd.exe"; 
     proc.Verb = "runas"; 
     proc.Arguments = "/C time " + timeInYourSystemFormat; 
     try 
     { 
      System.Diagnostics.Process.Start(proc); 
     } 
     catch 
     { 
      MessageBox.Show("Error to change time of your system"); 
      Application.ExitThread(); 
     } 
    } 

Esempio: chiamata in modo carico di forma setDate ("5-6-92"); setTime ("2: 4: 5 AM");

+0

Ecco una versione testata, pronta per la compilazione ed esecuzione del codice https://github.com/jtara1/MiscScripts/blob/master/MiscScripts/UpdateOSTime.cs Ho dovuto passare attraverso almeno 4 stackoverflow per questo come sono non ha familiarità con C# o queste librerie. –

-2

proc.Arguments = "/ C Data:" + dateInYourSystemFormat;

Questa è la funzione lavoro: "che cosa hai provato"

void setDate(string dateInYourSystemFormat) 
{ 
    var proc = new System.Diagnostics.ProcessStartInfo(); 
    proc.UseShellExecute = true; 
    proc.WorkingDirectory = @"C:\Windows\System32"; 
    proc.CreateNoWindow = true; 
    proc.FileName = @"C:\Windows\System32\cmd.exe"; 
    proc.Verb = "runas"; 
    proc.Arguments = "/C Date:" + dateInYourSystemFormat; 
    try 
    { 
     System.Diagnostics.Process.Start(proc); 
    } 
    catch 
    { 
     MessageBox.Show("Error to change time of your system"); 
     Application.ExitThread(); 
    } 
} 
+0

stessa risposta che hai dato ... –