답변:
Mutex를 사용하십시오. GetProcessByName을 사용하는 위의 예제 중 하나에는 많은주의 사항이 있습니다. 다음은 주제에 대한 좋은 기사입니다.
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;
}
다음은 하나의 인스턴스 만 실행되도록하는 데 필요한 코드입니다. 이것은 명명 된 뮤텍스를 사용하는 방법입니다.
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 은이를 위해 Microsoft.VisualBasic 어셈블리의 WinFormsApplicationBase 클래스를 사용하는 것에 대한 게시물 을 가지고 있습니다.
지금까지 제안 된 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 Windows 응용 프로그램 프로젝트입니다.
여기에서 모든 솔루션을 시도했지만 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
}
일부 조건에서만 다른 istance를 닫을 필요가 있었는데 이것은 내 목적에 잘 맞았습니다.
http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0 - 단 - 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를 사용해야합니다.
(참고 : 이것은 재미있는 솔루션입니다! 작동하지만 잘못된 GDI + 디자인을 사용하여이를 달성합니다.)
앱에 이미지를 넣고 시작할 때로드합니다. 앱이 종료 될 때까지 누르고 있습니다. 사용자는 두 번째 인스턴스를 시작할 수 없습니다. (물론 뮤텍스 솔루션은 훨씬 깨끗합니다)
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!
}
From : .NET 응용 프로그램의 단일 인스턴스 보장
@Smink 및 @Imjustpondering과 동일한 답변 :
GC.KeepAlive가 중요한 이유를 알아보기위한 Jon Skeet의 C # FAQ
일반적으로 이름이 지정된 Mutex (new Mutex ( "your app name", true) 사용 및 반환 값 확인)로 수행되지만 Microsoft.VisualBasic.dll에는이 를 수행 할 수있는 일부 지원 클래스도 있습니다 .
이것은 순수한 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
monodevelop을 사용하여 Linux에서 작업하는 데 필요했기 때문에이 답변 중 어느 것도 나를 위해 일하지 않았습니다. 이것은 나를 위해 잘 작동합니다.
이 메서드를 호출하여 고유 한 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);
}
}