Jawaban:
Gunakan Mutex. Salah satu contoh di atas menggunakan GetProcessByName memiliki banyak peringatan. Berikut adalah artikel bagus tentang masalah ini:
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;yang akan mendapatkan panduan rakitan pelaksana
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;
}
Berikut adalah kode yang Anda perlukan untuk memastikan bahwa hanya satu instance yang berjalan. Ini adalah metode menggunakan mutex bernama.
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();
}
}
}
Hanselman memiliki posting tentang menggunakan kelas WinFormsApplicationBase dari rakitan Microsoft.VisualBasic untuk melakukan ini.
Sepertinya ada 3 teknik dasar yang telah disarankan sejauh ini.
Ada peringatan yang saya lewatkan?
1 - Buat referensi di program.cs ->
using System.Diagnostics;
2 - Dimasukkan void Main()sebagai baris pertama kode ->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
Itu dia.
Mutex? Apakah ada tangkapan?
Menggunakan Visual Studio 2005 atau 2008 ketika Anda membuat proyek untuk eksekusi, pada jendela properti di dalam panel "Aplikasi" ada kotak centang bernama "Buat aplikasi contoh tunggal" yang dapat Anda aktifkan untuk mengonversi aplikasi pada aplikasi contoh tunggal .
Berikut adalah tangkapan dari jendela yang saya bicarakan:
Ini adalah proyek aplikasi Windows Visual Studio 2008.
saya mencoba semua solusi di sini dan tidak ada yang berhasil dalam proyek C # .net 4.0 saya. Berharap dapat membantu seseorang di sini solusi yang berhasil untuk saya:
Sebagai variabel kelas utama:
private static string appGuid = "WRITE AN UNIQUE GUID HERE";
private static Mutex mutex;
Saat Anda perlu memeriksa apakah aplikasi sudah berjalan:
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
}
Saya perlu menutup istance lain hanya dengan beberapa kondisi, ini bekerja dengan baik untuk tujuan saya
http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0 —Single-Instance_Detection_and_Management
Setelah mencoba beberapa solusi saya pertanyaannya. Saya akhirnya menggunakan contoh untuk WPF di sini: 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();
}
}
}
Di App.xaml:
x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Artikel ini hanya menjelaskan bagaimana Anda dapat membuat aplikasi windows dengan kontrol pada jumlah instance-nya atau menjalankan hanya satu instance. Ini adalah kebutuhan yang sangat khas dari aplikasi bisnis. Sudah ada banyak solusi lain yang mungkin untuk mengendalikan ini.
http://www.openwinforms.com/single_instance_application.html
Ini adalah kode untuk 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
Ini adalah kode untuk 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());
}
}
Anda harus menggunakan System.Diagnostics.Process.
(Catatan: ini adalah solusi yang menyenangkan! Ini berfungsi tetapi menggunakan desain GDI + yang buruk untuk mencapai ini.)
Masukkan gambar ke dalam aplikasi Anda dan muat saat memulai. Tahan sampai aplikasi keluar. Pengguna tidak akan dapat memulai instance kedua. (Tentu saja solusi mutex jauh lebih bersih)
private static Bitmap randomName = new Bitmap("my_image.jpg");
Main()metode yang bertentangan dengan bagaimana WPF seharusnya bekerja.
[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!
}
Dari: Memastikan satu contoh Aplikasi .NET
dan: Mutex Aplikasi Instance Tunggal
Jawaban yang sama dengan @Smink dan @Imjustpondering dengan twist:
FAQ Jon Skeet tentang C # untuk mencari tahu mengapa GC.KeepAlive penting
Cukup menggunakan a StreamWriter, bagaimana dengan ini?
System.IO.File.StreamWriter OpenFlag = null; //globally
dan
try
{
OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
Environment.Exit(0);
}
Biasanya ini dilakukan dengan Mutex bernama (gunakan Mutex baru ("nama aplikasi Anda", benar) dan periksa nilai yang dikembalikan), tetapi ada juga beberapa kelas dukungan di Microsoft.VisualBasic.dll yang dapat melakukannya untuk Anda .
Ini bekerja untuk saya di C # murni. coba / tangkap adalah ketika kemungkinan proses dalam daftar keluar selama loop Anda.
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());
}
Pastikan untuk mempertimbangkan keamanan saat membatasi aplikasi ke satu instance:
Artikel lengkap: https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
Kami menggunakan mutex bernama dengan nama tetap untuk mendeteksi apakah salinan lain dari program sedang berjalan. Tetapi itu juga berarti penyerang dapat membuat mutex terlebih dahulu, sehingga mencegah program kita berjalan sama sekali! Bagaimana cara mencegah serangan penolakan layanan jenis ini?
...
Jika penyerang berjalan dalam konteks keamanan yang sama dengan program Anda (atau akan) berjalan, maka tidak ada yang dapat Anda lakukan. Apapun "jabat tangan rahasia" yang Anda buat untuk menentukan apakah salinan lain dari program Anda sedang berjalan, penyerang dapat menirunya. Karena berjalan dalam konteks keamanan yang benar, ia dapat melakukan apa saja yang dapat dilakukan oleh program "sebenarnya".
...
Jelas Anda tidak dapat melindungi diri Anda dari penyerang yang menjalankan hak istimewa keamanan yang sama, tetapi Anda masih dapat melindungi diri Anda dari penyerang yang tidak memiliki hak istimewa yang menjalankan hak keamanan lainnya.
Coba atur DACL di mutex Anda, berikut cara .NET: https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx
Tak satu pun dari jawaban ini berhasil untuk saya karena saya membutuhkan ini untuk bekerja di Linux menggunakan monodevelop. Ini bagus untuk saya:
Panggil metode ini dengan meneruskan ID unik
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);
}
}