SimpleIsBest.NET

유경상의 닷넷 블로그

Interactive Service 만들기

by 블로그쥔장 | 작성일자: 2005-10-18 오전 12:50:00
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.
모 개발자 커뮤니티에서 어떤 분이 질문하셔서 답변을 달다가 길어져서 여기에 글로 남깁니다. 역시 게시판 놀이는 제 컨텐츠가 아닌 해당 커뮤니티의 컨텐츠가 되어 버리므로 그닥 좋아하지 않아서... 근데 길긴 길군요... 이렇게 긴 글을 쓰다보면 회의도 많이 생깁니다. 내가 이짓을 왜하지? -_-;

Creating Interactive Service

Windows 서비스, 혹은 NT 서비스, Win32 서비스 등으로 불리는 '서비스'는 윈도우 시스템 부팅과 더불어 수행되는 프로세스로서 UNIX로 말하자면 데몬(daemon) 프로세스 정도에 해당하는 프로세스가 되겠다. 이 서비스들이 제대로 설정되지 않거나 제대로 구동되지 않으면 윈도우 시스템은 제대로 부팅조차 되지 않는 무용지물이 되어 버린다. 많은 독자들이 알지 못하는 것 중 하나가, 디바이스 드라이버 역시 서비스의 일종이라는 점이다. 이렇게 서비스는 윈도우 시스템에서 매우 중요한 역할을 하는 운영체제 요소 중 하나이다.

What's the Interactive Service ?

Windows 서비스는 대개 사용자 인터페이스(UI)를 갖지 않는다. 그도 그럴 것이, UI를 갖기 위해서는 윈도우 스테이션(window station)이란 것이 필요하고(그냥 그런게 있다고 알아 두자. -_-;) 윈도우 스테이션은 사용자가 콘솔이나 터미널로 로그온 해야만 생성되지만, 서비스는 사용자 로그온 보다 먼저 실행되기 때문에 윈도우 스테이션을 가질 수 없기 때문이다. 아주 가끔 Windows 서비스가 UI를 갖아야 할 때가 생기곤 하는데, 이 때 서비스가 UI를 갖는 경우, 이 서비스를 Interactive 서비스라고 한다. 필자는 아직 이런 상황을 겪어보지 못했다. 사실 별로 겪고 싶지 않은 상황이다. 고려해야 할 사항들이 졸라 많기 때문이다. 고려해야 할 사항이 뭔지는 쪼매만 기둘려 봐봥...

어찌 되었건 Interactive 서비스를 꼭, 반드시, 절대로, 정말로, 완전히 사용해야 한다면 사용할 수 있는 방법이 있다. 먼저 서비스 관리자를 통해 화면 1과 같이 Interactive 서비스 설정을 해줄 수 있다. 화면 1을 보면 눈치를 챌 수 있겠지만 Interactive 서비스를 위해서는 기본적으로 로컬 시스템 계정이 사용되어야 한다. Interactive 서비스 관련 MSDN 자료를 살펴보면, 로컬 시스템 계정이 아니여도 되는 것처럼 설명하고는 있지만, 그게 제약이 훨씬 더 많다. 일단 로컬 시스템 계정이 사용되어야 한다고 알아두자. 이렇게 Interactive 서비스로 설정되면 서비스는 데스크톱 화면과 상호작용, 즉 UI를 표시하고 사용자의 입력을 받을 수 있게 된다.


화면 1. 서비스 관리자 MMC에서 Interactive 서비스 설정

Programmatic Setting to Interactive Services

서비스 관리자 MMC를 사용하지 않고 프로그램적으로 설치 시에 Interactive 서비스를 만들 수 있는 방법은 없을까? 설마 없기야 하겠는가? 있다. 서비스가 설치되기 위해서는 Win32 API 인 CreateService 함수를 호출해야 한다. 이 함수 호출 시 dwServiceType 매개변수에 SERVICE_INTERACTIVE_PROCESS 상수(0x100) 값을 추가해 주어야 한다. 뭐 C/C++로 서비스를 만든다면 어려울게 하나두 없겠지만, 닷넷 환경이라면 이것이 좀 문제가 된다.

친절한 닷넷씨라고 하지만 모든 경우를 대비하고 있지는 않는 것 만은 확실하다 (그렇다고 친절하지 않다고 치부하기엔 좀 오버가 심하닷!). 왜 이런 이야기를 하냐면... 닷넷에서 Windows 서비스를 만드는 것은 엄청나게 편리하다. C/C++로 Windows 서비스를 작성해 본 사람이라면 닷넷이 얼마나 편리한가를 뼈저리게 느낄 수 있을 것이다. 설치 역시 대단히 편리하다. ServiceInstaller 클래스와 ServiceProcessInstaller 클래스를 사용하면 간단한 코드로도 서비스 설치를 손쉽게 구현할 수 있다(이 클래스 내부에서 CreateService 함수가 호출된다). 하지만... 설치에 관여된 ServiceInstaller 클래스는 우리가 원하는 Interactive Service 설치를 전혀 지원하지 않는다. 손 안대고 코 풀려는 심산이 있었다면 일찌감치 포기해야 한다는 얘기 되겠다.

그렇다면, 닷넷으로 작성한 서비스를 설치 시에 Interactive 서비스로 만드는 것이 불가능한 걸까? 불가능이 어디 있겠는가? 걍 하면 되지...

Approach

닷넷에서 설치를 위한 클래스로 제공된는 System.Configuration.Install.Installer 클래스는 대단히 유연한 구조를 갖고 있어서 이것을 약간 수정하면, 설치된 후에 추가적인 액션(action)을 수행할 수 있다. 필자의 접근 방법은, 닷넷 프레임워크가 우리의 서비스를 설치한 후에 이미 설치된 서비스의 속성을 변경하여 서비스를 Interactive 로 만드는 것이다.

서비스가 설치된 후의 시점에 작업이 수행되어야 하므로, 서비스가 설치된 후에 발생하는 AfterInstall 이벤트를 사용하거나 Install 메쏘드를 오버라이드 하여 설치 작업이 끝난 이후에 Interactive로 설정하는 작업을 수행하면 될 것이다.

public class ProjectInstaller : System.Configuration.Install.Installer
{
    
public ProjectInstaller()
    {
        
// 여기서 InitailizeComponent가 호출되어 
        // ServiceProcessInstaller, ServiceInstaller 컴포넌트가 생성되고 초기화 될 것이다.
        ............ 생 략 ............
    
}

    
// Install 메쏘드를 오버라이드 한다.
    
public override void Install(System.Collections.IDictionary stateSaver)
    {
        
// 베이스 클래스의 Install 메쏘드를 호출함으로써 서비스가 설치되도록 한다.
        
base.Install(stateServer);

        
// 이제 서비스가 설치되었으므로 서비스 속성을 변경하여 'Interactive'로 만들면 된다.
        ............ 생 략 .............
    
}
}

위 코드는 프로젝트 인스톨러 클래스를 개략적으로 보여주고 있다. 살펴볼 부분은 Install 메쏘드의 오버라이드가 추가되었다는 것이다. 이 오버라이드 내에서 base.Install()을 호출하여 서비스가 설치되도록 한다. 일단 base.Install() 호출이 성공적으로 완료되면(리턴 되면), 서비스가 설치된 것이다. 이제 설치된 서비스의 속성을 변경하여 Interactive 서비스로 만들기만 하면 되는 것이다.

Registry Setting : Not Successful

쬐금이나마 쉽게 해보려는 필자의 마음에, 서비스와 관계된 레지스트리를 뒤져 보니 서비스의 Type을 지정하는 레지스트리 항목이 있었다. 이 항목의 값은 서비스가 Driver 인지, 단일 서비스를 갖는 프로세스(OwnProcess) 인지, 여러 서비스가 수행되는 공유 프로세스 인지를 보여준다. 그리고 이 Type의 값에 Interactive 서비스 설정 값(0x100)을 주면 서비스 관리자의 MMC 화면에 화면 1과 같이 마치 서비스가 Interactive로 설정된 것 처럼 나타난다.

테스트 결과, 레지스트리 값만을 변경하는 것은 서비스가 Interactive로 설정되는 것과 무관했다. 레지스트리의 값을 바꾸면 서비스 관리자 MMC에서는 화면 1과 같이 서비스가 Interactive 로 설정된 것 처럼 보이지만 실제로 서비스는 UI를 표시하지 못했다. -_-;; 결국 이 방법은 아니라는 결론이 쏟아지는 것이다. 뷁 !!!

WIN32 ChangeServiceConfig Function

Win32 API 중 ChangeServiceConfig 란 함수가 있다. 이 함수가 설치된 서비스의 설정을 바꾸는 API 함수이다. API가 있다면 닷넷 P/Invoke 및 Interop을 사용해서 호출하면 된다. 본인이 한 C/C++ 코딩을 하면서, Win32 API에도 일가견이 있고 또한 닷넷 역시 잘 한다면 요 함수를 호출해서 서비스를 바꾸면 되겠다... 아무리 생각해도 좀 무리다. 이놈을 호출하기 위해서는 SCM 핸들도 필요하고(OpenSCManager 함수를 호출해야 한다) 추가 작업이 많을 듯 싶다. 귀차니즘이 발동하여 필자는 다른 방법을 찾아 보기로 했다.

Using WMI

WMI를 사용하면 서비스의 정보를 얻을 수 있을 뿐더러, 서비스를 시작하거나 종료할 수 있으며, 서비스의 속성을 변경할 수도 있다. 그렇다. WMI를 쓰는 것이 ChangeServiceConfig 를 호출하는 것보다 쉬울 것 같았다. WMI 클래스 중에서 Windows 서비스를 대표하는 클래스는 Win32_Service 클래스이다(WMI 클래스에 익숙하지 않다면 WMI에 관련된 필자의 글을 먼저 읽어 보기 바란다). Win32_Service WMI 클래스는 Change 란 메쏘드를 제공하며, 이 메쏘드는 정확히 ChangeServiceConfig API 함수가 하는 일과 동일한 작업을 수행해 준다!!!

서비스가 이미 설치되어 있으므로 WMI를 통해 방금 설치한 서비스의 정보를 읽어오고 이 정보와 WMI 객체를 이용하여 Change 메쏘드를 호출하면 우리가 원하는 Interactive 서비스 설정을 수행할 수 있는 것이다.

Implementation

접근 방법이 나왔으니 구현은 그다지 어렵지 않다고 말하고 싶었지만... 약간 빡셌다. 이유는 Change 메쏘드에 대한 MSDN의 문서가 잘 못되어 있더라는 것이다. MSDN 문서에 의하면 Change 메쏘드의 매개변수 중 마지막 2개가 string 타입이라고 되어 있었지만 CIM Studio로 까본 결과 이들의 타입은 array of string 이였다. 이것 때문에 상당한 시간을 삽질해 댔고 그 결과 다음과 같은 코드를 작성할 수 있었다.

public override void Install(System.Collections.IDictionary stateSaver)
{
    
// base.Install을 호출하여 먼저 서비스를 설치한다.
    
base.Install(stateSaver);

    
// 서비스 설치 후, WMI를 통해 서비스를 변경하여 서비스를 Interactive Service로
    // 만든다.
    
this.Context.LogMessage("서비스를 Interactive 로 만듭니다.");

    
ManagementClass wmiClass = null;
    
ManagementObjectCollection wmiServices = null;
    try 
{
        
// WMI를 통해 서비스 목록을 읽는다.
        
wmiClass = new ManagementClass("Win32_Service");
        
wmiServices wmiClass.GetInstances();
        
// 서비스 목록에서 방금 설치한 서비스를 찾아 Interactive로 설정한다.
        
foreach(ManagementObject wmiService in wmiServices) {
            
string curName (string)wmiService.Properties["Name"].Value;
            if 
(curName == InteractiveService.ServiceNameConstant) {
                
string displayName (string)wmiService.Properties["DisplayName"].Value;
                string 
pathName (string)wmiService.Properties["PathName"].Value;
                string 
startMode (string)wmiService.Properties["StartMode"].Value;

                
// 주) MSDN에서 WMI의 Win32_Serice 클래스의 Change 메쏘드에 대한
                //    매개변수 타입 설명이 잘못되어 있다.
                //     Change 메쏘드의 마지막 2개의 매개변수는 MSDN의 설명처럼 string 이 아닌
                //     문자열의 배열이다. (null은 허용된다)
                
object[] args = new object[] {
                        displayName,    
// 디스플레이 이름
                        
pathName,        // 프로세스 exe 이미지 경로
                        
0x10,            // NOTE !! :프로세스에 2개 이상의 서비스가 있다면 0x20을 사용
                        
0x1,            // 오류 처리 (CreateService API 도움말 참조; 디폴트)
                        
startMode,        // 시작 모드
                        
true,            // Interactive Service 설정 !
                        
"LocalSystem",    // Local System 사용(Interactive Services 필수 조건)
                        
"",                // 암호
                        
"",                // LoadOrderGroup (사용하지 않음; 디폴트)
                        
null,            // LoadOrderGroupDependencies (없음; 디폴트)
                        
null,            // ServiceDependencies (없음; 디폴트)
                
};
                
wmiService.InvokeMethod("Change", args);
            
}
        }
    }
    
catch (Exception ex) {
        
this.Context.LogMessage("서비스를 Interactive 로 만들 수 없습니다.");
        this
.Context.LogMessage("예외 발생 : " + ex.ToString());
        throw;
    
}
    
finally {
        
if (wmiServices != null)
            wmiServices.Dispose()
;
        if 
(wmiClass != null)
            wmiClass.Dispose()
;
    
}
}

복잡해 보이지만 그다지 복잡하지 않다. 먼저 WMI를 통해 설치된 서비스 목록을 가져온다. 서비스 목록에서 방금 설치한 서비스를 찾아서 Change 메쏘드를 호출하는 것이다. Change 메쏘드를 호출할 때 하드 코드된 값을 사용하지 않고 WMI로 부터 정보를 읽어 사용하는 것이 더 좋기 때문에 관련 코드를 일부 추가했다(뭐 그런게 귀찮으면 하드 코딩을 하던가... 그건 니 맘대로 하세요...). 가장 핵심 적인 부분은 밑줄 좍 그어놓은 부분이다. Interactive Service 설정을 위해 Change 메쏘드의 DesktopInteract 매개변수를 true로 설정한 부분으로서 이 값에 의해 우리의 서비스가 Interactive Service로 변신하게 되는 것이다.

위 코드를 이용하여 서비스를 설치하면 Interactive Service로 서비스는 매우 잘 작동 했다. 코드에 오류가 보이면 곧바로 피드백 바라는 바이다.

Interactive Service Consideration

뭐 잘 작동하면 끝이다라고 생각할 수 있지만, UI를 갖는 서비스는 항상 주의에 또 주의를 기해야 한다. 첫째로, 로컬 서비스 계정이 사용되어야 하고 이 계정은 특정한 사용자 프로파일을 갖지 않기 때문에 프로파일을 액세스하는 코드의 수행은 절대로 금물이다. 예를 들어, HKEY_CURRENT_USER 레지스트리에 접근하면 데스크탑에 로그온한 사용자의 레지스트리가 아닌 로컬 서비스 계정의 레지스트리가 액세스되어 버릴 것이다.

두 번째로 주의할 것은, Windows 서비스는 여러 쓰레드에 의해 호출되지만 UI 요소들은 특정 쓰레드에 의존도가 높다. 예를 들어 화면의 윈도우는 그 윈도우를 생성한 쓰레드에게 윈도우 메시지(WM_TIMER, WM_PAINT 등등)를 전송해 버린다. 따라서 쓰레드 문제를 발생할 가능성이 농후하다는 점이다. 다중 쓰레드를 사용하는 UI 프로그램에서 뻔질나게 Control.Invoke 를 호출해야 한다는 점을 기억하자.

보다 구체적인 예로, Service 코드의 OnStart 메쏘드에서 폼을 생성해서는 결코 안된다. 그 이유는 OnStart 메쏘드를 호출하는 쓰레드는 SCM(Service Control Manager)가 생성한 쓰레드로서 사용자 쓰레드가 아니다. 또한 이 쓰레드는 메시지 펌프(Application.Run 호출을 생각하면 되겠다)를 갖지 않으므로 UI는 제대로 작동하지 않을 것이다. 따라서 UI를 전담하는 별도의 쓰레드를 OnStart 메쏘드내에서 만들고 이 쓰레드에서 Application.Run 을 수행해야만 한다. 다음 코드는 필자가 예제로 만든 Interactive 서비스에서 사용한 코드의 일부이다.

// 서비스 시작 핸들러
protected override void OnStart(string[] args)
{
    
// 주의!) UI를 사용할 수 없을 수도 있으므로 UI가 사용가능한가 확인
    // 해야 한다.
    
if (System.Windows.Forms.SystemInformation.UserInteractive) {
        
// UI 쓰레드를 만든다.
        
_UIEnabled = true;
        
_UIThread = new Thread(new ThreadStart(UIMain));
        
_UIThread.Start();
    
}
    
else {
        
this.EventLog.WriteEntry("현재 세션이 UserInteractive를 지원하지 않습니다." 
                    
" UI는 Disable 됩니다.");
    
}
}
// 서비스 중단 핸들러
protected override void OnStop()
{
    
if (_UIEnabled) {
        Application.Exit()
;
        
_UIThread.Join();
    
}
}
// UI 쓰레드 메인
// 모든 윈도우 및 기타 UI 관련 객체는 이 쓰레드에 의해 생성되어야만
// 제대로된 메시지 펌프에 의해 UI가 수행된다.
private void UIMain()
{
    Application.Run(
new UIForm());
    
// UI 화면은 윈도우 스테이션이 종료되거나(로그 오프, 시스템 셧다운 등)
    // UI 폼 자체가 닫히는 경우 종료된다.
    // 즉, Run 메쏘드에서 빠져나오게 된다.
    
this.EventLog.WriteEntry("UI 화면이 종료되었습니다.");
}

세 번째로 주의할 점은, UI 가 표시될 윈도우 스테이션이다. 윈도우 스테이션은 사용자가 콘솔(데스크톱)에 로그온 하거나 터미널 서비스를 통해 로그온 할 때 생성되는 화면 세션을 말한다. 대개의 경우, UI 윈도우는 윈도우 스테이션이 종료될 때 같이 닫히곤 한다. 즉, 사용자가 로그 오프를 해버리면 윈도우 스테이션이 종료되어 버린다. 하지만 서비스는 아직 종료된 것이 아닐 수 있기 때문에 모호성이 발생할 수도 있다. 또한 서비스가 서버에 설치될 때는 더욱더 그러하다 서버의 경우, 터미널 서비스 혹은 원격 데스크톱이 사용되는 경우가 잦기 때문에 서비스가 사용하는 윈도우 스테이션이 닫히게 될 가능성은 더더욱 높다.

네 번째로는 Windows 서비스란 녀석이 서버 타입 COM+와 더불어 디버깅하기가 영 까칠하다는 것이다. 뭐, 아쉬운대로 Attach Process 한 다음에 특정 이벤트(마우스 클릭, 버튼 클릭 등) 발생을 디버깅하는 것은 귀차니즘을 감수할 수 있지만, 초기 스타트업 코드를 디버깅하기는 영 구린지라...

이러 저러한 고려 사항을 생각해 보면, 서두에서 필자가 왜 Interactive 서비스를 사용해야 하는 상황을 반가워하지 않았는지 이해가 가리라고 믿는다. 아님 말고... -_-;;

Alternative

필자가 UI를 표시해야 하는 서비스를 만들어야 한다면, 다른 여러 패키지 들에서 사용하는 기법(?)을 사용하겠다(아직 그런 상황이 없었으므로 미래형이다). 개략적인 아이디어는 다음과 같다.


그림 1. 백 엔드와 프론트 엔드를 구분하여 작성

일단 프로그램을 크게 두 부분으로 짜갠다. 백 엔드(back-end)는 서비스 프로세스가 수행하며 말 그대로 서비스(데몬)으로서 수행해야 하는 일만을 집어 넣는다. 프론트 엔드(front-end)는 UI를 전담하는 프로세스로서 백 엔드 서비스 프로세스와 IPC, 닷넷 리모팅, 소켓 등의 방법으로 통신하여 필요한 UI를 표시한다. UI를 변화 시켜야 하는 경우 백 엔드 서비스는 다양한 방법을 통해 프론트 엔드 프로세스에 통지(notification)을 전달할 수 있다. 사용자가 콘솔이나 터미널 서비스를 통해 로그온 하면, "시작 프로그램" 그룹이나 레지스트리(Run 키)를 통해 프론트 엔드 프로세스가 자동으로 시작되도록 함으로써 항상 모든 사용자는 어떤 윈도우 스테이션을 사용하건 백 엔드 서비스에 관련된 UI 정보를 알아낼 수 있게 된다.

이러한 접근 방법은 앞서 언급한 다양한 문제들을 해결할 수 있다. UI 관련 코드가 로컬 시스템 계정 하에서 작동하지 않기 때문에 윈도우 스테이션에 관여된 사용자 계정(콘솔이나 터미널로 로그온한 사용자)을 사용할 수 있으며, 서비스가 아니므로 프론트 엔드 프로세스가 다중 스레드로 인한 복잡도를 최대한 낮출 수 있을 뿐 더러, 사용자가 로그 오프하여 윈도우 스테이션이 종료될지라도 다시 로그온 하면 UI 화면이 표시될 것이므로 문제가 없다. 다만... 단점은 좀 더 많은 코딩이 필요하며 백 엔드와 프론트 엔드 프로세스들이 통신을 해야 한다는 점이 있지만 닷넷 리모팅 같은 기법을 사용하면 크게 어려울 것도 없다.

고려해야 할 사항도 많으며 오류 가능성을 잠재하고 있는 Interactive 서비스를 사용하느니, 백 엔드와 프론트 엔드를 구분하는 기법을 사용하는 것이 정신건강에 이로울 뿐 더러 철야작업을 줄여줄 것 같다는 생각이 필자의 귀언저리 살, 후두부, 되퇴부를 팍 걷어 찬다.

우씨... Interactive 서비스가 별로 좋지 않다면 뭣하러 용쓰면서 Interactive 서비스를 만드는 방법을 침튀기며 설명했나? 걍... 잼 있으니까... 잼있지 않나요? 아니면 말고... 췟....


p.s. 혹시나 예제 코드가 필요하신 분은 연락 주세요. 물론, Interactive 서비스에 대한 예제 입니다.



Comments (read-only)
#re: Interactive Service 만들기 / sidabari2 / 2005-10-19 오후 5:30:00
친절한 답변 너무 감사합니다.. 많은 도움이 되었습니다.. 모 개발자 커뮤니티에서~
예제코드 좀 부탁드립니다. jeongsj77@naver.com
#re: Interactive Service 만들기 / glitter1 / 2006-01-05 오전 10:43:00
감사합니다...
예제 코드 부탁드립니다...
hskim@dsic.co.kr
#re: Interactive Service 만들기 / ttoss21 / 2006-03-21 오후 3:13:00
오하시스를 만났군요..^^
예제코드좀 부탁드립니다....
ttoss21@nate.com
#re: Interactive Service 만들기 / 예제 부탁... / 2006-03-21 오후 3:44:00
Interactive 서비스에 대한 예제 좀 부탁드립니다.
위와같이 했는데 서비스와 데스크탑상호작용이 체크가 안되네요.
감사합니다.
jhkwack@irissolution.com
#re: Interactive Service 만들기 / 원인이 있었네요. / 2006-03-22 오전 9:42:00
우선 감사합니다.
유경상님이 주신 예제코드는 서비스와 데스크탑상호작용이 체크가 되네요.
원인을 찾아보니, serviceInstaller.StartType = ServiceStartMode.Manual; 로 시작 타입을 수동으로 하면 체크가 되구요.
serviceInstaller.StartType = ServiceStartMode.Automatic; 같이 시작 타입을 자동으로 하면 체크가 안됩니다.(본인은 자동으로 사용했음)
시작타입도 자동으로 하고, 서비스와 데스크탑상호작용 체크도 하려면 한가지는 포기를 해야 하는건지 좀 궁금합니다.
좋은 하루 보내세요.

#re: Interactive Service 만들기 / 블로그쥔장 / 2006-03-22 오전 10:24:00
좋은 지적해 주셨습니다. 말씀하신대로 안 될 겁니다.
처음 저도 코딩할 때 알고 있었는데 귀차니즘으로 넘어가 버렸고...
지금은 까먹었다는... 그래서 다시 살펴봤죠. 덕분에 기억이 살아 났다는...

원인은 서비스가 자동 시작이면 Win32_Service 클래스의 StartMode 속성이 반환하는 값은 "Auto" 입니다.
하지만 Change 메쏘드가 요구하는 값은 "Auto"가 아닌 "Automatic" 이죠.
이 때문에 Change 호출을 수행하면 오류 코드 21(Invalid argument)을 반환합니다.
왜 이따구로 StartMode 속성이 구현되었는지 이해하기 힘듭니다만...

문제해결을 위해서는 관련 코드에서 startMode 변수가 "Auto" 이면 "Automatic"으로 바꾸어주는 코드를
집어 넣어 주면 됩니다.

string startMode = (string)wmiService.Properties["StartMode"].Value;
if (String.Compare(startMode, "Auto", true) == 0) {
startMode = "Automatic";
}
#re: Interactive Service 만들기 / 감사합니다...^^ / 2006-03-22 오후 2:54:00
덕분에 어려운 문제가 해결이 되었습니다.
많은 도움 감사드립니다.
좋은 하루 보내세요.
#re: Interactive Service 만들기 / 짱이 / 2006-11-01 오후 9:00:00
좋은 정보 감사드립니다.

제가 Windows Server 2003에 Interactive Service 설치하고 동작을 하려고 하니 프로세스는 실행이 되는데 폼이 뜨질 않네요..
XP에서는 잘 동작합니다..
혹시 security 설정 사항이 있는지요...
#re: Interactive Service 만들기 / 블로그쥔장 / 2006-11-02 오전 10:51:00
글쎄요... 저는 항상 개발환경이 Windows 2003 이기 때문에 테스트 역시 Windows 2003 이였으며
매우 잘 작동했었습니다만...
터미널을 사용한다면 이야기가 조금 달라지긴 하지만,
Windows 2003과 Windows XP에 따라 설정이 달라지는 것까지는 저도 아직 아는 바가 없습니다.
#re: Interactive Service 만들기 / under76 / 2007-04-18 오후 6:42:00
좋은 정보 감사드립니다.
예제코드 부탁드립니다.
under76@hanmail.net
그럼 부탁드리겠습니다.
#Interactive Service 만들기 / js4eh / 2007-07-30 오후 5:50:00
잘 읽었습니다..
정말 좋은 정보네요..
저도 예제코드 부탁드립니다.
js8318eh@gmail.com
부탁드립니다.
#re: Interactive Service 만들기 / jororo / 2008-01-05 오전 11:51:00
잘 읽어 보고 갑니다.
정말 도움되는 정보였습니다.
저도 예제 코드 부탁드리겠습니다.
jms9903@naver.com
부탁 드리겠습니다.
#re: Interactive Service 만들기 / sun07 / 2008-07-29 오후 5:57:00
자세하게 댓글도 응답해주시고. 감사합니다. 예제코드 필요없이 본문과 댓글만 봐도 되겠군요..
감사합니다.
앞으로도 종종찾아봐야 겠습니다. 수고하십시오.
#re: Interactive Service 만들기 / 아직적자인생 / 2008-10-07 오전 9:48:00
와우~ 감사합니다. 이것때문에 무지 고민했었는데.
친절한 설명 잘봤습니다. 이해가 팍팍되네요~ ^^
#re: Interactive Service 만들기 / i2uk4 / 2009-01-07 오후 2:20:00
문의 드려도??
Service 가 일반 프로세스를 띄우고 감시하는 프로그램을 만드려고하는데요..
동일 프로세스를 CreateProcess 했을경우 22개( XP ) 이후로는 생성을 못하더라구요.. 한 100개쯤 띄우고 싶거든요...
그런데 Interactive Service 로 실행을 할 경우 100까지도 CreateProcess 할 수 있더라구요..
그 이유를 찾고 있는데요... UI 없는 Service 로 실행하는 것이 최종목표입니다...
두서 없이 작성하여 전달력이 떨어지는데요... 답변을 기다려봅니다...
#re: Interactive Service 만들기 / 헬프미 / 2009-07-17 오전 1:27:00
혹시 너무 예제가 급한데 좀 받을수 있을까요?
부탁드립니다.
three11@naver.com
#re: Interactive Service 만들기 / 나이스 / 2010-03-16 오후 9:18:00
음..저도 xp에서는 되는데 windows 2003에서는 안되네요..
소스좀 부탑드립니다..
niceyss@naver.com