Windows Service Authoring (Windows Service,system permissions) program display interface and user interaction (xp,win7 general) _c# Tutorials

Source: Internet
Author: User
Tags sessions

1. Write the Windows Services (Windows Service) program in VC2008

SOURCE Resource Download:/201604/yuanma/testservice_jb51.rar

New ATL Project under Vc2008-Select to create a "service" type of ATL Project Testservice, the following code will be generated,

Class Ctestservicemodule:public catlservicemodulet< Ctestservicemodule, ids_servicename > {Public:declare_libi D (libid_testservicelib) Declare_registry_appid_resourceid (Idr_testservice, "{ 1ff78006-b225-4cc0-a7de-e0c9d31c9937} ") HRESULT initializesecurity () throw () {//TODO: Invoke the CoInitializeSecurity and provide the service with an appropriate
When//Security Settings/recommendations-PKT level of authentication,//Rpc_c_imp_level_identify impersonation level, and appropriate non-null security descriptor.
return S_OK; //rewrite This function to start the task the HRESULT Run (int nshowcmd = sw_hide) throw () {HRESULT hr = S_OK; hr = __super::P remessageloop (NSHOWCM
D); if (hr = = S_OK) {if (M_bservice) {///need to define #define _ATL_NO_COM_SUPPORT to come here//can start the thread here, or something else to do your work//here is nothing
Done, only output a message LogEvent (_t ("Widebright service start-up slightly, hehe"));
SetServiceStatus (service_running);
//Enter the message loop, keep processing messages, may finally be distributed to handler to deal with, call the OnShutdown function.
__super::runmessageloop ();
} if (SUCCEEDED (HR)) {hr = __super::P ostmessageloop ();}//Can call the Uninstall function at the appropriate time to uninstall the service//__super::uninstall ();
return HR; }//rewrite, service exit handling void OnShutdown () Throw () {LogEvent (_t ("Testservice service exit slightly, not funny at all")};

Ctestservicemodule _atlmodule; extern "C" int winapi _tWinMain (hinstance, HINSTANCE, LPTSTR, int nshowcmd) {return _atlmodule.
WinMain (nShowCmd); }

2, as long as I need to rewrite the corresponding function to achieve their desired function on the line

For example, you want to create a "service" with the system boot, you can rewrite the CAtlServiceModuleT install function, the inside of the CreateService function parameters modified, such as adding and user interaction can be used Service_interactive_ PROCESS, you can go to MSDN to find CreateService this API description.

If you want to handle the service stop and start action, you can refer to the CAtlServiceModuleT source code rewrite OnStop () and other functions. I am simple to rewrite the run function, output an "event" in fact, the specific work can be put here to complete the bar.

Compile, build the program, and then you can test it,

Execute "testservice-/service" can register the service to the system, the command line parameter is in fact in CAtlServiceModuleT::P arsecommandline This function inside processing, can go to see, if necessary rewrite also can, Adding the code that calls uninstall to remove the service is also pretty good.

After registration, you can use the "sc start" or "net start" and other commands to manipulate the service. In the "service" controller control with can: as shown

3, at this time in the run function to start a Notepad.exe, there is no interface display, under the XP can use the following method to achieve Notepad and user interaction:

For XP system DWORD _stdcall LaunchAppIntoSession0 (LPTSTR lpcommand) {////////////////////////////////////////////s
Ystem 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;}//Open WINSTA0//open winsta0 Hwinsta = openwindowstation (L "Winsta0", FALSE, Winst
a_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;}//Open DESKTOP Hdesk = OpenDesktop (L "Default", 0, FALSE, Desktop_crea
Temenu |
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 to be inheritable.
sathread.nlength = sizeof (Sathread);
Sathread.lpsecuritydescriptor = NULL; 


Sathread.binherithandle = FALSE; 

CreateProcess (NULL, Lpcommand, & Saprocess, &sathread, FALSE, 0, NULL, NULL, & Si, &AMP;PIPROCESSB); if (! SetProcessWindowStation (HwinstaCurrent), return FALSE; if (!
SetThreadDesktop (hdeskcurrent)) return FALSE; if (!
Closewindowstation (Hwinsta)) return FALSE; if (!
Closedesktop (hdesk)) return FALSE;
return TRUE; }


The key to this approach is the four functions openwindowstation, setprocesswindowstation, OpenDesktop, and SetThreadDesktop. The idea of this approach is that the session in which the current process is in must have interface interaction capabilities to display the dialog box. Because the first interactive user will be logged into session 0 with WINSTA0, it is possible to automatically associate the process of the service with the WINSTA0, open the current desktop, and then hang the worker thread on the desktop to display the dialog box.

4, this method in WinXP and Windows2003 work well, unfortunately, in Vista and Windows2008, once executed to Openwindowstation, trying to generation WINSTA0 workstation, the program will be abnormal.


First understand how the program has to have the conditions to interact with the interface. Windows provides three types of objects: User interface objects (users Interface), GDI objects, and kernel objects. The kernel object has security, and the first two are not. To provide security for the first two, user interface objects are managed through workstation objects (Window station) and Desktop Objects (Desktop), because workstation objects and desktop objects have security features. In short, a workstation is an object with a security feature that is associated with a process and contains one or more desktop objects. When a workstation object is created, it is associated with the calling process, and is assigned to the current session. Interactive workstation WINSTA0 is the only workstation that can display the user interface and accept user input. It is assigned to the interactive user's logon session, which includes a keyboard, mouse, and display device. All other workstations are non-interactive, which means they cannot display the user interface and cannot accept user input. When a user logs on to a computer with Terminal Services enabled, each user initiates a session. Each session will be associated with its own interactive workstation. The desktop is an object with a security feature that is contained in a window workstation object. A desktop object has a logical display area that contains user interface objects such as windows, menus, hooks, and so on.

Before Vista, it was possible to open the WINSTA0 and Default desktop display dialog box because both the service and the first logged-on interactive user were logged into session 0. Therefore, the service program can gain interactivity by forcing the WinSta0 and desktop to open.

However, in Vista and Windows2008, Session 0 is dedicated to services and other applications that do not interact with the user. The first login comes in and the user who can do the interactive operation is connected to session 1. The second logon user is assigned to session 2, and so on. Session 0 does not support the process of interacting with users at all. If you take a child process to display a dialog box in a service process, the Child dialog box will not display, and if you take a method that opens the WINSTA0 with the Openwindowstation system API, the function call fails. In short, Vista and Windows2008 have blocked the path of interactive interaction in session 0. That's why.

So, is it really impossible to pop up a dialog box in the service? For the service process itself, indeed, the operating system has blocked the road. But what we want is not "pop up a dialog box in the service process", all we want is "pop up a dialog on the desktop when something happens to the service." Since in session 0 can not pop-up dialog box, and we see the desktop is sessions X, not sessions 0, it is a natural idea is: can we let sessions 0 notify the other session, so that the current desktop is displayed in a dialog box to play it?

Luckily, it is possible to do so.

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, &AMP;TP, sizeof (token_privileges), (Ptoken_priviLeges) (null)) {Dwret = GetLastError (); break;} else;
LPVOID penv =null; if (Createenvironmentblock (&penv, Husertokendup, TRUE)) {dwcreationflags|=create_unicode_environment;} else pEn
V =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 inher Itable dwcreationflags,//Creation Flags penv,//Pointer to new environment blocks NULL,//Name of current directory ; Si,//Pointer to STARTUPINFO structure & PI//receives information about new process) {} else {dwret = Getlaste
Rror ();
Break
} while (0);
Perform all of 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, after starting the service shows the system permissions of the Notepad.exe, and can interact with the user


Of course, creating a dialog box where this example starts the process can also display the dialog box.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.