首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++编撰服务,在服务中打开外部exe

2013-12-04 
C++编写服务,在服务中打开外部exe现在服务中打开一个外部文件,exe、txt都行,目前用ShellExecute(NULL, ope

C++编写服务,在服务中打开外部exe
现在服务中打开一个外部文件,exe、txt都行,目前用ShellExecute(NULL, "open", "D:\\0.exe", "", "", SW_SHOW);没办法打开

代码在这里

#include <windows.h>
#include <stdio.h>
#include "XmlSettings.h"
#pragma comment(lib, "Advapi32")

SERVICE_STATUS ServiceStatus; 
SERVICE_STATUS_HANDLE hStatus; 
void ServiceMain(int argc, char** argv); 
void ControlHandler(DWORD request); 

int main(int argc, char* argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "yy8";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;

// 启动服务的控制分派机线程
StartServiceCtrlDispatcher(ServiceTable); 
}


void ServiceMain(int argc, char** argv) 
{
ServiceStatus.dwServiceType = 
SERVICE_WIN32; 
ServiceStatus.dwCurrentState = 
SERVICE_START_PENDING; 
ServiceStatus.dwControlsAccepted   =  
SERVICE_ACCEPT_STOP | 
SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0; 
ServiceStatus.dwServiceSpecificExitCode = 0; 
ServiceStatus.dwCheckPoint = 0; 
ServiceStatus.dwWaitHint = 0; 

hStatus = RegisterServiceCtrlHandler(
"MemoryStatus", 
(LPHANDLER_FUNCTION)ControlHandler); 
if (hStatus == (SERVICE_STATUS_HANDLE)0) 

// Registering Control Handler failed
return; 
}  

// We report the running status to SCM. 
ServiceStatus.dwCurrentState = 
SERVICE_RUNNING; 
SetServiceStatus (hStatus, &ServiceStatus);

/** 服务启动一分钟后开始进入循环 */
//Sleep(10000);

CXmlSettings xml;

xml.addTag("year");
xml.addTag("month");
xml.addTag("day");
xml.addTag("hour");
xml.addTag("minute");
xml.addTag("second");


// The worker loop of a service
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{

ShellExecute(NULL, "open", "D:\\0.bat", "", "", SW_SHOW);

SYSTEMTIME curr_st;
GetLocalTime(&curr_st);
int year = curr_st.wYear;
int month = curr_st.wMonth;
int day = curr_st.wDay;
int hour = curr_st.wHour;
int minute = curr_st.wMinute;
int second = curr_st.wSecond;

xml.setValue("year", year);
xml.setValue("month", month);
xml.setValue("day", day);
xml.setValue("hour", hour);
xml.setValue("minute", minute);
xml.setValue("second", second);
xml.saveFile("D:\\test.xml");


//MessageBox(NULL, "1111", "111", MB_OK);

Sleep(5000);
}

return; 
}

void ControlHandler(DWORD request) 

switch(request) 

case SERVICE_CONTROL_STOP: 
ServiceStatus.dwWin32ExitCode = 0; 
ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
SetServiceStatus (hStatus, &ServiceStatus);
return; 

case SERVICE_CONTROL_SHUTDOWN: 
ServiceStatus.dwWin32ExitCode = 0; 
ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
SetServiceStatus (hStatus, &ServiceStatus);
return; 

default:
break;


// Report current status
SetServiceStatus (hStatus, &ServiceStatus);

return; 
}
C++服务
[解决办法]
         这样就可以的,你试下

 HDESK   hdeskCurrent;
 HDESK   hdesk;
 HWINSTA hwinstaCurrent;
 HWINSTA hwinsta;
 hwinstaCurrent = GetProcessWindowStation();
 hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());

 //打开用户的winsta0
 hwinsta = OpenWindowStation("winsta0", FALSE,                          


 WINSTA_ACCESSCLIPBOARD   
[解决办法]

 WINSTA_ACCESSGLOBALATOMS 
[解决办法]

 WINSTA_CREATEDESKTOP     
[解决办法]

 WINSTA_ENUMDESKTOPS      
[解决办法]

 WINSTA_ENUMERATE         
[解决办法]

 WINSTA_EXITWINDOWS       
[解决办法]

 WINSTA_READATTRIBUTES    
[解决办法]

 WINSTA_READSCREEN        
[解决办法]

 WINSTA_WRITEATTRIBUTES);
 //打开desktop
 hdesk = OpenDesktop("default", 0, FALSE,                
 DESKTOP_CREATEMENU 
[解决办法]

 DESKTOP_CREATEWINDOW 
[解决办法]

 DESKTOP_ENUMERATE    
[解决办法]

 DESKTOP_HOOKCONTROL  
[解决办法]

 DESKTOP_JOURNALPLAYBACK 
[解决办法]

 DESKTOP_JOURNALRECORD 
[解决办法]

 DESKTOP_READOBJECTS 
[解决办法]

 DESKTOP_SWITCHDESKTOP 
[解决办法]

 DESKTOP_WRITEOBJECTS);
 SetThreadDesktop(hdesk);  
 ::ShellExecute(0,NULL,"F:\\Program Files\\kuwo\\KWMUSIC2013\\KwMusic.exe",NULL,NULL,SW_MAXIMIZE);
 SetProcessWindowStation(hwinstaCurrent);
 SetThreadDesktop(hdeskCurrent);
 CloseWindowStation(hwinsta);
 CloseDesktop(hdesk);


[解决办法]
学习二楼。
[解决办法]
修改服务启动的用户

或者参考下面:
用调试器(OD,WINDBG等)调试服务程序
To debug the initialization code of a service application, the debugger must be attached when the service is started. This is accomplished by creating a registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProgramName


The ProgramName is the image file for the service application you are debugging. Do not specify a path. For example, the ProgramName might look like MyService.exe.

Under this key create a string data value called Debugger. The value of this string should be set to the full path of the debugger that will be used. For example,

c:\Debuggers\windbg.exe



In addition to setting this registry key, the service application must be marked as "interactive". This allows your service to interact with the desktop, and allows the debugger window to appear on your desktop.

This again requires modifying a registry key: you must bitwise-or the type entry for your service with 0x100 (this is the value for SERVICE_INTERACTIVE_PROCESS according to Winnt.h). The exact location and name of this registry entry varies. For example:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyServiceKey


Finally, you need to adjust the service application timeout. Otherwise, the service application will kill the debugger within 20 seconds after starting. Adjusting the timeout involves setting an entry in the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control


Under this key, create a DWORD data value called ServicesPipeTimeout. Set this entry to the amount of time in milliseconds that you want the service to wait before timing out. For example, 60,000 is one minute, while 86,400,000 is 24 hours.

设置ServicesPipeTimeout后需要重启系统才生效

Now, when the service is started, the debugger will also start. When the debugger starts, it will stop at the initial process breakpoint, before the service has begun running. This allows you to set breakpoints or otherwise configure your debugging session to let you monitor the startup of your service. Another option is to place calls to the DebugBreak function in your service from the point at which you would like to break into the debugger. (For more information, see DebugBreak in the Platform SDK documentation.)



If your service is running with other services in a Service Host Process, you may need to isolate the service into its own Service Host Process.


[解决办法]
改用命令行注册你的服务:
sc create yy8 binPath= "D:\yourService.exe" DisplayName= "my service test" start= auto type= interact type= own
sc description yy8 "this is a service test"
sc start yy8

或者做一个批处理文件,如install.bat
内容如下:
@echo off
sc create yy8 binPath= "D:\yourService.exe" DisplayName= "my service test" start= auto type= interact type= own
sc description yy8 "this is a service test"
sc start yy8
或者干脆打开我的电脑的服务管理界面
右键你的服务属性,选择登录,勾选“允许服务与界面交互”



[解决办法]
引用:
Quote: 引用:

改用命令行注册你的服务:
sc create yy8 binPath= "D:\yourService.exe" DisplayName= "my service test" start= auto type= interact type= own
sc description yy8 "this is a service test"
sc start yy8

或者做一个批处理文件,如install.bat
内容如下:
@echo off
sc create yy8 binPath= "D:\yourService.exe" DisplayName= "my service test" start= auto type= interact type= own
sc description yy8 "this is a service test"
sc start yy8
或者干脆打开我的电脑的服务管理界面
右键你的服务属性,选择登录,勾选“允许服务与界面交互”
我已经将自己写的这个服务程序启动了,能够成功的将系统时间写入test.xml(用于测试服务程序是否有效),然后让服务程序每隔5秒打开一个mp3文件,确实打开了,不过是偶尔才能听到声音,但是目前还不能打开exe,好郁闷的。。  ‘右键你的服务属性,选择登录,勾选“允许服务与界面交互”
’我刚也试了,它会每次都弹出一个对话框显示‘此计算机上运行的程序正在尝试显示一条消息’,好郁闷的,点击查看消息会让机器分辨率都改变,然后才能看到那个音频文件在放!!!


你的mp3播放最好是用另外一个程序打开,你的服务程序就是用来守护你播放Mp3的那个程序
你先把你的服务停掉,在设置下,再重新启动试下。
[解决办法]
打开我的电脑的服务管理界面
右键你的服务属性,选择登录,勾选“允许服务与界面交互”

[解决办法]
system("D:\\0.exe")
[解决办法]
核心就是 window station
[解决办法]
要是我的思路,应该不会想着在服务中打开外部EXE。
首先服务本来就是一种后台程序,默默的工作,给用户的交互也是写写日志之类,在服务中弹窗可能违背了服务程序的初衷。
其次服务在运行时可能还没用户登录,也没有桌面窗口,这样即使弹出EXE也找不到顶层窗口。

可能更好的做法是:另外再写一个EXE界面守护程序,在用户登陆后运行,并最小化到托盘。这个程序可以通过某种机制与服务程序进行通讯(有专门的服务消息,或者管道等等)。这时服务需要弹什么通知守护EXE来弹就行。

我想这是大多数正常程序的套路,当然LZ要是想偷偷的进村,打枪的不要这类用途就当我没说,哈哈
[解决办法]
贴图上来看下
[解决办法]
http://www.cnblogs.com/flying_bat/archive/2007/09/26/906439.html

服务程序涉及权限问题, 因为用户可能还没有登陆. 上面你参考下. 我是试成功的.
[解决办法]
引用:
Quote: 引用:

要是我的思路,应该不会想着在服务中打开外部EXE。
首先服务本来就是一种后台程序,默默的工作,给用户的交互也是写写日志之类,在服务中弹窗可能违背了服务程序的初衷。
其次服务在运行时可能还没用户登录,也没有桌面窗口,这样即使弹出EXE也找不到顶层窗口。

可能更好的做法是:另外再写一个EXE界面守护程序,在用户登陆后运行,并最小化到托盘。这个程序可以通过某种机制与服务程序进行通讯(有专门的服务消息,或者管道等等)。这时服务需要弹什么通知守护EXE来弹就行。

我想这是大多数正常程序的套路,当然LZ要是想偷偷的进村,打枪的不要这类用途就当我没说,哈哈
其实我是想用服务程序监控界面程序。。界面程序不允许被终结,在服务程序里扫描不到界面程序的进程,立即重新启动这个界面程序。  所以才需要用服务去打开界面。。 挺感谢你的建议,谢谢!


果然是这类需求,以前我也接到过把一个EXE嵌入到另外一个EXE界面且看不出破绽的诡异需求。
服务是System权限,默认不具备与UI交互的权限,执行ShellExecute也会不成功。获取权限的办法要么使用CreateProcessAsUser,用当前桌面用户的权限启动外部程序,要么服务本身获取到UI权限再启动外部EXE。
这些办法前面高手已经说了,我就不班门弄斧了(虽然写过不少服务,但确实没有这么干过,囧)。

热点排行