[置顶]

[置顶] Windows服务(Windows Service,system权限)程序显示界面与用户交互(xp,win7通用)

2012-08-20 15:04 673人阅读 评论(1) 收藏 举报

1、VC2008中编写“Windows服务”(Windows Service)程序

源码资源下载: http://download.csdn.net/detail/stony1980/4512984
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" , 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、SetProcessWindowStation、OpenDesktop和SetThreadDesktop这四个函数。这种方法的思路是:当前进程所处于的Session必须有界面交互能力,这样才能显示出对话框。由于第一个交互式用户会登录到拥有WinSta0的Session 0,所以,强制性地把服务所在的进程与WinSta0关联起来,并且打开当前的桌面,把工作线程挂到该桌面上,就可以显示出对话框。

4、这种方法在WinXP和Windows2003下工作得不错,很遗憾,在Vista和Windows2008下,一旦执行到OpenWindowStation,试图代开WinSta0工作站时,程序就会出异常。

首先了解一下程序要具备怎样的条件才能与界面交互。Windows提供了三类对象:用户界面对象(User Interface)、GDI对象和内核对象。内核对象有安全性,而前两者没有。为了对前两者提供安全性,通过工作站对象(Window station)和桌面对象(Desktop)来管理用户界面对象,因为工作站对象和桌面对象有安全特性。简单说来,工作站是一个带有安全特性的对象,它与进程相关联,包含了一个或多个桌面对象。当工作站对象被创建时,它被关联到调用进程上,并且被赋给当前Session。交互式工作站WinSta0,是唯一一个可以显示用户界面,接受用户输入的工作站。它被赋给交互式用户的登录Session,包含了键盘、鼠标和显示设备。所有其他工作站都是非交互式的,这就意味着它们不能显示用户界面,不能接受用户的输入。当用户登录到一台启用了终端服务的计算机上时,每个用户都会启动一个Session。每个Session都会与自己的交互式工作站相联系。桌面是一个带有安全特性的对象,被包含在一个窗口工作站对象中。一个桌面对象有一个逻辑的显示区域,包含了诸如窗口、菜单、钩子等等这样的用户界面对象。

在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 1\n" );
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,并且可以与用户进行交互
当然,在本例子启动进程的地方创建一个对话框也是可以显示对话框的。

2012-08-20 15:04 673人阅读 评论(1) 收藏 举报

1、VC2008中编写“Windows服务”(Windows Service)程序

源码资源下载: http://download.csdn.net/detail/stony1980/4512984
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" , 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、SetProcessWindowStation、OpenDesktop和SetThreadDesktop这四个函数。这种方法的思路是:当前进程所处于的Session必须有界面交互能力,这样才能显示出对话框。由于第一个交互式用户会登录到拥有WinSta0的Session 0,所以,强制性地把服务所在的进程与WinSta0关联起来,并且打开当前的桌面,把工作线程挂到该桌面上,就可以显示出对话框。

4、这种方法在WinXP和Windows2003下工作得不错,很遗憾,在Vista和Windows2008下,一旦执行到OpenWindowStation,试图代开WinSta0工作站时,程序就会出异常。

首先了解一下程序要具备怎样的条件才能与界面交互。Windows提供了三类对象:用户界面对象(User Interface)、GDI对象和内核对象。内核对象有安全性,而前两者没有。为了对前两者提供安全性,通过工作站对象(Window station)和桌面对象(Desktop)来管理用户界面对象,因为工作站对象和桌面对象有安全特性。简单说来,工作站是一个带有安全特性的对象,它与进程相关联,包含了一个或多个桌面对象。当工作站对象被创建时,它被关联到调用进程上,并且被赋给当前Session。交互式工作站WinSta0,是唯一一个可以显示用户界面,接受用户输入的工作站。它被赋给交互式用户的登录Session,包含了键盘、鼠标和显示设备。所有其他工作站都是非交互式的,这就意味着它们不能显示用户界面,不能接受用户的输入。当用户登录到一台启用了终端服务的计算机上时,每个用户都会启动一个Session。每个Session都会与自己的交互式工作站相联系。桌面是一个带有安全特性的对象,被包含在一个窗口工作站对象中。一个桌面对象有一个逻辑的显示区域,包含了诸如窗口、菜单、钩子等等这样的用户界面对象。

在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 1\n" );
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,并且可以与用户进行交互
当然,在本例子启动进程的地方创建一个对话框也是可以显示对话框的。

[置顶] Windows服务(Windows Service,system权限)程序显示界面与用户交互(xp,win7通用)相关推荐

  1. Windows服务(Windows Service,system权限)程序显示界面与用户交互(xp,win7通用)

    1.VC2008中编写"Windows服务"(Windows Service)程序 源码资源下载: http://download.csdn.net/detail/stony198 ...

  2. 以Windows服务方式运行.NET Core程序

    原文:以Windows服务方式运行.NET Core程序 在之前一篇博客<以Windows服务方式运行ASP.NET Core程序>中我讲述了如何把ASP.NET Core程序作为Wind ...

  3. 用C#创建Windows服务(Windows Services)

    转载自 hyslove 最终编辑 hyslove Windows服务在Visual Studio 以前的版本中叫NT服务,在VS.net启用了新的名称.用Visual C# 创建Windows服务不是 ...

  4. C# windows服务:创建Windows服务(Windows Services)的一般步骤

    C#创建Windows服务(Windows Services) Windows服务在Visual Studio 以前的版本中叫NT服务,在VS.net启用了新的名称.用Visual C# 创建Wind ...

  5. 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离

    服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分.我们可以把服务想像成一种特殊的应用程序,它随系统的"开启-关闭"而"开始-停止 ...

  6. fileservice 类代码放哪里_一步步开发Windows服务(Windows Service)[转]

    基于0起步来创建一个服务,做到简单的记录时间日志功能,其具体招行方法可自行添加. 1.创建服务 2.删除默认服务文件 3.添加自己的服务文件 4.更改启动项目 5. 引用 using System.T ...

  7. windows服务安装(System.ComponentModel.Win32Exception:远程过程调用失败)

    "安装"阶段发生异常.System.ComponentModel.Win32Exception:远程过程调用失败 附上提示信息 C:\Windows\Microsoft.NET\F ...

  8. (转)创建Windows服务(Windows Services)N种方式总结

    转自:http://www.cnblogs.com/aierong/archive/2012/05/28/2521409.html 最近由于工作需要,写了一些windows服务程序,有一些经验,我现在 ...

  9. *用C#创建Windows服务(Windows Services)

    Windows服务在Visual Studio 以前的版本中叫NT服务,在VS.net启用了新的名称.用Visual C# 创建Windows服务不是一件困难的事,本文就将指导你一步一步创建一个Win ...

最新文章

  1. 存储过程,触发器,函数
  2. C++ 在字符串中插入子串+推断字符串是否由空格组成
  3. 【小白学习C++ 教程】十八、C++ 中文件处理
  4. On the coexistence of transport protocols in data centers
  5. Unable to execute dex: GC overhead limit exceeded
  6. 信息学奥赛一本通C++语言——1054:三角形判断
  7. 过年,设计师都爱的烫金红色PSD装饰素材
  8. Windows Phone开发(15):资源
  9. matlab怎么算方差和标准差,matlab怎么求矩阵的均值和标准差 看完你就知道了
  10. python27安装第三方抓包库(包括libdnet)
  11. windows系统上使用magic trackpad妙控触摸板
  12. 数据防泄露解决方案-智能制造
  13. HDU2063-过山车[Hopcroft-Carp]二分图匹配
  14. 细粒度图像分类(FGVC)--- 综述
  15. 如何利用Cacti监控机房温度
  16. R语言获取丁香园疫情数据动态网站
  17. linux下运行directx,使用DXVK在Linux上改善您的葡萄酒游戏
  18. MB525 系统软件说明
  19. RAD Studio 11中文发布会录像
  20. 计算机强制关机后重启报错,Windows7启动后报错uxtheme.dll丢失怎么办?

热门文章

  1. RGB 颜色空间肤色检测
  2. Developing for a Jailbroken iPhone A to Z (iOS 4.0.1)(转)
  3. python shell怎么改字体颜色_在shell或者perl中改变字体或背景的颜色
  4. mac linux latex,如何用 macOS 优雅的敲 LaTeX
  5. 隐身侠登陆显示连接服务器失败,隐身侠驱动主程序
  6. Java操作Cookie之添加Cookie
  7. hibernate mysql 中文乱码_使用Hibernate和mysql中文乱码问题
  8. 【VBScript】vbs 错误未结束的错误字符串常量
  9. mysql找出课程相同的两个学生_day41 mysql 学习 练习题重要
  10. 汉字风格迁移篇---数据集制作---ttf转png格式