在前一个实例中打开文件——SharpDevelop分析笔记
来源:互联网 发布:手机抢票软件下载 编辑:程序博客网 时间:2024/04/29 12:17
在前一个实例中打开文件
——SharpDevelop分析笔记
当我们在windows文件夹中双击一个文件的时候,有的程序可以实现在一个已经打开的应用程序中打开该文件。在sharpdevelop中提供了类似的实现。
原理是,在新开的应用程序实例中将接收到的参数,主要是文件名,写到一个临时的文件中,然后在window进程中寻找前一个实例,并向其主窗口发送自定义消息。而前一个实例的主窗口会捕获这个自定义消息,并从临时文件夹中读取参数信息,然后打开这些文件。
下面我们看具体实现。
从系统启动到主画面显示主要用到以下几个class.
SharpDevelopMain:这是存放应用程序入口Main函数的类,Main函数主要实现启动splashForm,并试图找到前一个实例并从前一个实例打开文件,如果没有前一个实例的话,就通过SharpDevelopHost的RunWorkbench方法开启主窗口。
这里我们主要介绍试图找到前一个实例并从前一个实例打开文件的这条路线。
首先SplashForm这个类接收命令行参数并从中找到要打开的文件列表。然后Main函数调用SingleInstanceHelper这个类的OpenFilesInPreviousInstance方法。下面具体看这个方法的内容。
public static bool OpenFilesInPreviousInstance(string[] fileList)
{
LoggingService.Info("Trying to pass arguments to previous instance...");
//获取当前进程的Id
int currentProcessId = Process.GetCurrentProcess().Id;
//获取入口Assembly的文件名
string currentFile = Assembly.GetEntryAssembly().Location;
//产生一个随机数
int number = new Random().Next();
//用这个随机数生成一个临时文件名
string fileName = Path.Combine(Path.GetTempPath(), "sd" + number + ".tmp");
try {
//将要打来的文件列表写入临时文件夹
File.WriteAllLines(fileName, fileList);
List<IntPtr> alternatives = new List<IntPtr>();
//循环所有进程名称为"SharpDevelop"的进程
foreach (Process p in Process.GetProcessesByName("SharpDevelop")) {
//忽略掉当前进程
if (p.Id == currentProcessId) continue;
//从主模块的文件名再次确认是否本系统进程
if (FileUtility.IsEqualFileName(currentFile, p.MainModule.FileName)) {
//取得该进程的主窗口的窗口句柄
IntPtr hWnd = p.MainWindowHandle;
if (hWnd != IntPtr.Zero) {
//向该窗口发送自定义消息,消息中包含存放要打开的文件列表的临时文件名,本次发送消息,是优先选择没有打开任何文件的进程。
long result = NativeMethods.SendMessage(hWnd, CUSTOM_MESSAGE, new IntPtr(number), IntPtr.Zero).ToInt64();
if (result == RESULT_FILES_HANDLED) {
return true;
} else if (result == RESULT_PROJECT_IS_OPEN) {
//已经打开文件的进程放入列表
alternatives.Add(hWnd);
}
}
}
}
//当所有的进程都已经打开文件的情况下,则用第一个进程打开文件。
foreach (IntPtr hWnd in alternatives) {
if (NativeMethods.SendMessage(hWnd, CUSTOM_MESSAGE, new IntPtr(number), new IntPtr(1)).ToInt64()== RESULT_FILES_HANDLED) {
return true;
}
}
return false;
} finally {
File.Delete(fileName);
}
}
可以看到,这段代码首先把要打开的文件列表写到一个以随机数命名的文本文件中,然后找到前一个进程的主窗口句柄,并向其发送Windows消息,消息中包含存放着要打开的文件名列表的文本文件的文件名。
而SharpDevelop进程的主窗口正是DefaultWorkbench类的实例。该类覆写了Form类的WndProc方法。
protected override void WndProc(ref Message m)
{
if (!SingleInstanceHelper.PreFilterMessage(ref m)) {
base.WndProc(ref m);
}
}
当这个窗口的实例接受到Windows消息的时候,这个方法会被系统调用。这个方法的内容是,首先调用SingleInstanceHelper.PreFilterMessage方法,返回值为False的时候,调用父类的WndProc方法。
那么,SingleInstanceHelper.PreFilterMessage的内容是什么呢。
internal static bool PreFilterMessage(ref Message m)
{
if (m.Msg != CUSTOM_MESSAGE)
return false;
long fileNumber = m.WParam.ToInt64();
long openEvenIfProjectIsOpened = m.LParam.ToInt64();
LoggingService.Info("Receiving custom message...");
//如果收到的消息是寻找没有打开任何文件的进程,并且当前进程已经打开文件的情况下,返回RESULT_PROJECT_IS_OPEN。否则用当前进程打开文件。
if (openEvenIfProjectIsOpened == 0 && ProjectService.OpenSolution != null) {
m.Result = new IntPtr(RESULT_PROJECT_IS_OPEN);
} else {
m.Result = new IntPtr(RESULT_FILES_HANDLED);
try {
//将当前进程的主窗口设为前台窗口。
WorkbenchSingleton.SafeThreadAsyncCall(delegate { NativeMethods.SetForegroundWindow(WorkbenchSingleton.MainForm.Handle) ; });
foreach (string file in File.ReadAllLines(Path.Combine(Path.GetTempPath(), "sd" + fileNumber + ".tmp"))) {
WorkbenchSingleton.SafeThreadAsyncCall(delegate(string openFileName) { FileService.OpenFile(openFileName); }, file);
}
} catch (Exception ex) {
LoggingService.Warn(ex);
}
}
return true;
}
这段代码是在符合条件的进程中打开文件。具体由FileService.OpenFile方法来实现。
这样就大致实现了在前面进程打开文件的功能。
这里简单提一下WndProc方法。可能没有做过Win32编程的朋友不太熟悉。
Windows操作系统是一个基于消息的窗口系统,该系统通过向窗口发送消息,并由窗口来响应消息来实现用户交互。在dotnet开发中,如果继承了Form类,就利用了Windows的窗口功能。Form类的WndProc方法用来处理送到该窗口的消息,被系统调用。该方法处理Windows的内置消息,比如最大化,最小化。我们也可以发送自定义消息,但是默认的WndProc方法不会处理自定义消息。这就需要我们覆写WndProc方法来处理自定义消息。
- 在前一个实例中打开文件——SharpDevelop分析笔记
- SharpDevelop源代码分析笔记
- SharpDevelop学习笔记(4)——SharpDevelop的核心
- SharpDevelop源码分析笔记(一)
- SharpDevelop学习笔记(5)—— AddIns系统详解
- SharpDevelop学习笔记(2)——体系结构
- SharpDevelop学习笔记(6)—— AddIn构建指南
- sharpdevelop中如何加载addin文件
- C# 在Sharpdevelop 中使用资源文件
- Android中 WebView打开一个网页实例
- Windows下自定义文件类型如何双击打开,如何双击文件后都在一个实例中打开
- SharpDevelop代码分析
- Sharpdevelop如何在项目中添加类文件
- SharpDevelop 使用笔记
- 使用jprofiler分析dump文件一个实例
- app中根据路径打开一个文件
- 11orange 打开文件操作从上到下的一个实例源码
- C# Winform中打开一个新进程+实例
- 实训C++语言设计——文件和流
- 浅析C++中的this指针
- Asp.NET Ajax学习笔记(4) -- Ajax.NET源程序分析2
- 实训C++语言设计——异常处理
- JAVA开发者应该去的20个英文网站
- 在前一个实例中打开文件——SharpDevelop分析笔记
- RedHat 7.x 专题:TCP Wrapper and xinetd (之一)
- PHP比ASP优秀的七个理由
- RedHat 7.x 专题:TCP Wrapper and xinetd (之三)
- 搜索模块思路及代码说明
- PHP 中执行系统外部命令
- 文件的各种操作
- 改变一生的100句至理明言
- PHP中的Linq-用SQL语法操作PHP数组