使用 WPF 创建单实例应用程序
一个简单的例子就是大家在使用很多应用程序,例如在使用Microsoft Word 时会遇到一种情况,不管你打开多少个文档,系统一次只能加载一个winword.exe 实例。当打开新文档时,文档在新窗口显示,但是始终只有一个应用程序控制所有文档窗口;如:可以提供平铺当前所有文档中相邻窗口的文档的特性。
对于创建单实例的应用程序,WPF本身没有提供自带的解决方法,但可以通过变通的方式来实现——思路是当触发ApplicationStartup事件时,检查另一个实例是否在运行。方法是通过使用全局的mutex对像(mutex是操做系统中提供的用于进程间通信的同步方法)。虽然简单,但功能有限,如新实例无法与已经存在的实例进行通信。尤其是对于基于文档的用于程序而言,这确实是一个问题,如果新实例需要告诉已经存在的实例打开一个新的文档或者该文档是通过命令行参数传递的情况,那该使用什么方法来解决问题呢??
WPF团队推荐我们一种最简单的方法就是:使用Windows 窗体提供的内置支持,该内置支持最初是用于VisualBasic 应用程序的,使用Window窗体和VisualBasic 的这一特新来开发基于C#的WPF程序会存在一个新旧应用程序之分,本质上旧式应用程序充当了WPF应用程序的封装器。流程是:当启动程序时将创建旧式应用程序,旧式应用程序接着创建WPF应用程序,旧式应用程序处理实例管理,而WPF应用程序处理正真的应用。
下面我们通过一个实例来演示创建单实例应用程序的具体步骤:
一.创建WPF窗体项目,并添加Microsoft.VisualBasic.dll 引用。
二.首先创建一个Document.xaml,和 DocumentList.xaml 窗口文件,使用定义的类DocumentReference 表示对Document引用。
DocumentReference :
public class DocumentReference
{
private Document document;
public Document Document
{
get { return document; }
set { document = value; }
} private string name;
public string Name
{
get { return name; }
set { name = value; }
} public DocumentReference(Document document, string name)
{
Document = document;
Name = name;
}
}
Document.LoadFile() 通过文件名读取文档内容,Document.OnClosed() 事件在文档窗体关闭时触发,用于从动态集合移除实例。
public partial class Document : Window
{
private DocumentReference docRef; public Document()
{
InitializeComponent();
} public void LoadFile(DocumentReference docRef)
{
this.docRef = docRef;
this.Content = File.ReadAllText(docRef.Name);
this.Title = docRef.Name;
} protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
((WpfApp)Application.Current).Documents.Remove(docRef);
} }
DocumentList 窗体放置一个 <ListBox Name="lstDocuments"></ListBox> 的 lstDocuments控件,用于显示当前文档列表。
public partial class DocumentList : Window
{
public DocumentList()
{
InitializeComponent(); lstDocuments.DisplayMemberPath = "Name";
lstDocuments.ItemsSource = ((WpfApp)Application.Current).Documents;
}
}
三.接着创建一个自定义的WPF类WpfApp.cs,该类继承于Windows.Application。在这里每当通过命令行参数传递给SingleInstanceApplication 类文件名时,会触发 SingleInstanceApplication 类的 OnStartupNextInstance 方法,并调用自定义的 ShowDocument() 方法为指定的文档加载文档窗体。
WpfApp:
public class WpfApp : Application
{
private ObservableCollection<DocumentReference> documents =
new ObservableCollection<DocumentReference>();
public ObservableCollection<DocumentReference> Documents
{
get { return documents; }
set { documents = value; }
} protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
//WpfApp.Current = this; DocumentList list = new DocumentList();
this.MainWindow = list;
list.Show(); // Load the document that was specified as an argument.
if (e.Args.Length > ) ShowDocument(e.Args[]); } public void ShowDocument(string fileName)
{
try
{
Document doc = new Document();
DocumentReference docRef = new DocumentReference(doc, fileName);
doc.LoadFile(docRef);
doc.Owner = this.MainWindow;
doc.Show();
doc.Activate();
Documents.Add(docRef);
}
catch
{
MessageBox.Show("Could not load document.");
}
}
}
四.创建继承于WindowsFormsApplicationBase 的自定义类 SingleInstanceApplication.cs 该类将提供3个用于管理实例的重要成员。
- IsSingleInstance 用于确定此应用程序是否为单实例应用程序,在构造函数中设置值为true。
- 重写 OnStartup(),程序启动时,重写该方法并创建WPF应用程序对象。
- 重写 OnStartupNextInstance(),当另一个应用程序启动时触发该方法,该方法提供了访问命令行的参数的功能。此时可以调用WPF应用程序类的方法来创建窗口,但不能创建另一个应用程序对象。
SingleInstanceApplication:
public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private WpfApp App;
public SingleInstanceApplication()
{
this.IsSingleInstance = true;
} protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
{
string extension = ".testDoc";
string title = "SingleInstanceApplication";
string extensionDescription = "A Test Document"; //return base.OnStartup(eventArgs);
App = new WpfApp();
App.Run();
return false;
} protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
//base.OnStartupNextInstance(eventArgs);
if (eventArgs.CommandLine.Count > )
App.ShowDocument(eventArgs.CommandLine[]);
}
}
五. 由于应用程序需要在APP类之前就要创建SingleInstanceApplication 类,所以这里就需要同过传统的Main方法作为启动入口。
public class Startup
{
[STAThread]
public static void Main(string[] args)
{
SingleInstanceApplication wrapper = new SingleInstanceApplication();
wrapper.Run(args);
}
}
六,为了测试单例程序,需要使用Window文件扩展名与程序相关联,将其文件类型注册。运行结果如下:
使用 WPF 创建单实例应用程序的更多相关文章
- WPF学习笔记 - 如何用WPF创建单实例应用程序
使用一个已命名的(操作系统范围的)互斥量. bool mutexIsNew; using(System.Threading.Mutex m = new System.Threading.Mulex(t ...
- WPF点滴(2) 创建单实例应用程序
最近有同事问道在应用程序启动之后,再次双击应用程序,如何保证不再启动新的应用程序,而是弹出之前已经启动的进程,本质上这就是创建一个单实例的WPF应用程序.在VS的工程树中有一个App.xaml和App ...
- WPF 单实例应用程序
例如:Microsoft Word,不管打开多少个文档(也不管它们是如何打开的),一次只能加载 winword.exe 一个实例. 这便是单实例应用程序. 对于这种单实例应用程序,WPF 本身并未提供 ...
- [WPF]WPF设置单实例启动
WPF设置单实例启动 使用Mutex设置单实例启动 using System; using System.Threading; using System.Windows; namespace Test ...
- WPF使用Mutex创建单实例程序失效
vs2019 1.引入名称空间 using System.Threading; using System.Runtime.InteropServices; 2.导入dll并声明方法 [DllImpor ...
- Oracle - 给rac创建单实例dg,并做主从切换
一.概述 本文将介绍如何给rac搭建单节点的dg,以及如何对其进行角色转换.预先具备的知识(rac搭建,单实例-单实例dg搭建) 二.实验环境介绍 主库rac(已安装rac,并已有数据库orcl)ra ...
- 关于struts和Spring 结合到一起之后存在ACtion创建单实例还是多
struts 2的Action是多实例的并非单例,也就是每次请求产生一个Action的对象.原因是:struts 2的Action中包含数据,例如你在页面填写的数据就会包含在Action的成员变量里面 ...
- C# 实现单实例程序
在我们经常使用的软件中,当我们已经打开后,再次打开时,有的软件不会出现两个.例如有道词典,会将上次的界面显示出来,或者提示我们“该程序已经运行...”.我通过一个简单的C# WPF例子来说明. 首先我 ...
- DevExpress Winform使用单例运行程序方法和非DevExpress使用Mutex实现程序单实例运行且运行则激活窗体的方法
原文:DevExpress Winform使用单例运行程序方法和非DevExpress使用Mutex实现程序单实例运行且运行则激活窗体的方法 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA ...
随机推荐
- 算法起步之Prim算法
原文:算法起步之Prim算法 prim算法是另一种最小生成树算法.他的安全边选择策略跟kruskal略微不同,这点我们可以通过一张图先来了解一下. prim算法的安全边是从与当前生成树相连接的边中选择 ...
- brutal是什么意思_brutal在线翻译_英语_读音_用法_例句_海词词典
brutal是什么意思_brutal在线翻译_英语_读音_用法_例句_海词词典 brutal
- DataGirdView 设置单元格居中
设置标题行居中: dgvShow.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter ...
- python语言学习8——字符串和编码
Unicode编码 计算机只能处理数字,如果要处理文本,就必须把文本转化为数字才能处理 有许多编码标准,但是不同的编码标准有时候会混乱,所以Unicode应运而生 Unicode把所有语言统一到一套编 ...
- JavaWeb 项目中的绝对路径和相对路径以及问题的解决方式
近期在做JavaWeb项目,总是出现各种的路径错误,并且发现不同情况下 / 所代表的含义不同,导致在调试路径上浪费了大量时间. 在JavaWeb项目中尽量使用绝对路径 由于使用绝对路径是绝对不会出 ...
- java中常用的字符串的截取方法
java中常用的字符串的截取方法 1.length() 字符串的长度 例:char chars[]={'a','b'.'c'}; String s=new String(chars); int l ...
- hdu3886(数位dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3886 题意:给一定区间[A,B],一串由/,\,-组成的符号串.求满足符号串的数字个数. •/表示数字 ...
- 安卓---项目中插入百度地图sdk
百度地图 应用里面 自带地图 搜房网 下载百度地图的sdk 熟悉api 注冊百度开发人员的账号 2.12 仅仅要有一个ak就能够 高版本号须要提供应用程序的包名和签名返回开发人员的序列号 使用百度地图 ...
- HttpClient(联网)
抽样: void GameRequest::initRequset(const char* url, cocos2d::CCObject* pTarget, cocos2d::SEL_CallFunc ...
- Cacti监控Tomcatserver实现过程
1 首先去官网上面下载通用的监控模板 一般使用TomcatStats-0.1.zip 模板居多,下载地址: http://forums.cacti.net/download/file.php?id=1 ...