Windows服务编写(Windows Service,system权限)程序显示界面与
1、VC2008中编写“Windows服务”(Windows Service)程序 源码资源下载:/201604/yuanma/TestService_jb51.rar vc2008下新建一个 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上查找CreateService这个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",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,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 ; }
4、这种方法在WinXP和Windows2003下工作得不错,很遗憾,在Vista和Windows2008下,一旦执行到OpenWindowStation,试图代开WinSta0工作站时,程序就会出异常。
在Vista之前,之所以可以通过打开Winsta0和缺省桌面显示对话框,是因为不管是服务还是第一个登录的交互式用户,都是登录到Session 0中。因此,服务程序可以通过强制打开WinSta0和桌面来获得交互能力。 然而,在Vista和Windows2008中,Session 0专用于服务和其他不与用户交互的应用程序。第一个登录进来,可以进行交互式操作的用户被连到Session 1上。第二个登录进行的用户被分配给Session 2,以此类推。Session 0完全不支持要与用户交互的进程。如果采取在服务进程中启动子进程来显示对话框,子对话框将无法显示;如果采取用OpenWindowStation系统API打开WinSta0的方法,函数调用会失败。总之,Vista和Windows2008已经堵上了在Session 0中产生界面交互的路。这就是原因所在。 那么,是否真的没法在服务中弹出对话框了呢?对于服务进程自身来说,确实如此,操作系统已经把这条路堵上了。但是,我们想要的并不是“在服务进程中弹出对话框”,我们想要的不过是“当服务出现某些状况的时候,在桌面上弹出对话框”。既然在Session 0中无法弹出对话框,而我们看到的桌面是Session X,并非Session 0,很自然的一个想法是:能不能让Session 0通知其他的Session,让当前桌面正显示着的Session弹一个对话框呢? 幸运的是,还真可以这样做。 //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 1n" ); 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"winsta0default" ; 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,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,&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,并且可以与用户进行交互
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c# – MVVM中的ContextMenu
- React-native bundle command generated old mai
- ruby-on-rails-3 – Rails 3.1 ActiveAdmin GEM
- 将shapefile(.shp)转换为xml/json
- Cocos2dx 禁止锁屏
- Objective-C = operator vs stringWithString /
- React Native 环境搭建for macOS
- swift – 你如何着色/定制UIImagePickerControll
- C#自定义的GridView操作类,简化GridView操作
- 如何打开扩展名为.DB 文件. 使用sqlite3 很方便