回答:
Mutexを使用します。GetProcessByNameを使用した上記の例の1つには、多くの警告があります。これは主題に関する良い記事です:
http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
[STAThread]
static void Main()
{
using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
{
if(!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance already running");
return;
}
Application.Run(new Form1());
}
}
private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), true)[0]).Value;これにより、実行中のアセンブリのGUIDが取得されます
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
{
AppLog.Write("Application XXXX already running. Only one instance of this application is allowed", AppLog.LogMessageType.Warn);
return;
}
以下は、1つのインスタンスのみが実行されていることを確認するために必要なコードです。これは、名前付きミューテックスを使用する方法です。
public class Program
{
static System.Threading.Mutex singleton = new Mutex(true, "My App Name");
static void Main(string[] args)
{
if (!singleton.WaitOne(TimeSpan.Zero, true))
{
//there is already another instance running!
Application.Exit();
}
}
}
これまでに提案されてきた3つの基本的なテクニックがあるようです。
私が見逃した警告はありますか?
1-program.csに参照を作成します->
using System.Diagnostics;
2- void Main()コードの最初の行として配置->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
それでおしまい。
Mutexですか?落とし穴はありますか?
実行可能ファイルのプロジェクトを作成するときにVisual Studio 2005または2008を使用すると、[アプリケーション]パネル内のプロパティウィンドウに、[単一インスタンスアプリケーションを作成する]というチェックボックスがあり、これをアクティブにして、単一インスタンスアプリケーションでアプリケーションを変換できます。 。
これが私が話しているウィンドウのキャプチャです:
これはVisual Studio 2008のウィンドウアプリケーションプロジェクトです。
ここですべてのソリューションを試しましたが、私のC#.net 4.0プロジェクトでは何も機能しませんでした。私のために働いた解決策をここの誰かを助けることを願っています:
主なクラス変数として:
private static string appGuid = "WRITE AN UNIQUE GUID HERE";
private static Mutex mutex;
アプリが既に実行されているかどうかを確認する必要がある場合:
bool mutexCreated;
mutex = new Mutex(true, "Global\\" + appGuid, out mutexCreated);
if (mutexCreated)
mutex.ReleaseMutex();
if (!mutexCreated)
{
//App is already running, close this!
Environment.Exit(0); //i used this because its a console app
}
私はいくつかの条件でのみ他のインスタンスを閉じる必要がありました、これは私の目的のためにうまくいきました
http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0 —Single-Instance_Detection_and_Management
複数のソリューションを試した後、私は質問します。ここでWPFの例を使用することになりました:http : //www.c-sharpcorner.com/UploadFile/f9f215/how-to-restrict-the-application-to-just-one-instance/
public partial class App : Application
{
private static Mutex _mutex = null;
protected override void OnStartup(StartupEventArgs e)
{
const string appName = "MyAppName";
bool createdNew;
_mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
//app is already running! Exiting the application
Application.Current.Shutdown();
}
}
}
App.xamlで:
x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
この記事では、インスタンスの数を制御する、または単一のインスタンスのみを実行するWindowsアプリケーションを作成する方法について簡単に説明します。これは、ビジネスアプリケーションの非常に一般的なニーズです。これを制御する他の可能な解決策はすでにたくさんあります。
http://www.openwinforms.com/single_instance_application.html
これはVB.Netのコードです
Private Shared Sub Main()
Using mutex As New Mutex(False, appGuid)
If Not mutex.WaitOne(0, False) Then
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
Application.Run(New Form1())
End Using
End Sub
これはC#のコードです
private static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid)) {
if (!mutex.WaitOne(0, false)) {
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Application.Run(new Form1());
}
}
System.Diagnostics.Processを使用する必要があります。
チェックアウト:http : //www.devx.com/tips/Tip/20044
(注:これは楽しいソリューションです!機能しますが、これを実現するために不適切なGDI +デザインを使用しています。)
アプリに画像を入れて、起動時にロードします。アプリが終了するまで押し続けます。ユーザーは2番目のインスタンスを開始できません。(もちろん、mutexソリューションはよりクリーンです)
private static Bitmap randomName = new Bitmap("my_image.jpg");
Main()WPFの動作方法に反する方法も必要です。
[STAThread]
static void Main() // args are OK here, of course
{
bool ok;
m = new System.Threading.Mutex(true, "YourNameHere", out ok);
if (! ok)
{
MessageBox.Show("Another instance is already running.");
return;
}
Application.Run(new Form1()); // or whatever was there
GC.KeepAlive(m); // important!
}
@Sminkと@Imjustponderingをひねりを加えたのと同じ答え:
GC.KeepAliveが重要である理由を見つけるためのC#に関するJon SkeetのFAQ
これは私にとっては純粋なC#で機能しました。try / catchは、リスト内のプロセスがループ中に終了する可能性がある場合です。
using System.Diagnostics;
....
[STAThread]
static void Main()
{
...
int procCount = 0;
foreach (Process pp in Process.GetProcesses())
{
try
{
if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0)
{
procCount++;
if(procCount > 1) {
Application.Exit();
return;
}
}
}
catch { }
}
Application.Run(new Form1());
}
アプリケーションを単一のインスタンスに制限する場合は、セキュリティを考慮してください。
完全な記事:https : //blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
プログラムの別のコピーが実行されているかどうかを検出するために、固定名の名前付きミューテックスを使用しています。ただし、これは攻撃者が最初にミューテックスを作成できるため、プログラムがまったく実行されないことも意味します。このタイプのサービス拒否攻撃を防ぐにはどうすればよいですか?
...
攻撃者がプログラムが実行されているのと同じセキュリティコンテキストで実行されている場合(または実行される可能性がある場合)、実行できることは何もありません。プログラムの別のコピーが実行されているかどうかを判断するために思いつく「秘密のハンドシェイク」が何であれ、攻撃者はそれを模倣できます。正しいセキュリティコンテキストで実行されているため、「実際の」プログラムで実行できることは何でも実行できます。
...
明らかに、同じセキュリティ特権で実行されている攻撃者から身を守ることはできませんが、他のセキュリティ特権で実行されている権限のない攻撃者から身を守ることはできます。
ミューテックスにDACLを設定してみてください。これが.NETの方法です。https: //msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v = vs.110).aspx
Linuxでは、monodevelopを使用して作業するためにこれが必要だったため、この回答はどれもうまくいきませんでした。これは私にとってはうまくいきます:
一意のIDを渡してこのメソッドを呼び出します
public static void PreventMultipleInstance(string applicationId)
{
// Under Windows this is:
// C:\Users\SomeUser\AppData\Local\Temp\
// Linux this is:
// /tmp/
var temporaryDirectory = Path.GetTempPath();
// Application ID (Make sure this guid is different accross your different applications!
var applicationGuid = applicationId + ".process-lock";
// file that will serve as our lock
var fileFulePath = Path.Combine(temporaryDirectory, applicationGuid);
try
{
// Prevents other processes from reading from or writing to this file
var _InstanceLock = new FileStream(fileFulePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_InstanceLock.Lock(0, 0);
MonoApp.Logger.LogToDisk(LogType.Notification, "04ZH-EQP0", "Aquired Lock", fileFulePath);
// todo investigate why we need a reference to file stream. Without this GC releases the lock!
System.Timers.Timer t = new System.Timers.Timer()
{
Interval = 500000,
Enabled = true,
};
t.Elapsed += (a, b) =>
{
try
{
_InstanceLock.Lock(0, 0);
}
catch
{
MonoApp.Logger.Log(LogType.Error, "AOI7-QMCT", "Unable to lock file");
}
};
t.Start();
}
catch
{
// Terminate application because another instance with this ID is running
Environment.Exit(102534);
}
}