65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Azure AppFabric 服务总线自动化 Windows 应用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (38投票s)

2010年11月13日

CPOL

8分钟阅读

viewsIcon

48052

downloadIcon

1363

没有导出程序接口的非托管 Windows GUI 应用程序通过注入代码得到自动化。一个支持 WCF 的注入组件允许位于世界各地的客户端通过 Azure AppFabric Service Bus 与自动化应用程序通信,即使存在防火墙和动态 IP 地址。

AutomatingWinAppsServiceBus_schema.png

引言

本文是我在 CodeProject 上发表的关于自动化没有导出程序接口的非托管 Windows GUI 应用程序(“黑盒”应用程序)系列文章中的第三篇。这些应用程序下文称作目标应用程序。尽管使用相同的注入技术,但本文展示了注入代码与外部世界通信的不同方式。

背景

提出的技术将目标应用程序转换为自动化服务器,即,其独立的客户端(订阅者)能够以同步或异步(通过接收事件通知)模式控制目标应用程序并获取其部分服务。在之前的文章 [1][2] 中,已经详细描述了这种转换并提供了相应的代码示例。因此,这里只作简要概述。

转换的操作流程如下:

  • 使用远程线程技术 [3] 将一段外部代码注入到目标应用程序中;
  • 注入的代码对目标应用程序的窗口进行子类化,为子类化窗口接收的 Windows 消息添加所需的 [预]处理;
  • 在目标应用程序进程的上下文中,在注入的代码中创建一个 COM 对象。该对象负责自动化目标应用程序与外部世界的通信。

上述步骤对于所有三篇文章都是通用的。主要区别在于目标应用程序内部运行的 COM 对象的性质和构成。在最早的文章 [1] 中,通信对象是一个普通的 COM 对象,它本身已在运行对象表 (ROT) 中注册。它支持用于入站调用的直接接口和用于异步通知订阅者的外出(宿主)接口。这类对象支持与同一台机器上多个订阅者应用程序(托管和非托管)的双工通信,但由于 ROT 仅在本地可用,因此无法支持与远程订阅者应用程序的通信。

下一代通信对象 [2] 是托管 WCF 服务器组件的 COM 可调用包装器 (CCW)。这使得自动化目标应用程序能够连接到本地和远程订阅者,从而极大地扩展了新形成的自动化服务器的访问范围。但是,这个高级通信对象仍然存在限制:它只能支持位于同一本地区域网络 (LAN) 中的远程订阅者。同一局域网外的订阅者会受到防火墙的阻碍,并且目标应用程序的机器没有永久 IP 地址。这意味着,如果我在家里的台式机上自动化一个 GUI 应用程序,我的女儿和我的狗就可以从家里的其他机器(在同一局域网内)使用它的服务,而我的朋友在他/她家(局域网外)则无法享受这种乐趣。

Azure AppFabric Service Bus

这就是 Microsoft Azure 平台 [4] 发挥作用的地方。除了其他有用的功能外,它还提供了 AppFabric Service Bus,这是一项技术和基础设施,能够连接 WCF 感知的服务器和位于防火墙后且 IP 地址可变的客户端。由于动态 IP 地址和防火墙是入站调用的障碍,但对出站调用透明,因此 Service Bus 在客户端和服务器的出站调用之间充当基于 Internet 的中介。

事实证明,使用 Azure Service Bus 使自动化目标应用程序在全球范围内可用非常简单。以本文 [2] 中的软件为出发点,我发现无需更改代码(好吧,实际上我确实稍微更改了代码,但这并不是强制性的)。实际上,需要执行三个操作:

  • 修改目标应用程序和客户端的配置文件。

需要新的配置文件,因为使用 Service Bus 需要特殊的中继绑定以及适当的安全设置和支持 Service Bus 连接的特殊终结点行为。在我们的示例中,使用了 netTcpRelayBinding。终结点行为提供了用于 Service Bus 连接的 issuerNameissuerSecret 参数。这两个参数都应从您的 Azure AppFabric Service Bus 账户复制。同样,WCF 服务基本地址的强制部分也应从该账户复制。

sb://SERVICE-NAMESPACE.servicebus.windows.net

SERVICE-NAMESPACE 占位符应替换为您的服务命名空间)。配置文件详情可在示例中查看。

代码示例

与之前的文章一样,我们将著名的记事本文本编辑器作为自动化的目标应用程序。控制台应用程序 InjectorToNotepad.exe 使用 Injector.dll COM 对象通过远程线程技术将 NotepadPlugin.dll 注入到目标应用程序中。注入的 NotepadPluginNotepad 的框架和视图窗口进行子类化,并通过 COM 可调用包装器 (CCW) 创建 NotepadHandlerNET 托管组件。NotepadHandlerNET 负责与外部世界的通信。这项技术在我之前的文章 [2] 中已详细解释。

构建和运行示例

  • 以管理员身份运行 Visual Studio 2010 并打开 NotepadAuto.sln
  • 打开解决方案属性页,选择多个启动项目,为项目 InjectorToNotepad AutomationClientNET 操作属性设置为启动,然后按 OK 按钮。
  • NotepadHandlerNET AutomationClientNET 项目的 App.config 文件中,在 <sharedSecret> 标签中替换 issuerNameissuerSecret 属性的值,并将 SERVICE-NAMESPACE 占位符替换为您 Azure AppFabric Service Bus 账户的相应值。
  • 构建并运行解决方案。
项目的输出将放在 Release 或 Debug(取决于您的构建选择)工作目录中。InjectorToNotepad 应用程序会将 Notepad.exe 复制到同一目录,并且在构建过程中会创建一个漂亮的配置文件 Notepad.exe.configInjectorToNotepad 控制台应用程序会从工作目录运行 Notepad,并应报告 SUCCESS!然而,记事本窗口标题中出现 [AUTOMATED] 字样需要一些时间。然后,按标记为“Bind to Automated Notepad via Azure Service Bus”的大按钮。绑定需要时间(最多 30 秒)。绑定完成后,大按钮将禁用,三个较小的操作按钮将被启用。请参阅测试示例部分进行测试。

运行演示

演示包含两个目录,即 Injector Client Injector 目录应放在目标应用程序机器上。它包含注入 Notepad 目标应用程序所需的所有组件。Client 目录应放在客户端(订阅者)机器上。

在开始运行示例之前,请在目标应用程序和客户端机器上都安装 Windows Azure SDK。在配置文件 Notepad.exe.configAutomationClientNET.exe.config 中,替换 <sharedSecret> 标签中 issuerNameissuerSecret 属性的值,并将 SERVICE-NAMESPACE 占位符替换为您 Azure AppFabric Service Bus 账户的相应值。请注意,cmd exe (目标应用程序 Notepad 除外)文件应以管理员身份运行。确保已停止保护您的软件免受注入(因为这类保护软件会将任何注入视为恶意行为)。

首先运行 COMRegisteration.cmd 命令文件。它使用 regsvr32.exe 工具注册 COM 组件 WindowFinder.dllInjector.dll,并使用 regasm.exe 工具注册 NotepadHandlerNET.dll 的 CCW。然后运行 InjectorToNotepad.exe 控制台应用程序。它从系统中将 Notepad.exe 复制到工作目录(为了使注入的 COM 对象成功运行,Notepad 必须从工作目录运行),并执行注入。在注入器打印 SUCCESS! 消息后,记事本标题中显示 [AUTOMATED] 字样需要一些时间。InjectorToNotepad.exe 控制台应用程序可以关闭。现在我们的 Notepad 目标应用程序已被自动化,并准备好为客户端服务。

Client 目录(可以放在世界上的任何机器上),运行 AutomationClientNET.exe 客户端应用程序,并按其上的大按钮“Bind to Automated Notepad via Azure Service Bus”。客户端与自动化 Notepad 绑定需要一些时间(约 30 秒)。如果绑定成功,大按钮将禁用,操作按钮将被启用。

测试示例

现在示例已准备好进行测试。您可以打开记事本的查找对话框,通过按客户端应用程序的相应按钮添加自定义菜单项。您可以键入一些文本到记事本中,然后通过按客户端的“Copy Text”按钮将其复制到客户端。要测试异步操作,请在记事本中键入一些文本,后跟句子结束符(“.”、“?” 或 “!”)。键入的文本将在客户端应用程序的编辑框中显示。

您可以为多个客户端测试此示例。为此,您需要确保每个客户端的 URI 都是唯一的。因此,在另一个 AutomationClientNET.exe 客户端应用程序的 AutomationClientNET.exe.config 文件中,将其服务基本地址的后缀从 /Subscriber1 替换为,例如,/Subscriber2,启动此新客户端并将其绑定到自动化 Notepad。所有活动的客户端在记事本中键入的文本以“.”、“?” 或 “!” 结尾时,都会收到复制的文本和异步事件。

讨论

所描述的方法展示了 Azure AppFabric Service Bus 在自动化桌面应用程序方面的巨大实用性。Service Bus 允许自动化应用程序为全球范围内的客户端提供服务,克服了防火墙和动态 IP 地址的限制,而且无需额外编写代码。Service Bus 可以作为任何自动化应用程序与其客户端之间的中介。

在本篇文章的示例中,目标应用程序及其客户端仅通过 Service Bus 进行通信。在实际自动化中,应为本地客户端、位于同一局域网 (LAN) 中的客户端以及“远程”客户端提供不同的终结点。Service Bus 终结点应为混合类型,以实现与每个客户端最高效的通信方式。

结论

本文介绍了一种使用注入对象自动化 Windows 应用程序的技术演进。非托管目标进程内部的、支持 .NET WCF 的组件,通过 Azure AppFabric Service Bus 在自动化应用程序与其客户端之间提供通信。这种方法克服了双方的防火墙和动态 IP 地址等障碍,使自动化服务器在全球范围内可用。

参考文献

[1] Igor Ladnik. Automating Windows Applications. CodeProject.
[2] Igor Ladnik. Automating Windows Applications Using the WCF Equipped Injected Component. CodeProject.
[3] Jeffrey Richter, Christophe Nasarre. Windows via C/C++. Fifth edition. Microsoft Press, 2008.
[4] Roger Jennings. Cloud Computing with the Windows Azure Platform. Wiley Publishing, 2009.
[5] Juval Lowy. Programming WCF Services. Third edition. O'Reilly, 2010.

历史

  • 2010 年 11 月 12 日:初版
© . All rights reserved.