Samstag, 5. Juni 2010

Systemzeit ändern

Um die Uhrzeit des PCs zu lesen bzw. zu ändern, gibt es im .Net Framework keine hauseigene Version. Mit allen .Net Sprachen kann man jedoch auf die Funktionen der Win32-API zugreifen.
Die Win32-API ist eine sehr umfangreiche Programmierschnittstelle, welche Funktionen für die Windowsprogrammierung bereitstellt.
Die oft systemnahen Funktionen sind alle in C oder Assembler geschrieben und sind in dll - Dateien gespeichert.
Glücklicherweise gibt es auch eine API - Funktion zur Verwaltung der Systemzeit, welche wir in unsere C# - Anwendung einbinden können. Das einbinden von externen Funktionen bezeichnet man in der Fachsprache als Platform Invoke (P/Invoke).
Nun zum Code:
Um DLLs einbinden zu können, ist folgende using - Direktive notwendig:
using System.Runtime.InteropServices;

Die externe Funktion zur Systemzeitsetzung wird dem Programm schließlich folgenderweise bekannt gemacht:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetSystemTime(ref str_Zeit neueZeit);

Die Funktion SetSystemTime() lässt sich dann wie eine gewöhnliche Funktion aufrufen.
Als Parameter erwartet sie ein Objekt vom Typ der Struktur str_Zeit, die wir selber definieren:

struct str_Zeit
        {
            public ushort Jahr;
            public ushort Monat;
            public ushort TagInDerWoche;
            public ushort Tag;
            public ushort Stunde;
            public ushort Minute;
            public ushort Sekunde;
            public ushort Millisekunde;
        }

Diese Struktur ist in der API so nicht gespeichert, unsere Struktur ist nur eine Nachbildung des Typs, den die Funktion erwartet - jeder Typ mit 8 vorzeichenlosen 16-Bit-Ganzzahlen erfüllt die Anforderungen.
Der komplette Code könnte schließlich so aussehen (Aufruf der Funktion SetzeSystemzeit() mit einem Datumsobjekt als Parameter ändert die Systemzeit auf den übergebenen Wert):

public class ZeitSetzen
    {
        struct str_Zeit
        {
            public ushort Jahr;
            public ushort Monat;
            public ushort TagInDerWoche;
            public ushort Tag;
            public ushort Stunde;
            public ushort Minute;
            public ushort Sekunde;
            public ushort Millisekunde;
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool SetSystemTime(ref str_Zeit neueZeit);

        public void SetzeSystemzeit(DateTime neueZeit)
        {
            str_Zeit Zeit = new str_Zeit();
            Zeit.Jahr = (ushort)neueZeit.Year;
            Zeit.Monat = (ushort)neueZeit.Month;
            Zeit.TagInDerWoche = (ushort)neueZeit.DayOfWeek;
            Zeit.Tag = (ushort)neueZeit.Day;
            Zeit.Stunde = (ushort)neueZeit.Hour;
            Zeit.Minute = (ushort)neueZeit.Minute;
            Zeit.Sekunde = (ushort)neueZeit.Second;
            Zeit.Millisekunde = (ushort)neueZeit.Millisecond;
            
            SetSystemTime(ref Zeit);
        }
    }

Aufpassen bei Windows Vista und 7: Zum Ändern der Systemzeit braucht das Programm Administratorrechte. Wie die Anwendung diese erhält, steht in einem anderen Post.

Kommentare:

  1. Also bei mir kommt IMMER Fehler beim Senden von Mail.

    AntwortenLöschen
  2. Kannst du vielleicht mal ein Beispiel machen wie man die neue Zeit/Datum setzt? Also wie genau die Parameter heißen müssen um die Zeit/Datum zu setzen.

    AntwortenLöschen
  3. Hi,
    SetzeSystemzeit() muss mit einem DateTime Objekt aufgerufen werden, z.B. so:

    SetzeSystemzeit(new DateTime(2012, 5, 23, 2, 12, 0, 0));

    AntwortenLöschen
  4. Hi,
    das ist ja eine Klasse, aber wenn ich jetzt auf meinem Projekt in meinem Button das hier eingeben will: SetzeSystemzeit(new DateTime(2012, 5, 23, 2, 12, 0, 0));

    wird das in Rot angestrichen. Oder wenn ich in den Button schreibe: ZeitSetzen.SetzeSystemzeit(new DateTime(2012, 5, 23, 2, 12, 0, 0));

    das funktioniert auch nicht. Kannst du mir bitte helfen?

    Gruss

    AntwortenLöschen
  5. Hi Anonym,

    Hast du auch eine Instanz der Klasse ZeitSetzen per new erstellt?

    Beste Grüße,
    Postremus

    AntwortenLöschen
    Antworten
    1. Hi Postremus,
      wie funktioniert denn das? Vielleicht so: Zeitsetzen zeitsetzen = new Zeitsetzen();
      ??

      Gruß

      Löschen
    2. Hallo,
      genau, und dann rufst du zeitsetzen.SetzeSystemzeit(bla) auf.

      Löschen
  6. bei mir kommt: " Can't find PInvoke DLL 'kernel32.dll' "
    was ist zu machen

    AntwortenLöschen
    Antworten
    1. Hallo,
      ist die PC auf deinem Rechner im Applikations- oder Windowsverzeichnis vorhanden? Ansonsten lade sie dir herunter, klappt es jetzt?

      Löschen