知乎周源微信
I got an interesting question recently emphasis mine:
我最近遇到一个有趣的问题,重点是我的:
I am regular reader of you blog. I need some help in single instance winform. I have to open application when a file (.ext) is clicked (File is associated with that application like .doc with WINWORD). Application should be single instance. When I click the .ext file it should open the application with that content. If an instance is runnng it should ask the user whether you want to close this application and then open the new .ext file. Need help in C#.
我是您博客的定期读者。 我在单实例winform中需要一些帮助。 单击文件(.ext)时,我必须打开应用程序(文件与该应用程序相关联,例如带有WINWORD的.doc)。 应用程序应为单个实例。 当我单击.ext文件时,应打开包含该内容的应用程序。 如果实例正在运行,则应询问用户是否要关闭此应用程序,然后打开新的.ext文件。 在C#中需要帮助。
Some questions are more interesting than others, but I think we've all had to solve this "Single Instance" problem over and over again over the last 15 years. I did this with a Dan Appleman VBX in Visual Basic 3 and I've seen piles of solutions with Mutexes and all sorts of overly complex dancing to solve this apparently simple problem. This is a really old technique, but three years later, there's just not enough people that know that the WindowsFormsApplicationBase class exists and has a lot of useful functionality in it.
有些问题比其他问题有趣,但我认为在过去的15年中,我们都不得不一遍又一遍地解决这个“单实例”问题。 我在Visual Basic 3中使用Dan Appleman VBX进行了此操作,并且看到了成堆的互斥解决方案以及各种过分复杂的舞蹈来解决这个看似简单的问题。 这是一种非常古老的技术,但是三年之后,没有足够的人知道WindowsFormsApplicationBase类的存在,并且其中包含许多有用的功能。
There was an interesting thread over here about handling this. Someone asked the question and someone said "WinForms 2.0 has support for single instance apps built in." and the next guy said "Only for Visual Basic applications, though."
这里有一个有趣的线程来处理这个问题。 有人问这个问题,有人说“ WinForms 2.0支持内置的单实例应用程序。” 下一个家伙说:“不过,仅适用于Visual Basic应用程序。”
Microsoft.VisualBasic.dll has got to be one of the most useful standard installed parts of the .NET Framework out there. Folks are afraid to reference it from C#. It feels wrong.
Microsoft.VisualBasic.dll必须成为.NET Framework中最有用的标准安装部分之一。 人们害怕从C#引用它。 感觉不对。
Kind of like busting out with French words in the middle of English sentences, referencing Microsoft.VisualBasic.dll has that je ne sais quoi that tends to give C# folks a feeling of mal de mer but that assembly has a specific raison d'être. See? Feels wrong, but it still works. There's good stuff in Microsoft.VisualBasic.dll, and just because it isn't System.Something doesn't mean you shouldn't reference it with abandon. Go nuts.
引用Microsoft.VisualBasic.dll有点像在英语句子的中间用法语单词抽空,它具有je ne sais quoi的特征,倾向于使C#人士感觉不良,但该汇编具有特定的存在理由。 看到? 感觉不对,但仍然可以使用。 Microsoft.VisualBasic.dll中有很多东西,仅仅是因为它不是System.Something并不意味着您不应该放弃它。 发疯。
Back to the problem. There's many examples, but the easiest one I've seen was over at OpenWinForms.com and it was written in C# referencing Microsoft.VisualBasic.dll. I've modified it here to make a single instance app that will open a text file name passed in on the command line. If you call the same application a second time, it'll take the new command line argument and load that text file in the first instance.
回到问题。 有很多示例,但是我见过的最简单的示例是在OpenWinForms.com上,它是用C#编写的,引用了Microsoft.VisualBasic.dll。 我在这里对其进行了修改,以制作一个单实例应用程序,该应用程序将打开在命令行中传递的文本文件名。 如果您第二次调用相同的应用程序,它将使用新的命令行参数,并在第一个实例中加载该文本文件。
Launching it as "SuperSingleInstance foo.txt" from a command line...
从命令行将其作为“ SuperSingleInstance foo.txt ”启动...
Then, from the same command line, while the first one runs, launching a second "SuperSingleInstance bar.txt" from a command line. The first instance is reused, brought to the front, and gets an event letting us know someone tried to launch us and that event includes the new command line.
然后,在同一命令行中,第一个运行时,从命令行启动第二个“ SuperSingleInstance bar.txt ”。 第一个实例被重用,放在最前面,并获得一个事件,让我们知道有人试图启动我们,并且该事件包括新的命令行。
The code is really cool as all the work is in WindowsFormsApplicationBase. It's a little confusing because you have to call a controller instance and tell it about your MainForm, rather than calling Application.Run(). The StartupNextInstance event is called in your first application when a second instance of your app gets fired up. It talks cross process between the new second instance and your original one and passes over the command line.
该代码真的很酷,因为所有工作都在WindowsFormsApplicationBase中。 这有点令人困惑,因为您必须调用控制器实例并将其告知您的MainForm,而不是调用Application.Run()。 当您的应用程序的第二个实例启动时,将在第一个应用程序中调用StartupNextInstance事件。 它讨论新的第二个实例和您的原始实例之间的交叉过程,并通过命令行传递。
using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;
namespace SuperSingleInstance
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string[] args = Environment.GetCommandLineArgs();
SingleInstanceController controller = new SingleInstanceController();
controller.Run(args);
}
}
public class SingleInstanceController : WindowsFormsApplicationBase
{
public SingleInstanceController()
{
IsSingleInstance = true;
StartupNextInstance += this_StartupNextInstance;
}
void this_StartupNextInstance(object sender, StartupNextInstanceEventArgs e)
{
Form1 form = MainForm as Form1; //My derived form type
form.LoadFile(e.CommandLine[1]);
}
protected override void OnCreateMainForm()
{
MainForm = new Form1();
}
}
}
The Form is trivial, just loading the text from the file into a TextBox.
表单很简单,只需将文件中的文本加载到TextBox中即可。
using System;
using System.Windows.Forms;
using System.IO;
namespace SuperSingleInstance
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string[] args = Environment.GetCommandLineArgs();
LoadFile(args[1]);
}
public void LoadFile(string file)
{
textBox1.Text = File.ReadAllText(file);
}
}
}
There's other nice functionality in WindowsFormsApplicationBase like support for SplashScreens and network availability events. Again, check out the good stuff over at http://www.openwinforms.com/, like the Controller I used in this post.
WindowsFormsApplicationBase中还有其他不错的功能,例如对SplashScreens和网络可用性事件的支持。 再次,在http://www.openwinforms.com/上检查好东西,例如我在本文中使用的Controller。
知乎周源微信