.NET 应用程序自动化






2.67/5 (4投票s)
2007年7月22日
2分钟阅读

46029

511
一篇关于创建 .NET 应用程序自动接口的文章。

引言
通过应用程序集成,通常可以以更低的成本实现更多的功能,而不是在单个应用程序中实现所有功能。 存在许多为 COM 平台创建的现有应用程序。 它们仍然被大量使用,但当前 Microsoft Windows 上的趋势是迁移到 .NET 作为开发平台。 因此,出现了将现有 COM 应用程序与使用 .NET 开发的新应用程序集成的问题。
在 COM 世界中,Microsoft Excel 是应用程序自动化的一个很好的例子。 可以将该应用程序作为独立的完整应用程序运行,也可以从外部脚本控制它。
在 .NET 和 Visual Basic 应用程序之间进行集成时,产生了使用类似机制的想法,以允许使用两种不同框架创建的两个应用程序之间进行强制集成。 众所周知,.NET 平台提供了从 COM 调用它和反之亦然的工具。 但是,在 .NET 世界中寻找 Visual Basic ActiveX-exe 的类似物并没有成功。 通过手动加载程序集并使用反射来查找启动应用程序的一些线索,找到了实现所需集成能力的方法。
为了研究这种可能性,创建了本文中介绍的原型。
概念验证原型
该解决方案的通用架构如下
集成的核心是接口库:它向客户端公开应用程序接口,并提供工厂来加载自动化应用程序。
// FILE: IControllableApp.cs
// automation interface exposed to COM
namespace icontrollable_app
{
[Guid("63B13299-D126-488f-8CCD-807C00456EDB")]
public interface IControllableApp
{
void Start();
void Finish();
void AddLine(string line);
}
}
// FILE: ControllableAppFactory.cs
// automation application factory
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace icontrollable_app
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("027BD25E-DDA9-4152-9430-59EC342347B4")]
[ProgId("ControllableApp.ControllableAppFactory")]
public class ControllableAppFactory
{
///
/// for access from COM
///
/// path to exe assembly.
/// NOTE: dependend assemblies must be availble
/// in search path.
///
public IControllableApp CreateApp(string appPath)
{
return ControllableAppFactory.Create(appPath);
}
[ComVisible(false)]
public static IControllableApp Create(string appPath)
{
Assembly assembly = Assembly.LoadFile(appPath);
Type t = assembly.GetType("controllable_app.AppMainForm");
Object instance = Activator.CreateInstance(t);
IControllableApp app = (IControllableApp)instance;
return app;
}
}
}
自动化应用程序必须具有实现公开的自动化接口的类。 最简单的方法是通过主窗体实现接口。
//FILE: AppMainForm.cs
namespace controllable_app
{
public partial class AppMainForm : Form, IControllableApp
{
public AppMainForm()
{
InitializeComponent();
}
#region IControllableApp Members
public void Start()
{
this.Show();
}
public void Finish()
{
this.Hide();
}
public void AddLine(string line)
{
listBox1.Items.Add(line);
}
#endregion
}
}
从 .NET 和 Visual Basic 客户端的访问都通过接口库执行。 从 VB6 执行此操作的最简单方法是使用后期绑定来访问工厂和自动化应用程序。
//FILE: TestDriverForm.cs
namespace net_driver
{
public partial class TestDriverForm : Form
{
IControllableApp m_app = null;
public TestDriverForm()
{
InitializeComponent();
}
private void btnFinish_Click(object sender, EventArgs e)
{
if (m_app != null)
{
m_app.Finish();
m_app = null;
}
}
private void btnStart_Click(object sender, EventArgs e)
{
const string PATH = @"..\..\..\controllable_app\bin\Debug\controllable_app.exe";
string test_app_path = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), PATH);
m_app = ControllableAppFactory.Create(test_app_path);
m_app.Start();
}
private void btnAddLine_Click(object sender, EventArgs e)
{
if (m_app != null)
{
m_app.AddLine(textBox1.Text);
}
}
}
}
'FILE: Form1.frm
Private m_app As Object
Private Sub btnFinish_Click()
If Not m_app Is Nothing Then
m_app.Finish
Set m_app = Nothing
End If
End Sub
Private Sub cmdAddLine_Click()
If Not m_app Is Nothing Then
m_app.AddLine txtLine.Text
End If
End Sub
Private Sub cmdStart_Click()
Dim factory As Object
Set factory = CreateObject("ControllableApp.ControllableAppFactory")
Dim appPath As String
appPath = App.Path + "\..\controllable_app\bin\Debug\controllable_app.exe"
Set m_app = factory.CreateApp(appPath)
Set factory = Nothing
m_app.Start
End Sub
优点
所提出的方法有几个好处- 可以从 COM 和 .NET 客户端访问自动化应用程序。
- 迁移到 .NET 平台而不会丢失现有功能。
- 可以独立创建系统的各个部分。
- 可以逐步使用重新设计的 .NET 版本更新旧应用程序。
Visual Studio 2005 特定
VS2005 有一个与将 .NET 公开给 COM 相关的怪癖。 在将所需的属性应用于类和接口后,需要打开 AssemblyInfo.cs 并手动修改下一行
[assembly: ComVisible(true)]
如果没有此行,则所有访问 COM 接口的尝试都将失败。