Laden...

Message an Fensterhandle in einem Dienst

Erstellt von chilic vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.155 Views
C
chilic Themenstarter:in
2.122 Beiträge seit 2010
vor 11 Jahren
Message an Fensterhandle in einem Dienst

Hallo
Ich such mich grad in den Wahnsinn. Ich habe ein Programm in dem ein System.Windows.Form erzeugt wird, das nicht angezeigt wird sondern nur Messages in der WndProc entgegennimmt. Das Handle dieses Fensters wird einer externen DLL übergeben, die über diese Messages Nachrichten mit dem Fenster und somit dem Programm austauscht.

Seit ich den Code dieses Programms in einen Dienst gepackt habe, funktioniert das nicht mehr. Das Fenster wird erzeugt, Handle existiert und wird in die DLL übergeben, aber es kommen keine Nachrichten mehr an.
Liegt das am Dienst?

Dass ich in einem Dienst kein Fenster anzeigen kann ist mir schon klar. Aber eins erstellen und dir Funktionalität mit der WndProc müsste ich doch trotzdem nutzen können?
Dieser Punkt ist jedenfalls das einzige was für mich gerade noch als Problem in Frage kommt.

F
10.010 Beiträge seit 2004
vor 11 Jahren

Ein Dienst kann nicht mit der Nachrichten Queue kommunizieren.

Warum willst du das so machen statt ein "vernünftiges" IPC zu benutzen?

C
chilic Themenstarter:in
2.122 Beiträge seit 2010
vor 11 Jahren

Warum willst du das so machen statt ein "vernünftiges" IPC zu benutzen?

Ich will nicht, ich muss. Die DLL ist so ausgelegt, an der kann ich nichts drehen.

156 Beiträge seit 2010
vor 11 Jahren

Moin,

mir stellt sich die Frage wieso wurde die DLL so ausgelegt das man damit nicht vernüftig Kommunizieren kann

Ich will nicht, ich muss. Die DLL ist so ausgelegt, an der kann ich nichts drehen.

Du musst nicht, es geht nicht. Das Betriebssystem ist so ausgelegt, daran kannst Du nichts drehen ^^

Alles andere ist eine Verletzung der BS-Sicherheit. Das wurde zum Glück entfernt.

hand, mogel

Gelöschter Account
vor 11 Jahren

Der Dienst läuft sicherlich in einem anderen Benutzeraccount und daher funktionierts jetzt nicht mehr. IPC basiertes Remoting funktioniert über verschiedene Benutzeraccounts auch nicht. Was funktioniert wäre TCP basiertes Remoting oder Named Pipes(Admin-Rechte benötigt)

Für die Kommunikation zwischen Desktop Programmen und Diensten verwende ich vorzugsweise die Named Pipes.

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo chilic,

unter XP gings relativ einfach per ==> "Datenaustausch zwischen Dienst und Desktop zulassen", aber bei Windows 7 geht das wohl nicht mehr.

herbivore

C
chilic Themenstarter:in
2.122 Beiträge seit 2010
vor 11 Jahren

mir stellt sich die Frage wieso wurde die DLL so ausgelegt das man damit nicht vernüftig Kommunizieren kann

Das ist eine uralte DLL mit diesem Mechanismus, der eigentlich nur für fensterbasierte Programme gedacht war.
An der DLL kann ich nichts ändern, die kann ich leider entweder so einsetzen wie sie ist, oder gar nicht.

@herbivore
Das Häkchen gibt es bei mir unter Win 7 noch. Allerdings nur wenn man "lokales Systemkonto" wählt. Funktioniert aber bei mir trotzdem noch nicht.

Ich habe in Pickles asks "Message pump in .NET Windows service" noch was gefunden, das probier ich noch aus. Wenn das nicht geht, muss die Sache wohl gestrichen werden.

Vielen Dank an alle fürs Mitdiskutieren!

C
chilic Themenstarter:in
2.122 Beiträge seit 2010
vor 11 Jahren

Ich habs tatsächlich hinbekommen 😃
Wen es interessiert, hier ist der Ansatz der aus dem obigen Link folgt. Bitte beachtet dass es sich hier um einen "entweder so oder gar nicht" Fall handelt, bei dem Drittsoftware im Spiel ist die nicht beeinflusst werden kann. Sonst hätt ich es sicher anders gelöst. Ich kann nicht garantieren dass das auf jedem System läuft.

Man muss Application.Run() aufrufen und zwar in dem Thread, der auch das Fenster erzeugt. Dieser Thread ist sinnvollerweise ein anderer als der aufrufende Thread, denn die Methode nach dem Run bleibt ja blockiert.


  public class MessagePumpManager
  {
    static bool _initialized = false;

    static AutoResetEvent messagePumpRunning = new AutoResetEvent(false);

    public static void Init()
    {
      if (_initialized)
        return;

      _initialized = true;

      // MessageLoop in einem neuen Thread starten
      Thread th = new Thread(RunMessagePump);
      th.IsBackground = true;     // sonst beendet sich die MessageLoop nicht mehr
      th.Start();
      messagePumpRunning.WaitOne();
    }

    // Message Pump Thread
    static void RunMessagePump()
    {
      --> hier passiert die Erstellung des Form, sowie die Übergabe des Form.Handle an die DLL,
      die dann Nachrichten an das Fenster sendet.
      messagePumpRunning.Set();
      Application.Run();
    }
  }