Windows 서비스 작성(Windows Service,system 권한)프로그램 디 스 플레이 인터페이스 와 사용자 상호작용(xp,win 7 통용)
12039 단어 Windows 서비스
원본 자원 다운로드:/201604/yuanma/TestService_jb51.rar
vc 2008 다음 에 새로 만 든 ATL 프로젝트-"서비스"형식의 ATL 프로젝트 TestService 를 선택 하면 다음 과 같은 코드 를 생 성 합 니 다.
class CTestServiceModule : public CAtlServiceModuleT< CTestServiceModule, IDS_SERVICENAME >
{
public :
DECLARE_LIBID(LIBID_TestServiceLib )
DECLARE_REGISTRY_APPID_RESOURCEID (IDR_TESTSERVICE, "{1FF78006-B225-4CC0-A7DE-E0C9D31C9937}" )
HRESULT InitializeSecurity () throw()
{
// TODO : CoInitializeSecurity
//
// - PKT 、
// RPC_C_IMP_LEVEL_IDENTIFY
// NULL 。
return S_OK ;
}
//
HRESULT Run (int nShowCmd = SW_HIDE ) throw()
{
HRESULT hr = S_OK;
hr = __super ::PreMessageLoop( nShowCmd);
if (hr == S_OK)
{
if (m_bService )
{
// #define _ATL_NO_COM_SUPPORT
// ,
// ,
LogEvent(_T ("widebright , "));
SetServiceStatus(SERVICE_RUNNING );
}
// , , Handler , OnShutdown 。
__super::RunMessageLoop ();
}
if (SUCCEEDED (hr))
{
hr = __super ::PostMessageLoop();
}
// Uninstall
//__super::Uninstall();
return hr ;
}
// ,
void OnShutdown () throw()
{
LogEvent(_T ("TestService , "));
}
};
CTestServiceModule _AtlModule;
//
extern "C" int WINAPI _tWinMain (HINSTANCE , HINSTANCE ,
LPTSTR , int nShowCmd)
{
return _AtlModule .WinMain( nShowCmd);
}
2.저 는 필요 에 따라 해당 하 는 함 수 를 다시 써 서 원 하 는 기능 을 실현 하면 됩 니 다.예 를 들 어 당신 이 만 들 고 싶 은'서비스'는 시스템 에 따라 시 작 됩 니 다.CAtlServiceModuleT 의 Install 함 수 를 다시 쓸 수 있 습 니 다.그 안에 있 는 CreateService 함수 의 인 자 를 수정 할 수 있 습 니 다.예 를 들 어 사용자 와 의 상호작용 을 추가 하면 SERVICE 를 사용 할 수 있 습 니 다.INTERACTIVE_PROCESS,구체 적 으로 MSDN 에서 Create Service 라 는 API 에 대한 설명 을 찾 을 수 있 습 니 다.
서비스 정지 와 시작 동작 을 처리 하려 면 CAtlServiceModuleT 의 소스 코드 재 작성 OnStop()등 함 수 를 참고 하 세 요.제 위 에 Run 함 수 를 다시 쓸 정도 로 간단 합 니 다.'이벤트'를 출력 하 는 것 은 사실 구체 적 인 작업 은 여기에 놓 고 완성 할 수 있 습 니 다.
컴 파일,프로그램 생 성 후 테스트 할 수 있 습 니 다.
"TestService-/Service"를 실행 하면 서 비 스 를 시스템 에 등록 할 수 있 습 니 다.명령 행 인 자 는 사실 CAtlServiceModuleT:ParseCommandLine 이라는 함수 에서 처리 되 었 습 니 다.가서 보 셔 도 됩 니 다.필요 하 다 면 다시 쓰 셔 도 됩 니 다.게다가 UnInstall 을 호출 하여 서비스 코드 를 삭제 하 는 것 도 좋 을 것 같 습 니 다.
등록 후'sc start'나'net start'등의 명령 으로 서 비 스 를 조작 하 는 것 을 볼 수 있 습 니 다."서비스"컨트롤 러 에서 제어 할 수 있 습 니 다.그림 참조
3.이때 Run 함수 에서 Notepad.exe 를 시작 합 니 다.이 때 인터페이스 가 표시 되 지 않 고 xp 에서 다음 방법 으로 notepad 와 사용자 의 상호작용 을 실현 할 수 있 습 니 다.
//for xp system
DWORD _stdcall LaunchAppIntoSession0( LPTSTR lpCommand )
{
////////////////////////////////////////////system show dlg////////////////////
HDESK hdeskCurrent ;
HDESK hdesk ;
HWINSTA hwinstaCurrent ;
HWINSTA hwinsta ;
hwinstaCurrent = GetProcessWindowStation ();
if (hwinstaCurrent == NULL)
{
return FALSE ;
}
hdeskCurrent = GetThreadDesktop (GetCurrentThreadId());
if (hdeskCurrent == NULL){
return FALSE ;
}
// winsta0
// winsta0
hwinsta = OpenWindowStation (L"Winsta0" , FALSE, WINSTA_ALL_ACCESS);
// WINSTA_ACCESSCLIPBOARD|
// WINSTA_ACCESSGLOBALATOMS |
// WINSTA_ENUMDESKTOPS |
// WINSTA_CREATEDESKTOP |
// WINSTA_CREATEDESKTOP |
// WINSTA_ENUMERATE |
// WINSTA_EXITWINDOWS |
// WINSTA_READATTRIBUTES |
// WINSTA_READSCREEN |
// WINSTA_WRITEATTRIBUTES);
if (hwinsta == NULL){
return FALSE ;
}
if (!SetProcessWindowStation (hwinsta))
{
return FALSE ;
}
// desktop
hdesk = OpenDesktop (L"default" , 0, FALSE,
DESKTOP_CREATEMENU |
DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE|
DESKTOP_HOOKCONTROL|
DESKTOP_JOURNALPLAYBACK |
DESKTOP_JOURNALRECORD |
DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP |
DESKTOP_WRITEOBJECTS);
if (hdesk == NULL){
return FALSE ;
}
SetThreadDesktop(hdesk );
////////////////////////////////////////////end of system show dlg////////////////////
STARTUPINFO si = { sizeof( si) };
SECURITY_ATTRIBUTES saProcess , saThread;
PROCESS_INFORMATION piProcessB , piProcessC;
// Prepare to spawn Process B from Process A.
// The handle identifying the new process
// object should be inheritable.
saProcess.nLength = sizeof( saProcess);
saProcess.lpSecurityDescriptor = NULL;
saProcess.bInheritHandle = TRUE;
// The handle identifying the new thread
// object should NOT be inheritable.
saThread.nLength = sizeof( saThread);
saThread.lpSecurityDescriptor = NULL;
saThread.bInheritHandle = FALSE;
CreateProcess(NULL , lpCommand, & saProcess, &saThread ,
FALSE, 0, NULL , NULL, & si, &piProcessB );
if (!SetProcessWindowStation (hwinstaCurrent))
return FALSE ;
if (!SetThreadDesktop (hdeskCurrent))
return FALSE ;
if (!CloseWindowStation (hwinsta))
return FALSE ;
if (!CloseDesktop (hdesk))
return FALSE ;
return TRUE ;
}
이런 방법의 관건 은 OpenWindowStation,SetProcess WindowStation,OpenDesktop 과 SetThreadDesktop 이라는 네 가지 함수 다.이러한 방법의 사고방식 은 현재 프로 세 스 가 처 한 Session 은 인터페이스 상호작용 능력 이 있어 야 대화 상 자 를 표시 할 수 있다 는 것 이다.첫 번 째 대화 식 사용 자 는 WinSta 0 이 있 는 Session 0 에 로그 인 하기 때문에 서비스 가 있 는 프로 세 스 를 WinSta 0 과 강제 적 으로 연결 하고 현재 데스크 톱 을 열 어 이 데스크 톱 에 작업 스 레 드 를 걸 면 대화 상 자 를 표시 할 수 있 습 니 다.4.이런 방법 은 WinXP 와 Windows 2003 에서 잘 작 동 합 니 다.안 타 깝 게 도 Vista 와 Windows 2008 에서 OpenWindow Station 을 실행 하면 WinSta 0 워크스테이션 을 대신 열 려 고 할 때 프로그램 에 이상 이 생 깁 니 다.
우선 프로그램 이 어떤 조건 을 갖 추어 야 인터페이스 와 상호작용 을 할 수 있 는 지 알 아 보 자.윈도 는 세 가지 대상 을 제공 했다.사용자 인터페이스 대상(User Interface),GDI 대상 과 커 널 대상 이다.커 널 대상 은 안전성 이 있 지만 앞 에는 없다.앞의 두 가지 안전성 을 제공 하기 위해 워크스테이션 대상(Window station)과 데스크 톱 대상(Desktop)을 통 해 사용자 인터페이스 대상 을 관리 합 니 다.워크스테이션 대상 과 데스크 톱 대상 이 안전 하기 때 문 입 니 다.쉽게 말 하면 워크스테이션 은 프로 세 스 와 연 결 된 보안 기능 을 가 진 대상 으로 하나 이상 의 데스크 톱 대상 을 포함 합 니 다.워크스테이션 대상 이 생 성 되 었 을 때 호출 프로 세 스에 연결 되 어 현재 세 션 에 부 여 됩 니 다.대화 형 워크스테이션 WinSta 0 은 사용자 인터페이스 를 표시 하고 사용자 의 입력 을 받 아들 일 수 있 는 유일한 워크스테이션 입 니 다.키보드,마우스,디 스 플레이 장 치 를 포함 한 대화 형 사용자 에 게 부 여 된 로그 인 세 션 입 니 다.모든 다른 워크스테이션 은 비 상호작용 적 이다.이것 은 사용자 인 터 페 이 스 를 표시 할 수 없고 사용자 의 입력 을 받 아들 일 수 없다 는 것 을 의미한다.사용자 가 터미널 서 비 스 를 사용 하 는 컴퓨터 에 로그 인하 면 모든 사용자 가 세 션 을 시작 합 니 다.모든 Session 은 자신의 대화 형 워크스테이션 과 연결된다.데스크 톱 은 창 워크스테이션 대상 에 보안 기능 을 가 진 대상 입 니 다.데스크 톱 대상 은 창,메뉴,갈고리 등 사용자 인터페이스 대상 을 포함 하 는 논리 적 인 디 스 플레이 영역 이 있 습 니 다.
Vista 에 앞서 Winsta 0 과 결 성 된 데스크 톱 디 스 플레이 대화 상 자 를 열 수 있 는 이 유 는 서비스 든 첫 번 째 로 로그 인 한 대화 형 사용자 든 모두 Session 0 에 로그 인 하기 때 문 입 니 다.따라서 서비스 프로그램 은 윈 스타 0 과 데스크 톱 을 강제로 열 어 상호작용 을 할 수 있다.
그러나 Vista 와 윈도 2008 에서 Session 0 은 서비스 와 사용자 와 상호작용 하지 않 는 다른 응용 프로그램 에 만 사용 된다.첫 번 째 로그 인 으로 대화 식 작업 을 할 수 있 는 사용자 가 세 션 1 에 연결 되 었 습 니 다.두 번 째 로그 인 을 진행 한 사용 자 는 세 션 2 에 배정 되 어 유추 된다.Session 0 은 사용자 와 대화 할 프로 세 스 를 전혀 지원 하지 않 습 니 다.서비스 프로 세 스에 서 하위 프로 세 스 를 시작 해서 대화 상 자 를 표시 하면 하위 대화 상 자 를 표시 할 수 없습니다.OpenWindowStation 시스템 API 로 WinSta 0 을 여 는 방법 을 사용 하면 함수 호출 이 실패 합 니 다.한 마디 로 비 스타 와 윈도 2008 은 세 션 0 에서 인터페이스 상호작용 을 하 는 길 을 막 았 다.그게 이유 야.
그렇다면 서비스 에서 대화 상 자 를 꺼 낼 수 없 는 것 일 까?서비스 프로 세 스 자체 에 있어 서 는 운영 체제 가 이 길 을 막 았 다.그러나 우리 가 원 하 는 것 은'서비스 프로 세 스에 서 팝 업 대화 상자'가 아 닙 니 다.우리 가 원 하 는 것 은'서비스 가 어떤 상황 이 발생 했 을 때 데스크 톱 에서 팝 업 대화 상자'에 불과 합 니 다.세 션 0 에서 대화 상 자 를 꺼 낼 수 없 으 며,우리 가 보 는 데스크 톱 은 세 션 X 입 니 다.세 션 0 이 아 닌 자 연 스 러 운 생각 은 세 션 0 이 다른 세 션 에 게 알려 주 고 현재 데스크 톱 에 표시 되 어 있 는 세 션 이 대화 상 자 를 꺼 낼 수 있 습 니까?
다행히 이렇게 할 수 있 었 다.
//for win7
DWORD _stdcall LaunchAppIntoDifferentSession( LPTSTR lpCommand )
{
DWORD dwRet = 0;
PROCESS_INFORMATION pi ;
STARTUPINFO si ;
DWORD dwSessionId ;
HANDLE hUserToken = NULL;
HANDLE hUserTokenDup = NULL;
HANDLE hPToken = NULL;
HANDLE hProcess = NULL;
DWORD dwCreationFlags ;
HMODULE hInstKernel32 = NULL;
typedef DWORD (WINAPI * WTSGetActiveConsoleSessionIdPROC)();
WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;
hInstKernel32 = LoadLibrary (L"Kernel32.dll" );
if (!hInstKernel32 )
{
return FALSE ;
}
OutputDebugString(L "LaunchAppIntoDifferentSession 1
" );
WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC )GetProcAddress( hInstKernel32,"WTSGetActiveConsoleSessionId" );
// Log the client on to the local computer.
dwSessionId = WTSGetActiveConsoleSessionId ();
do
{
WTSQueryUserToken( dwSessionId ,&hUserToken );
dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
ZeroMemory( &si , sizeof( STARTUPINFO ) );
si.cb = sizeof( STARTUPINFO );
si.lpDesktop = L"winsta0\\default" ;
ZeroMemory( &pi , sizeof( pi) );
TOKEN_PRIVILEGES tp ;
LUID luid ;
if( !::OpenProcessToken ( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
| TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
| TOKEN_READ | TOKEN_WRITE , &hPToken ) )
{
dwRet = GetLastError ();
break;
}
else;
if ( !LookupPrivilegeValue ( NULL, SE_DEBUG_NAME, &luid ) )
{
dwRet = GetLastError ();
break;
}
else;
tp.PrivilegeCount =1;
tp.Privileges [0].Luid = luid;
tp.Privileges [0].Attributes = SE_PRIVILEGE_ENABLED;
if( !DuplicateTokenEx ( hPToken, MAXIMUM_ALLOWED, NULL , SecurityIdentification , TokenPrimary, & hUserTokenDup ) )
{
dwRet = GetLastError ();
break;
}
else;
//Adjust Token privilege
if( !SetTokenInformation ( hUserTokenDup,TokenSessionId ,(void*)& dwSessionId,sizeof (DWORD) ) )
{
dwRet = GetLastError ();
break;
}
else;
if( !AdjustTokenPrivileges ( hUserTokenDup, FALSE, &tp , sizeof(TOKEN_PRIVILEGES ), (PTOKEN_PRIVILEGES) NULL, NULL ) )
{
dwRet = GetLastError ();
break;
}
else;
LPVOID pEnv =NULL;
if( CreateEnvironmentBlock ( &pEnv, hUserTokenDup, TRUE ) )
{
dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT ;
}
else pEnv =NULL;
// Launch the process in the client's logon session.
if( CreateProcessAsUser ( hUserTokenDup, // client's access token
NULL, // file to execute
lpCommand, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
dwCreationFlags,// creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
& si, // pointer to STARTUPINFO structure
& pi // receives information about new process
) )
{
}
else
{
dwRet = GetLastError ();
break;
}
}
while( 0 );
//Perform All the Close Handles task
if( NULL != hUserToken )
{
CloseHandle( hUserToken );
}
else;
if( NULL != hUserTokenDup)
{
CloseHandle( hUserTokenDup );
}
else;
if( NULL != hPToken )
{
CloseHandle( hPToken );
}
else;
return dwRet ;
}
5.서 비 스 를 시작 한 후에 system 권한 의 Notepad.exe 를 표시 하고 사용자 와 상호작용 을 할 수 있 습 니 다.물론 이 예 에서 프로 세 스 를 시작 하 는 곳 에 대화 상 자 를 만 드 는 것 도 대화 상 자 를 표시 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Windows 서비스 작성(Windows Service,system 권한)프로그램 디 스 플레이 인터페이스 와 사용자 상호작용(xp,win 7 통용)그러나 Vista 와 윈도 2008 에서 Session 0 은 서비스 와 사용자 와 상호작용 하지 않 는 다른 응용 프로그램 에 만 사용 된다.첫 번 째 로그 인 으로 대화 식 작업 을 할 수 있 는 사용자 가 세 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.