Domanda

Come posso cambiare la data del sistema locale & amp; tempo programmaticamente con C #?

È stato utile?

Soluzione

Ecco dove ho trovato la risposta.

L'ho ripubblicato qui per migliorare la chiarezza.

Definisci 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;
}

Aggiungi il seguente metodo extern alla tua classe:

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

Quindi chiama il metodo con un'istanza della tua struttura in questo modo:

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.

Altri suggerimenti

È possibile utilizzare una chiamata a un comando DOS ma l'invocazione della funzione nella dll di Windows è 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);
}  

Molti grandi punti di vista e approcci sono già qui, ma qui ci sono alcune specifiche che sono attualmente escluse e che ritengo possano inciampare e confondere alcune persone.

  1. Su Windows Vista, 7, 8 OS ciò richiederà un prompt UAC per ottenere i diritti amministrativi necessari per eseguire correttamente SetSystemTime funzione. Il motivo è che il processo di chiamata richiede il privilegio SE_SYSTEMTIME_NAME .
  2. La funzione SetSystemTime si aspetta una struttura SYSTEMTIME in tempo universale coordinato (UTC) . In caso contrario, non funzionerà come desiderato.

A seconda di dove / come stai ottenendo i tuoi valori DateTime , potrebbe essere meglio riprodurli in sicurezza e usare ToUniversalTime () prima di impostare i valori corrispondenti in SYSTEMTIME struct.

Esempio di codice:

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); 
  1. PInvoke per chiamare l'API Win32 SetSystemTime, ( esempio )
  2. Classi System.Management con classe WMI Win32_OperatingSystem e chiama SetDateTime su quella classe.

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

Utilizzare questa funzione per modificare l'ora del sistema (testato nella 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: Metodo di chiamata nel modulo di caricamento setDate (" 5-6-92 "); setTime (" 2: 4: 5 AM ");

Da quando l'ho menzionato 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 codice client C # è ora molto semplice:

JDanielSmith.Utilities.SetSystemTime(DateTime.Now);

Stai attento !. Se si elimina la proprietà non utilizzata dalla struttura, si imposta l'ora errata. Ho perso 1 giorno a causa di questo. Penso che l'ordine della struttura sia importante.

Questa è la struttura corretta:

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;

        };

Se si esegue SetSystemTime (), funziona come previsto. Per il test ho impostato l'ora come di seguito;

SystemTime st = new SystemTime();
st.Year = 2019;
st.Month = 10;
st.Day = 15;
st.Hour = 10;
st.Minute = 20;
st.Second = 30;

SetSystemTime(ref st);

Il tempo impostato: 15.10.2019 10:20, va bene.

Ma cancello la proprietà DayOfWeek che non è stata utilizzata;

public struct SystemTime
            {
                public ushort Year;
                public ushort Month;
                public ushort Day;
                public ushort Hour;
                public ushort Minute;
                public ushort Second;
                public ushort Millisecond;

            };

SystemTime st = new SystemTime();
    st.Year = 2019;
    st.Month = 10;
    st.Day = 15;
    st.Hour = 10;
    st.Minute = 20;
    st.Second = 30;

    SetSystemTime(ref st);

Esegui lo stesso codice ma il tempo è impostato su: 10.10.2019 20:30

Prestare attenzione all'ordine e a tutti i campi della struttura di SystemTime. Yusuf

  

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

Questa è la funzione di lavoro:

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();
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top