本文主要是介绍多个可执行程序协同工作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
背景
最近的项目涉及到一个漫游场景和多个小实验室,一开始是把小实验室和漫游场景放置在一个工程下面并且通过场景切换的方式来链接跳转。考虑到网络应用的大趋势和程序的扩展性,这样做下去实在是难以维护日渐增加的小实验室场景和逻辑。
实现
本文将实现一个大场景打开小场景并且可以跳转回大场景和功能,这个功能建立在window平台提供的Api的基础上,涉及到程序窗口的隐藏显示,初始进程参数的传递。还有一点,虽然是在unity3d开发的程序中使用,但最后实现的场景跳转控制器应该能在任何c#开发的程序中使用.
一、设计界面
目的的设计一个程序,可以打开同样的程序可以观察到实现的效果。功能按扭和显示信息的文字组合一个形成如下的一个界面程序:
点击打开子程序将弹出文件选择窗口,实现exe文件的选中,如果打开成功,这个窗口将隐藏。同时被打开的程序中的父级窗口将显示刚才隐藏窗口的句柄(用于还原隐藏的窗口)。如果点击关闭本程序,这样程序的进行将终止,同时还原隐藏的那个程序。这样不可以无缝的实现场景的切换同时兼顾应用程序的扩展性了。
二,接口设计
有了界面显示,当然想写一个通用的场景切换的控制器(Controller),需要实现的也就保存父级句柄,接收程序初始的参数,打开子窗口,关闭子窗口还有自身关闭的清理掉所打开的进程。(bool hideThis,这个变量用于不想隐藏父级窗口)
public interface IWindowSwitchCtrl {
IntPtr Parent { get; }
bool OnOpenedByParent(out string[] args);
bool OpenChildWindow(string path,bool hideThis,params string[] args);
bool CloseChildWindow();
void OnCloseThisWindow();
}
三,实现参数传入
unity3d程序可以在程序进行的Awake中调用控制器获取参数,接口的实现部分如下(参数用空格分割,本程序中默认第三位起为用户参数)
/// <summary>
/// 仅当第二个参数为1时,隐藏父级
/// </summary>
/// <param name="pwindow"></param>
/// <param name="hideParent"></param>
public bool OnOpenedByParent(out string[] argus)
{
hideParent = false;
parentWindow = IntPtr.Zero;
argus = null;
string[] CommandLineArgs = Environment.GetCommandLineArgs();
if (CommandLineArgs.Length == 1)
{
//无参数
return false;
}
if (CommandLineArgs.Length > 1)
{
parentWindow = new IntPtr(int.Parse(CommandLineArgs[1]));
}
if (CommandLineArgs.Length > 2)
{
hideParent = new IntPtr(int.Parse(CommandLineArgs[2])) == (IntPtr)1;
}
if (CommandLineArgs.Length > 3)
{
argus = new string[CommandLineArgs.Length - 3];
for (int i = 0; i < argus.Length; i++)
{
argus[i] = CommandLineArgs[(i + 3)];
}
}
if (hideParent)
{
User32.ShowWindow(parentWindow, WindowShowStyle.Hide);
}
return true;
}
本程序将获取到的参数将显示在对应的小框中,父级句柄显示为3540948...
四、用进程打开程序并传入参数
上面一步已经实现了接收参数的功能,下面是打开进程并传入参数的方法
/// <summary>
/// 打开一个子窗口,并记录
/// </summary>
/// <param name="path"></param>
/// <param name="hideThis"></param>
public bool OpenChildWindow(string path, bool hideThis,params string[] args)
{
if (childProcess == null|| childProcess.HasExited)
{
if (System.IO.File.Exists(path))
{
ProcessStartInfo startInfo = new ProcessStartInfo(path);
startInfo.Arguments = (WindowCalc.GetCurrProcessWnd() + " " + (hideThis ? 1 : 0).ToString()).ToString();
for (int i = 0; i < args.Length; i++)
{
startInfo.Arguments += " " + args[i];
}
startInfo.UseShellExecute = true;
startInfo.WindowStyle = ProcessWindowStyle.Normal;
childProcess = new Process();
childProcess.StartInfo = startInfo;
childProcess.Start();
return true;
}
}
return false;
}
这一中先判断了文件是否存在,不存在将不会开启进行以及后续操作。一但进程开启,将对应的参数传入就可以了。同时如果需要就可将自己的窗口进行隐藏处理
五,隐藏窗口
/// <summary>
/// 关闭所有打开的窗口
/// </summary>
public void OnCloseThisWindow()
{
CloseChildWindow();
if (hideParent)
{
User32.ShowWindow(parentWindow, WindowShowStyle.Show);
}
}
在关闭所打开的窗口的同时,要将上一个窗口打开,否则只能去进程管理器关程序啦。
六、Demo其他功能
window程序开发过程中可以使用很多window自己提供的api接口可以省不少事,比如本程序中打开选择文件的窗口就是调用Comdlg32内的方法实现的
七,程序源码
github地址:https://github.com/zouhunter/WindowSwitch
这篇关于多个可执行程序协同工作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!