Mengembangkan Aplikasi WinForm C # .NET 2.0. Perlu aplikasi untuk menutup dan memulai ulang sendiri.
Application.Restart();
Metode di atas terbukti tidak bisa diandalkan .
Apa cara yang lebih baik untuk memulai ulang aplikasi?
Mengembangkan Aplikasi WinForm C # .NET 2.0. Perlu aplikasi untuk menutup dan memulai ulang sendiri.
Application.Restart();
Metode di atas terbukti tidak bisa diandalkan .
Apa cara yang lebih baik untuk memulai ulang aplikasi?
Jawaban:
Sayangnya Anda tidak dapat menggunakan Process.Start () untuk memulai sebuah instance dari proses yang sedang berjalan. Menurut dokumen Process.Start (): "Jika proses sudah berjalan, tidak ada sumber daya proses tambahan yang dimulai ..."
Teknik ini akan bekerja dengan baik di bawah debugger VS (karena VS melakukan semacam sihir yang menyebabkan Proses. Mulailah berpikir bahwa proses belum berjalan), tetapi akan gagal jika tidak dijalankan di bawah debugger. (Perhatikan bahwa ini mungkin khusus OS - saya sepertinya ingat bahwa dalam beberapa pengujian saya, ini berfungsi baik di XP atau Vista, tetapi saya mungkin hanya mengingat menjalankannya di bawah debugger.)
Teknik ini persis seperti yang digunakan oleh programmer terakhir pada proyek yang sedang saya kerjakan, dan saya telah mencoba mencari solusi untuk ini selama beberapa waktu. Sejauh ini, saya hanya menemukan satu solusi, dan itu terasa kotor dan kusut bagi saya: mulai aplikasi kedua, yang menunggu di latar belakang hingga aplikasi pertama dihentikan, lalu luncurkan kembali aplikasi pertama. Saya yakin itu akan berhasil, tapi, yuck.
Edit: Menggunakan karya aplikasi ke-2. Yang saya lakukan di aplikasi kedua adalah:
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, ""); }
(Ini adalah contoh yang sangat sederhana. Kode sebenarnya memiliki banyak pemeriksaan kewarasan, penanganan kesalahan, dll.)
sumber
Process.Start
tidak melihat daftar proses OS yang sedang berjalan. Pernyataan dokumentasi ini hanya berbicara tentang itu contoh objek dariProcess
kelas. TheProcess
kelas dapat melekat pada proses yang berjalan, tetapi juga bisa dalam keadaan Tidak dimulai. Menurut pendapat saya ini adalah desain yang mengacaukan. Praktik terbaik, IMO, adalah tidak pernah menggunakan kembali sebuahProcess
instance dan segera memulainya setelah pembuatan. Idealnya, gunakanProcess.Start
metode statis . Kemudian, kekurangan dokumentasi dan desain ini tidak pernah ikut bermain.WaitForExit(1000)
. Tetapi seluruh penantian tidak perlu untuk memulai proses baru. Ini mungkin perilaku tambahan yang Anda inginkan, tetapi tidak diperlukan untuk memulai proses baru.Pendekatan yang jauh lebih sederhana yang berhasil bagi saya adalah:
Application.Restart(); Environment.Exit(0);
Ini mempertahankan argumen baris perintah dan berfungsi meskipun ada penangan kejadian yang biasanya mencegah aplikasi ditutup.
Panggilan Restart () mencoba keluar, tetap memulai instance baru dan kembali. Panggilan Exit () kemudian menghentikan proses tanpa memberikan kesempatan untuk menjalankan event handler. Ada periode yang sangat singkat di mana kedua proses berjalan, yang tidak menjadi masalah dalam kasus saya, tetapi mungkin dalam kasus lain.
Kode keluar 0 dalam
Environment.Exit(0);
menentukan shutdown bersih. Anda juga dapat keluar dengan 1 untuk menentukan kesalahan terjadi.sumber
OnClose()
acara formulir dan sejenisnya.Jika Anda berada dalam bentuk aplikasi utama coba gunakan
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application this.Close(); //to turn off current app
sumber
Enviorment.Exit(0)
juga akan melakukan pekerjaan itu.Enviorment.Exit
adalah jalan keluar yang kotor dan cukup invasif karena mencegah kode pembersihan aplikasi berjalan. Bukan pilihan yang tepat di sebagian besar waktu.Saya mungkin terlambat ke pesta, tetapi ini adalah solusi sederhana saya dan berfungsi dengan baik dengan setiap aplikasi yang saya miliki:
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 { }
sumber
Saya memiliki masalah yang persis sama dan saya juga memiliki persyaratan untuk mencegah contoh duplikat - Saya mengusulkan solusi alternatif untuk yang diusulkan HiredMind (yang akan berfungsi dengan baik).
Apa yang saya lakukan adalah memulai proses baru dengan processId dari proses lama (yang memicu restart) sebagai argumen baris 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);
Kemudian ketika aplikasi baru dimulai, saya pertama-tama mengurai argumen baris cm dan memeriksa apakah flag restart ada di sana dengan processId, lalu tunggu proses itu untuk Keluar:
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 } }
Saya jelas tidak menunjukkan semua pemeriksaan keamanan yang saya miliki, dll.
Bahkan jika tidak ideal - saya menemukan ini alternatif yang valid sehingga Anda tidak perlu memiliki aplikasi terpisah hanya untuk menangani restart.
sumber
/allowMultipleInstances
bendera daripada yang agak aneh/restart
.Metode Mulai / Keluar
// 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);
Ini tampaknya bekerja lebih baik daripada Application.Restart ();
Tidak yakin bagaimana ini menangani jika program Anda melindungi dari banyak contoh. Dugaan saya adalah lebih baik Anda meluncurkan .exe kedua yang berhenti dan kemudian memulai aplikasi utama untuk Anda.
sumber
Sederhana Anda hanya perlu memanggil
Application.Restart()
metode yang cenderung memanggil aplikasi Anda untuk direstart. Tetapi Anda harus keluar dari lingkungan Lokal dengan kode kesalahannya:Application.Restart(); Environment.exit(int errorcode);
Anda dapat membuat penghitungan kode kesalahan untuk itu Anda dapat menggunakannya secara efektif.
Metode lain adalah hanya keluar dari aplikasi dan memulai proses dengan jalur yang dapat dieksekusi:
sumber
Coba kode ini:
bool appNotRestarted = true;
Kode ini juga harus berfungsi:
if (appNotRestarted == true) { appNotRestarted = false; Application.Restart(); Application.ExitThread(); }
sumber
Saya menemukan solusi lain, mungkin siapa pun dapat menggunakannya juga.
string batchContent = "/c \"@ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\""; batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath); Process.Start("cmd", batchContent); Application.Exit();
Kode disederhanakan jadi jaga Pengecualian dan hal-hal lainnya;)
sumber
Anda lupa opsi / parameter baris perintah yang diteruskan ke instance yang sedang Anda jalankan. Jika Anda tidak meneruskannya, Anda tidak melakukan restart nyata. Atur
Process.StartInfo
dengan klon parameter proses Anda, lalu lakukan permulaan.Misalnya, jika proses Anda dimulai sebagai
myexe -f -nosplash myfile.txt
, metode Anda hanya akan dijalankanmyexe
tanpa semua flag dan parameter tersebut.sumber
Saya ingin aplikasi baru memulai setelah yang lama dimatikan.
Menggunakan process.WaitForExit () untuk menunggu proses Anda sendiri dimatikan tidak masuk akal. Waktu akan selalu habis.
Jadi, pendekatan saya adalah menggunakan Application.Exit () lalu tunggu, tetapi izinkan peristiwa untuk diproses, untuk jangka waktu tertentu. Kemudian mulai aplikasi baru dengan argumen yang sama dengan yang lama.
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 ); }
sumber
Anda juga bisa menggunakan Restarter .
sumber
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 mengembalikan jalur file .exe aplikasi Anda Harap ikuti urutan panggilan. Anda mungkin ingin menempatkannya di klausa coba-tangkap.
sumber
Bagaimana membuat file bat, menjalankan file batch sebelum menutup, dan kemudian tutup instance saat ini.
File batch melakukan ini:
sumber
Ini 2 sen saya:
Urutan Mulai Instans Baru-> Tutup Instans Saat Ini harus berfungsi bahkan untuk aplikasi yang tidak mengizinkan menjalankan banyak salinan secara bersamaan seperti dalam kasus ini instans baru dapat melewati argumen baris perintah yang akan menunjukkan bahwa ada proses restart yang sedang berlangsung jadi tidak perlu memeriksa contoh lain yang sedang berjalan. Menunggu contoh pertama untuk benar-benar menyelesaikan implementasi saya juga jika benar-benar penting bahwa tidak ada dua keadaan yang berjalan secara paralel.
sumber
Saya khawatir memulai ulang seluruh aplikasi menggunakan Proses mendekati masalah Anda dengan cara yang salah.
Cara yang lebih mudah adalah dengan memodifikasi file Program.cs untuk memulai ulang:
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; } } }
sumber
Saya memiliki masalah yang sama, tetapi masalah saya terkait dengan kebocoran memori yang tidak dapat dikelola yang tidak dapat saya temukan di aplikasi yang harus berjalan 24/7. Dengan pelanggan, saya setuju bahwa waktu aman untuk memulai ulang aplikasi adalah pukul 03:00 pagi jika konsumsi memori melebihi nilai yang ditentukan.
Saya mencoba
Application.Restart
, tetapi karena tampaknya menggunakan beberapa mekanisme yang memulai contoh baru saat sudah berjalan, saya menggunakan skema lain. Saya menggunakan trik yang ditangani sistem file bertahan sampai proses yang membuatnya mati. Jadi, dari Aplikasi, saya menjatuhkan file ke disk, dan tidakDispose()
menanganinya. Saya menggunakan file tersebut untuk mengirim direktori yang dapat dieksekusi dan mulai 'sendiri' juga (untuk menambah fleksibilitas).Kode:
_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()
pada akhirnya akan memulai penutupan aplikasi, dan pegangan file yang saya gunakan diStreamWriter
sini akan dibuka sampai proses benar-benar mati. Kemudian...Restarter.exe mulai beraksi. Mencoba membaca file dalam mode eksklusif, mencegahnya mendapatkan akses sampai aplikasi utama tidak mati, kemudian memulai aplikasi utama, menghapus file dan ada. Saya kira itu tidak bisa lebih sederhana:
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); } }
sumber
Saya menggunakan yang berikut dan itu melakukan persis apa yang Anda cari:
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); }
sumber
untuk menggunakan Sebagai logout Anda harus menghentikan semua aplikasi dari Ram Cache jadi tutup Aplikasi terlebih dahulu dan kemudian Jalankan kembali
// saat mengklik Tombol Keluar
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList()) { frm.Close(); } System.Diagnostics.Process.Start(Application.ExecutablePath);
sumber
Masalah menggunakan Application.Restart () adalah, ia memulai proses baru tetapi yang "lama" masih tersisa. Oleh karena itu saya memutuskan untuk menghentikan proses lama dengan menggunakan potongan kode berikut:
if(Condition){ Application.Restart(); Process.GetCurrentProcess().Kill(); }
Dan itu bekerja dengan baik. Dalam kasus saya MATLAB dan Aplikasi C # berbagi database SQLite yang sama. Jika MATLAB menggunakan database, Aplikasi Formulir harus memulai ulang (+ Hitung Mundur) lagi, hingga MATLAB mereset bit sibuknya dalam database. (Hanya untuk informasi sampingan)
sumber
Anda dapat memasukkan kode Anda di dalam suatu fungsi dan ketika restart diperlukan Anda cukup memanggil fungsi tersebut.
sumber
Ambil contoh aplikasi yang:
Sementara aplikasi tidak terdaftar; (setelah memulai) aplikasi harus meminta pengguna untuk mendaftarkan aplikasi dan membuat akun login.
Setelah pendaftaran dikirimkan dan kredensial login dibuat; aplikasi harus dimulai ulang, periksa pendaftaran dan minta pengguna untuk masuk dengan kredensial yang dimasukkan (sehingga pengguna dapat mengakses semua fitur aplikasi).
Masalah: Dengan membangun dan meluncurkan aplikasi dari Visual Studio; salah satu dari 4 alternatif di bawah ini akan gagal untuk menyelesaikan tugas yang diperlukan.
/* * Note(s): * Take into consideration that the lines bellow don't represent a code block. * They are just a representation of possibilities, * that can be used to restart the application. */ Application.Restart(); Application.Exit(); Environment.Exit(int errorCode); Process.GetCurrentProcess().Kill();
Apa yang terjadi adalah: Setelah membuat Pendaftaran, Login dan memanggil Application.Restart (); aplikasi akan (anehnya) membuka kembali Formulir Pendaftaran dan melewatkan data dalam Database (meskipun sumber daya disetel ke "Salin jika Lebih Baru").
Solusi: Batch Building aplikasi (bagi saya) adalah bukti bahwa salah satu baris di atas benar-benar berfungsi seperti yang diharapkan. Hanya saja tidak saat membangun dan menjalankan aplikasi dengan Visual Studio.
Pertama-tama, saya akan mencoba membangun aplikasi secara batch; jalankan di luar Visual Studio dan periksa apakah Application.Restart () benar-benar berfungsi seperti yang diharapkan.
Juga Periksa Info lebih lanjut tentang subjek utas ini: Bagaimana cara me-restart Aplikasi C # WinForm saya?
sumber