내 C # WinForm 응용 프로그램을 어떻게 다시 시작합니까?
C # .NET 2.0 WinForm 애플리케이션 개발. 응용 프로그램을 닫고 자체적으로 다시 시작해야합니다.
Application.Restart();
위의 방법은 신뢰할 수없는 것으로 입증되었습니다 .
응용 프로그램을 다시 시작하는 더 좋은 방법은 무엇입니까?
불행히도 Process.Start ()를 사용하여 현재 실행중인 프로세스의 인스턴스를 시작할 수 없습니다. Process.Start () 문서에 따르면 : "프로세스가 이미 실행 중이면 추가 프로세스 리소스가 시작되지 않습니다 ..."
이 기술은 VS 디버거에서 잘 작동하지만 (VS는 Process.Start가 프로세스가 아직 실행 중이 아니라고 생각하게하는 일종의 마법을 수행하기 때문에) 디버거에서 실행되지 않으면 실패합니다. (이것은 OS에 따라 다를 수 있습니다. 일부 테스트에서는 XP 또는 Vista에서 작동했지만 디버거에서 실행 한 것을 기억하고있을 수 있습니다.)
이 기술은 내가 현재 작업하고있는 프로젝트의 마지막 프로그래머가 사용한 기술이며, 이에 대한 해결 방법을 꽤 오랫동안 찾으려고 노력해 왔습니다. 지금까지 한 가지 해결책 만 찾았는데, 그저 더럽고 칙칙한 느낌이 듭니다. 첫 번째 애플리케이션이 종료 될 때까지 백그라운드에서 대기하는 두 번째 애플리케이션을 시작한 다음 첫 번째 애플리케이션을 다시 시작합니다. 나는 그것이 작동 할 것이라고 확신하지만, 쉿.
편집 : 두 번째 응용 프로그램을 사용하면 작동합니다. 두 번째 앱에서 제가 한 것은 다음과 같습니다.
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, "");
}
(이것은 매우 간단한 예제입니다. 실제 코드에는 온 전성 검사, 오류 처리 등이 많이 있습니다.)
메인 앱 형태라면 사용 해보세요
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app
나를 위해 일한 훨씬 간단한 접근 방식은 다음과 같습니다.
Application.Restart();
Environment.Exit(0);
이렇게하면 명령 줄 인수가 유지되고 일반적으로 응용 프로그램이 닫히지 않도록하는 이벤트 처리기가 있어도 작동합니다.
Restart () 호출은 종료를 시도하고 어쨌든 새 인스턴스를 시작하고 반환합니다. 그런 다음 Exit () 호출은 이벤트 처리기에 실행할 기회를주지 않고 프로세스를 종료합니다. 두 프로세스가 모두 실행되는 매우 짧은 기간이 있습니다. 제 경우에는 문제가되지 않지만 다른 경우에는 가능합니다.
종료 코드 0 입력은 Environment.Exit(0);
완전 종료 를 지정합니다. 1로 종료하여 오류가 발생했음을 지정할 수도 있습니다.
나는 파티에 늦을 수도 있지만 여기에 내 간단한 해결책이 있으며 내가 가진 모든 응용 프로그램에서 매력처럼 작동합니다.
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가 제안한 대안에 대한 대안을 제안합니다 (잘 작동합니다).
내가하고있는 일은 이전 프로세스 (다시 시작을 트리거하는 프로세스)의 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
}
}
나는 내가 가지고있는 모든 안전 점검 등을 분명히 보여주지 않고있다.
이상적이지 않더라도-나는 이것이 유효한 대안이라고 생각하므로 다시 시작을 처리하기 위해 별도의 앱을 배치 할 필요가 없습니다.
간단합니다 Application.Restart()
. 다시 시작하기 위해 애플리케이션을 호출하는 경향이 있는 메소드를 호출하면됩니다. 그러나 오류 코드를 사용하여 로컬 환경을 종료해야합니다.
Application.Restart();
Environment.exit(int errorcode);
효율적으로 사용할 수 있도록 오류 코드 열거 형을 만들 수 있습니다.
또 다른 방법은 응용 프로그램을 종료하고 실행 경로가있는 프로세스를 시작하는 것입니다.
Application.exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);
시작 / 종료 방법
// 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를 실행하는 것이 더 나을 것입니다.
이 코드를 시도하십시오.
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
모든 플래그 및 매개 변수없이 만 실행 됩니다.
이전 애플리케이션이 종료 된 후 새 애플리케이션이 시작되기를 원했습니다.
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 );
}
Restarter 를 사용할 수도 있습니다 .
Restarter는 충돌하거나 중단 된 프로그램 및 응용 프로그램을 자동으로 모니터링하고 다시 시작하는 응용 프로그램입니다. 원래 게임 서버를 모니터링하고 다시 시작하기 위해 개발되었지만 모든 콘솔 또는 양식 기반 프로그램 또는 응용 프로그램에 대한 작업을 수행합니다.
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 파일 경로를 반환합니다. 호출 순서를 따르십시오. try-catch 절에 배치 할 수 있습니다.
여기 내 2 센트입니다.
새 인스턴스 시작-> 현재 인스턴스 닫기 시퀀스는 여러 복사본을 동시에 실행하는 것을 허용하지 않는 응용 프로그램에서도 작동해야합니다.이 경우 새 인스턴스에 다시 시작이 진행 중임을 나타내는 명령 줄 인수가 전달 될 수 있습니다. 따라서 실행중인 다른 인스턴스를 확인할 필요가 없습니다. 두 인스턴스가 병렬로 실행되지 않는 것이 절대적으로 필수적인 경우 첫 번째 인스턴스가 실제로 구현을 완료 할 때까지 기다립니다.
Process를 사용하여 전체 응용 프로그램을 다시 시작하는 것이 잘못된 방식으로 문제에 접근하는 것이 두렵습니다.
더 쉬운 방법은 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;
}
}
}
I had a similar problem, but mine was related to unmanageable memory leak that I couldn't find on an app that has to run 24/7. With the customer I agreed that safe time to restart the app was 03:00AM if the memory consumption was over the defined value.
I tried Application.Restart
, but since it seems to use some mechanism that starts new instance while it is already running, I went for another scheme. I used the trick that file system handles persist until process that created them dies. So, from The Application, i dropped the file to the disk, and didn't Dispose()
the handle. I used the file to send 'myself' executable and starting directory also (to add flexibility).
Code:
_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()
at the end would initiate app shutdown, and file handle I used for StreamWriter
here would be held open until process really dies. Then...
Restarter.exe comes into action. It TRIES to read the file in exclusive mode, preventing it to gain access until main app wasn't dead, then starts main app, deletes the file and exists. I guess that it can't be simpler:
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);
}
}
How about create a bat file, run the batch file before closing, and then close the current instance.
The batch file does this:
- wait in a loop to check whether the process has exited.
- start the process.
I use the following and it does exactly what you are looking for:
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);
}
for using As logout you need to terminate all app from Ram Cache so close The Application first and then Rerun it
//on clicking Logout Button
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList())
{
frm.Close();
}
System.Diagnostics.Process.Start(Application.ExecutablePath);
The problem of using Application.Restart() is, that it starts a new process but the "old" one is still remaining. Therefor I decided to Kill the old process by using the following code snippet:
if(Condition){
Application.Restart();
Process.GetCurrentProcess().Kill();
}
And it works proper good. In my case MATLAB and a C# Application are sharing the same SQLite database. If MATLAB is using the database, the Form-App should restart (+Countdown) again, until MATLAB reset its busy bit in the database. (Just for side information)
You could enclose your code inside a function and when restart is needed you can just call the function.
참고URL : https://stackoverflow.com/questions/779405/how-do-i-restart-my-c-sharp-winform-application
'Nice programing' 카테고리의 다른 글
strpos에서 배열을 바늘로 사용 (0) | 2020.10.13 |
---|---|
C #에서 잘못된 XML 문자 이스케이프 (0) | 2020.10.13 |
Node.js를 통해 Amazon S3에 base64 인코딩 이미지 업로드 (0) | 2020.10.13 |
python SimpleHTTPServer를 localhost에서만 실행할 수 있습니까? (0) | 2020.10.13 |
'android-24'를 컴파일하려면 JDK 1.8 이상이 필요합니다. (0) | 2020.10.13 |