Làm cách nào để khởi động lại Ứng dụng C # WinForm của tôi?


86

Phát triển ứng dụng WinForm C # .NET 2.0. Cần ứng dụng tự đóng và khởi động lại.

Application.Restart();

Phương pháp trên đã được chứng minh là không đáng tin cậy .

Cách tốt hơn để khởi động lại ứng dụng là gì?


3
Tôi tò mò về sự cần thiết phải khởi động lại ứng dụng của bạn. Tôi chưa bao giờ nghĩ về nhu cầu đó trước đây Hoàn cảnh của bạn là gì?
— JeffH

Trường hợp cụ thể của chúng tôi - một ứng dụng trình phát đa phương tiện được cho là chạy qua một số hình ảnh và nội dung flash trong một vòng lặp. Nên chạy nhiều ngày liên tục mà máy không khởi động lại, và không có bàn phím / chuột nên không có tương tác của người dùng. Nếu chương trình bị treo (ngoại lệ chưa được xử lý), cần khởi động lại chương trình, không thoát ra ngoài hoặc hiển thị lỗi. stackoverflow.com/questions/773768/… Hãy xem lý do tại sao chương trình liên tục có các ngoại lệ mà tôi không thể ngăn chặn. :(
— Adam Nofsinger 30/04/09

1
Cuối cùng, một giải pháp tốt hơn nhiều cho ứng dụng của chúng tôi là phát triển một ứng dụng Watchdog nhỏ được khởi động (nếu chưa chạy) từ ứng dụng chính. Cơ quan giám sát chỉ cần kiểm tra sau mỗi 10 giây hoặc lâu hơn để xem liệu ứng dụng chính có còn một tiến trình đang chạy hay không và nếu không, nó sẽ khởi động một tiến trình. Đơn giản, thanh lịch và chắc chắn hơn nhiều so với việc cố gắng khởi động lại từ ứng dụng chính.
— Adam Nofsinger

2
Một lý do khác để khởi động lại là khi bạn thay đổi ngôn ngữ hoặc đã tải xuống bản cập nhật.
— Andrew Truckle

1
Nhưng nếu ... Ứng dụng cơ quan giám sát bị treo?
— Metoniem 16/1017

Câu trả lời:


39

Rất tiếc, bạn không thể sử dụng Process.Start () để bắt đầu một phiên bản của quy trình hiện đang chạy. Theo tài liệu Process.Start (): "Nếu quá trình đang chạy, không có tài nguyên quy trình bổ sung nào được bắt đầu ..."

Kỹ thuật này sẽ hoạt động tốt trong trình gỡ lỗi VS (vì VS thực hiện một số phép thuật khiến Process.Start nghĩ rằng tiến trình chưa chạy), nhưng sẽ thất bại khi không chạy dưới trình gỡ lỗi. (Lưu ý rằng điều này có thể dành riêng cho hệ điều hành - dường như tôi nhớ rằng trong một số thử nghiệm của mình, nó hoạt động trên XP hoặc Vista, nhưng tôi có thể chỉ nhớ đang chạy nó trong trình gỡ lỗi.)

Kỹ thuật này chính xác là kỹ thuật được sử dụng bởi lập trình viên cuối cùng trong dự án mà tôi hiện đang làm việc và tôi đã cố gắng tìm ra giải pháp cho điều này trong một thời gian khá dài. Cho đến nay, tôi chỉ tìm thấy một giải pháp và nó chỉ cảm thấy bẩn thỉu và khó chịu với tôi: khởi động ứng dụng thứ hai, chờ ứng dụng đầu tiên kết thúc trong nền, sau đó khởi chạy lại ứng dụng đầu tiên. Tôi chắc rằng nó sẽ hoạt động, nhưng, yuck.

Chỉnh sửa: Sử dụng ứng dụng thứ 2 hoạt động. Tất cả những gì tôi đã làm trong ứng dụng thứ hai là:

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

(Đây là một ví dụ rất đơn giản. Mã thực có rất nhiều kiểm tra tỉnh táo, xử lý lỗi, v.v.)


Tôi đồng ý với HiredMind và tôi thực sự đã tự thực hiện cùng một "chương trình Cơ quan giám sát" ngay sau khi viết câu trả lời. Xin lỗi, đáng lẽ phải quay lại đây và cập nhật. Tôi sẽ không nghĩ rằng nó sẽ cảm thấy quá xấu xí / yucky / bẩn thỉu khủng khiếp. Mẫu chương trình Watchdog được sử dụng khá rộng rãi.
— Adam Nofsinger 29/09/09

Bạn không thực sự cần ứng dụng thứ hai trên đĩa ... bạn có thể sử dụng một tập lệnh và tạo nó ngay lập tức với tên tạm thời ... Tôi nghĩ điều này có thể làm giảm bớt cảm giác tội lỗi của bạn khi có ứng dụng thứ hai vì mục đích khởi động lại riêng của bạn ... Hoặc bạn có thể "phát ra" một toàn bộ C # ứng dụng, biên dịch nó, lưu nó vào đĩa và thực hiện nó (bẩn, suy nghĩ bẩn) ..
— Loudenvier

Đoạn đầu tiên không đúng: Process.Startkhông nhìn vào danh sách các tiến trình HĐH đang chạy. Câu lệnh tài liệu này chỉ nói về thể hiện đối tượng đó của Processlớp. Các Processlớp có thể được gắn vào một quá trình hoạt động nhưng nó cũng có thể được trong tình trạng Unstarted. Theo tôi đây là một thiết kế vặn lên. Cách tốt nhất, IMO, là không bao giờ sử dụng lại một Process phiên bản và bắt đầu ngay lập tức nó sau khi tạo. Tốt nhất, hãy sử dụng Process.Startphương pháp tĩnh . Sau đó, tài liệu và lỗi thiết kế này không bao giờ phát huy tác dụng.
— usr

Mã hiển thị ở đây cũng không đáng tin cậy vì WaitForExit(1000). Nhưng toàn bộ thời gian chờ đợi là không cần thiết để bắt đầu một quy trình mới. Đó có thể là hành vi bổ sung mà bạn muốn, nhưng không bắt buộc phải bắt đầu một quy trình mới.
— usr

Tôi không biết bây giờ, nhưng chín năm trước (ahem) điều này chắc chắn là chính xác. :-)
— HiredMind

71

Một cách tiếp cận đơn giản hơn nhiều phù hợp với tôi là:

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

Điều này bảo toàn các đối số dòng lệnh và hoạt động bất chấp các trình xử lý sự kiện thường ngăn ứng dụng đóng.

Lời gọi Restart () cố gắng thoát, vẫn bắt đầu một phiên bản mới và quay trở lại. Sau đó, lệnh Exit () kết thúc quá trình mà không cho bất kỳ trình xử lý sự kiện nào có cơ hội chạy. Có một khoảng thời gian rất ngắn trong đó cả hai quá trình đang chạy, đây không phải là vấn đề trong trường hợp của tôi, nhưng có thể trong các trường hợp khác.

Mã thoát 0 trong Environment.Exit(0);chỉ định tắt máy hoàn toàn. Bạn cũng có thể thoát bằng 1 để xác định lỗi đã xảy ra.


Đơn giản, nhưng đáng tin cậy. Đây phải là câu trả lời được chấp nhận. Tôi đang cố gắng triển khai tính năng đăng xuất sẽ làm trống tất cả các biến toàn cục và xuất hiện như thể ứng dụng mới bắt đầu. Tôi sẽ chỉ hiển thị bảng điều khiển để đăng nhập và đặt lại tất cả các biến toàn cục chứa thông tin quan trọng từ DB thành vô ích. Điều này làm cho cuộc sống trở nên đơn giản hơn rất nhiều. Cảm ơn!
— DavidG

System.Windows.Forms.Application.Restart () cũng hoạt động cho các ứng dụng WPF. Đã thử nghiệm với HĐH Windows 10.
— NthDeveloper

Cái gì vậy ?! Cậu nhóc ... đúng không? C # <3. Hãy nhớ rằng, điều này theo mặc định sẽ không tăng OnClose()các sự kiện biểu mẫu và tương tự.
— F8ER

56

Nếu bạn đang ở biểu mẫu ứng dụng chính, hãy thử sử dụng

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

7
Nó tương tự, nhưng khác nhau. Application.Exit đã không hoạt động với tôi, và this.Close () đã thực hiện công việc.
— Darqer

1
May Enviorment.Exit(0)cũng sẽ làm được việc.
— Dwza

2
Enviorment.Exitlà một lối thoát bẩn và khá xâm lấn vì nó ngăn không cho mã dọn dẹp ứng dụng chạy. Không phải là lựa chọn đúng trong hầu hết thời gian.
— usr

16

Tôi có thể đến muộn bữa tiệc nhưng đây là giải pháp đơn giản của tôi và nó hoạt động như một sự quyến rũ với mọi ứng dụng tôi có:

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

Hoạt động rất tốt trên Win-7-x64 và Win-XP-x32. Tôi không thấy gì về bất kỳ ràng buộc nào trong tài liệu . Đây phải là câu trả lời được chấp nhận.
— Bitterblue,

@Bitterblue Liên kết đến tài liệu bạn đã đăng cho biết "Nếu quá trình đang chạy, không có tài nguyên quy trình bổ sung nào được bắt đầu." Đây là dòng thứ 3 trong phần nhận xét. Tôi ước nó không phải theo cách này, nhưng nó là.
— HiredMind

@HnticMind Tôi đoán chúng ta có thể tranh luận về ý nghĩa của "ràng buộc" đối với mỗi chúng ta. Nhưng phần có tiêu đề "Nhận xét" không phải "Ràng buộc". Vì vậy, tôi có thể sống với nó. Và tại sao bạn ước nó không phải theo cách này? Bạn có gặp bất kỳ vấn đề nào với điều đó không? Bởi vì tôi đã không. Hoạt động hoàn hảo cho tôi.
— Bitterblue

@HnticMind Đây không phải là vấn đề cá nhân hay bất cứ điều gì nhưng ý tưởng sử dụng ứng dụng thứ hai hoặc tập lệnh chỉ để khởi động lại ứng dụng C # của tôi thật tuyệt vời đối với tôi. Win7 thực thi phương pháp này ở chế độ Phát hành một cách hoàn hảo cho đến nay (tôi sử dụng nó để khởi động lại ứng dụng của mình khi người dùng thay đổi ngôn ngữ = không có gì quan trọng). Vì vậy, tôi thà yêu cầu người dùng khởi động lại ứng dụng theo cách thủ công hơn là sử dụng các phương pháp mà bản thân tôi không chấp thuận. Tôi đã sử dụng script trong quá khứ và tôi hoàn toàn không thích nó.
— Bitterblue

@BitterBlue Tôi đồng ý rằng việc sử dụng ứng dụng thứ hai rất tệ - tôi đã nói như vậy trong câu trả lời của mình. Nhưng bạn đã thử phương pháp ứng dụng đơn bên ngoài trình gỡ lỗi chưa? Nó không hoạt động trên một số phiên bản Windows khi để lại câu trả lời này và chế độ Phát hành hoặc Gỡ lỗi không liên quan gì đến nó. Nếu nó làm việc cho bạn, tuyệt vời! Nhưng tôi đã gặp phải vấn đề này và những gì tôi nhận được là hàng trăm người dùng giận dữ.
— HiredMind vào

12

Tôi đã gặp vấn đề chính xác tương tự và tôi cũng có yêu cầu ngăn chặn các trường hợp trùng lặp - tôi đề xuất một giải pháp thay thế cho giải pháp mà HiredMind đang đề xuất (sẽ hoạt động tốt).

Những gì tôi đang làm là bắt đầu quy trình mới với processId của quy trình cũ (quy trình kích hoạt khởi động lại) dưới dạng đối số dòng 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);

Sau đó, khi ứng dụng mới khởi động, trước tiên, tôi phân tích cú pháp dòng cm args và kiểm tra xem cờ khởi động lại có ở đó với processId hay không, sau đó đợi quá trình đó thoát:

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

Tôi rõ ràng là không hiển thị tất cả các kiểm tra an toàn mà tôi có, v.v.

Ngay cả khi không lý tưởng - tôi thấy đây là một giải pháp thay thế hợp lệ để bạn không cần phải có một ứng dụng riêng chỉ để xử lý việc khởi động lại.


1
IMHO rằng có một giải pháp gọn gàng hơn cho việc này. Tôi cũng có yêu cầu phải có một phiên bản duy nhất và cho phép người dùng khởi động lại ứng dụng (ví dụ: khi nó gặp sự cố). Tôi gần như đã triển khai giải pháp của bạn, tuy nhiên tôi nhận ra rằng tốt hơn là chỉ cần thêm một đối số dòng lệnh khác cho phép chạy nhiều phiên bản.
— Dennis

mmm, bạn đang đảo ngược logic - tôi thích nó! Chỉ vấn đề là nếu con số người nào đó ra các đối số dòng cmd cho phép nhiều trường hợp thứ kỳ lạ có thể xảy ra: D
— JohnIdol

Chà, tôi thật may mắn rằng đó là một tính năng mà người dùng đã yêu cầu nên nó là WIN-WIN. Tôi muốn họ 'tìm thấy' một /allowMultipleInstanceslá cờ hơn là một lá cờ kỳ lạ /restart.
— Dennis

Vâng nếu bạn cho phép cho nhiều trường hợp đó là một giải pháp tốt hơn cho chắc :)
— JohnIdol

@JohnIdol Đẹp. Tôi nghĩ rằng tôi sẽ thay đổi cờ của mình thành "-waitForProcessToExit" hoặc một cái gì đó nhưng nếu không thì đó là một giải pháp thanh lịch hơn. Hiện tại, tôi đang vật lộn với sự cố ClickOnce khi tham chiếu một EXE từ EXE khác và điều này sẽ giải quyết được điều đó.
— HiredMind

6

Phương thức Bắt đầu / Thoát

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

Điều này dường như hoạt động tốt hơn Application.Restart ();

Không chắc điều này sẽ xử lý như thế nào nếu chương trình của bạn bảo vệ khỏi nhiều phiên bản. Tôi đoán là bạn nên khởi chạy tệp .exe thứ hai tạm dừng và sau đó khởi động ứng dụng chính cho bạn.


2
Điều đó có thể không hoạt động nếu ứng dụng được bảo vệ khỏi nhiều trường hợp.
— majkinetor

Yah, tôi có cảm giác khi gọi Application.Exit () chỉ khiến một số thông báo được thêm vào hàng đợi ở đâu đó cần được bơm, vì vậy bit mã thứ hai ở đây trong câu trả lời của tôi có thể thực sự sẽ không hoạt động.
— Adam Nofsinger

Thật không may, kỹ thuật này không hoạt động (Tôi ước nó đã làm được! Nó đơn giản hơn nhiều so với giải pháp của tôi). Nó sẽ hoạt động bên trong trình gỡ lỗi Visual Studio nhưng không hoạt động trong thực tế. Xem câu trả lời của tôi để biết giải pháp kludgy hoạt động bên ngoài trình gỡ lỗi.
— HiredMind

HiredMind có thể đúng. Tôi đã kết thúc với giải pháp mẫu Watchdog.
— Adam Nofsinger

6

Đơn giản của nó, bạn chỉ cần gọi các Application.Restart()phương thức có xu hướng gọi ứng dụng của bạn để được khởi động lại. Nhưng bạn phải thoát khỏi môi trường Cục bộ với mã lỗi của chúng:

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

bạn có thể tạo một bảng liệt kê mã lỗi mà bạn có thể sử dụng nó một cách hiệu quả.
Một phương pháp khác là chỉ cần thoát khỏi biểu mẫu ứng dụng và bắt đầu quá trình có đường dẫn thực thi:

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

Hoạt động tốt đối với tôi, không cần ứng dụng cơ quan giám sát trong trường hợp của tôi.
— user685590

3

Hãy thử mã này:

bool appNotRestarted = true;

Mã này cũng phải có trong hàm:

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

3

Tôi đã tìm ra một giải pháp khác, có lẽ ai cũng có thể sử dụng nó.

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

Mã được đơn giản hóa nên hãy quan tâm đến Ngoại lệ và nội dung;)


2

Bạn đang quên các tùy chọn / tham số dòng lệnh đã được chuyển vào phiên bản hiện đang chạy của bạn. Nếu bạn không vượt qua những điều đó, bạn không thực hiện khởi động lại thực sự. Đặt Process.StartInfomột bản sao các thông số quy trình của bạn, sau đó bắt đầu.

Ví dụ: nếu quy trình của bạn được bắt đầu myexe -f -nosplash myfile.txt, phương thức của bạn sẽ chỉ thực thi myexemà không có tất cả các cờ và tham số đó.


2

Tôi muốn ứng dụng mới khởi động sau khi ứng dụng cũ tắt.

Sử dụng process.WaitForExit () để đợi quá trình của riêng bạn tắt không có ý nghĩa gì. Nó sẽ luôn luôn hết thời gian.

Vì vậy, cách tiếp cận của tôi là sử dụng Application.Exit () sau đó đợi, nhưng cho phép các sự kiện được xử lý, trong một khoảng thời gian. Sau đó, khởi động một ứng dụng mới với các đối số giống như ứng dụng cũ.

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

Bạn cũng có thể sử dụng Restarter .

Restarter là ứng dụng tự động theo dõi và khởi động lại các chương trình, ứng dụng bị treo hoặc bị treo. Ban đầu nó được phát triển để giám sát và khởi động lại máy chủ trò chơi, nhưng nó sẽ thực hiện công việc đối với bất kỳ bảng điều khiển hoặc chương trình hoặc ứng dụng dựa trên biểu mẫu nào


1
Công trình liên kết đã cung cấp không còn, nhưng tôi nghĩ rằng đây là cùng một ứng dụng trên 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 trả về đường dẫn tệp .exe aplication của bạn Vui lòng thực hiện theo thứ tự lệnh gọi. Bạn có thể muốn đặt nó trong một mệnh đề try-catch.


1

Làm thế nào về tạo một tệp bat, chạy tệp loạt trước khi đóng, sau đó đóng phiên bản hiện tại.

Tệp lô thực hiện điều này:

  1. chờ trong vòng lặp để kiểm tra xem quá trình đã thoát chưa.
  2. bắt đầu quá trình.

Đó là ứng dụng cơ quan giám sát của một người nghèo, mà tôi mô tả chi tiết hơn một chút ở trên. Lợi ích chính của một ứng dụng cơ quan giám sát thực sự là nó thậm chí sẽ xử lý nếu ứng dụng gốc bị chết mà không thể tắt một cái gì đó.
— Adam Nofsinger

@AdamNofsinger Tôi thấy bây giờ. Tôi đã bỏ lỡ nhận xét đó. Bạn có thể muốn chỉnh sửa bài đăng của mình bằng giải pháp bạn sử dụng.
— AZ.

1

Đây là 2 xu của tôi:

Trình tự Bắt đầu phiên bản mới-> Đóng phiên bản hiện tại sẽ hoạt động ngay cả đối với các ứng dụng không cho phép chạy nhiều bản sao đồng thời vì trong trường hợp này, phiên bản mới có thể được truyền một đối số dòng lệnh sẽ cho biết đang có khởi động lại vì vậy việc kiểm tra các trường hợp khác đang chạy sẽ không cần thiết. Việc chờ đợi phiên bản đầu tiên thực sự hoàn thành của tôi cũng được thực hiện nếu nó hoàn toàn bắt buộc rằng không có hai nội dung nào đang chạy song song.


1

Tôi sợ rằng việc khởi động lại toàn bộ ứng dụng bằng Quy trình đang tiếp cận vấn đề của bạn theo cách sai.

Một cách dễ dàng hơn là sửa đổi tệp Program.cs để khởi động lại:

    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
Điều đáng nói là với giải pháp này, bạn có thể khởi động lại ứng dụng X lần, sau đó thoát ứng dụng để tránh vòng lặp vô hạn.
— RooiWillie

Cảm ơn @RooiWillie Tôi đã thêm một bộ đếm để làm điều đó, trong trường hợp chương trình không thể thoát bình thường.
— Andrew

0

Tôi đã gặp sự cố tương tự, nhưng vấn đề của tôi liên quan đến rò rỉ bộ nhớ không thể quản lý mà tôi không thể tìm thấy trên một ứng dụng phải chạy 24/7. Với khách hàng, tôi đồng ý rằng thời gian an toàn để khởi động lại ứng dụng là 03:00 sáng nếu mức tiêu thụ bộ nhớ vượt quá giá trị đã xác định.

Tôi đã thử Application.Restart, nhưng vì nó dường như sử dụng một số cơ chế khởi động phiên bản mới trong khi nó đang chạy, tôi đã chuyển sang một chương trình khác. Tôi đã sử dụng thủ thuật rằng hệ thống tệp xử lý vẫn tồn tại cho đến khi quá trình tạo ra chúng chết. Vì vậy, từ Ứng dụng, tôi đã thả tệp vào đĩa chứ không phải Dispose()xử lý. Tôi đã sử dụng tệp để gửi thư mục thực thi và thư mục bắt đầu của 'chính tôi' (để thêm tính linh hoạt).

Mã:

_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()ở cuối sẽ bắt đầu tắt ứng dụng và xử lý tệp mà tôi sử dụng StreamWriterở đây sẽ được giữ mở cho đến khi quá trình thực sự chết. Sau đó...

Restarter.exe bắt đầu hoạt động. Nó TRIES để đọc tệp ở chế độ độc quyền, ngăn nó có quyền truy cập cho đến khi ứng dụng chính chưa chết, sau đó khởi động ứng dụng chính, xóa tệp và tồn tại. Tôi đoán rằng nó không thể đơn giản hơn:

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

Tôi sử dụng những thứ sau và nó thực hiện chính xác những gì bạn đang tìm kiếm:

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

để sử dụng Khi đăng xuất, bạn cần phải chấm dứt tất cả ứng dụng khỏi Ram Cache vì vậy hãy đóng Ứng dụng trước rồi chạy lại nó

// khi nhấp vào nút Đăng xuất

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

0

Vấn đề của việc sử dụng Application.Restart () là nó bắt đầu một quy trình mới nhưng quy trình "cũ" vẫn còn sót lại. Vì vậy, tôi quyết định Hủy quy trình cũ bằng cách sử dụng đoạn mã sau:

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

Và nó hoạt động tốt. Trong trường hợp của tôi, MATLAB và Ứng dụng C # đang chia sẻ cùng một cơ sở dữ liệu SQLite. Nếu MATLAB đang sử dụng cơ sở dữ liệu, thì Biểu mẫu-Ứng dụng sẽ khởi động lại (+ Đếm ngược), cho đến khi MATLAB đặt lại bit bận của nó trong cơ sở dữ liệu. (Chỉ để biết thông tin phụ)


0

Bạn có thể đặt mã của mình bên trong một hàm và khi cần khởi động lại, bạn chỉ có thể gọi hàm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.