Trong .NET, cách tốt nhất để ngăn nhiều phiên bản của một ứng dụng chạy cùng một lúc là gì? Và nếu không có kỹ thuật "tốt nhất", một số lưu ý cần xem xét với mỗi giải pháp là gì?
Trong .NET, cách tốt nhất để ngăn nhiều phiên bản của một ứng dụng chạy cùng một lúc là gì? Và nếu không có kỹ thuật "tốt nhất", một số lưu ý cần xem xét với mỗi giải pháp là gì?
Câu trả lời:
Sử dụng Mutex. Một trong những ví dụ trên sử dụng GetProcessByName có nhiều cảnh báo. Đây là một bài viết tốt về chủ đề:
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;
sẽ lấy hướng dẫn của hội đồng thi hành
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;
}
Đây là mã bạn cần để đảm bảo rằng chỉ có một phiên bản đang chạy. Đây là phương pháp sử dụng một mutex có tên.
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 có một bài đăng về việc sử dụng lớp WinFormsApplicationBase từ hội đồng Microsoft.VisualBasic để làm điều này.
Có vẻ như có 3 kỹ thuật cơ bản đã được đề xuất cho đến nay.
Có bất kỳ cảnh báo nào tôi đã bỏ lỡ?
1 - Tạo một tài liệu tham khảo trong chương trình.cs ->
using System.Diagnostics;
2 - Đặt vào void Main()
làm dòng mã đầu tiên ->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
Đó là nó.
Mutex
gì? Có bắt được không?
Sử dụng Visual Studio 2005 hoặc 2008 khi bạn tạo dự án để thực thi, trên các cửa sổ thuộc tính bên trong bảng "Ứng dụng" có một hộp kiểm có tên là Tạo một ứng dụng cá thể đơn lẻ mà bạn có thể kích hoạt để chuyển đổi ứng dụng trên một ứng dụng cá thể .
Đây là một bản chụp cửa sổ mà tôi đang nói đến:
Đây là một dự án ứng dụng cửa sổ Visual Studio 2008.
tôi đã thử tất cả các giải pháp ở đây và không có gì hoạt động trong dự án C # .net 4.0 của tôi. Hy vọng sẽ giúp được ai đó ở đây giải pháp hiệu quả cho tôi:
Là biến lớp chính:
private static string appGuid = "WRITE AN UNIQUE GUID HERE";
private static Mutex mutex;
Khi bạn cần kiểm tra xem ứng dụng đã chạy chưa:
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
}
Tôi cần phải đóng các istances khác chỉ với một số điều kiện, điều này hoạt động tốt cho mục đích của tôi
http://en.csharp-online.net/Application_Arch architecture_in_Windows_Forms_2.0.
Sau khi thử nhiều giải pháp tôi câu hỏi. Tôi đã kết thúc bằng cách sử dụng ví dụ cho WPF tại đây: 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();
}
}
}
Trong App.xaml:
x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Bài viết này chỉ giải thích cách bạn có thể tạo một ứng dụng windows với quyền kiểm soát số lượng phiên bản của nó hoặc chỉ chạy một thể hiện duy nhất. Đây là nhu cầu rất điển hình của một ứng dụng kinh doanh. Đã có rất nhiều giải pháp khả thi khác để kiểm soát điều này.
http://www.openwinforms.com/single_instance_application.html
Sử dụng VB.NET! Không: thực sự;)
sử dụng Microsoft.VisualBasic.ApplicationService;
WindowsFormsApplicationBase từ VB.Net cung cấp cho bạn Thuộc tính "SingleInstace", xác định các Trường hợp khác và chỉ cho phép một Trường hợp chạy.
Đây là mã cho 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
Đây là mã cho 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());
}
}
Bạn phải sử dụng System.Diagnostics.Process.
Kiểm tra: http://www.devx.com/tips/Tip/20044
(Lưu ý: đây là một giải pháp thú vị! Nó hoạt động nhưng sử dụng thiết kế GDI + xấu để đạt được điều này.)
Đặt một hình ảnh với ứng dụng của bạn và tải nó khi khởi động. Giữ nó cho đến khi ứng dụng thoát. Người dùng sẽ không thể bắt đầu phiên bản thứ 2. (Tất nhiên giải pháp mutex sạch hơn nhiều)
private static Bitmap randomName = new Bitmap("my_image.jpg");
Main()
phương pháp đi ngược lại cách WPF hoạt động.
[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!
}
Từ: Đảm bảo một phiên bản duy nhất của Ứng dụng .NET
Câu trả lời tương tự như @Smink và @Imjustpondering với một twist:
Câu hỏi thường gặp của Jon Skeet về C # để tìm hiểu lý do tại sao GC.KeepAlive quan trọng
Đơn giản chỉ cần sử dụng một StreamWriter
, làm thế nào về điều này?
System.IO.File.StreamWriter OpenFlag = null; //globally
và
try
{
OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
Environment.Exit(0);
}
Thông thường, nó được thực hiện với Mutex có tên (sử dụng Mutex mới ("tên ứng dụng của bạn", đúng) và kiểm tra giá trị trả về), nhưng cũng có một số lớp hỗ trợ trong Microsoft.VisualBasic.dll có thể làm điều đó cho bạn .
Điều này làm việc cho tôi trong C # tinh khiết. thử / bắt là khi có thể một quá trình trong danh sách thoát trong vòng lặp của bạn.
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());
}
Hãy chắc chắn xem xét bảo mật khi giới hạn ứng dụng trong một trường hợp duy nhất:
Bài viết đầy đủ: https://bloss.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
Chúng tôi đang sử dụng một mutex có tên với một tên cố định để phát hiện xem một bản sao khác của chương trình có đang chạy hay không. Nhưng điều đó cũng có nghĩa là kẻ tấn công có thể tạo ra mutex trước, do đó ngăn chương trình của chúng tôi không chạy! Làm thế nào tôi có thể ngăn chặn loại tấn công từ chối dịch vụ này?
...
Nếu kẻ tấn công đang chạy trong cùng bối cảnh bảo mật như chương trình của bạn (hoặc sẽ) đang chạy, thì bạn không thể làm gì được. Bất cứ "cái bắt tay bí mật" nào bạn nghĩ ra để xác định xem một bản sao khác của chương trình của bạn có đang chạy hay không, kẻ tấn công có thể bắt chước nó. Vì nó đang chạy trong bối cảnh bảo mật chính xác, nó có thể làm bất cứ điều gì mà chương trình "thực" có thể làm.
...
Rõ ràng bạn không thể tự bảo vệ mình khỏi kẻ tấn công chạy cùng đặc quyền bảo mật, nhưng bạn vẫn có thể tự bảo vệ mình trước những kẻ tấn công không có đặc quyền chạy ở các đặc quyền bảo mật khác.
Hãy thử thiết lập một DACL trên mutex của bạn, đây là cách .NET: https://msdn.microsoft.com/en-us/l Library / system.security.accesscontrol.mutexsecurity (v = vs.110) .aspx
Không có câu trả lời nào phù hợp với tôi vì tôi cần nó để hoạt động trong Linux bằng cách sử dụng phát triển đơn. Điều này làm việc rất tốt cho tôi:
Gọi phương thức này là ID duy nhất
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);
}
}