.NET- এ, একই সাথে কোনও অ্যাপ্লিকেশনটির একাধিক ঘটনা চালানো থেকে রোধ করার সর্বোত্তম উপায় কী? এবং যদি কোনও "সেরা" কৌশল না থাকে তবে প্রতিটি সমাধানের সাথে বিবেচনা করার মতো কিছু সাবধানবাণী কী?
.NET- এ, একই সাথে কোনও অ্যাপ্লিকেশনটির একাধিক ঘটনা চালানো থেকে রোধ করার সর্বোত্তম উপায় কী? এবং যদি কোনও "সেরা" কৌশল না থাকে তবে প্রতিটি সমাধানের সাথে বিবেচনা করার মতো কিছু সাবধানবাণী কী?
উত্তর:
Mutex ব্যবহার করুন। গেটপ্রসেসবাইনেম ব্যবহার করে উপরের উদাহরণগুলির মধ্যে একটিতে অনেকগুলি সতর্কতা রয়েছে। এখানে বিষয় সম্পর্কে একটি ভাল নিবন্ধ:
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;
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();
}
}
}
হ্যানসেলম্যানের মাইক্রোসফ্ট থেকে উইনফরমস অ্যাপ্লিকেশনবেস ক্লাসটি ব্যবহার করার জন্য একটি পোস্ট রয়েছে is এটি করার জন্য ভিজুয়ালবাসিক সমাবেশ।
দেখে মনে হচ্ছে 3 টি মৌলিক কৌশল রয়েছে যা এখন পর্যন্ত পরামর্শ দেওয়া হয়েছে।
কোন অনুমান আমি মিস করেছি?
1 - program.cs -> এ একটি রেফারেন্স তৈরি করুন
using System.Diagnostics;
2 - void Main()কোডের প্রথম লাইন হিসাবে লিখুন ->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
এটাই.
Mutex? একটা ধরা আছে?
আপনি যখন কোনও এক্সিকিউটেবলের জন্য একটি প্রকল্প তৈরি করেন তখন ভিজুয়াল স্টুডিও 2005 বা 2008 ব্যবহার করে "অ্যাপ্লিকেশন" প্যানেলের অভ্যন্তরীণ বৈশিষ্ট্য উইন্ডোগুলিতে "একক উদাহরণ প্রয়োগ করুন" নামে একটি চেক বাক্স থাকে যা আপনি একক উদাহরণ অ্যাপ্লিকেশনটিতে অ্যাপ্লিকেশনটি রূপান্তর করতে সক্রিয় করতে পারেন ।
আমি যে উইন্ডোটির সাথে কথা বলছি তার একটি ক্যাপচার এখানে দেওয়া হয়েছে:
এটি একটি ভিজ্যুয়াল স্টুডিও ২০০৮ উইন্ডোজ অ্যাপ্লিকেশন প্রকল্প।
আমি এখানে সমস্ত সমাধান চেষ্টা করেছি এবং আমার সি #। নেট 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 -Single-Instance_Detection_and_Management
একাধিক সমাধান চেষ্টা করার পরে আমি প্রশ্ন। আমি এখানে ডাব্লুপিএফ এর উদাহরণটি ব্যবহার করে শেষ করেছি : 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"
এই নিবন্ধটি সহজভাবে ব্যাখ্যা করে যে আপনি কীভাবে উইন্ডোজ অ্যাপ্লিকেশনটির উদাহরণগুলির সংখ্যার উপর নিয়ন্ত্রণ রেখে তৈরি করতে পারেন বা কেবলমাত্র একক উদাহরণ চালাতে পারেন। এটি একটি ব্যবসায়িক প্রয়োগের খুব সাধারণ প্রয়োজন typ এটি নিয়ন্ত্রণ করার জন্য ইতিমধ্যে প্রচুর অন্যান্য সম্ভাব্য সমাধান রয়েছে।
http://www.openwinforms.com/single_instance_application.html
এটি ভিবি.নেটের কোড
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
এটি সি # এর জন্য কোড
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 ব্যবহার করতে হবে।
পরীক্ষা করে দেখুন: http://www.devx.com/tips/Tip/20044
(দ্রষ্টব্য: এটি একটি মজাদার-সমাধান! এটি কাজ করে তবে এটি অর্জনের জন্য খারাপ জিডিআই + ডিজাইন ব্যবহার করে))
আপনার অ্যাপ্লিকেশন সহ একটি চিত্র রাখুন এবং এটি শুরুতে লোড করুন। অ্যাপটি প্রস্থান না হওয়া অবধি এটিকে ধরে রাখুন। ব্যবহারকারী 2 য় দৃষ্টান্ত শুরু করতে সক্ষম হবে না। (অবশ্যই মিউটেক্স দ্রবণটি অনেক ক্লিনার)
private static Bitmap randomName = new Bitmap("my_image.jpg");
Main()এটিতে এমন একটি পদ্ধতিও প্রয়োজন যা ডাব্লুপিএফ কীভাবে কাজ করবে বলে মনে করা যায় তার বিপরীতে।
[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!
}
থেকে: নেট অ্যাপ্লিকেশনটির একক উদাহরণ নিশ্চিত করা
এবং: একক দৃষ্টিকোণ অ্যাপ্লিকেশন নীরব
টুইটারের সাহায্যে @ সিমিং এবং @ সামঞ্জস্যপূর্ণ হিসাবে একই উত্তর:
উপর সি # জন স্কিট এর প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী খুঁজে বের করতে কেন GC.KeepAlive বিষয়
কেবল একটি ব্যবহার করছেন StreamWriter, এটি কীভাবে?
System.IO.File.StreamWriter OpenFlag = null; //globally
এবং
try
{
OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
Environment.Exit(0);
}
সাধারণত এটি একটি নামযুক্ত মুটেক্স (নতুন ম্যাটেক্স ব্যবহার করে ("আপনার অ্যাপের নাম", সত্য)) ব্যবহার করে সম্পন্ন হয় এবং ফেরতের মানটি পরীক্ষা করে থাকে) তবে মাইক্রোসফ্টে কিছু সমর্থন ক্লাস রয়েছে V ভিজুয়ালবাসিক.ডিল যা এটি আপনার পক্ষে করতে পারে ।
এটি খাঁটি সি # তে আমার জন্য কাজ করেছে। চেষ্টা / ধরা তখনই হয় যখন তালিকার কোনও প্রক্রিয়া আপনার লুপের সময় প্রস্থান করে।
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
প্রোগ্রামটির আর একটি অনুলিপি চলছে কিনা তা সনাক্ত করতে আমরা একটি স্থির নামের সাথে একটি নামযুক্ত মুটেক্স ব্যবহার করছি। তবে এর অর্থ এটিও হ'ল কোনও আক্রমণকারী প্রথমে মিউটেক্স তৈরি করতে পারে, যার ফলে আমাদের প্রোগ্রামটি একেবারেই চলতে বাধা দেয়! কীভাবে আমি এই ধরণের পরিষেবা আক্রমণকে অস্বীকার করতে পারি?
...
যদি আক্রমণকারী আপনার সুরক্ষা প্রসঙ্গে একই প্রোগ্রামে চলছে (বা হবে) তবে আপনি যা করতে পারেন তা কিছুই নেই। আপনার প্রোগ্রামটির আর একটি অনুলিপি চলছে কিনা তা নির্ধারণ করতে আপনি যে কোনও "গোপন হ্যান্ডশেক" নিয়ে আসেন না কেন, আক্রমণকারী এটি নকল করতে পারে। যেহেতু এটি সঠিক সুরক্ষা প্রসঙ্গে চলছে তাই এটি "আসল" প্রোগ্রামটি যা কিছু করতে পারে তা করতে পারে।
...
স্পষ্টতই আপনি একই সুরক্ষা সুবিধায় চালিত আক্রমণকারীর হাত থেকে নিজেকে রক্ষা করতে পারবেন না, তবে আপনি এখনও অন্য সুরক্ষা সুবিধায় দৌড়াদৌড়িহীন আক্রমণকারীদের হাত থেকে নিজেকে রক্ষা করতে পারবেন।
আপনার নিঃশব্দে একটি ডিএসিএল সেট করার চেষ্টা করুন, এখানে নেট নেট পদ্ধতি: https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx
এই উত্তরগুলির কোনওটিই আমার পক্ষে কাজ করেনি কারণ মনোপল্ফ ব্যবহার করে লিনাক্সের অধীনে কাজ করার জন্য আমার এটির দরকার ছিল। এটি আমার পক্ষে দুর্দান্ত কাজ করে:
এই পদ্ধতিটিকে একটি অনন্য আইডি পাস করার জন্য কল করুন
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);
}
}