如何判断其他应用是不是注册了 IPC Remoting 通道?

Posted

技术标签:

【中文标题】如何判断其他应用是不是注册了 IPC Remoting 通道?【英文标题】:How can I tell if another app has registered an IPC Remoting channel?如何判断其他应用是否注册了 IPC Remoting 通道? 【发布时间】:2010-12-01 06:43:42 【问题描述】:

所以我有一个具有 .NET API 可用的应用程序。他们的 API 库通过 .NET 远程调用与其主应用程序通信。为了使用 API,应用程序必须已经启动并运行。

所以,我有一个实例,我需要以编程方式启动应用程序,然后实例化其中一个 API 对象,它试图打开到主应用程序的 IPC 远程处理通道。问题是,在我启动进程后,启动和应用程序注册通道之间有几秒钟的时间。如果我尝试在注册通道之前实例化一个 API 对象,它就会失败。

我对 .NET 远程处理知之甚少,这于事无补。

我如何从我的应用程序中确定使用他们的 API 的应用程序是否已注册通信通道以便我知道可以实例化他们的 API 对象?

【问题讨论】:

乔恩斯基特!你一定知道答案! =[ 【参考方案1】:

试试这个:

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;
 

传入端口,您应该会得到一个值,指示该端口上是否有侦听器。希望这会有所帮助

【讨论】:

问题是......它不是一个端口。它是 IPC 远程处理,所以有端口“名称”,但没有实际端口。 如果您以编程方式创建一个监听连接的进程,那么它必须监听某个端口。这个 MSDN 示例让服务器在端口 9090 上侦听 IPC 调用:msdn.microsoft.com/en-us/library/… 如果您不知道该端口,请尝试从命令行运行 netstat,您应该能够看到正在使用的端口 啊,这似乎有道理。但是,端口会随机更改。有什么建议吗? 你是如何推断出端口是随机变化的?只是为了好玩,您可以从命令行运行 netstat 并验证它在应用程序的不同运行中随机变化吗?检查应用程序是否有配置文件以及配置文件中是否指定了任何端口号等也可能会有所帮助。 我正是这样推断的:应用程序的不同运行每次都会导致不同的端口号。应用程序在创建 IPC 通道时没有指定端口号,这是我通过使用 Reflector 查看他们的代码确定的。【参考方案2】:

开箱即用,您是否考虑过将 WCF 与 MSMQ 结合使用?我不确定我是否完全理解您的架构,但听起来 API 的客户端必须启动另一个托管 API 的进程。在您启动 API 主机和客户端尝试进行调用之间可能存在时间问题。 Microsoft 最近已弃用 .NET Remoting(以及他们以前的所有其他通信技术,例如 ASMX Web 服务)作为遗留技术,并强烈建议开发人员迁移到 WCF 平台。

如果您将 WCF 与 MSMQ 一起使用,您应该不会遇到计时问题。无论 API 主机是否正在运行,您的客户端应用程序都可以将消息放入持久队列中。 API 主机可以随时启动,它将拾取并处理队列中等待的任何消息。即使您仍然让客户端应用程序启动 API 主机,时间问题也不再是问题,因为您使用队列而不是 .NET Remoting 来传输消息。 WCF 为 MSMQ 提供了一个漂亮、方便、易于使用的包装器,因此入门门槛相对较低。

使用 WCF over .NET Remoting 的另一个好处是,您可以轻松地将 API 主机移动到不同的物理服务器,而无需更改客户端应用程序。如果您愿意,您甚至可以迁移到不同的队列平台(例如 AMQP 上的 RabbitMQ),而无需更改客户端或 API 主机应用程序。 WCF 为您处理所有这些交互,在您的客户端应用程序和 API 主机之间提供更清晰的解耦和更可靠的通信。

如果迁移到 WCF 不是一个选项,您应该能够使用 .NET Remoting 显式设置端口。我不确定您是如何配置 API 主机的,但任何给定远程对象的 URL 通常采用以下形式:

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

如果您添加端口,那么您应该能够使用 Abhijeet 的解决方案来确定端口是否打开。您不会获得 WCF 的松散耦合和可靠的通信优势,但肯定会减少工作量。 ;)

【讨论】:

WCF 不是一个选项。我不控制服务器的来源。有一个用非托管语言(可能是 C++)编写的闭源应用程序和一个作为 .NET 库提供的 API。库是创建远程对象的东西。我必须使用远程处理,即使我知道它已被弃用并且很糟糕。【参考方案3】:

您是否考虑过将实例化 API 对象的尝试包装到 try-catch 块中?然后你可以分析异常,看看是不是服务器没有监听造成的。如果是,您可以等待并重试。

有道理吗?

【讨论】:

是的,但不幸的是,闭源 API 写得很糟糕,并且设置了一些静态变量,阻止它在同一运行时再次实例化,而无需使用大量反射来修复它。这将是一个令人讨厌的解决方案。 那么在另一个 AppDomain 中做呢? 我尝试将 myObj = Activator.GetObject(...) 包装在 try-catch 块中,测试 null 等。它不起作用,因为它返回一个 _TransparentProxy 对象,无论服务器是否启动或不。直到稍后您尝试使用 myObj 时,您才会倾斜。在我看来,Abjiheet 的答案是正确的。【参考方案4】:

只是代码中的一个小错字。 更正如下:

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; 
 

【讨论】:

【参考方案5】:

当您注册一个 IpcServerChannel 时,它会创建一个命名管道来与您为 IpcServerChannel 选择的端口名称进行通信。您可以查看命名管道列表以查看您的端口名称是否存在。

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

【讨论】:

以上是关于如何判断其他应用是不是注册了 IPC Remoting 通道?的主要内容,如果未能解决你的问题,请参考以下文章

前端js 怎么判断用户是不是安装了某APP,安装了不直接打开这个应用而是进行其他操作

如何判断 Web 应用程序是不是是使用 Angular(或其他技术)构建的?

注册页面用户名注册时需判断数据库里是不是有该用户名,如何将提示显示到同一页面上?

如何判断推送通知是尚未注册还是已关闭?

IPC::Shareable 是不是适用于受祝福的对象?

如何判断 IPC::Run 作业何时完成