'프로그래밍'에 해당되는 글 1건

  1. 2014.10.22 서비스프로그램의 통신방법


서비스프로그램은 프로그램의 특성상 많은 수의 서비스프로그램들이 Local Admin 권한을 가지고 실행된다.

이러한 서비스의 특성상 다른 프로그램과의 통신은 제약을 가질 수 밖에 없다.

예를들면 윈도우 메시지는 서비스와 다른 응용프로그램사이에 전달이 안된다. 

따라서 서비스 프로그램을 처음 개발하는 개발자들은 다른 응용프로그램과의 통신을 위해 고민하는 경우가 생기는데, 막상 가장 유용한 방법은 아마도 네임드 파이프(Named Pipe)를 사용하는 방법일 것이다.

윈도우즈 프로그래머라면 네임드 파이프에 대해 잘 알테니 그 부분은 생략하기로 하고.

이 문서에서는 서비스가 통신할 때 발생할 수 있는 간단한 문제와 그 해결방법을 보여주고자 한다.


막상 서비스프로그램을 작성하고 간단한 테스트프로그램을 작성하여 통신을 하면 잘 동작하는 듯이 보인다. 만약 서비스프로그램이 동일한 컴퓨터안의 프로그램과 통신을 하는 것이 아닌, 다른 컴퓨터와도 원격파이프를 사용하여 통신을 해야한다면 다른 컴퓨터로부터의 파이프 입력이 안된다거나, 또는  일반유저프로파일 상의 프로그램과 통신을 해야 한다면 서비스의 파이프에 적속할 수 없다는 것을 알게 될 것이다.

이유는 간단하다. 서비스는 시스템 어카운트로 실행중이기 때문에 시스템 어카운트가 생성한 네임드 파이프에 다른 유저권한의 응용 프로그램이 접속할 수 없기 때문이다.

이런 경우 해결방법은 파이프를 생성할 때 시큐리티 어트리뷰트에 Everyone의 억세스 권한을 가진 시큐리티 디스트립터를 생성해서 적용해 주면 된다.

해결방법은 아래와 같다.


  DWORD dwPipeOpenMode = PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED|PIPE_ACCESS_DUPLEX;


  SECURITY_ATTRIBUTES sa;

  SECURITY_DESCRIPTOR sd;

  if (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {

    if(!SetSecurityDescriptorDacl(&sd, TRUE, (PACL)NULL, FALSE)) {

      DbgOutW(L"SetSecurityDescriptorDacl failed %d\n\n", GetLastError());

    }

  }

  sa.nLength = (DWORD) sizeof(SECURITY_ATTRIBUTES);

  sa.lpSecurityDescriptor = (LPVOID)&sd;

  sa.bInheritHandle = TRUE;


  while(m_bServerThread) {

    m_hCurrentPipe = CreateNamedPipe(m_wszPipeName,       // pipe name 

                            dwPipeOpenMode,

                            PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT,

                            PIPE_UNLIMITED_INSTANCES, // max. instances  

                            BUFSIZE,                  // output buffer size 

                            BUFSIZE,                  // input buffer size 

                            1000,                     // client time-out 

                            &sa);                    // default security attribute 




Posted by 도움돌 :