Windowsアプリケーション(C#)があり、一度にアプリケーションから1つのインスタンスを実行するように構成する必要があります。これは、1人のユーザーが.exeファイルをクリックしてアプリケーションが実行され、ユーザーが最初のインスタンスを閉じなかったことを意味します。実行中のアプリケーションの次のインスタンスを実行する必要があるため、最初のインスタンスが表示され、新しいインスタンスは開かないはずです。
誰かが私にそれをする方法を手伝ってくれる?
前もって感謝します
私はよく同じ名前の他のプロセスをチェックすることでこれを解決します。これの長所/短所は、exeの名前を変更することで、あなた(またはユーザー)がチェックから「離れる」ことができることです。望まない場合は、返されたProcess-objectを使用できます。
string procName = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcessesByName(procName).Length == 1)
{
...code here...
}
必要に応じて、再コンパイルせずにチェックをバイパスするのが便利だと思います(これはサーバープロセスであり、サービスとして実行されることもあります)。
VB.Netチームはすでにソリューションを実装しています。Microsoft.VisualBasic.dllに依存する必要がありますが、それが気にならない場合は、これは私見の良い解決策です。次の記事の最後を参照してください:シングルインスタンスアプリ
記事の関連部分は次のとおりです。
1)Microsoft.VisualBasic.dllへの参照を追加します。2)プロジェクトに次のクラスを追加します。
public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private SingleInstanceApplication()
{
base.IsSingleInstance = true;
}
public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
{
SingleInstanceApplication app = new SingleInstanceApplication();
app.MainForm = f;
app.StartupNextInstance += startupHandler;
app.Run(Environment.GetCommandLineArgs());
}
}
Program.csを開き、次のusingステートメントを追加します。
using Microsoft.VisualBasic.ApplicationServices;
クラスを次のように変更します。
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
SingleInstanceApplication.Run(new Form1(), StartupNextInstanceEventHandler);
}
public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e)
{
MessageBox.Show("New instance");
}
}
編集:質問がc#を含むように修正された後。私の答えはvb.netアプリケーションでのみ機能します
ユーザーがアプリケーションの複数のインスタンスを実行できないようにするには、[単一インスタンスアプリケーションを作成する]チェックボックスをオンにします。このチェックボックスのデフォルト設定はオフになっており、アプリケーションの複数のインスタンスを実行できます。
これは、[プロジェクト]->[プロパティ]->[アプリケーション]タブから実行できます。
まったく同じ問題がありました。プロセスアプローチを試しましたが、ユーザーが他のプロセス、つまり管理者以外のプロセスに関する情報を読む権利がない場合、これは失敗します。そこで、以下のソリューションを実装しました。
基本的に、私たちは排他的な読み取りのためにファイルを開こうとします。これが失敗した場合(anohterインスタンスがすでにこれを行っているため)、例外が発生し、アプリを終了できます。
bool haveLock = false;
try
{
lockStream = new System.IO.FileStream(pathToTempFile,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite,System.IO.FileShare.None);
haveLock = true;
}
catch(Exception)
{
System.Console.WriteLine("Failed to acquire lock. ");
}
if(!haveLock)
{
Inka.Controls.Dialoge.InkaInfoBox diag = new Inka.Controls.Dialoge.InkaInfoBox("App has been started already");
diag.Size = new Size(diag.Size.Width + 40, diag.Size.Height + 20);
diag.ShowDialog();
Application.Exit();
}
C#を使用していると仮定します
static Mutex mx;
const string singleInstance = @"MU.Mutex";
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
try
{
System.Threading.Mutex.OpenExisting(singleInstance);
MessageBox.Show("already exist instance");
return;
}
catch(WaitHandleCannotBeOpenedException)
{
mx = new System.Threading.Mutex(true, singleInstance);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
Mutex
このシナリオではを使用します。あるいは、aSemaphore
も機能します(ただし、Mutex
より適切なようです)。
これが私の例です(WPFアプリケーションからのものですが、同じ原則が他のプロジェクトタイプにも適用されるはずです):
public partial class App : Application
{
const string AppId = "MY APP ID FOR THE MUTEX";
static Mutex mutex = new Mutex(false, AppId);
static bool mutexAccessed = false;
protected override void OnStartup(StartupEventArgs e)
{
try
{
if (mutex.WaitOne(0))
mutexAccessed = true;
}
catch (AbandonedMutexException)
{
//handle the rare case of an abandoned mutex
//in the case of my app this isn't a problem, and I can just continue
mutexAccessed = true;
}
if (mutexAccessed)
base.OnStartup(e);
else
Shutdown();
}
protected override void OnExit(ExitEventArgs e)
{
if (mutexAccessed)
mutex?.ReleaseMutex();
mutex?.Dispose();
mutex = null;
base.OnExit(e);
}
}
私はこのコードを見つけました、それはうまくいきました!
/// <summary>
/// The main entry point for the application.
/// Limit an app.to one instance
/// </summary>
[STAThread]
static void Main()
{
//Mutex to make sure that your application isn't already running.
Mutex mutex = new System.Threading.Mutex(false, "MyUniqueMutexName");
try
{
if (mutex.WaitOne(0, false))
{
// Run the application
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
MessageBox.Show("An instance of the application is already running.",
"An Application Is Running", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Application Error 'MyUniqueMutexName'",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (mutex != null)
{
mutex.Close();
mutex = null;
}
}
}