.NET에서 특정 앱의 여러 인스턴스를 방지합니까?
.NET에서 여러 앱 인스턴스가 동시에 실행되지 않도록하는 가장 좋은 방법은 무엇입니까? "최상의"기술이 없다면 각 솔루션에서 고려해야 할 몇 가지주의 사항은 무엇입니까?
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";
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 가지 기본 기술이있는 것 같습니다.
- Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase 클래스에서 파생하고 IsSingleInstance 속성을 true로 설정하십시오. (여기서 경고는 WPF 응용 프로그램에서 작동하지 않는다는 것입니다.)
- 명명 된 뮤텍스를 사용하고 이미 생성되었는지 확인하십시오.
- 실행중인 프로세스 목록을 가져 와서 프로세스 이름을 비교하십시오. (이는 주어진 사용자의 컴퓨터에서 실행되는 다른 프로세스와 비교하여 프로세스 이름이 고유해야한다는 경고가 있습니다.)
내가 놓친 경고가 있습니까?
실행 파일 용 프로젝트를 만들 때 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
}
어떤 조건에서만 다른 자세를 취해야했습니다. 이것은 내 목적에 잘 작동했습니다.
http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0 — 단일 인스턴스 _ 감지 _ 및 _ 관리
1-program.cs에서 참조 작성->
using System.Diagnostics;
2- void Main()
코드의 첫 줄로 입력->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
그게 다야.
이 기사에서는 인스턴스 수를 제어하거나 단일 인스턴스 만 실행할 수있는 Windows 애플리케이션을 작성하는 방법에 대해서만 설명합니다. 이것은 비즈니스 응용 프로그램의 매우 일반적인 요구입니다. 이를 제어 할 수있는 다른 많은 솔루션이 이미 있습니다.
http://www.openwinforms.com/single_instance_application.html
VB.NET을 사용하십시오! 아니오 : 정말로;)
Microsoft.VisualBasic.ApplicationServices 사용;
VB.Net의 WindowsFormsApplicationBase는 "SingleInstace"속성을 제공하여 다른 인스턴스를 결정하고 하나의 인스턴스 만 실행하도록합니다.
http://www.codeproject.com/KB/cs/SingleInstancingWithIpc.aspx
System.Diagnostics.Process를 사용해야합니다.
체크 아웃 : http://www.devx.com/tips/Tip/20044
이것은 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());
}
}
(Note: this is a fun-solution! It works but uses bad GDI+ design to achieve this.)
Put an image in with your app and load it on startup. Hold it until the app exits. The user wont be able to start a 2nd instance. (Of course the mutex solution is much cleaner)
private static Bitmap randomName = new Bitmap("my_image.jpg");
After trying multiple solutions i the question. I ended up using the example for WPF here: 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();
}
}
}
In App.xaml:
x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
[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: Ensuring a single instance of .NET Application
and: Single Instance Application Mutex
Same answer as @Smink and @Imjustpondering with a twist:
Jon Skeet's FAQ on C# to find out why GC.KeepAlive matters
Simply using a StreamWriter
, how about this?
System.IO.File.StreamWriter OpenFlag = null; //globally
and
try
{
OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
Environment.Exit(0);
}
Normally it's done with a named Mutex (use new Mutex( "your app name", true ) and check the return value), but there's also some support classes in Microsoft.VisualBasic.dll that can do it for you.
This worked for me in pure C#. the try/catch is when possibly a process in the list exits during your loop.
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());
}
Be sure to consider security when restricting an application to a single instance:
Full article: https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
We are using a named mutex with a fixed name in order to detect whether another copy of the program is running. But that also means an attacker can create the mutex first, thereby preventing our program from running at all! How can I prevent this type of denial of service attack?
...
If the attacker is running in the same security context as your program is (or would be) running in, then there is nothing you can do. Whatever "secret handshake" you come up with to determine whether another copy of your program is running, the attacker can mimic it. Since it is running in the correct security context, it can do anything that the "real" program can do.
...
분명히 동일한 보안 권한으로 실행되는 공격자로부터 자신을 보호 할 수는 없지만 다른 보안 권한으로 실행되는 권한이없는 공격자로부터 자신을 보호 할 수 있습니다.
뮤텍스에서 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);
}
}
참고 URL : https://stackoverflow.com/questions/93989/prevent-multiple-instances-of-a-given-app-in-net
'Programing' 카테고리의 다른 글
Phonegap Cordova 설치 창 (0) | 2020.07.14 |
---|---|
구조체가 상속을 지원하지 않는 이유는 무엇입니까? (0) | 2020.07.14 |
파라미터로 메소드를 문서화하는 방법은 무엇입니까? (0) | 2020.07.14 |
JavaScript와 Lua의 미묘한 차이점 (0) | 2020.07.14 |
배쉬 : 구문 오류 : 예기치 않은 리디렉션 (0) | 2020.07.14 |