ฉันจะรีสตาร์ท C # WinForm Application ได้อย่างไร


86

การพัฒนาโปรแกรม C # .NET 2.0 WinForm ต้องการให้แอปพลิเคชันปิดและรีสตาร์ทตัวเอง

Application.Restart();

วิธีการดังกล่าวได้รับการพิสูจน์จะไม่น่าเชื่อถือ

วิธีที่ดีกว่าในการรีสตาร์ทแอปพลิเคชันคืออะไร?


3
ฉันสงสัยเกี่ยวกับความจำเป็นในการรีสตาร์ทแอปของคุณ ฉันไม่เคยคิดถึงความต้องการนั้นมาก่อนสถานการณ์ของคุณเป็นอย่างไร?
JeffH

สถานการณ์เฉพาะของเรา - แอปพลิเคชันเครื่องเล่นสื่อซึ่งควรจะทำงานผ่านรูปภาพและเนื้อหาแฟลชในวง ควรทำงานเป็นวัน ๆ โดยไม่ต้องรีสตาร์ทเครื่องและไม่มีแป้นพิมพ์ / เมาส์จึงไม่มีการโต้ตอบกับผู้ใช้ หากโปรแกรมขัดข้อง (ข้อยกเว้นที่ไม่สามารถจัดการได้) จำเป็นต้องรีสตาร์ทโปรแกรมไม่ออกจากระบบหรือแสดงข้อผิดพลาด stackoverflow.com/questions/773768/… ดูว่าทำไมโปรแกรมถึงมีข้อยกเว้นที่ฉันไม่สามารถป้องกันได้ :(
Adam Nofsinger

1
ท้ายที่สุดแล้วทางออกที่ดีกว่าสำหรับแอปพลิเคชันของเราคือการพัฒนาแอปพลิเคชัน Watchdog ขนาดเล็กที่เริ่มต้น (หากยังไม่ได้ใช้งานอยู่) จากแอปพลิเคชันหลัก สุนัขเฝ้าบ้านจะตรวจสอบทุกๆ 10 วินาทีหรือมากกว่านั้นเพื่อดูว่าแอปพลิเคชันหลักยังคงมีกระบวนการทำงานอยู่หรือไม่และหากไม่เป็นเช่นนั้นก็จะเริ่มต้นอย่างใดอย่างหนึ่ง เรียบง่ายหรูหราและทนทานกว่าการพยายามรีสตาร์ทจากแอปหลัก
Adam Nofsinger

2
อีกเหตุผลหนึ่งสำหรับการรีสตาร์ทคือเมื่อคุณเปลี่ยนภาษาหรือดาวน์โหลดการอัปเดต
Andrew Truckle

1
แต่ถ้า ... แอปพลิเคชั่นสุนัขเฝ้าบ้านขัดข้องล่ะ?
Metoniem

คำตอบ:


40

น่าเสียดายที่คุณไม่สามารถใช้ Process.Start () เพื่อเริ่มอินสแตนซ์ของกระบวนการที่กำลังทำงานอยู่ ตามเอกสาร Process.Start (): "หากกระบวนการทำงานอยู่แล้วจะไม่มีการเริ่มทรัพยากรกระบวนการเพิ่มเติม ... "

เทคนิคนี้จะทำงานได้ดีภายใต้ดีบักเกอร์ VS (เนื่องจาก VS ทำเวทมนตร์บางอย่างที่ทำให้เกิดกระบวนการเริ่มคิดว่ากระบวนการยังไม่ทำงาน) แต่จะล้มเหลวเมื่อไม่ได้ทำงานภายใต้ดีบักเกอร์ (โปรดทราบว่านี่อาจเป็นเฉพาะระบบปฏิบัติการ - ฉันดูเหมือนจะจำได้ว่าในการทดสอบบางอย่างของฉันมันทำงานบน XP หรือ Vista แต่ฉันอาจจำได้ว่ากำลังรันภายใต้ดีบักเกอร์)

เทคนิคนี้เป็นเทคนิคที่โปรแกรมเมอร์คนสุดท้ายใช้ในโครงการที่ฉันกำลังทำงานอยู่และฉันพยายามหาวิธีแก้ปัญหานี้มาระยะหนึ่งแล้ว จนถึงตอนนี้ฉันพบวิธีแก้ปัญหาเพียงวิธีเดียวและมันก็รู้สึกสกปรกและไม่ดีสำหรับฉัน: เริ่มแอปพลิเคชั่นที่ 2 ซึ่งรออยู่เบื้องหลังเพื่อให้แอปพลิเคชันแรกยุติจากนั้นจึงเปิดแอปพลิเคชันตัวแรกอีกครั้ง ฉันแน่ใจว่ามันจะใช้งานได้ แต่แย่แล้ว

แก้ไข: การใช้แอปพลิเคชันที่ 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, "");
    }

(นี่เป็นตัวอย่างที่เรียบง่ายมากรหัสจริงมีการตรวจสอบความมีสติการจัดการข้อผิดพลาด ฯลฯ )


ฉันเห็นด้วยกับ HiredMind และจริงๆแล้วฉันก็ใช้ "โปรแกรม Watchdog" แบบเดียวกันหลังจากเขียนคำตอบไม่นาน ขออภัยควรกลับมาที่นี่และอัปเดต ฉันจะไม่คิดว่ามันควรจะรู้สึกมากเกินไปอย่างน่ากลัวน่าเกลียด / แหยะ / สกปรก รูปแบบโปรแกรม Watchdog ค่อนข้างใช้กันอย่างแพร่หลาย
Adam Nofsinger

คุณไม่จำเป็นต้องมีแอปพลิเคชั่นที่สองบนดิสก์ ... คุณสามารถใช้สคริปต์และสร้างได้ทันทีด้วยชื่อชั่วคราว ... ฉันคิดว่านี่อาจช่วยบรรเทาความรู้สึกผิดของคุณที่มีแอปพลิเคชันที่สองเพื่อการรีสตาร์ท ของคุณเอง ... หรือคุณสามารถ "ปล่อย" แอปพลิเคชัน C # ทั้งหมดรวบรวมบันทึกลงในดิสก์และดำเนินการ (สกปรกคิดสกปรก) ..
Loudenvier

ย่อหน้าแรกไม่ถูกต้อง: Process.Startไม่ดูรายการของกระบวนการ OS ที่รันอยู่ คำสั่งเอกสารนี้พูดถึงเฉพาะอินสแตนซ์วัตถุของProcessคลาส Processระดับสามารถแนบไปกับกระบวนการทำงาน แต่ก็ยังสามารถอยู่ในสถานะที่ยกเลิกการเริ่ม ในความคิดของฉันนี่เป็นการออกแบบที่สกรูขึ้น แนวทางปฏิบัติที่ดีที่สุด IMO คือห้ามใช้Process อินสแตนซ์ซ้ำ และเริ่มต้นทันทีหลังจากสร้าง ตามหลักการแล้วให้ใช้Process.Startวิธีคงที่ จากนั้นเอกสารและข้อบกพร่องในการออกแบบนี้จะไม่เข้ามามีบทบาท
usr

WaitForExit(1000)รหัสที่แสดงที่นี่ยังเป็นที่ไม่น่าเชื่อถือเพราะ แต่ไม่จำเป็นต้องรอทั้งหมดเพื่อเริ่มกระบวนการใหม่ อาจเป็นพฤติกรรมเพิ่มเติมที่คุณต้องการ แต่ไม่จำเป็นต้องเริ่มกระบวนการใหม่
usr

ตอนนี้ฉันไม่รู้ แต่เก้าปีที่แล้ว (อะแฮ่ม) นี่ถูกต้องแน่นอน :-)
HiredMind

73

วิธีที่ง่ายกว่ามากที่ได้ผลสำหรับฉันคือ:

Application.Restart();
Environment.Exit(0);

สิ่งนี้รักษาอาร์กิวเมนต์บรรทัดคำสั่งและใช้งานได้แม้จะมีตัวจัดการเหตุการณ์ที่โดยปกติจะป้องกันไม่ให้แอปพลิเคชันปิด

การเรียกรีสตาร์ท () พยายามออกเริ่มอินสแตนซ์ใหม่ต่อไปและส่งคืน จากนั้นการเรียก Exit () จะยุติกระบวนการโดยไม่ให้โอกาสตัวจัดการเหตุการณ์ใด ๆ ในการเรียกใช้ มีช่วงเวลาสั้น ๆ ที่กระบวนการทั้งสองกำลังทำงานอยู่ซึ่งไม่ใช่ปัญหาในกรณีของฉัน แต่อาจเป็นในกรณีอื่น

รหัสทางออก 0 ในEnvironment.Exit(0);ระบุการปิดระบบทั้งหมด คุณยังสามารถออกด้วย 1 เพื่อระบุข้อผิดพลาดที่เกิดขึ้น


เรียบง่าย แต่เชื่อถือได้ นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ฉันพยายามใช้คุณลักษณะการออกจากระบบที่จะทำให้ตัวแปรส่วนกลางทั้งหมดว่างเปล่าและดูเหมือนว่าแอปพลิเคชันเพิ่งเริ่มต้น ฉันจะแสดงแผงควบคุมสำหรับการเข้าสู่ระบบและรีเซ็ตตัวแปรส่วนกลางทั้งหมดที่เก็บข้อมูลสำคัญจาก DB ไปเป็นอะไรเลย สิ่งนี้ทำให้ชีวิตเรียบง่ายขึ้นมาก ขอบคุณ!
DavidG

System.Windows.Forms.Application.Restart () ยังใช้งานได้กับแอปพลิเคชัน WPF ทดสอบกับ Windows 10 OS
NthDeveloper

ว้าาาาา?! คุณ kiddin ... ใช่มั้ย? C # <3. โปรดทราบว่าโดยค่าเริ่มต้นจะไม่ทำให้OnClose()เกิดเหตุการณ์แบบฟอร์มและสิ่งที่คล้ายกัน
F8ER

56

หากคุณอยู่ในรูปแบบแอปหลักลองใช้

System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app

7
มันคล้ายกัน แต่แตกต่างกัน แอปพลิเคชันออกจากรูปแบบฉันไม่ได้ผลและสิ่งนี้ปิด () ได้งาน
Darqer

1
เมย์Enviorment.Exit(0)ก็จะทำหน้าที่
Dwza

2
Enviorment.Exitเป็นทางออกที่สกปรกและค่อนข้างรุกรานเนื่องจากป้องกันไม่ให้รหัสล้างแอปพลิเคชันทำงาน ไม่ใช่ทางเลือกที่ถูกต้องเกือบตลอดเวลา
usr

16

ฉันอาจจะไปงานปาร์ตี้สาย แต่นี่คือวิธีง่ายๆของฉันและมันใช้งานได้ดีกับทุกแอปพลิเคชันที่ฉันมี:

        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
        { }

ทำงานได้ดีบน Win-7-x64 และ Win-XP-x32 ผมเห็นอะไรเกี่ยวกับข้อ จำกัด ใด ๆ ในเอกสาร นี่ควรเป็นคำตอบที่ได้รับการยอมรับ
Bitterblue

@Bitterblue ลิงก์ไปยังเอกสารที่คุณโพสต์ระบุว่า "หากกระบวนการทำงานอยู่แล้วจะไม่มีการเริ่มต้นทรัพยากรของกระบวนการเพิ่มเติม" เป็นบรรทัดที่ 3 ในส่วนหมายเหตุ ฉันหวังว่ามันจะไม่ใช่แบบนี้ แต่เป็น
HiredMind

@HiredMind ฉันเดาว่าเราสามารถโต้แย้งได้ว่า "ข้อ จำกัด " หมายถึงอะไรสำหรับเราแต่ละคน แต่หัวข้อนี้มีชื่อว่า "หมายเหตุ" ไม่ใช่ "ข้อ จำกัด " ดังนั้นฉันสามารถอยู่กับมัน แล้วทำไมคุณถึงคิดว่ามันไม่ใช่แบบนี้ล่ะ? คุณประสบปัญหาหรือไม่? เพราะฉันไม่ได้ ทำงานได้อย่างไม่มีที่ติสำหรับฉัน
Bitterblue

@HiredMind นี่ไม่ใช่เรื่องส่วนตัวหรืออะไร แต่ความคิดในการใช้แอพที่สองหรือสคริปต์เพื่อรีสตาร์ทแอป C # ของฉันเป็นเรื่องที่น่ารังเกียจสำหรับฉัน Win7 เรียกใช้วิธีนี้ในโหมด Release อย่างไม่มีที่ติ (ฉันใช้มันเพื่อรีสตาร์ทแอปเมื่อผู้ใช้เปลี่ยนภาษา = ไม่มีอะไรสำคัญ) ดังนั้นฉันอยากจะบอกให้ผู้ใช้รีสตาร์ทแอปด้วยตนเองแทนที่จะใช้วิธีที่ฉันไม่เห็นด้วยกับตัวเอง ฉันเคยใช้สคริปต์ในอดีตและฉันไม่ชอบมันเลย
Bitterblue

@BitterBlue ฉันยอมรับว่าการใช้แอพตัวที่ 2 นั้นแย่ - ฉันพูดอย่างนั้นในคำตอบของฉัน แต่คุณได้ลองใช้วิธีการแอปเดียวนอกโปรแกรมดีบั๊กหรือไม่? มันใช้ไม่ได้กับ Windows บางเวอร์ชันเมื่อทิ้งคำตอบนี้ไว้และโหมด Release หรือ Debug ก็ไม่มีส่วนเกี่ยวข้องใด ๆ ถ้ามันเหมาะกับคุณเยี่ยม! แต่ฉันโดนปัญหานี้กัดและสิ่งที่ฉันได้รับคือผู้ใช้ที่โกรธแค้นหลายร้อย
HiredMind

13

ฉันมีปัญหาเหมือนกันและฉันก็มีข้อกำหนดในการป้องกันไม่ให้เกิดอินสแตนซ์ที่ซ้ำกันด้วยเช่นกันฉันขอเสนอทางเลือกอื่นให้กับที่ HiredMind เสนอ (ซึ่งจะใช้ได้ดี)

สิ่งที่ฉันกำลังทำคือเริ่มต้นกระบวนการใหม่ด้วย processId ของกระบวนการเก่า (กระบวนการที่ทริกเกอร์การรีสตาร์ท) เป็นอาร์กิวเมนต์บรรทัด 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);

จากนั้นเมื่อแอปใหม่เริ่มต้นฉันจะแยกวิเคราะห์อาร์เรย์บรรทัด cm ก่อนและตรวจสอบว่าแฟล็กรีสตาร์ทอยู่ที่นั่นด้วย processId หรือไม่จากนั้นรอให้กระบวนการนั้นออก:

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
   }
}

เห็นได้ชัดว่าฉันไม่ได้แสดงการตรวจสอบความปลอดภัยทั้งหมดที่ฉันมีอยู่เป็นต้น

แม้ว่าจะไม่เหมาะ - ฉันพบว่านี่เป็นทางเลือกที่ถูกต้องเพื่อที่คุณจะได้ไม่ต้องมีแอพแยกต่างหากเพื่อจัดการกับการรีสตาร์ท


1
IMHO ว่ามีวิธีแก้ปัญหาที่ดีกว่านี้ ฉันยังมีข้อกำหนดที่จะต้องมีอินสแตนซ์เดียวและอนุญาตให้ผู้ใช้รีสตาร์ทแอปพลิเคชัน (เช่นเมื่อเกิดปัญหา) ฉันเกือบจะนำโซลูชันของคุณไปใช้แล้ว แต่เกิดขึ้นกับฉันว่าจะเป็นการดีกว่าที่จะเพิ่มอาร์กิวเมนต์บรรทัดคำสั่งอื่นที่อนุญาตให้ทำงานหลายอินสแตนซ์
Dennis

อืมคุณกำลังย้อนกลับตรรกะ - ฉันชอบมัน! ปัญหาเดียวคือถ้ามีคนหาอาร์กิวเมนต์บรรทัด cmd ที่อนุญาตให้มีหลาย ๆ อินสแตนซ์แปลก ๆ อาจเกิดขึ้น: D
JohnIdol

ฉันโชคดีที่เป็นคุณสมบัติที่ผู้ใช้ร้องขอดังนั้นจึงเป็นแบบ WIN-WIN ฉันชอบที่พวกเขา 'พบ' เกิด/allowMultipleInstancesธงกว่าค่อนข้างแปลก/restartหนึ่ง
Dennis

ใช่ถ้าคุณอนุญาตหลายอินสแตนซ์ซึ่งเป็นทางออกที่ดีกว่าแน่นอน :)
JohnIdol

@JohnIdol Nice. ฉันคิดว่าฉันจะเปลี่ยนแฟล็กเป็น "-waitForProcessToExit" หรือบางอย่าง แต่เป็นวิธีที่ดีกว่า ตอนนี้ฉันกำลังต่อสู้กับปัญหา ClickOnce ด้วยการอ้างถึง EXE หนึ่งจาก EXE อื่นและสิ่งนี้จะช่วยแก้ปัญหานั้นได้
HiredMind

6

วิธีเริ่ม / ออก

// 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 ตัวที่สองซึ่งจะหยุดชั่วคราวจากนั้นเริ่มแอปพลิเคชันหลักให้คุณ


2
ซึ่งอาจใช้ไม่ได้หากแอปพลิเคชันได้รับการปกป้องจากหลายอินสแตนซ์
majkinetor

ใช่ฉันรู้สึกว่ากำลังเรียกใช้ Application.Exit () ทำให้ข้อความบางส่วนถูกเพิ่มไปยังคิวที่ซึ่งจำเป็นต้องมีการสูบดังนั้นรหัสบิตที่สองที่นี่ในคำตอบของฉันอาจใช้ไม่ได้
Adam Nofsinger

น่าเสียดายที่เทคนิคนี้ใช้ไม่ได้ (ฉันหวังว่ามันจะเป็นเช่นนั้น! มันง่ายกว่าวิธีแก้ปัญหาของฉันมาก) มันจะทำงานภายในดีบักเกอร์ Visual Studio แต่ไม่ได้ใช้ ดูคำตอบของฉันสำหรับโซลูชัน kludgy ที่ทำงานนอกดีบักเกอร์
HiredMind

HiredMind อาจจะใช่ ฉันลงเอยด้วยการแก้ปัญหารูปแบบ Watchdog
Adam Nofsinger

6

มันง่ายที่คุณเพียงแค่ต้องเรียกApplication.Restart()วิธีการที่มีแนวโน้มที่จะเรียกใช้แอปพลิเคชันของคุณเพื่อเริ่มต้นใหม่ แต่คุณต้องออกจากสภาพแวดล้อม Local ด้วยรหัสข้อผิดพลาด:

Application.Restart();
Environment.exit(int errorcode);

คุณสามารถสร้างการแจกแจงรหัสข้อผิดพลาดที่คุณสามารถใช้อย่างมีประสิทธิภาพ
อีกวิธีหนึ่งคือเพียงแค่ออกจากฟอร์มแอปพลิเคชันและเริ่มกระบวนการที่มีเส้นทางปฏิบัติการ:

Application.exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);

ทำงานได้ดีสำหรับฉันไม่จำเป็นต้องมีแอปสุนัขเฝ้าบ้านในกรณีของฉัน
user685590

3

ลองใช้รหัสนี้:

bool appNotRestarted = true;

รหัสนี้ต้องอยู่ในฟังก์ชันด้วย:

if (appNotRestarted == true) {
    appNotRestarted = false;
    Application.Restart();
    Application.ExitThread();
}

3

ฉันคิดหาวิธีแก้ปัญหาอื่นบางทีใคร ๆ ก็สามารถใช้ได้เช่นกัน

string batchContent = "/c \"@ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\"";
batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath);
Process.Start("cmd", batchContent);
Application.Exit();

รหัสถูกทำให้ง่ายขึ้นดังนั้นโปรดดูแลข้อยกเว้นและสิ่งต่างๆ;)


2

คุณกำลังลืมตัวเลือก / พารามิเตอร์บรรทัดคำสั่งที่ส่งผ่านไปยังอินสแตนซ์ที่กำลังทำงานอยู่ หากคุณไม่ผ่านสิ่งเหล่านั้นแสดงว่าคุณไม่ได้ทำการรีสตาร์ทจริง ตั้งค่าProcess.StartInfoด้วยการโคลนพารามิเตอร์กระบวนการของคุณจากนั้นเริ่มต้น

ตัวอย่างเช่นหากกระบวนการของคุณเริ่มต้นเมื่อmyexe -f -nosplash myfile.txtวิธีของคุณจะดำเนินการmyexeโดยไม่มีแฟล็กและพารามิเตอร์เหล่านั้นทั้งหมด


2

ฉันต้องการให้แอปพลิเคชันใหม่เริ่มทำงานหลังจากที่แอปพลิเคชันเก่าปิดตัวลง

การใช้ process.WaitForExit () เพื่อรอให้กระบวนการของคุณปิดระบบนั้นไม่มีเหตุผล มันจะหมดเวลาเสมอ

ดังนั้นแนวทางของฉันคือใช้ 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 );
}

2

นอกจากนี้คุณยังสามารถใช้Restarter

Restarter เป็นแอปพลิเคชันที่ตรวจสอบและรีสตาร์ทโปรแกรมและแอปพลิเคชันที่ขัดข้องหรือหยุดทำงานโดยอัตโนมัติ เดิมได้รับการพัฒนาเพื่อตรวจสอบและรีสตาร์ทเซิร์ฟเวอร์เกม แต่จะทำงานสำหรับคอนโซลหรือโปรแกรมหรือแอปพลิเคชันแบบฟอร์มใด ๆ


1
ลิงก์ที่ให้มาใช้งานไม่ได้อีกต่อไป แต่ฉันคิดว่านี่เป็นแอปพลิเคชั่นเดียวกันกับ CNET: download.cnet.com/Restarter/3000-2094_4-75810552.html
Surfbutler

2
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ส่งคืนไฟล์ aplication .exe ของคุณโปรดทำตามลำดับการโทร คุณอาจต้องการวางไว้ในประโยค try-catch


1

วิธีสร้างไฟล์ bat รันไฟล์แบตช์ก่อนปิดจากนั้นปิดอินสแตนซ์ปัจจุบัน

ไฟล์แบตช์ทำสิ่งนี้:

  1. รอวนซ้ำเพื่อตรวจสอบว่ากระบวนการออกแล้วหรือไม่
  2. เริ่มกระบวนการ

ซึ่งเป็นแอปพลิเคชันสุนัขเฝ้าบ้านของคนจนซึ่งฉันอธิบายรายละเอียดเพิ่มเติมเล็กน้อยด้านบน ประโยชน์ที่สำคัญของแอปพลิเคชันสุนัขเฝ้าบ้านตัวจริงคือมันจะจัดการได้แม้แอปดั้งเดิมจะตายโดยไม่สามารถหมุนบางอย่างออกไปได้
Adam Nofsinger

@AdamNofsinger ฉันเห็นแล้ว ฉันพลาดความคิดเห็นนั้น คุณอาจต้องการแก้ไขโพสต์ของคุณด้วยโซลูชันที่คุณใช้
AZ.

1

นี่คือ 2 เซ็นต์ของฉัน:

ลำดับเริ่มต้นอินสแตนซ์ใหม่ -> ปิดอินสแตนซ์ปัจจุบันควรใช้งานได้แม้กระทั่งสำหรับแอปพลิเคชันที่ไม่อนุญาตให้เรียกใช้หลายสำเนาพร้อมกันในกรณีนี้อินสแตนซ์ใหม่อาจส่งผ่านอาร์กิวเมนต์บรรทัดคำสั่งซึ่งจะระบุว่ากำลังดำเนินการรีสตาร์ท ดังนั้นการตรวจสอบอินสแตนซ์อื่น ๆ ที่ทำงานอยู่จึงไม่จำเป็น กำลังรอให้อินสแตนซ์แรกเสร็จสิ้นการใช้งานจริงของฉันด้วยเช่นกันหากจำเป็นอย่างยิ่งที่จะต้องไม่มีสองสถานการณ์ทำงานควบคู่กัน


1

ปัญหาในการใช้Application.Restart ()คือจะเริ่มกระบวนการใหม่ แต่ "เก่า" ยังคงมีอยู่ ด้วยเหตุนี้ฉันจึงตัดสินใจฆ่ากระบวนการเก่าโดยใช้ข้อมูลโค้ดต่อไปนี้:

            if(Condition){
            Application.Restart();
            Process.GetCurrentProcess().Kill();
            }

และทำงานได้ดีอย่างเหมาะสม ในกรณีของฉัน MATLAB และแอปพลิเคชัน C # กำลังแชร์ฐานข้อมูล SQLite เดียวกัน ถ้า MATLAB กำลังใช้ฐานข้อมูล Form-App ควรรีสตาร์ท (+ นับถอยหลัง) อีกครั้งจนกว่า MATLAB จะรีเซ็ตบิตที่ไม่ว่างในฐานข้อมูล (สำหรับข้อมูลด้านข้าง)


1

ฉันกลัวว่าการรีสตาร์ทแอปพลิเคชันทั้งหมดโดยใช้กระบวนการกำลังเข้าใกล้ปัญหาของคุณในทางที่ผิด

วิธีที่ง่ายกว่าคือการแก้ไขไฟล์ 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;
           }
        }
    }

1
เป็นที่น่าสังเกตว่าด้วยวิธีนี้คุณสามารถรีสตาร์ทแอปพลิเคชัน X ครั้งจากนั้นออกจากแอปพลิเคชันเพื่อหลีกเลี่ยงการวนซ้ำที่ไม่มีที่สิ้นสุด
RooiWillie

ขอบคุณ @RooiWillie ฉันได้เพิ่มตัวนับเพื่อทำสิ่งนั้นในกรณีที่โปรแกรมไม่สามารถออกได้ตามปกติ
Andrew

0

ฉันมีปัญหาที่คล้ายกัน แต่ของฉันเกี่ยวข้องกับการรั่วไหลของหน่วยความจำที่ไม่สามารถจัดการได้ซึ่งฉันไม่พบในแอปที่ต้องทำงานตลอด 24 ชั่วโมงทุกวัน กับลูกค้าฉันตกลงว่าเวลาที่ปลอดภัยในการรีสตาร์ทแอปคือ 03:00 น. หากการใช้หน่วยความจำเกินค่าที่กำหนด

ฉันลอง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);
    }
}

0

ฉันใช้สิ่งต่อไปนี้และทำในสิ่งที่คุณกำลังมองหา:

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);
}

0

สำหรับการใช้ As logout คุณจะต้องยุติแอพทั้งหมดจาก Ram Cache ดังนั้นให้ปิดแอปพลิเคชันก่อนแล้วจึงรันใหม่

// เมื่อคลิกปุ่มออกจากระบบ

foreach(Form frm in Application.OpenForms.Cast<Form>().ToList())
        {
            frm.Close();
        }
System.Diagnostics.Process.Start(Application.ExecutablePath);

0

คุณสามารถใส่รหัสของคุณไว้ในฟังก์ชันและเมื่อจำเป็นต้องรีสตาร์ทคุณก็สามารถเรียกใช้ฟังก์ชันได้


0

ยกตัวอย่างเช่นแอปพลิเคชันที่:

  1. ในขณะที่ไม่ได้ลงทะเบียนแอปพลิเคชัน (เมื่อเริ่มต้น) แอปพลิเคชันควรแจ้งให้ผู้ใช้ลงทะเบียนแอปพลิเคชันและสร้างบัญชีเข้าสู่ระบบ

  2. เมื่อส่งการลงทะเบียนและสร้างข้อมูลรับรองการเข้าสู่ระบบแล้ว แอปพลิเคชันควรรีสตาร์ทตรวจสอบการลงทะเบียนและแจ้งให้ผู้ใช้เข้าสู่ระบบด้วยข้อมูลรับรองที่ใส่ไว้ (เพื่อให้ผู้ใช้สามารถเข้าถึงคุณสมบัติทั้งหมดของแอปพลิเคชัน)

ปัญหา: โดยการสร้างและเปิดแอปพลิเคชันจาก Visual Studio การร้องทางเลือกใด ๆ จาก 4 ทางเลือกจะไม่สามารถบรรลุภารกิจที่ต้องการได้

/*
 * 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();

สิ่งที่เกิดขึ้นคือ: หลังจากสร้างการลงทะเบียนเข้าสู่ระบบและเรียกใช้ Application.Restart (); แอปพลิเคชันจะ (แปลก ๆ ) เปิดแบบฟอร์มการลงทะเบียนอีกครั้งและข้ามข้อมูลในฐานข้อมูล (แม้ว่าทรัพยากรจะถูกตั้งค่าเป็น "คัดลอกถ้าใหม่กว่า")

วิธีการแก้: สร้างแบทช์แอปพลิเคชัน (สำหรับฉัน) เป็นข้อพิสูจน์ว่าบรรทัดใด ๆ ข้างต้นทำงานได้จริงตามที่คาดไว้ ไม่ใช่เมื่อสร้างและเรียกใช้แอปพลิเคชันด้วย Visual Studio

ในตอนแรกฉันจะลองสร้างแอปพลิเคชันเป็นกลุ่ม เรียกใช้ภายนอก Visual Studio และตรวจสอบว่า Application.Restart () ใช้งานได้จริงตามที่คาดไว้หรือไม่

ตรวจสอบข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อนี้ด้วย: ฉันจะรีสตาร์ทแอปพลิเคชัน C # WinForm ของฉันได้อย่างไร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.