<h3>一.Service</h3>
<p>借助MSDN上<a href="http://code.msdn.microsoft.com/CppWin7TriggerStartService-8ba5bd5b/sourcecode?fileId=64923&pathId=927862711" rel="noopener noreferrer" target="_blank">Win7 Service的Demo</a>和《<a href="http://blog.csdn.net/lincyang/article/details/6231406" rel="noopener noreferrer" target="_blank">用VC++建立Service服务应用程序</a>》,在Win8上经历各种磨难,终于跑起来自己改装的服务程序了。</p>
<p>原来API基本没变,我所困惑的是Win7上直接运行都没有问题,在Win8上不可以。</p>
<p>报错:</p>
<pre class="blockcode"><code class="language-plain">OpenSCManager failed w/err 0x00000005</code></pre>
<p>原来是Win8上权限的问题,也许我自己的Win7一启动就拥有了Admin权限吧。</p>
<p><br> </p>
<p>下面直接进入正题,我整合了一下代码,共三个文件:main.c,Service.h, Service.cpp。(项目是控制台程序。)</p>
<p>main.c只是程序的入口,运行时接受参数。</p>
<pre class="blockcode"><code class="language-cpp">#pragma region "Includes"
#include <stdio.h>
#include <windows.h>
#include "Service.h"
#pragma endregion
int wmain(int argc, wchar_t* argv[])
{
if ((argc > 1) && ((*argv[1] == L'-' || (*argv[1] == L'/'))))
{
if (_wcsicmp(L"install", argv[1] + 1) == 0)
{
SvcInstall();
}
else if (_wcsicmp(L"remove", argv[1] + 1) == 0)
{
SvcUninstall();
}
else if (_wcsicmp(L"query", argv[1] + 1) == 0)
{
SvcQueryConfig();
}
else if(_wcsicmp(L"start",argv[1] + 1) == 0)
{
SvcStart();
}
else if(_wcsicmp(L"stop",argv[1] + 1) == 0)
{
SvcStopNow();
}
}
else
{
_putws(L"Parameters:");
_putws(L" -install to install the service (require admin permission)");
_putws(L" -remove to remove the service (require admin permission)");
_putws(L" -query to query the configuration of the service");
_putws(L" -start to start the service");
_putws(L" -stop to stop the service");
RunService();
}
return 0;
}</code></pre>
<p>代码中已经写的很清楚了,我的项目名称为Win8Service,只要运行Win8Service.exe -install,服务就会被安装。</p>
<p><strong>注意:cmd必须要用admin启动。win8下做法:WIN+Q键,打开Search panel,输入cmd,右击Command Prompt,选择Run as administrator。</strong></p>
<p><br> </p>
<p>下面看看这几个函数的实现:</p>
<p>Service.h</p>
<pre class="blockcode"><code class="language-cpp">#pragma once
// Internal name of the service
#define SERVICE_NAME L"CppWin8Service"
// Displayed name of the service
#define SERVICE_DISPLAY_NAME L"CppWin8Service Demo"
// List of service dependencies - "dep1\0dep2\0\0"
#define SERVICE_DEPENDENCIES L""
// The name of the account under which the service should run
#define SERVICE_ACCOUNT L"NT AUTHORITY\\LocalService"
// The password to the service account name
#define SERVICE_PASSWORD NULL
VOID RunService();
VOID SvcInstall();
VOID SvcUninstall();
VOID SvcQueryConfig();
BOOL SvcStart();
VOID SvcStopNow();</code></pre>
<p><br> </p>
<p>Service.cpp</p>
<p></p>
<pre class="blockcode"><code class="language-cpp">#pragma region "Includes"
#include <stdio.h>
#include <windows.h>
#include "Service.h"
#pragma endregion
SERVICE_STATUS g_ssSvcStatus; // Current service status
SERVICE_STATUS_HANDLE g_sshSvcStatusHandle; // Current service status handle
HANDLE g_hSvcStopEvent;
VOID WINAPI SvcMain(DWORD dwArgc, LPWSTR* lpszArgv);
VOID WINAPI SvcCtrlHandler(DWORD dwCtrl);
VOID SvcInit(DWORD dwArgc, LPWSTR* lpszArgv);
VOID SvcStop();
VOID SvcReportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
VOID SvcReportEvent(LPWSTR lpszFunction, DWORD dwErr = 0);
VOID RunService()
{
// You can add any additional services for the process to this table.
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
{ NULL, NULL }
};
// This call returns when the service has stopped.
// The process should simply terminate when the call returns.
if (!StartServiceCtrlDispatcher(dispatchTable))
{
SvcReportEvent(L"StartServiceCtrlDispatcher", GetLastError());
}
}
VOID WINAPI SvcMain(DWORD dwArgc, LPWSTR* lpszArgv)
{
SvcReportEvent(L"Enter SvcMain");
// Register the handler function for the service
g_sshSvcStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME,
SvcCtrlHandler);
if (!g_sshSvcStatusHandle)
{
SvcReportEvent(L"RegisterServiceCtrlHandler", GetLastError());
return;
}
// These SERVICE_STATUS members remain as set here
g_ssSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ssSvcStatus.dwServiceSpecificExitCode = 0;
// Report initial status to the SCM
SvcReportStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
// Perform service-specific initialization and work.
SvcInit(dwArgc, lpszArgv);
}
VOID WINAPI SvcCtrlHandler(DW |
|