通过 C# API 调用 Windows Forms 应用程序
Calling a Windows Forms Application via C# API
我有一个用 C# 编写的 windows 表单应用程序,它允许我指向图像文件夹并将这些图像解析为用户易于查看的格式。这是一个独立的应用程序,运行良好。我想扩展这个应用程序,这样我就可以把它交给一个预建的数据集,而不是解析一个图像文件夹,所有的图像和元数据都由外部应用程序通过 API.
我已经能够将应用程序编译成 class 库并访问 classes 和结构来实际构建数据集而没有问题,我现在遇到的问题是启动使用我构建的数据集在外部应用程序。
对于上下文,我正在编写一个工具,允许用户从 Spotfire 调用此 windows 表单应用程序。在 spotfire 中,我正在解析一个 DataTable 对象并根据我拥有的信息构建数据集。构建此数据集后,我需要能够将应用程序作为独立进程启动,而不是在 Spotfire 内部显式调用表单。 (这是由于 Spotfire 中 GUI 线程的限制,我们不能在单线程应用程序中调用多线程进程,而且我们希望保持 Spotfire GUI 响应,如果我们直接调用表单则无法做到这一点)
我知道我可以使用 Process.Start() 独立启动 exe,但是这不允许我将我的信息传递给应用程序。我如何构建此应用程序以允许我将信息传递给它?我一直在尝试 google 如何做到这一点的例子,并不断空手而归,因为人们会参考 ASP.net 或我无法理解的事情。
提前致谢!
编辑:下面是一个很好地处理这个问题的应用程序示例。我们使用 DPlot Jr 在外部创建图形。 dplot.dll 公开了以下函数:
[System.Runtime.InteropServices.DllImport("dplotlib64.dll")]
public static extern int DPlot_Plot8(
ref DPLOT d, double[] x, double[] y, string cmds);
然后我可以在我的代码中使用它
docNum = dplot.DPlot_Plot8(ref dPlot, X, Y, cmds);
docNums.Add(docNum);
以这种方式调用此函数实际上会启动 dplot 应用程序并传递我构建的对象 "dPlot" 以及 X 和 Y 数据以绘制信息。我想在我的 windows 表单应用程序中构建这样的东西,以便能够从外部应用程序轻松启动它。不幸的是,我不知道这个函数在 .dll
中是如何工作的
EDIT2:我已经能够按照 Aybe 的建议通过命令行修改运行时。在我的桌面应用程序中,我在主程序中创建了一个条件,就像这样。
if (args.Length == 0 && false)
{
Application.Run(new frmWaveFormViewer());
}
else
{
DataSet dataSet = new DataSet();
//dataSet.LoadMetaData(args[0]);
dataSet.LoadMetaData(@"C:\Users\a0273881\AppData\Local\Temp\tmp1141.tmp");
Application.Run(new frmWaveFormViewer(dataSet));
}
然后用户可以使用以下命令从外部调用表单...
DataSet dataSet = new DataSet(dpList);
dataSet.PrintDatasetMetadataToFile(String.Format(@"C:\Spotfire\DataSetTesting_{0}.csv", DateTime.Now.ToString("yyyyMMdd_HHmmss")));
string args = dataSet.GetMetaData();
ProcessStartInfo starter = new ProcessStartInfo();
starter.FileName = @"C:\Users\a0273881\Desktop\WaveFormViewer.exe";
starter.Arguments = args;
Process.Start(starter);
但是,这对其他开发人员来说并不容易使用。
我开始研究 WCF,谁能为傻瓜提供有关 WCF 的良好资源?我目前正在通读:http://www.codemag.com/article/0705041
我已经能够在应用程序启动时在其上生成一个 NamedPipeServer。命名的管道服务器用应用程序的名称+它生成的进程 ID 来命名自己。进程号记录到用户 appdata 文件夹中的 ini 文件中。该过程可以使用可选的命令行参数启动,以影响 "callingApplication" 的值,即 INI Header。这样,我们可以从不同的调用者创建应用程序的多个实例,而不会干扰并确保连接到正确的命名管道。
static void Main(string[] args)
{
string callingApplication = "None";
if (args.Length != 0)
{
callingApplication = args[0];
}
int pId = Process.GetCurrentProcess().Id;
PipeServer.StartPipeServer(pId, callingApplication);
// do things
PipeServer.StopPipeServer();
}
通过 public 静态 class 中可用的 public 函数访问 PipeClient 端。通过管道连接的函数都位于一个单独的 PipeClient class 中。这些函数需要生成的进程 ID 才能连接到正确的管道。这些 api 函数可以从 api
启动或 return 所需的管道
public static class API
{
public static int SendCommand(int aKey, ...)
{
try
{
PipeClient.StartCommandSendClient(input, aKey);
}
catch (TimeoutException)
{
// returns error codes based on exceptions
}
return 0;
}
}
因此,我设法在两个应用程序之间创建了一个 link。在此之前真正需要的是通过 API class 公开的方法的自定义实现,这些方法也具有要调用的自定义客户端方法。从我的调用应用程序调用所有这些都非常简单...
int aKey = API.GetKey("callingAppName");
API.SendCommand(aKey, "[Reset()][AddPoint(arg1, arg2, arg3)]");
我有一个用 C# 编写的 windows 表单应用程序,它允许我指向图像文件夹并将这些图像解析为用户易于查看的格式。这是一个独立的应用程序,运行良好。我想扩展这个应用程序,这样我就可以把它交给一个预建的数据集,而不是解析一个图像文件夹,所有的图像和元数据都由外部应用程序通过 API.
我已经能够将应用程序编译成 class 库并访问 classes 和结构来实际构建数据集而没有问题,我现在遇到的问题是启动使用我构建的数据集在外部应用程序。
对于上下文,我正在编写一个工具,允许用户从 Spotfire 调用此 windows 表单应用程序。在 spotfire 中,我正在解析一个 DataTable 对象并根据我拥有的信息构建数据集。构建此数据集后,我需要能够将应用程序作为独立进程启动,而不是在 Spotfire 内部显式调用表单。 (这是由于 Spotfire 中 GUI 线程的限制,我们不能在单线程应用程序中调用多线程进程,而且我们希望保持 Spotfire GUI 响应,如果我们直接调用表单则无法做到这一点)
我知道我可以使用 Process.Start() 独立启动 exe,但是这不允许我将我的信息传递给应用程序。我如何构建此应用程序以允许我将信息传递给它?我一直在尝试 google 如何做到这一点的例子,并不断空手而归,因为人们会参考 ASP.net 或我无法理解的事情。
提前致谢!
编辑:下面是一个很好地处理这个问题的应用程序示例。我们使用 DPlot Jr 在外部创建图形。 dplot.dll 公开了以下函数:
[System.Runtime.InteropServices.DllImport("dplotlib64.dll")]
public static extern int DPlot_Plot8(
ref DPLOT d, double[] x, double[] y, string cmds);
然后我可以在我的代码中使用它
docNum = dplot.DPlot_Plot8(ref dPlot, X, Y, cmds);
docNums.Add(docNum);
以这种方式调用此函数实际上会启动 dplot 应用程序并传递我构建的对象 "dPlot" 以及 X 和 Y 数据以绘制信息。我想在我的 windows 表单应用程序中构建这样的东西,以便能够从外部应用程序轻松启动它。不幸的是,我不知道这个函数在 .dll
中是如何工作的EDIT2:我已经能够按照 Aybe 的建议通过命令行修改运行时。在我的桌面应用程序中,我在主程序中创建了一个条件,就像这样。
if (args.Length == 0 && false)
{
Application.Run(new frmWaveFormViewer());
}
else
{
DataSet dataSet = new DataSet();
//dataSet.LoadMetaData(args[0]);
dataSet.LoadMetaData(@"C:\Users\a0273881\AppData\Local\Temp\tmp1141.tmp");
Application.Run(new frmWaveFormViewer(dataSet));
}
然后用户可以使用以下命令从外部调用表单...
DataSet dataSet = new DataSet(dpList);
dataSet.PrintDatasetMetadataToFile(String.Format(@"C:\Spotfire\DataSetTesting_{0}.csv", DateTime.Now.ToString("yyyyMMdd_HHmmss")));
string args = dataSet.GetMetaData();
ProcessStartInfo starter = new ProcessStartInfo();
starter.FileName = @"C:\Users\a0273881\Desktop\WaveFormViewer.exe";
starter.Arguments = args;
Process.Start(starter);
但是,这对其他开发人员来说并不容易使用。
我开始研究 WCF,谁能为傻瓜提供有关 WCF 的良好资源?我目前正在通读:http://www.codemag.com/article/0705041
我已经能够在应用程序启动时在其上生成一个 NamedPipeServer。命名的管道服务器用应用程序的名称+它生成的进程 ID 来命名自己。进程号记录到用户 appdata 文件夹中的 ini 文件中。该过程可以使用可选的命令行参数启动,以影响 "callingApplication" 的值,即 INI Header。这样,我们可以从不同的调用者创建应用程序的多个实例,而不会干扰并确保连接到正确的命名管道。
static void Main(string[] args)
{
string callingApplication = "None";
if (args.Length != 0)
{
callingApplication = args[0];
}
int pId = Process.GetCurrentProcess().Id;
PipeServer.StartPipeServer(pId, callingApplication);
// do things
PipeServer.StopPipeServer();
}
通过 public 静态 class 中可用的 public 函数访问 PipeClient 端。通过管道连接的函数都位于一个单独的 PipeClient class 中。这些函数需要生成的进程 ID 才能连接到正确的管道。这些 api 函数可以从 api
启动或 return 所需的管道public static class API
{
public static int SendCommand(int aKey, ...)
{
try
{
PipeClient.StartCommandSendClient(input, aKey);
}
catch (TimeoutException)
{
// returns error codes based on exceptions
}
return 0;
}
}
因此,我设法在两个应用程序之间创建了一个 link。在此之前真正需要的是通过 API class 公开的方法的自定义实现,这些方法也具有要调用的自定义客户端方法。从我的调用应用程序调用所有这些都非常简单...
int aKey = API.GetKey("callingAppName");
API.SendCommand(aKey, "[Reset()][AddPoint(arg1, arg2, arg3)]");