| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- // TimeSyncServer.cpp : 定义应用程序的类行为。
- //
- #include "stdafx.h"
- #include "TimeSyncServer.h"
- #include "TimeSyncServerDlg.h"
- #include "Simplelog.h"
- #include <thread>
- #include "AppService.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- //设置两个全局变量
- SERVICE_STATUS m_ServiceStatus;
- SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
- void WINAPI ServiceMain(DWORD argc, LPTSTR * argv)
- {
- // DWORD status;
- // DWORD specificError;
- CSimpleLog::Save("当用SCM启动程序的时候,程序执行下面的代码", true, CSimpleLog::info);
- m_ServiceStatus.dwServiceType = SERVICE_WIN32;
- m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
- m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- m_ServiceStatus.dwWin32ExitCode = 0;
- m_ServiceStatus.dwServiceSpecificExitCode = 0;
- m_ServiceStatus.dwCheckPoint = 0;
- m_ServiceStatus.dwWaitHint = 0;
- m_ServiceStatusHandle = RegisterServiceCtrlHandler("TimeSyncServer", ServiceCtrlHandler);
- if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
- {
- CSimpleLog::Save("Handler not installed", true, CSimpleLog::error);
- return;
- }
- m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
- m_ServiceStatus.dwCheckPoint = 0;
- m_ServiceStatus.dwWaitHint = 0;
- if (!SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus))
- {
- }
- std::thread th(CTimeSyncServerApp::StartTheAppServices, 2);
- th.detach();
- return;
- }
- void WINAPI ServiceCtrlHandler(DWORD Opcode)
- {
- switch (Opcode)
- {
- case SERVICE_CONTROL_PAUSE:
- m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
- break;
- case SERVICE_CONTROL_CONTINUE:
- m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
- break;
- case SERVICE_CONTROL_STOP:
- m_ServiceStatus.dwWin32ExitCode = 0;
- m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
- m_ServiceStatus.dwCheckPoint = 0;
- m_ServiceStatus.dwWaitHint = 0;
- SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
- //bRunning=false;
- break;
- case SERVICE_CONTROL_INTERROGATE:
- break;
- }
- return;
- }
- BOOL InstallService(CString &strPath)//无法创建其他应用程序为服务,因为它们不能响应启动请求
- {
- //char strDir[1024]={0};
- SC_HANDLE schSCManager, schService;
- // GetCurrentDirectory(1024,strDir);
- // strcat(strDir," //test.exe ");
- schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if (schSCManager == NULL)
- return false;
- //LPCTSTR lpszBinaryPathName=strDir;
- LPCTSTR lpszBinaryPathName;
- if (strPath == "")
- {
- AfxMessageBox("You must tell me Exepath!");
- return FALSE;
- }
- else
- {
- lpszBinaryPathName = strPath;
- }
- schService = CreateService(schSCManager, "DataServices", "DataServices",// service name to display
- SERVICE_ALL_ACCESS, // desired access
- SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // service type
- //SERVICE_DEMAND_START, // start type
- SERVICE_AUTO_START, //系统启动时自动启动
- SERVICE_ERROR_NORMAL, // error control type
- lpszBinaryPathName, // service's binary
- NULL, // no load ordering group
- NULL, // no tag identifier
- NULL, // no dependencies
- NULL, // LocalSystem account
- NULL); // no password
- if (schService == NULL)
- return false;
- CloseServiceHandle(schService);
- return true;
- }
- BOOL DeleteService()
- {
- SC_HANDLE schSCManager;
- SC_HANDLE hService;
- schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if (schSCManager == NULL)
- return false;
- hService = OpenService(schSCManager, "DataServices", SERVICE_ALL_ACCESS);
- if (hService == NULL)
- return false;
- if (DeleteService(hService) == 0)
- return false;
- if (CloseServiceHandle(hService) == 0)
- return false;
- else
- return true;
- }
- CDumpCatch g_dumpCatch;
- //////////////////////////////////////////////////////////////////////////////////////
- void CDumpCatch::MyPureCallHandler(void)
- {
- throw std::invalid_argument("");
- }
- void CDumpCatch::MyInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
- {
- //The parameters all have the value NULL unless a debug version of the CRT library is used.
- throw std::invalid_argument("");
- }
- void CDumpCatch::SetInvalidHandle()
- {
- #if _MSC_VER >= 1400 // MSVC 2005/8
- m_preIph = _set_invalid_parameter_handler(MyInvalidParameterHandler);
- #endif // _MSC_VER >= 1400
- m_prePch = _set_purecall_handler(MyPureCallHandler); //At application, this call can stop show the error message box.
- }
- void CDumpCatch::UnSetInvalidHandle()
- {
- #if _MSC_VER >= 1400 // MSVC 2005/8
- _set_invalid_parameter_handler(m_preIph);
- #endif // _MSC_VER >= 1400
- _set_purecall_handler(m_prePch); //At application this can stop show the error message box.
- }
- LPTOP_LEVEL_EXCEPTION_FILTER WINAPI CDumpCatch::TempSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
- {
- return NULL;
- }
- BOOL CDumpCatch::AddExceptionHandle()
- {
- m_preFilter = ::SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
- PreventSetUnhandledExceptionFilter();
- return TRUE;
- }
- BOOL CDumpCatch::RemoveExceptionHandle()
- {
- if (m_preFilter != NULL)
- {
- ::SetUnhandledExceptionFilter(m_preFilter);
- m_preFilter = NULL;
- }
- return TRUE;
- }
- CDumpCatch::CDumpCatch()
- {
- SetInvalidHandle();
- AddExceptionHandle();
- }
- CDumpCatch::~CDumpCatch()
- {
- UnSetInvalidHandle();
- RemoveExceptionHandle();
- }
- BOOL CDumpCatch::ReleaseDumpFile(const std::string& strPath, EXCEPTION_POINTERS* pException)
- {
- HANDLE hDumpFile = ::CreateFile(strPath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hDumpFile == INVALID_HANDLE_VALUE)
- {
- return FALSE;
- }
- MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
- dumpInfo.ExceptionPointers = pException;
- dumpInfo.ThreadId = ::GetCurrentThreadId();
- dumpInfo.ClientPointers = TRUE;
- // ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
- BOOL bRet = ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hDumpFile, MiniDumpWithFullMemory, &dumpInfo, NULL, NULL);
- ::CloseHandle(hDumpFile);
- return bRet;
- }
- #include <spdlog/fmt/fmt.h>
- LONG WINAPI CDumpCatch::UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS* pException)
- {
- char szPath[MAX_PATH] = { 0 };
- ::GetModuleFileName(NULL, szPath, MAX_PATH);
- ::PathRemoveFileSpec(szPath);
- SYSTEMTIME st;
- GetLocalTime(&st);
- std::string strPath = fmt::format("{}\\DataServiceS_{}_{:0>4}{:0>2}{:0>2}_{:0>2}{:0>2}{:0>2}.dmp",
- szPath, g_strVersion, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
- SPDLOG_CRITICAL("异常崩溃:{} 版本:{}", strPath, g_strVersion);
- BOOL bRelease = ReleaseDumpFile(strPath.c_str(), pException);
- //::FatalAppExit(0, L"Error");
- NOTIFYICONDATA nid;
- nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
- nid.hWnd = AfxGetMainWnd()->GetSafeHwnd();
- nid.uID = IDI_DATASERVICS;//删除图标,仅使用ID即可(我们使用的是图标的ID)
- Shell_NotifyIcon(NIM_DELETE, &nid); //在托盘区删除图标
- if (bRelease)
- {
- return EXCEPTION_EXECUTE_HANDLER;
- }
- return EXCEPTION_CONTINUE_SEARCH;
- }
- BOOL CDumpCatch::PreventSetUnhandledExceptionFilter()
- {
- HMODULE hKernel32 = LoadLibrary("kernel32.dll");
- if (hKernel32 == NULL)
- {
- return FALSE;
- }
- void* pOrgEntry = ::GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
- if (pOrgEntry == NULL)
- {
- return FALSE;
- }
- unsigned char newJump[5];
- DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;
- dwOrgEntryAddr += 5; //jump instruction has 5 byte space.
- void* pNewFunc = &TempSetUnhandledExceptionFilter;
- DWORD dwNewEntryAddr = (DWORD)pNewFunc;
- DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
- newJump[0] = 0xE9; //jump
- memcpy(&newJump[1], &dwRelativeAddr, sizeof(DWORD));
- SIZE_T bytesWritten;
- DWORD dwOldFlag, dwTempFlag;
- ::VirtualProtect(pOrgEntry, 5, PAGE_READWRITE, &dwOldFlag);
- BOOL bRet = ::WriteProcessMemory(::GetCurrentProcess(), pOrgEntry, newJump, 5, &bytesWritten);
- ::VirtualProtect(pOrgEntry, 5, dwOldFlag, &dwTempFlag);
- return bRet;
- }
- // CTimeSyncServerApp
- BEGIN_MESSAGE_MAP(CTimeSyncServerApp, CWinApp)
- ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
- END_MESSAGE_MAP()
- // CTimeSyncServerApp 构造
- CTimeSyncServerApp::CTimeSyncServerApp()
- {
- // 支持重新启动管理器
- m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
- // TODO: 在此处添加构造代码,
- // 将所有重要的初始化放置在 InitInstance 中
- }
- // 唯一的一个 CTimeSyncServerApp 对象
- CTimeSyncServerApp theApp;
- // CTimeSyncServerApp 初始化
- BOOL CTimeSyncServerApp::InitInstance()
- {
- // 如果一个运行在 Windows XP 上的应用程序清单指定要
- // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
- //则需要 InitCommonControlsEx()。 否则,将无法创建窗口。
- INITCOMMONCONTROLSEX InitCtrls;
- InitCtrls.dwSize = sizeof(InitCtrls);
- // 将它设置为包括所有要在应用程序中使用的
- // 公共控件类。
- InitCtrls.dwICC = ICC_WIN95_CLASSES;
- InitCommonControlsEx(&InitCtrls);
- CWinApp::InitInstance();
- if (!AfxSocketInit())
- {
- AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
- return FALSE;
- }
- AfxEnableControlContainer();
- // 创建 shell 管理器,以防对话框包含
- // 任何 shell 树视图控件或 shell 列表视图控件。
- CShellManager *pShellManager = new CShellManager;
- // 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
- CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
- // 标准初始化
- // 如果未使用这些功能并希望减小
- // 最终可执行文件的大小,则应移除下列
- // 不需要的特定初始化例程
- // 更改用于存储设置的注册表项
- // TODO: 应适当修改该字符串,
- // 例如修改为公司或组织名
- SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
- HANDLE hMutex = ::CreateMutex(NULL, FALSE, "DataServices");
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- ::TerminateProcess((HANDLE)-1, 0);
- std::string strParam = R"(netsh advfirewall firewall delete rule name="DataServices" dir=in & netsh advfirewall firewall add rule name="DataServices" dir=in protocol=tcp localport=10086,10088,10089,21006,21008,51609 action=allow & netsh advfirewall firewall delete rule name="DataServicesUDP" dir=in & netsh advfirewall firewall add rule name="DataServicesUDP" dir=in protocol=udp localport=51609 action=allow)";
- hjfunc_CmdExecParam(strParam, 1, SW_HIDE);
- //日志初始化
- CSpdlogMng::Instance()->InitLog("DataServices");
- //启动服务(两种方式:双击运行和SCM启动,执行流程如刚开始提到的那样),对话框在下面显示
- SERVICE_TABLE_ENTRY DispatchTable[] = { { "DataServices",ServiceMain },{ NULL,NULL } };
- //StartServiceCtrlDispatcher(DispatchTable);
- if (!StartServiceCtrlDispatcher(DispatchTable))
- {
- CSimpleLog::Save("当不是用SCM启动程序的时候,程序执行下面的代码", true, CSimpleLog::info);
- std::thread th(CTimeSyncServerApp::StartTheAppServices, 2);
- th.detach();
-
- CTimeSyncServerDlg dlg;
- m_pMainWnd = &dlg;
- int nResponse = dlg.DoModal();
- if (nResponse == IDOK)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with OK
- }
- else if (nResponse == IDCANCEL)
- {
- // TODO: Place code here to handle when the dialog is
- // dismissed with Cancel
- }
- }
- // 删除上面创建的 shell 管理器。
- if (pShellManager != NULL)
- {
- delete pShellManager;
- }
- #ifndef _AFXDLL
- ControlBarCleanUp();
- #endif
- // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
- // 而不是启动应用程序的消息泵。
- return FALSE;
- }
- void CTimeSyncServerApp::StartTheAppServices(WORD seconds)
- {
- for (auto i = 0; i < seconds; i++)
- std::this_thread::sleep_for(std::chrono::seconds(1));
- if (CAppService::Instance()->Start())
- {
- CSimpleLog::Info("启动成功.");
- }
- else
- {
- CSimpleLog::Error("启动失败.程序退出");
- ::TerminateProcess((HANDLE)-1, 0);
- }
- }
|