Forum: PC-Programmierung C# Service - auf PowerBroadcast reagieren


von Paul (Gast)


Lesenswert?

Hallo,

ich versuche gerade mit Visual Studio 2012 in C# (.Net 4.0) einen Dienst 
zu erstellen, der auf PowerBroadcasts reagiert...
1
        private void InitializeComponent()
2
        {
3
            this.CanHandlePowerEvent = true;
4
            this.ServiceName = "WinService";
5
        }
1
        protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
2
        {
3
            FileStream fs = new FileStream(folderPath + "\\logDatei.txt", FileMode.OpenOrCreate, FileAccess.Write);
4
            StreamWriter m_streamWriter = new StreamWriter(fs);
5
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
6
            m_streamWriter.WriteLine(" WindowsService: PowerEvent erkannt - " +
7
              DateTime.Now.ToShortDateString() + " " +
8
              DateTime.Now.ToShortTimeString() + "\n");
9
            m_streamWriter.Flush();
10
            m_streamWriter.Close();
11
            return base.OnPowerEvent(powerStatus);
12
        }

Der Dienst an sich scheint laut Dienste-Panel soweit zu laufen und in 
der LogDatei wird auch das Starten bzw. Beenden des Dienstes 
protokolliert(in den Methoden OnStart und OnStop wird auf die gleiche 
Weise eine Meldung in die logDatei.txt geschrieben. Schicke ich den PC 
jedoch in den StandBy und wecke ihn wieder auf, wird nichts in die 
Logdatei eingetgragen. Weiß jemand, wo der Fehler liegt?

Grüße,
Paul

von Coder (Gast)


Lesenswert?

C# benutzt man heutzutage nicht mehr.

von CSharpler (Gast)


Lesenswert?

Coder schrieb:
> C# benutzt man heutzutage nicht mehr.
Gibt ja auch kaum noch Hardware für ...

von Tobias K. (t_k)


Lesenswert?

wie registrierst du denn das callback?
afaik muss man hier was aus der win32api oder einer dll importieren - 
zumindest in win xp zeiten, als ich das letzte mal was damit gemacht 
habe.

grüsse,
tk
(man verzeihe mir mein lowercase - mobile device)

von Paul (Gast)


Lesenswert?

Hallo tk,

ich dachte eigentlich, dass es bei Diensten reicht, wenn ich die 
CanHandlePowerEvents-Eigenschaft auf TRUE setze und dann die zur 
Eigenschaft gehörende ServiceBase-Methode überschreibe. Wobei ich mir 
nicht sicher bin, ob ich das richtig gemacht habe...

Hier ist nochmal der aktuelle Code:
1
namespace WinServiceProject
2
{
3
    using System;
4
    using System.IO;
5
    using System.ServiceProcess;
6
    class WinService : System.ServiceProcess.ServiceBase
7
    {
8
        private string folderPath = @"c:\logs";
9
        static void Main()
10
        {
11
            System.ServiceProcess.ServiceBase[] ServicesToRun;
12
            ServicesToRun =
13
            new System.ServiceProcess.ServiceBase[] { new WinService() };
14
            System.ServiceProcess.ServiceBase.Run(ServicesToRun);
15
        }
16
        private void InitializeComponent()
17
        {
18
            this.ServiceName = "WinService";
19
            this.CanHandlePowerEvent = true;
20
        }
21
        protected override void OnStart(string[] args)
22
        {
23
            WriteLog("Gestartet");
24
        }
25
        protected override void OnStop()
26
        {
27
            WriteLog("Beendet");
28
        }
29
        protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
30
        {
31
            WriteLog(powerStatus.ToString());
32
            return base.OnPowerEvent(powerStatus);
33
        }
34
        private void WriteLog(string text)
35
        {
36
            if (!System.IO.Directory.Exists(folderPath))
37
                System.IO.Directory.CreateDirectory(folderPath);
38
            FileStream fs = new FileStream(folderPath + "\\logDatei.txt", FileMode.OpenOrCreate, FileAccess.Write);
39
            StreamWriter m_streamWriter = new StreamWriter(fs);
40
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
41
            m_streamWriter.WriteLine(text + " - " +
42
                DateTime.Now.ToShortDateString() + " " +
43
                DateTime.Now.ToLongTimeString() + "\n");
44
            m_streamWriter.Flush();
45
            m_streamWriter.Close();
46
        }   
47
    
48
    }
49
}

Falls da doch noch mehr nötig ist wäre ich für einen Tipp dankbar.

Viele Grüße,
Paul

von bluppdidupp (Gast)


Lesenswert?

Sollte eigentlich so stimmen, vermutlich irgendein Windows-Bug ;D
Vllt. geht alternativ: 
http://msdn.microsoft.com/de-de/library/microsoft.win32.systemevents.powermodechanged(v=vs.100).aspx

von Tobias K. (t_k)


Lesenswert?

Ich hatte das damals mit WM_POWERBROADCAST nachrichten gemacht, da meine 
Applikation in der tray lief und der User für meinen Usecase angemeldet 
war.
Ich nehme mal an, dass Dienste keine WMs erhalten?

Habe auf Codeproject ein Beispiel (1) gefunden, da macht es einer 
genauso wie du - scheint aus meiner Sicht auch plausibel. Welches 
Windows ist es denn eigentlich?

Grüße,
tk

(1) 
http://www.codeproject.com/Articles/14353/Creating-a-Basic-Windows-Service-in-C

von Paul (Gast)


Lesenswert?

Hallo tk,

vielen Dank für Deine Mühe. Dienste erhalten meines Wissens nach die 
Nachrichten normalerweise über eine alternative MessagePump(zumindest 
wenn man kein Fenster erzeugt). Ich habe inzwischen von jemand anderem 
den Tipp bekommen, doch einfach mal InitializeComponent() aufzurufen. 
Und schon funktionierts...

Viele Grüße,
Paul

von Simsalabim (Gast)


Lesenswert?

Paul schrieb:
> wenn man kein Fenster erzeugt). Ich habe inzwischen von jemand anderem
> den Tipp bekommen, doch einfach mal InitializeComponent() aufzurufen.
> Und schon funktionierts...

Rätsel gelöst ... Wenn du die Projektdateien von VS generieren lässt, 
steht ungefähr das hier drin:

public Service1()
{
  InitializeComponent();
}

Die Grundeinstellungen kannst du dann über die Eigenschaften vornehmen, 
ohne alles in deine eigene (Teil-) Klasse schreiben zu müssen.

// Service1.Designer.cs
private void InitializeComponent()
{
  //
  // Service1
  //
  this.CanHandlePowerEvent = true;
  this.CanHandleSessionChangeEvent = true;
  this.ServiceName = "Bla";
}

Ich muss aber gestehen, dass mir nicht gleich aufgefallen ist, dass in 
deinem Code statt

public partial class Service1 : ServiceBase

das hier

class WinService : System.ServiceProcess.ServiceBase

steht. Dann musst du die Initialisierung natürlich komplett "von Hand" 
durchführen.

von Tobias K. (t_k)


Lesenswert?

Was übrigens ein Aspekt ist, den ich bei C# mehr als Fluch denn als 
Segen betrachte: Die n:m Beziehung von Klassen und Dateien. Von 
Namespaces und Verzeichnissen ganz zu Schweigen.
Da Lobe ich mir Java in der Hinsicht...

tk

PS: ja ich weiss - "schreib mal nen Windows Dienst mit Java..." ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.