我如何在我的C#程序面板中运行另一个应用程序?

我一直在阅读如何从C#程序(Process.Start())中触发应用程序,但是我一直没有find任何有关如何让这个新应用程序在我的C#程序面板中运行的信息。 例如,我想点击一个button,在我的应用程序中打开一个notepad.exe,而不是外部。

我不知道这是否仍然是推荐使用,但“对象链接和embedded”框架允许您将某些对象/控件直接embedded到应用程序中。 这可能只适用于某些应用程序,我不确定记事本是否是其中之一。 对于非常简单的事情,如记事本,你可能会有一个更简单的时间,只要使用任何媒体提供的文本框控件(例如WinForms)。

这里有一个OLE信息的链接开始:

http://en.wikipedia.org/wiki/Object_Linking_and_Embedding

使用win32 API可以“吃”另一个应用程序。 基本上,你得到该应用程序的顶部窗口,并设置它的父母是要放置它的面板的句柄。如果你不想要的MDI风格效果,你也必须调整窗口风格,使其最大化和删除标题栏。

这里有一些简单的示例代码,我有一个button和一个面板的窗体:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; namespace WindowsFormsApplication2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Process p = Process.Start("notepad.exe"); Thread.Sleep(500); // Allow the process to open it's window SetParent(p.MainWindowHandle, panel1.Handle); } [DllImport("user32.dll")] static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); } } 

我刚刚看到另一个例子,他们叫WaitForInputIdle而不是睡觉。 所以代码会是这样的:

 Process p = Process.Start("notepad.exe"); p.WaitForInputIdle(); SetParent(p.MainWindowHandle, panel1.Handle); 

代码项目有一个好的文章整个过程: 在WinForm项目中托pipeEXE应用程序

  • 在答案中添加一些解决scheme.. **

这段代码帮助我将一些可执行文件停靠在窗体中。 像记事本,Excel,单词,Acrobat阅读器n更多…

但它不适用于某些应用程序。 有时当你启动一些应用程序的进程….等待空闲时间…并尝试获取其mainWindowHandle ….直到主窗口句柄成为空…..

所以我已经做了一个窍门来解决这个问题

如果你得到主窗口句柄为空…然后search系统上的所有运行进程,并find你的过程…然后获取进程的主hadle和设置面板作为其父。

  ProcessStartInfo info = new ProcessStartInfo(); info.FileName = "xxxxxxxxxxxx.exe"; info.Arguments = "yyyyyyyyyy"; info.UseShellExecute = true; info.CreateNoWindow = true; info.WindowStyle = ProcessWindowStyle.Maximized; info.RedirectStandardInput = false; info.RedirectStandardOutput = false; info.RedirectStandardError = false; System.Diagnostics.Process p = System.Diagnostics.Process.Start(info); p.WaitForInputIdle(); Thread.Sleep(3000); Process[] p1 ; if(p.MainWindowHandle == null) { List<String> arrString = new List<String>(); foreach (Process p1 in Process.GetProcesses()) { // Console.WriteLine(p1.MainWindowHandle); arrString.Add(Convert.ToString(p1.ProcessName)); } p1 = Process.GetProcessesByName("xxxxxxxxxxxx"); //p.WaitForInputIdle(); Thread.Sleep(5000); SetParent(p1[0].MainWindowHandle, this.panel2.Handle); } else { SetParent(p.MainWindowHandle, this.panel2.Handle); } 

如果你想在你的应用程序中运行记事本,你可能会更好的文本编辑器组件。 显然WinForms附带了一个基本的文本框,但是我怀疑可以在Interweb上find提供记事本function(或更好)的更高级的组件。

我知道这是可能的,如果其他应用程序可以附加到一个win32窗口句柄。 例如,我们有一个单独的C#应用​​程序,在其窗口之一中托pipeDirectX应用程序。 我并不熟悉如何实现它的具体细节,但我认为只要将面板的win32 Handle传递给其他应用程序就足以让该应用程序附加其DirectX表面。

我注意到,所有以前的答案使用较旧的Win32用户库函数来完成这一点。 我认为这在大多数情况下都可以工作,但是随着时间的推移,工作会变得不可靠

现在,没有这样做,我不能告诉你它将如何工作,但我知道,目前的Windows技术可能是一个更好的解决scheme: 桌面Windowspipe理器API 。

DWM是相同的技术,可以让你看到使用任务栏和任务切换器用户界面的应用程序的实时缩略图预览。 我相信这与远程terminal服务密切相关。

我认为,当你强迫一个应用程序成为不是桌面窗口的父窗口的孩子时,可能发生的一个可能的问题是,一些应用程序开发人员会假设设备上下文(DC),指针(鼠标)的位置,屏幕宽度等等,当它被“embedded”在主窗口中时,这可能导致不稳定或有问题的行为。

我怀疑你可以通过依靠DWM来帮助你pipe理必要的翻译,以便可靠地显示应用程序的窗口,并与另一个应用程序的容器窗口内部进行交互,从而大大消除这些问题。

该文档假定C ++编程,但我发现一个人谁已经产生他声称是一个开源的C#包装库: https : //bytes.com/topic/c-sharp/answers/823547-desktop-window-manager-wrapper 。 该post是旧的,而来源是不是像GitHub,bitbucket或sourceforge大仓库,所以我不知道它是如何目前。

另外一个有趣的解决scheme是使用WinForm容器安装一个exeternal应用程序,如下所示:

 [DllImport("user32.dll")] static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); private void Form1_Load(object sender, EventArgs e) { ProcessStartInfo psi = new ProcessStartInfo("notepad.exe"); psi.WindowStyle = ProcessWindowStyle.Minimized; Process p = Process.Start(psi); Thread.Sleep(500); SetParent(p.MainWindowHandle, panel1.Handle); CenterToScreen(); psi.WindowStyle = ProcessWindowStyle.Normal; } 

从ProcessWindowStyle.Normal ProcessWindowStyle.Minimized的步骤消除恼人的延迟。

在这里输入图像描述

简答:

没有

Shortish答案:

只有在其他应用程序被devise为允许它的时候,通过为你提供组件来添加到你自己的应用程序中。