2009-09-25 11 views
5

So habe ich eine Anwendung, die eine .NET API zur Verfügung hat. Ihre API-Bibliothek kommuniziert mit ihrer Hauptanwendung über .NET-Remoting-Aufrufe. Um die API zu verwenden, muss die Anwendung bereits ausgeführt werden.Wie kann ich feststellen, ob eine andere App einen IPC Remoting-Kanal registriert hat?

So habe ich eine Instanz, wo ich programmatisch die Anwendung starten und dann eine der API-Objekte instanziieren muss, die versucht, einen IPC-Remoting-Kanal für die Haupt-App zu öffnen. Das Problem ist, nachdem ich den Prozess gestartet habe, gibt es ein paar Sekunden zwischen dem Start und wenn die Anwendung den Kanal registriert. Wenn ich versuche, ein API-Objekt zu instanziieren, bevor der Kanal registriert ist, bloggt es.

Es hilft nicht, dass ich sehr wenig über .NET Remoting weiß.

Wie kann ich aus meiner Anwendung ermitteln, welche ihre API verwendet, wenn die Anwendung den Kanal für die Kommunikation registriert hat, damit ich weiß, dass es in Ordnung ist, ihr API-Objekt zu instanziieren?

+0

Jon Skeet! Du musst die Antwort wissen! = [ – snicker

Antwort

2

Versuchen Sie folgendes:

using System.Net.NetworkInformation; 
using System.Net; 
private static bool IsPortAvailable(int port) 
{ 
     IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); 
     IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); 
     if (activeListeners.Any(conn => conn.Port == port)) 
     { 
      return true; 
     } 
     return false; 
} 

Pass im Hafen, und Sie sollten einen Wert bekommen das anzeigt, ob ein Zuhörer an diesem port.Hope ist dies

für ein
+1

Das Problem ist ... es ist kein Port. Es ist IPC Remoting, also gibt es Port "Namen", aber nicht die tatsächlichen Ports. – snicker

+0

Wenn Sie einen Prozess programmatisch erstellen, der auf Verbindungen wartet, muss er auf einem Port warten. In diesem MSDN-Beispiel überwacht der Server IPC-Anrufe an Port 9090: http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.ipc.ipcchannel.aspx Ich kenne den Port, versuche netstat von der Befehlszeile aus zu starten, du solltest sehen können, welche Ports benutzt werden –

+0

Ah, das scheint Sinn zu machen. Der Port ändert sich jedoch zufällig. Irgendwelche Vorschläge dafür? – snicker

0

Nur um aus der Box hilft Moment, haben Sie darüber nachgedacht, WCF mit MSMQ zu verwenden? Ich bin mir nicht sicher, ob ich Ihre Architektur vollständig verstehe, aber es klingt so, als ob der Client der API einen anderen Prozess in Gang setzen muss, der die API hostet. Möglicherweise liegt ein Zeitproblem zwischen dem Start des API-Hosts und dem Versuch des Clients vor, Anrufe zu tätigen. Microsoft hat .NET Remoting (sowie alle anderen bisherigen Kommunikationstechnologien wie ASMX-Webdienste) vor kurzem als veraltet deklariert und empfiehlt dringend, dass Entwickler auf die WCF-Plattform wechseln.

Wenn Sie WCF mit MSMQ verwenden, sollten Sie kein Problem mit dem Timing haben. Ihre Clientanwendung kann Nachrichten in einer dauerhaften Warteschlange ablegen, unabhängig davon, ob der API-Host ausgeführt wird oder nicht. Der API-Host kann jederzeit gestartet werden und alle Nachrichten, die in der Warteschlange warten, werden abgeholt und verarbeitet. Selbst wenn die Client-Anwendung den API-Host noch immer startet, ist das Timing-Problem kein Problem mehr, da Sie Warteschlangen zum Übertragen der Nachrichten anstelle von .NET Remoting verwenden. WCF bietet einen schönen, praktischen und einfach zu verwendenden Wrapper für MSMQ, so dass die Einstiegshürde relativ gering ist.

Die andere schöne Sache über WCF über .NET Remoting ist, dass Sie den API-Host leicht auf einen anderen physischen Server verschieben können, ohne die Client-App (s) ändern zu müssen. Sie können sogar zu einer anderen Warteschlangenplattform wechseln, wenn Sie dies wünschen (z. B. RabbitMQ auf AMQP), ohne die Client- oder API-Host-Apps zu ändern. WCF wickelt all diese Interaktionen für Sie ab und bietet eine wesentlich sauberere Entkopplung und zuverlässigere Kommunikation zwischen Ihrer Client-Anwendung und dem API-Host.

Wenn der Wechsel zu WCF keine Option ist, sollten Sie den Port mit .NET Remoting explizit festlegen können. Ich bin nicht sicher, wie Sie Ihre API-Host konfigurieren, aber die URL für jedes gegebenes remoted Objekt ist in der Regel in Form von:

tcp://<hostname>[:<port>]/<object> 

Wenn Sie den Port hinzufügen, dann sollten Sie in der Lage sein, Abhijeet-Lösung zu verwenden Bestimmen Sie, ob der Port offen ist oder nicht. Sie werden nicht die losen Kopplungs- und zuverlässigen Kommunikationsvorteile von WCF erhalten, aber es wäre definitiv weniger Arbeit. ;)

+0

WCF ist keine Option. Ich kontrolliere nicht die Quelle des Servers. Es gibt eine Closed-Source-Anwendung in einer nicht verwalteten Sprache (wahrscheinlich C++) und eine API als .NET-Bibliothek. Die Bibliothek erstellt die Remoting-Objekte. Ich muss Remoting verwenden, obwohl ich weiß, dass es veraltet ist und saugt. – snicker

0

Haben Sie erwogen, den Versuch, ein API-Objekt in einen try-catch-Block zu instanziieren, zu umbrechen? Dann können Sie die Ausnahme analysieren und sehen, ob sie durch den Server verursacht wurde, der nicht abhört. Und wenn es war, können Sie einfach warten und es erneut versuchen.

Macht Sinn?

+0

Ja, aber leider ist die Closed-Source-API schlecht geschrieben und setzt einige statische Variablen, die verhindern, dass sie in der gleichen Laufzeit erneut instanziiert werden, ohne dass Tonnen von Reflektion verwendet werden, um sie zu beheben. Es wäre eine schlimme Lösung. – snicker

+0

Tun Sie es in einer anderen AppDomain dann? –

+0

Ich habe versucht, myObj = Activator.GetObject (...) in einen try-catch-Block zu schreiben, auf Null usw. zu testen. Es funktioniert nicht, weil es ein _TransparentProxy-Objekt zurückgibt, egal ob der Server aktiv ist oder nicht. Es ist nicht bis später, wenn Sie versuchen, myObj zu verwenden, dass Sie kippen. Abjiheet hat meiner Meinung nach die richtige Antwort. – IAbstract

0

Nur ein kleiner Tippfehler im Code. Korrektur ist wie folgt:

using System.Net.NetworkInformation; 
using System.Net; 
private static bool IsPortAvailable(int port) 
{ 
    IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); 
    IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); 
    if (activeListeners.Any(conn => conn.Port == port)) 
    { 
     return true; 
    } 
    return false; 
} 
0

Wenn Sie sich registrieren ein IpcServerChannel es eine Named Pipe macht mit dem Namen des Port Name für Ihre IpcServerChannel wählte zu kommunizieren. Sie können sich die Liste der Named Pipes ansehen, um zu sehen, ob Ihr Port Name dort ist.

System.IO.Directory.GetFiles(@"\\.\pipe\").Any((path) => path.Contains(@"\\.\pipe\" + pipeName));