2011-12-16 3 views
2

새 버전이있을 때 자동으로 응용 프로그램을 다시 시작하는 Windows 서비스를 얻으려고 노력했습니다. 내 코드는 아래에 있으며 실제로 작동합니다. 제 질문은 이것입니다 : 여기에 큰 노 - 노가 있습니까? 나는 별도의 스레드에 응용 프로그램 도메인을 만드는 것에 익숙하지 않으며이를 달성하는보다 우아한 방법이 있는지 알고 싶습니다. 나는 또한 내가 이것을 어떻게 다루고 있는지에 관해서는 큰 맹점을 가지고 있을까 우려하고있다. 모든 조언을 부탁드립니다.다른 스레드에 응용 프로그램 도메인이있는 자체 업데이트 응용 프로그램

일반적인 두 가지 요소가 있습니다. 실행중인 Windows 서비스가 다른 프로세스에서 내 응용 프로그램을 시작한 다음 해당 응용 프로그램의 새 버전을 사용할 수있을 때이를 폴링합니다. 두 번째 부분은 시작, 업데이트, 다시 시작되는 실제 앱입니다.

먼저 서비스가 시작되면 LoadApp()를 호출하여 앱이 실행되기 시작합니다.

private void Process(object stateInfo) 
{ 
    if (!Monitor.TryEnter(_locker)) { return; } 

    try 
    { 
     // Check for new binaries. If new, copy the files and restart the app domain.    
     if (!NewAppVersionReady()) { return; } 
     DeleteFiles(); 
     CopyFiles(); 
     RestartAppDomain(); 
    } 
    finally 
    { 
     Monitor.Exit(_locker); 
    } 
} 

RestartAppDomain()과 같습니다 : 다음

private void LoadApp() 
    { 
    // ** appDomainSetup here ** 

    this._appDomain = AppDomain.CreateDomain("MyUpdatedApp", AppDomain.CurrentDomain.Evidence, appDomainSetup); 

    this._tokenSource = new CancellationTokenSource(); 

    Task.Factory.StartNew(() => 
    { 
     try 
     { 
      this._appDomain.ExecuteAssembly(assembly); 
     } 
     catch (AppDomainUnloadedException ex) 
     { 
      Debug.WriteLine(ex.ToString()); 
     } 
    }, _tokenSource.Token); 
} 

, 매 10 초 타이머가이 메소드를 호출합니다. 이 메소드에서 두 번째 줄에 앱 도메인을 언로드하면 예외가 발생합니다. (나는 그것을 무시 기본적으로 예외를 잡기에 의해 그 주위에 얻을.)

private void RestartAppDomain() 
{ 
    this._tokenSource.Cancel(); 
    AppDomain.Unload(this._appDomain); 
    LoadApp(); 
} 

편집을 다음의 AppDomain.Unload() 라인이 불필요하다고 발견 이후가했습니다. 이 기능이 없으면 서비스는 새 버전으로 앱을 업데이트 한 다음 새 버전의 앱을 시작합니다. 나의 큰 관심사는 토큰 소스에서 Cancel()을 호출하는 것이다. 나는 앱을 그냥 강제로 종료하지 않고 정상적으로 종료 할 수 있기를 바랍니다.

답변

3

몇 번의 시행 착오와 학습을 통해 필자는 적절한 해결책을 찾은 것으로 보인다. 다른 사람들에게 도움이 될 수 있기를 바랍니다.

먼저 별도의 프로젝트에서 인터페이스를 만들었으므로 자동 업데이트 응용 프로그램은 실제로 자체 응용 프로그램 도메인에서 실행되는 응용 프로그램을 참조 할 필요가 없습니다. 이 인터페이스는 자동 업데이트 앱이 다른 앱에서 시작 및 중지를 호출 할 수 있도록 사용되었습니다. 별도의 도메인에서 실행됩니다 응용 프로그램에서

public interface IStartStop 
{ 
    void Start(); 
    void Stop(); 
} 

, 나는 클래스가 MarshalByRefObject에서 파생 및 IStartStop을 구현했다.

this._appDomain = AppDomain.CreateDomain(this._appName, AppDomain.CurrentDomain.Evidence, appDomainSetup); 
this._startStopControllerToRun = (IStartStop)this._appDomain.CreateInstanceFromAndUnwrap(assemblyName, this._fullyQualifiedClassName); 
this._startStopControllerToRun.Start(); 

그리고이 방법으로 수행 멈추는 :

this._startStopControllerToRun.Stop(); 
AppDomain.Unload(this._appDomain); 

좀 더 자세한 내용이 있습니다를

public class PrestoTaskRunnerController : MarshalByRefObject, IStartStop, IDisposable 

이 나를 시작하고 내 자기 갱신 응용 프로그램에서이 응용 프로그램을 중지 할 수 있습니다 하지만 이것은 일반적인 개념이며 잘 작동하는 것 같습니다.

+0

당신이 듣고있어 기쁘다! 나는 매우 비슷한 일을하고 있습니다. 그래서 여러분의 코드/psuedocode를 비교해보고 더 많은 것을보고 싶을 것입니다. 그리고 아마도 우리는 서로에게서 무언가를 배울 수 있습니다. 필자의 주요 목표는 데이터베이스에서 어셈블리를 호스트하는 것이었지만 일반적인 종속성 (IStartStop 인터페이스, 추가 dll)에 대한 필요성을 피하는 등 관리 할 수있는 몇 가지 좋은면이 있습니다. – Thracx

+0

어떻게 공통 의존성을 피 했습니까? –

관련 문제