Laden...

Welche config-Datei wird von DLL verwendet und wo muß sie liegen?

Erstellt von Rübe vor 15 Jahren Letzter Beitrag vor 15 Jahren 15.451 Views
R
Rübe Themenstarter:in
6 Beiträge seit 2008
vor 15 Jahren
Welche config-Datei wird von DLL verwendet und wo muß sie liegen?

Ich habe folgende Aufgabenstellung:

Eine DLL (WCF, .Net 3.5, VS2008 ) soll über WCF von einem Programm (.exe) und einer DLL aufgerufen werden und Funktionen bereitsstellen.

Der Aufruf durch das Programm funktioniert, wesentliche Einstellung (z.B. endpoint, contract binding, address) werden in der app.config bereitgestellt und erfolgreich ausgelesen.

Die gleiche app.config verwende ich auch fur den Aufruf aus der DLL. Hier bekomme ich allerdings eine Fehlermedung:

A first chance exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll

Additional information: Es wurde kein standardmäßiges Endpunktelement gefunden, das auf den Vertrag "IRemoteAdapter" im ServiceModel-Clientkonfigurationsabschnitt verweist. Dies kann folgende Ursachen haben: Für die Anwendung wurde keine Konfigurationsdatei gefunden, oder im Clientelement wurde kein Endpunktelement gefunden, das diesem Vertrag entsprach.

Der Code, der die Exception verursacht ist:

 private RemoteAdapterClient proxy = new RemoteAdapterClient(); 

Da die app.config für beide, Programm und DLL-Assembly, gleich ist, vermute ich, dass die DLL die app.config nicht findet bzw. einen anderen Namen erwartet.
Beide verwenden auch dieselben generierten Proxy-Klassen (mit SvcUtil.exe erzeugt)

Meine Fragen:

  1. Wo muß die config-Datei für die DLL abgelegt sein, und wie muß sie heißen?
  2. Gibt es eine Möglichkeit, zu debuggen, um herauszufinden, welcher Name und Ort der config-Datei erwartet werden?
  3. Gibt es gängige, alternative Methoden, um die EndPoint-Definitionen einzustellen?

Ein weiterer Hinweis: Die aufrufende DLL wird wiederum von einem FoxPro-Programm aufgerufen.

Die App.Config sieht wie folgt aus:

<?xml version="1.0" encoding="utf-8" ?>
  <configuration>
    <system.diagnostics>
      <trace autoflush="true" />
      <sources>
        <source name="System.ServiceModel"
                switchValue="Information, ActivityTracing"
                propagateActivity="true">
          <listeners>
            <add name="sdt"
                type="System.Diagnostics.XmlWriterTraceListener"
                initializeData="myTraceFile.txt"  />
          </listeners>
        </source>
      </sources>
    </system.diagnostics>

  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IRemoteAdapter" closeTimeout="00:01:00"
            openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
            bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
            maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
            allowCookies="false">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00"
              enabled="false" />
          <security mode="Message">
            <transport clientCredentialType="Windows" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="Windows" negotiateServiceCredential="true"
                algorithmSuite="Default" establishSecurityContext="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://w2k3-server.dss.com/RemoteAdapter/Service.RemoteAdapter.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IRemoteAdapter"
                contract="IRemoteAdapter" name="WSHttpBinding_IRemoteAdapter">
        <identity>
          <servicePrincipalName value="host/w2k3-server.dss.com" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration> 

Vielen Dank für jede Hilfe!

3.728 Beiträge seit 2005
vor 15 Jahren
Konfiguration für DLLs

Hallo Rübe,

es gibt keine App.config für DLLs! DLLs verwenden die Konfiguration des Prozesses, in den sie geladen werden. Das ist im Normalfall die EXE der Applikation.
Es gibt natürlich Ausnahmen. So haben z.B. VSTO-Addins eine eigene Konfiguration, obwohl sie DLLs sind. Das liegt aber daran, dass der Host (also das Office-Programm, welches die AddIn-DLL lädt) für jedes AddIn eine separate Anwendungsdomäne erzeugt. Eine Anwendungsdomäne kann man als virtuellen Prozess im Prozess verstehen (Anwendungsdomänen sind ein Feature von .NET). Jede Anwendungsdomäne hat ihre eigene Konfiguration. Der Ersteller der Anwendungsdomäne legt die Eigenschaften beim Erzeugen fest. Deshalb haben manchmal auch DLLs eine eigene Konfigurationsdatei.

Die App.config hängt also gar nicht an der Assembly-Datei, sondern eigentlich an der Anwendungsdomäne. Standardmäig erzeugen nur EXE-Dateien eigene Anwendungsdomänen. Dass die Konfigurationsdateien ähnlich benannt werden wie die Assembly, ist nur eine Konvention. Bei benutzerdefinierten Anwendungsdomänen ist das aber keinesfalls Pflicht.

WCF-Dienste laufen für gewöhnlich in der Standard-Anwendungsdomäne des Host-Prozesses. Deshalb beziehen die Dienste deshalb automatisch ihre Konfiguration aus der App.config des Hosts. In den meisten Fällen ist das auch gut so. Kein Admin möchte gerne eine Anwendung betreuen, deren Konfiguration in zwanzig Unterverzeichnissen verstreut ist.

R
Rübe Themenstarter:in
6 Beiträge seit 2008
vor 15 Jahren

Hallo Rainbird,

herzlichen Dank für Deine Ausführungen. Damit komme ich einen sehr wichtigen Schritt weiter. Vor allen Dingen habe ich nun ein klare Vorstellung davon, woran es liegt!
Etwas in der Richtung hatte ich zwischenzeitlich beobachten können: Die besagte DLL wird von einem FoxPro-Programm gestartet; nachdem ich die Config-Datei in MS-FoxPro-Verzeichnis kopiert und sie "vfp9.config" genannt hatte, lief auch die DLL.

Mich wundert allerdings, dass die Config-Datei in meinem Fall nicht app.config heißen darf, sondern eben ähnlich wie die FoxPro-EXE (vfp9.exe).

Wie geht man mit einem solchen Fall um?
Das FoxPro läuft beim Kunden selbstverständlich nicht nur für die Anwendung, für die ich die DLL geschrieben habe, sondern für verschiedene FoxPro-Programme. Deshalb kann ich dem FoxPro nicht meine config-Datei aufzwingen.
Mir fallen folgende Möglichkeiten ein:
1.) Das FoxPro-Programm erzeugt eine Anwendungsdomäne, wie Du sie beschrieben hast. Ist das überhaupt möglich mit FoxPro? Es ist allerdings auch möglicherweise organisatorisch schwierig, weil ich diese FoxPro-Programm nicht verändern kann.
2.) Können die Anwendungskonfigurationen (hier in erster Linie EndPoint, Contract, Binding und Address) in der DLL selbst definiert werden (ohne app.config), und wenn ja, wie?

3.) Gibt es weitere und gebräuchliche Ansätze?

Vielen Dank schon mal im voraus!

3.728 Beiträge seit 2005
vor 15 Jahren
Hosting der CLR in FoxPro

Hallo Rübe,

ich habe zwar keine Erfahrung mit FoxPro, aber dafür sehr viel mit Access. FoxPro ist soweit ich weiß auch eine COM-Anwendung. Das Hosting von .NET Komponenten wird deshalb wahrscheinlich genauso funktionieren.

Deine .NET Komponente kommt entweder als COM-Verweis oder als Add-In in die FoxPro Umgebung. Die Konfigurationsdatei legst Du unter einem X-beliebigen Namen in dem Verzeichnis ab, wo Deine .NET Assemblies liegen. Du musst jetzt nur eine Loader-Klasse schreiben, die ohne Konfiguration auskommt. Diese Loader-Klasse erzeugt eine neue Anwendungsdomäne und verknüpft die Konfigurationsdatei damit. Anschließend muss der Loader die benötigten Assemblies in die neue Anwendungsdomäne laden. Nun musst Du nur noch die eigentliche Funktionalität über CreateAndUnwrap innerhalb der benutzerdefinierten Anwendungsdomäne aufrufen. So kannst Du Deine Assembly mit einer anderen Konfigurationsdatei betreiben.

In Office-Anwendungen funkioniert das ausgezeichnet. VSTO macht das automatisch so. Da die CLR in jedem Betriebssystem-Prozess gehostet werden kann, funktioniert das auch so unter FoxPro.

R
Rübe Themenstarter:in
6 Beiträge seit 2008
vor 15 Jahren

Hallo Rainbird,

vielen Dank für die Herangehensweise. Hast Du auch ein paar Code-Snippets dazu?

3.728 Beiträge seit 2005
vor 15 Jahren
Snippets

Hallo Rübe,

ich habe leider keine Snippets zu diesem Thema. Die Implementierungen sind Teil größerer Projekte in der Firma.

Es ist aber nicht schwer. Schau Dir die Beispiele in der Visual Studio Online-Hilfe zu AppDomain.Create und CreateAndUnwrap an. Wenn Du irgendwo nicht weiterkommst, kannst Du gerne hier fragen.

R
Rübe Themenstarter:in
6 Beiträge seit 2008
vor 15 Jahren

Ich werd's ausprobieren, bei Fragen melde ich mich - Vielen Dank Rainbird!

B
325 Beiträge seit 2005
vor 15 Jahren

Ich möchte auch einen Webservice innerhalb eines Class Library Projektes ansprechen.
Dazu habe ich den Webservice als Service Reference hinzugefügt (VS hat daraufhin eine App.config erstellt) und möchte nun von diser eine Instanz erzeugen.


WebServiceReference.serviceSoapClient ws = new WebServiceReference.serviceSoapClient();
ws.GetSessionKey(userId);

Dabei tritt leider folgender Fehler auf:

Es wurde kein standardmäßiges Endpunktelement gefunden...

Die notwendigen Daten für die Nutzung des Webservices stehen also in der App.config, diese wird aber nicht ausgelesen, da mein Projekt eine DLL wird?
Kann ich die erforderlichen Daten nicht auch direkt in den Code schreiben?

Oder mache ich etwas anderes falsch?

Vielen Dank!

3.971 Beiträge seit 2006
vor 15 Jahren

Was recht gut und einfach geht, ist das du die Funktion, die den WCF-Host oder Client erstellt, um ein string-Parameter erweiterst. dem Parameter übergibst du EndPointConfigurationName aus der App.Config deiner Exe.

Die App.Config deiner Bibliothek brauchst du nicht, alle Settings kannst in die App.Config deiner Anwendung kopieren.

Zweite Möglichkeit, du erstellst eine eigene AppDomain und lädst dort die App.Config deiner Dll rein (sowie das Rainbird oben geschrieben hat)

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

B
325 Beiträge seit 2005
vor 15 Jahren

Den Webservice nutze ich innerhalb einer DLL. Dieses Projekt hat auch eine app.config.


<client>
            <endpoint address="http://foobar.com/service.asmx" binding="basicHttpBinding"
                bindingConfiguration="serviceSoap" contract="WebServiceReference.serviceSoap"
                name="serviceSoap" />
        </client>

Die Webserverinstanz wird innerhalb folgender Methode erzeugt:


private bool ConnectToFacebook(int userId)
{
    WebServiceReference.serviceSoapClient ws = new WebServiceReference.serviceSoapClient();
    ws.GetSessionKey(userId);
    .
    .
    .
}

Nun habe ich zusätzlich eine Windows-Forms-Anwendung, die meine DLL inkl. Webservice nutzen soll. Diese besitzt keine app.config.

Könntest du deinen ersten Lösungsansatz mit ein wenig Sample-Code versehen? Stehe nämlich leider noch auf dem Schlauch.

Vielen Dank!

3.971 Beiträge seit 2006
vor 15 Jahren

Bei dir dürfte es aber schon reichen, wenn du den Inhalt der App.Config von der Bibliothek in die App.Config deiner Anwendung (Winforms.Exe) kopierst.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

B
325 Beiträge seit 2005
vor 15 Jahren

Danke! 🙂