Window Anwendung von der dll aus starten

CopWorker

Mitglied
Hallo zusammen,

ich habe eine Windows Forms Anwendung.
die läuft. Der Programmstart erfolgt über die *.exe Datei.
Jetzt brauche ich aber eine DLL davon.
Die kann ich ja auch erzeugen über "Projekt | Eigenschaften | Anwendung -> Ausgabetyp: Klassenbibliothek".
Ich binde die DLL in ein weiteres Projekt ein mit "using MyDll;", das geht auch.
Ich greife auf Klassen und Funktionen zu, sofern diese als "public" deklariert sind.

Mein Ziel:
Ich will die komplette Anwendung starten aber das Haupt Dialogfenster nicht anzeigen.
Erst wenn dies gebraucht wird soll es per Funktionsaufruf sichtbar gemacht werden.

Ist sowas überhaupt möglich oder sinnvoll?
Oder wie soll ich da sonst vorgehen?

Vielen Dank für eure Tipps.
Ich stehe momentan total auf dem Schlauch.

Grüße von CopWorker
 

ComFreek

Mod | @comfreek
Moderator
Ich will die komplette Anwendung starten aber das Haupt Dialogfenster nicht anzeigen.
Erst wenn dies gebraucht wird soll es per Funktionsaufruf sichtbar gemacht werden.
Was meinst du mit "die komplette Anwendung starten"? Was beinhaltet "starten" in deinem Anwendungsfall?

Sicherlich kannst du die WinMain der eingebundenen DLL irgendwie starten mithilfe der WinAPI. Beachte, dass du dann möglicherweise (*) einen zweiten Thread bekommst und eine zweite WinAPI-Hauptschleife. Möglicherweise möchtest du das nicht?

(*) So genau kenne ich die WinAPI nicht -- ich rate auch nur.
 

Spyke

Premium-User
@ComFreek
so Tief muss man bei C# nicht gehen.
Man kann einfach ein ShowDialog einer Form Aufrufen und .Net startet dann intern selbst eine Nachrichtenschleife, sollte diese noch nicht existieren, oder der Dialog läuft normal im Kontext der bestehenden Nachrichtenschleife die schon da ist.

@CopWorker
wie ComFreek schon schrieb, was genau hast du vorher?
du kannst in deiner DLL theoretisch belieg viele unterschiedliche Formulare machen und extern aufrufen.
Das erste Formular welches mit ShowDialog aufgerufen wird startet halt einfach erstmal die Nachrichtenschleife.

Kleine Randnotiz:
Der sicherer Aufruf eines ersten Formulares wäre schon mit Application.Run, anstatt einfach Dialog.
Aber kleinere Seiteneffekte hatte ich bisher nur erlebt als ich das Fenster eines Prozesses in ein anderen Prozess einbetten wollte und das eigebettet Fenster normal zur Anwendung laufen/ausschauen sollte (wie ein Control), da braucht ich dann wirklich Application.Run.
 

CopWorker

Mitglied
Hallo Spyke,

ich habe eine Anwendung die mir eine Kommunikationsschnittstelle (RPC Server und Clients)
zur Verfügung stellt.
Der Gesamtprozess geht von der Klasse "TestComMain" aus.
So soll es auch sein wenn ich diese Anwendung als DLL erstelle und benutze.

Diese Schnittstelle bediene ich bis jetzt über ein Dialogfenster Klasse "TestComMainDlg() : Form".
In dieser Klasse erstelle ich eine Instanz der Klasse "TestComMain"
C#:
private TestComMain clTestCom = new TestComMain();
und rufe die Funktionen dieser Instanz auf.

Wenn die Anwendung von der DLL aus gestartet wird, soll die Dialogfenster Klasse entweder im Hintergrund mitlaufen und auf Kommando der Dialog sichtbar gemacht werden.
Oder die Dialogfenster Klasse soll auf Kommando erstellt werden.
Dieses Dialogfenster dient als eine Art Debugger im Echtzeitbetrieb.

Aber wie kann ich diese beiden Instanzen dann miteinander koppeln?

Vielen Dank
CopWorker
 

CopWorker

Mitglied
Hallo nochmals,

hier der Code des Projekts in dem ich die DLL aufrufen will.
C#:
using System;
using System.Windows.Forms;
using CSharpTestCom;

namespace PcsOrderManager
{
    public partial class Form1 : Form
    {

        CSharpTestCom.TestComMainDlg MainDlg = new TestComMainDlg();
        CSharpTestCom.TestComMain Main = new TestComMain();

        public Form1()
        {
            InitializeComponent();
        }

        private void btInitInterface_Click(object sender, EventArgs e)
        {
            Main.InitInterface();
        }

        private void btDeinitInterface_Click(object sender, EventArgs e)
        {
            Main.DeinitInterface();
        }

        private void BtSendMsg_Click(object sender, EventArgs e)
        {
            int iCmd = 3002;
            int[] iParam = new[] {11111, 22222, 33333, 44444, 55555};
            byte[] bMsgBuf;

            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            bMsgBuf = enc.GetBytes("Hier der Text der gesendet werden soll");

            Main.SendMessage(iCmd, iParam, bMsgBuf, 1);
        }

        private void btReadMsg_Click(object sender, EventArgs e)
        {
            byte[] bMsgBuf = new byte[]{};

            Main.ReadMsgQueue(ref bMsgBuf);
        }
    }
}

Mit "BtSendMsg_Click" und "btReadMsg_Click" möchte ich die beiden Funktionen "Main.SendMessage()" und "Main.ReadMsgQueue()" vom Main - Programm aufrufen. Diese beiden Funktionen möchte ich auch vom MainDlg - Programm aus aufrufen, im Debugmodus so zu sagen.

Mein Problem ist, wie verknüpfe ich die beiden Prozesse miteinander?

Vielen Dank im Voraus
CopWorker
 

Spyke

Premium-User
Der Hauptbestandteil ist ja dein TestComMain was sich eigentlich um alles kümmert oder?
Dort ist quasi deine ganz businesslogik für die Verarbeitung, (senden, empfangen, etc) drin oder?

Das heißt du musst ja nur dafür sorgen das die Klasse TestComMain in deiner DLL public ist (und alle relevanten Methoden und Eigenschaften der Klasse), dann könntest du es überall in exen, dlls verwenden mit unterschiedlichen Formularen, wie de willst.
 

CopWorker

Mitglied
Hallo Spyke,

so ist mein Plan. Und so ist es auch.
Wenn das Projekt als DLL verwendet wird funktioniert das ja auch alles.

Was ich noch erreichen möchte:
Während der Laufzeit mochte ich zu Debugzwecken die Dialogklasse aktivieren.
Wie soll ich das anstellen. Führe ich folgenden Code aus
CSharpTestCom.TestComMainDlg MainDlg = new TestComMainDlg();
Wird die Methode "TestComMainDlg_Load(,)" nicht durchlaufen.

Wie kann ich das Dialogfenster starten und auch die Klasse vollständig instantzieren?
Der Aufruf des Dialogfensters muss in der Klasse "TestComMain();" von Statten gehen.

Vielen Dank.
Grüße von CopWorker
 

Spyke

Premium-User
MainDlg.ShowDialog oder MainDlg.Show

Ansonsten kommt drauf an was im Load Ereignis deines Formulares passiert.
Falls das was dort passiert auch ohne sichtbaren Fenster passieren soll, ob du es eventuell auslagerst in eine extra Methode oder so, die du dann explizit aufrufst.
 

CopWorker

Mitglied
Hallo Spyke,

nun bin ich der Sache schon näher, allerdings noch ein kleines Problem.
Durch ein übergeordnetes Programm rufe ich die erforderlichen Methoden der Klasse "TestComMain" aus der DLL auf. Danach wird eine Instanz der Klasse "TestComMainDlg" erstellt. Der Konstruktor der Dialogklasse enthält erhält die Instanz der Klasse "TestComMain".
Das sieht so aus:
C#:
public static TestComMain clMain = new TestComMain();
public static TestComMainDlg clMainDlg = new TestComMainDlg(true, clMain);
Das Dialogfenster aus der DLL wird nicht geöffnet, soll es auch nicht.
Danach lege ich im übergeordneten Programme eine Thread an, der mir auf die Queue von Der Klasse "TestComMain" aus der DLL zugreift und die Inhalte ausliest.
C#:
public void InitQueueThreading()
{
    QueueCycle = new Thread(ReadQueue);
    QueueCycle.Start();
}
Bei einem eintreffenden RPC Telegramm schlägt der Thread auch zu und liest die Queue aus. Die Queue liegt in der Klasse "TestComMain" der DLL.
C#:
public int Read(ref RpcStack.tRpcMsg sRpcMsg)
        {
            int iRet = 0;

            //Information über Anzahl der ungelesenen Einträge als Rückgabe ermitteln
            iRet = liBuffer.Count;

            if (iRet > 0)
            {
                //Schwerwiegender Ausnahmefehler: Empfangspuffer überlaufen
                if (iRet > iMaxCount)
                    iRet = -1;

                //nach dem ersten Index suchen, diesen auslesen und aus Liste entfernen
                sRpcMsg = liBuffer[0];
                liBuffer.RemoveAt(0);
            }
            

            return iRet;
        }

Nach Aufruf folgender Funktion(Klasse "TestComMain" der DLL.) öffnet auch das Dialogfenster. Die Methode "ShowMainDlg()" der Dialogklasse wird auch durchlaufen.
Code:
public int ShowMainDlg()
{
  if (this.clParent != null)
  {
    if (!this.clParent.Visible)
    {
      if (this.clParent.InvokeRequired)
      {
        this.clParent.Invoke((Delegate) (() => this.ShowMainDlg()));
      }
      else
      {
        this.clParent.ShowDialog();
      }
      if (this.clParent.Visible)
    }
  }
  return iValue;
}
Das Dialogfenster wird sichtbar.

Jetzt kommt´s.
Ab diesem Zeitpunkt ist im übergeordneten Programm der Thread zum Auslesen der Queue tot.
Warum weiß ich nicht. Initialisiere ich den Thread wieder dann läuft der weiter.

Vielen Dank.
Grüße von CopWorker
 

Spyke

Premium-User
Erstmal ich glaube
Code:
if (!this.clParent.Visible)
birgt eine Gefahr für eine potenzielle Thread Exception, glaub ich (Exception das Threadübergreifend auf ein Objekt zugegriefen wird).
Besser so machen:
Code:
public int ShowMainDlg()
{
  if (this.clParent != null)
  {
      if (this.clParent.InvokeRequired)
      {
        this.clParent.Invoke((Delegate) (() => this.ShowMainDlg()));
      }
      else
      {
        if (!this.clParent.Visible) //<--- visible nach unten verschoben das diese Prüfung dann auch im UI Thread erfolgt
            this.clParent.ShowDialog();
      }
  }
  return iValue;
}

Und wenn ich dich richtig verstehe läuft zu erst dein Thread und dann machste irgendwann ShowDialog?
Klingt mir als wenn mit deinem ShowDialog Aufruf das erste mal der UI Thread angefordert/erstellt wird.

Könnte jetzt sein weil der UI Threa plötzlich kommt oder weil ShowDialog ja eigentlich eher ein blockierender Aufurf ist.
Alternativ könntest es erstmal mit nur Show probieren.
 

Neue Beiträge