C # .NET 2.0 WinForm एप्लीकेशन विकसित करना। एप्लिकेशन को बंद करने और खुद को पुनरारंभ करने की आवश्यकता है।
Application.Restart();
उपरोक्त विधि अविश्वसनीय साबित हुई है ।
एप्लिकेशन को पुनरारंभ करने का एक बेहतर तरीका क्या है?
C # .NET 2.0 WinForm एप्लीकेशन विकसित करना। एप्लिकेशन को बंद करने और खुद को पुनरारंभ करने की आवश्यकता है।
Application.Restart();
उपरोक्त विधि अविश्वसनीय साबित हुई है ।
एप्लिकेशन को पुनरारंभ करने का एक बेहतर तरीका क्या है?
जवाबों:
दुर्भाग्य से आप वर्तमान में चल रही प्रक्रिया का एक उदाहरण शुरू करने के लिए Process.Start () का उपयोग नहीं कर सकते हैं। Process.Start () डॉक्स के अनुसार: "यदि प्रक्रिया पहले से ही चल रही है, तो कोई अतिरिक्त प्रक्रिया संसाधन प्रारंभ नहीं है ..."
यह तकनीक वीएस डिबगर के तहत ठीक काम करेगी (क्योंकि वीएस कुछ प्रकार का जादू करता है जो प्रोसेस का कारण बनता है। यह सोचने के लिए कि प्रक्रिया पहले से ही नहीं चल रही है), लेकिन डिबगर के नीचे नहीं चलने पर विफल हो जाएगी। (ध्यान दें कि यह ओएस-विशिष्ट हो सकता है - मुझे याद है कि मेरे कुछ परीक्षण में, इसने XP या विस्टा पर काम किया था, लेकिन मैं इसे डिबगर के तहत चलाने के लिए याद रख सकता हूं।)
यह तकनीक ठीक उसी तरह है जिसका उपयोग पिछले प्रोग्रामर द्वारा उस परियोजना पर किया गया है जिस पर मैं वर्तमान में काम कर रहा हूं, और मैं काफी समय से इसके लिए वर्कअराउंड खोजने की कोशिश कर रहा हूं। अब तक, मैंने केवल एक समाधान पाया है, और यह सिर्फ मुझे गंदा और कर्कश लगता है: एक 2 एप्लिकेशन शुरू करें, जो पहले आवेदन को समाप्त करने के लिए पृष्ठभूमि में इंतजार करता है, फिर 1 आवेदन को फिर से लॉन्च करता है। मुझे यकीन है कि यह काम करेगा, लेकिन, हाँ।
संपादित करें: एक 2 आवेदन कार्यों का उपयोग करना। मैंने दूसरे ऐप में किया था:
static void RestartApp(int pid, string applicationName )
{
// Wait for the process to terminate
Process process = null;
try
{
process = Process.GetProcessById(pid);
process.WaitForExit(1000);
}
catch (ArgumentException ex)
{
// ArgumentException to indicate that the
// process doesn't exist? LAME!!
}
Process.Start(applicationName, "");
}
(यह एक बहुत ही सरल उदाहरण है। वास्तविक कोड में बहुत सारी जाँच की गई है, त्रुटि से निपटने, आदि)
Process.Startओएस प्रक्रियाओं को चलाने की सूची को नहीं देखता है। यह दस्तावेजी बयान केवल कक्षा के उस ऑब्जेक्ट उदाहरण के बारे में बात करता है Process। Processवर्ग एक चलने वाली प्रक्रिया के साथ संलग्न किया जा सकता है लेकिन यह भी एक प्रारंभ नहीं किया गया राज्य में हो सकता है। मेरी राय में यह एक डिज़ाइन पेंच है। सबसे अच्छा अभ्यास, आईएमओ, एक Process उदाहरण का पुन: उपयोग नहीं करना है और निर्माण के तुरंत बाद इसे शुरू करना है। आदर्श रूप में, स्थैतिक Process.Startविधि का उपयोग करें । फिर, यह प्रलेखन और डिज़ाइन दोष कभी भी खेल में नहीं आते हैं।
WaitForExit(1000)। लेकिन नई प्रक्रिया शुरू करने के लिए पूरी प्रतीक्षा आवश्यक नहीं है। यह अतिरिक्त व्यवहार हो सकता है जिसे आप चाहते हैं, लेकिन एक नई प्रक्रिया शुरू करने की आवश्यकता नहीं है।
मेरे लिए काम करने वाला बहुत सरल तरीका है:
Application.Restart();
Environment.Exit(0);
यह कमांड-लाइन तर्कों को संरक्षित करता है और घटना संचालकों के बावजूद काम करता है जो सामान्य रूप से एप्लिकेशन को बंद होने से रोकते हैं।
रिस्टार्ट () कॉल से बाहर निकलने की कोशिश करता है, वैसे भी एक नया उदाहरण शुरू करता है और वापस लौटता है। एक्ज़िट () कॉल फिर किसी भी घटना संचालकों को चलाने का मौका दिए बिना प्रक्रिया को समाप्त कर देता है। एक बहुत ही संक्षिप्त अवधि है जिसमें दोनों प्रक्रियाएं चल रही हैं, जो मेरे मामले में समस्या नहीं है, लेकिन शायद अन्य मामलों में।
निकास कोड 0 Environment.Exit(0);एक साफ शटडाउन निर्दिष्ट करता है। आप एक त्रुटि उत्पन्न करने के लिए 1 से भी बाहर निकल सकते हैं।
OnClose()फॉर्म ईवेंट और समान नहीं बढ़ाएगा ।
यदि आप मुख्य एप्लिकेशन फॉर्म में हैं तो उपयोग करने का प्रयास करें
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app
Enviorment.Exit(0)भी काम करेगा।
Enviorment.Exitयह एक गंदा और काफी आक्रामक निकास है क्योंकि यह एप्लिकेशन क्लीनअप कोड को चलने से रोकता है। ज्यादातर समय सही विकल्प नहीं।
मुझे पार्टी में देर हो सकती है लेकिन यहाँ मेरा सरल समाधान है और यह मेरे पास हर एप्लिकेशन के साथ एक आकर्षण की तरह काम करता है:
try
{
//run the program again and close this one
Process.Start(Application.StartupPath + "\\blabla.exe");
//or you can use Application.ExecutablePath
//close this one
Process.GetCurrentProcess().Kill();
}
catch
{ }
मेरे पास एक ही सटीक समस्या थी और मुझे भी डुप्लिकेट इंस्टेंसेस को रोकने के लिए एक आवश्यकता थी - मैं प्रस्ताव देता हूं कि HiredMind एक वैकल्पिक समाधान प्रस्तावित कर रहा है (जो ठीक काम करेगा)।
मैं जो कर रहा हूं वह नई प्रक्रिया शुरू कर रहा है पुरानी प्रक्रिया की प्रक्रिया के साथ (जो कि पुनरारंभ होता है) एक cmd लाइन तर्क के रूप में:
// Shut down the current app instance.
Application.Exit();
// Restart the app passing "/restart [processId]" as cmd line args
Process.Start(Application.ExecutablePath, "/restart" + Process.GetCurrentProcess().Id);
फिर जब नया ऐप शुरू होता है, तो मैं सबसे पहले सेमी लाइन आर्ग्स को पार्स करता हूं और जांचता हूं कि क्या रिस्टार्ट फ्लैग एक प्रोसेसआईड के साथ है, तो उस प्रक्रिया से बाहर निकलने का इंतजार करें:
if (_isRestart)
{
try
{
// get old process and wait UP TO 5 secs then give up!
Process oldProcess = Process.GetProcessById(_restartProcessId);
oldProcess.WaitForExit(5000);
}
catch (Exception ex)
{
// the process did not exist - probably already closed!
//TODO: --> LOG
}
}
मैं स्पष्ट रूप से उन सभी सुरक्षा जांचों को नहीं दिखा रहा हूं जो मेरे पास हैं आदि।
आदर्श न होने पर भी - मुझे यह एक वैध विकल्प लगता है ताकि आपको पुनः आरंभ करने के लिए एक अलग ऐप न रखना पड़े।
/allowMultipleInstancesअजीब से एक झंडे को 'खोज' लेंगे /restart।
// Get the parameters/arguments passed to program if any
string arguments = string.Empty;
string[] args = Environment.GetCommandLineArgs();
for (int i = 1; i < args.Length; i++) // args[0] is always exe path/filename
arguments += args[i] + " ";
// Restart current application, with same arguments/parameters
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath, arguments);
यह Application.Restart () से बेहतर काम करने लगता है;
सुनिश्चित नहीं है कि यह कैसे संभालता है यदि आपका प्रोग्राम कई उदाहरणों से बचाता है। मेरा अनुमान है कि आप एक दूसरा। Exe लॉन्च करने से बेहतर होंगे जो आपके लिए रुकेगी और फिर आपके लिए अपना मुख्य आवेदन शुरू करेगी।
इसका सिंपल आपको बस उन Application.Restart()तरीकों को कॉल करने की आवश्यकता है जो आपको पुनः आरंभ करने के लिए आवेदन आमंत्रित करने के लिए कहते हैं। लेकिन आपको स्थानीय परिवेश से उनके त्रुटि कोड से बाहर निकलना होगा:
Application.Restart();
Environment.exit(int errorcode);
आप त्रुटि कोड की गणना कर सकते हैं, जिसके लिए आप इसका उपयोग आसानी से कर सकते हैं।
एक अन्य तरीका यह है कि केवल आवेदन से बाहर निकलें और निष्पादन योग्य पथ की प्रक्रिया शुरू करें:
Application.exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);
इस कोड को आज़माएं:
bool appNotRestarted = true;
यह कोड फ़ंक्शन में भी होना चाहिए:
if (appNotRestarted == true) {
appNotRestarted = false;
Application.Restart();
Application.ExitThread();
}
मुझे एक और उपाय सूझा, शायद कोई भी इसका उपयोग कर सकता है।
string batchContent = "/c \"@ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\"";
batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath);
Process.Start("cmd", batchContent);
Application.Exit();
कोड सरल है इसलिए अपवाद और सामान का ख्याल रखें;)
आप कमांड-लाइन विकल्पों / मापदंडों को भूल रहे हैं जो आपके वर्तमान में चल रहे उदाहरण में पारित किए गए थे। यदि आप उन लोगों को पास नहीं करते हैं, तो आप वास्तविक पुनरारंभ नहीं कर रहे हैं। Process.StartInfoअपनी प्रक्रिया के मापदंडों के क्लोन के साथ सेट करें , फिर एक शुरुआत करें।
उदाहरण के लिए, यदि आपकी प्रक्रिया के रूप में शुरू किया गया था, तो आपकी myexe -f -nosplash myfile.txtविधि केवल myexeउन सभी झंडे और मापदंडों के बिना निष्पादित होगी ।
मैं चाहता था कि पुराने एक के बाद नया आवेदन शुरू हो जाए।
प्रक्रिया का उपयोग करना। शटडाउन के लिए खुद की प्रक्रिया का इंतजार करने के लिए IaFForExit () का कोई मतलब नहीं है। यह हमेशा बाहर समय होगा।
इसलिए, मेरा दृष्टिकोण Application.Exit () का उपयोग करना है, फिर प्रतीक्षा करें, लेकिन घटनाओं को संसाधित करने की अनुमति दें, समय की अवधि के लिए। फिर पुराने के समान तर्कों के साथ एक नया एप्लिकेशन शुरू करें।
static void restartApp() {
string commandLineArgs = getCommandLineArgs();
string exePath = Application.ExecutablePath;
try {
Application.Exit();
wait_allowingEvents( 1000 );
} catch( ArgumentException ex ) {
throw;
}
Process.Start( exePath, commandLineArgs );
}
static string getCommandLineArgs() {
Queue<string> args = new Queue<string>( Environment.GetCommandLineArgs() );
args.Dequeue(); // args[0] is always exe path/filename
return string.Join( " ", args.ToArray() );
}
static void wait_allowingEvents( int durationMS ) {
DateTime start = DateTime.Now;
do {
Application.DoEvents();
} while( start.Subtract( DateTime.Now ).TotalMilliseconds > durationMS );
}
आप रेस्टोरर का उपयोग भी कर सकते हैं ।
रेस्टोरर एक ऐसा एप्लिकेशन है जो स्वचालित रूप से मॉनिटर और पुनरारंभ हो जाता है और प्रोग्राम और एप्लिकेशन को लटका देता है। यह मूल रूप से गेम सर्वर की निगरानी और पुनरारंभ करने के लिए विकसित किया गया था, लेकिन यह किसी भी कंसोल या फॉर्म आधारित प्रोग्राम या एप्लिकेशन के लिए काम करेगा
public static void appReloader()
{
//Start a new instance of the current program
Process.Start(Application.ExecutablePath);
//close the current application process
Process.GetCurrentProcess().Kill();
}
Application.ExecutablePath आपकी एप्लायंस .exe फ़ाइल पथ लौटाता है कृपया कॉल के क्रम का पालन करें। आप इसे एक कोशिश-पकड़ खंड में रखना चाह सकते हैं।
बैट फ़ाइल बनाने के बारे में, बंद करने से पहले बैच फ़ाइल को चलाएं, और फिर वर्तमान उदाहरण को बंद करें।
बैच फ़ाइल यह करता है:
यहाँ मेरे 2 सेंट हैं:
अनुक्रम नई आवृत्ति प्रारंभ करें -> वर्तमान प्रवाह बंद करें उन अनुप्रयोगों के लिए भी काम करना चाहिए जो एक साथ कई प्रतियों को चलाने की अनुमति नहीं देते हैं क्योंकि इस मामले में नया उदाहरण एक कमांड-लाइन तर्क पारित किया जा सकता है जो इंगित करेगा कि प्रगति में फिर से शुरू है। इसलिए चल रहे अन्य उदाहरणों के लिए जाँच आवश्यक नहीं होगी। पहले उदाहरण के लिए प्रतीक्षा करना वास्तव में मेरे खत्म होने पर भी लागू किया जाना चाहिए अगर यह बिल्कुल जरूरी है कि कोई भी दो अंतर समानांतर में नहीं चल रहे हैं।
मुझे डर है कि प्रक्रिया का उपयोग करके पूरे एप्लिकेशन को पुनरारंभ करने से आपकी समस्या गलत तरीके से आ रही है।
एक आसान तरीका है Program.cs फ़ाइल को पुनरारंभ करने के लिए संशोधित करना:
static bool restart = true; // A variable that is accessible from program
static int restartCount = 0; // Count the number of restarts
static int maxRestarts = 3; // Maximum restarts before quitting the program
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
while (restart && restartCount < maxRestarts)
{
restart = false; // if you like.. the program can set it to true again
restartCount++; // mark another restart,
// if you want to limit the number of restarts
// this is useful if your program is crashing on
// startup and cannot close normally as it will avoid
// a potential infinite loop
try {
Application.Run(new YourMainForm());
}
catch { // Application has crashed
restart = true;
}
}
}
मुझे भी इसी तरह की समस्या थी, लेकिन मेरा संबंध असहनीय स्मृति रिसाव से था, जो मुझे एक ऐप पर नहीं मिल रहा था जिसे 24/7 चलाना है। ग्राहक के साथ मैं इस बात पर सहमत था कि यदि मेमोरी की निर्धारित मात्रा से अधिक है तो ऐप को पुनः आरंभ करने का सुरक्षित समय 03:00 AM है।
मैंने कोशिश की Application.Restart, लेकिन जब से यह कुछ तंत्र का उपयोग करने लगता है जो नई आवृत्ति शुरू करता है जबकि यह पहले से ही चल रहा है, मैं दूसरी योजना के लिए चला गया। मैंने उस तरकीब का इस्तेमाल किया जो फ़ाइल सिस्टम हैंडल तब तक कायम रहती है जब तक कि प्रक्रिया उनकी मृत्यु न कर दे। इसलिए, अनुप्रयोग से, मैंने फ़ाइल को डिस्क पर गिरा दिया, और Dispose()हैंडल नहीं किया। मैंने 'खुद को' निष्पादन योग्य और आरंभिक निर्देशिका (लचीलापन जोड़ने के लिए) भेजने के लिए फ़ाइल का उपयोग किया।
कोड:
_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
WorkingDirectory = Application.StartupPath,
Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();
Close()अंत में ऐप शटडाउन शुरू होगा, और मैं StreamWriterयहाँ इस्तेमाल के लिए फ़ाइल हैंडल को तब तक खुला रखा जाएगा जब तक कि प्रक्रिया वास्तव में मर नहीं जाती। फिर...
Restarter.exe कार्रवाई में आता है। यह फ़ाइल को अनन्य मोड में पढ़ने की कोशिश करता है, इसे तब तक एक्सेस करने से रोकता है जब तक कि मुख्य ऐप मृत न हो, फिर मुख्य ऐप शुरू करता है, फ़ाइल को हटाता है और मौजूद होता है। मुझे लगता है कि यह सरल नहीं हो सकता है:
static void Main(string[] args)
{
string filename = args[0];
DateTime start = DateTime.Now;
bool done = false;
while ((DateTime.Now - start).TotalSeconds < 30 && !done)
{
try
{
StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
string[] runData = new string[2];
runData[0] = sr.ReadLine();
runData[1] = sr.ReadLine();
Thread.Sleep(1000);
Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
sr.Dispose();
File.Delete(filename);
done = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(1000);
}
}
मैं निम्नलिखित का उपयोग करता हूं और यह वही करता है जो आप देख रहे हैं:
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
UpdateCheckInfo info = null;
info = ad.CheckForDetailedUpdate();
if (info.IsUpdateRequired)
{
ad.UpdateAsync(); // I like the update dialog
MessageBox.Show("Application was upgraded and will now restart.");
Environment.Exit(0);
}
लॉगआउट के रूप में उपयोग करने के लिए आपको राम कैश से सभी एप्लिकेशन को समाप्त करने की आवश्यकता है इसलिए पहले एप्लिकेशन को बंद करें और फिर इसे फिर से चलाएँ
// लॉगआउट बटन पर क्लिक करने पर
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList())
{
frm.Close();
}
System.Diagnostics.Process.Start(Application.ExecutablePath);
Application.Restart () का उपयोग करने की समस्या यह है कि यह एक नई प्रक्रिया शुरू करता है लेकिन "पुराना" अभी भी शेष है। इसके बाद मैंने निम्नलिखित कोड स्निपेट का उपयोग करके पुरानी प्रक्रिया को मारने का निर्णय लिया:
if(Condition){
Application.Restart();
Process.GetCurrentProcess().Kill();
}
और यह उचित अच्छा काम करता है। मेरे मामले में MATLAB और C # एप्लिकेशन समान SQLite डेटाबेस साझा कर रहे हैं। यदि MATLAB डेटाबेस का उपयोग कर रहा है, तो फॉर्म-ऐप को फिर से (+ उलटी गिनती) फिर से शुरू करना चाहिए, जब तक कि MATLAB डेटाबेस में अपने व्यस्त बिट को रीसेट न कर दे। (सिर्फ पक्ष जानकारी के लिए)