功能描述:在无人看守的情况下,防止软件意外退出。
接口调用简单,只需要简单声明就行:
int main(int argc, char **argv)
{
QShareProcess shareProcess("共享内存名称随意");
// 下面实现自己的主体代码即可
......
}
类声明:
#if !defined(AFX_SHAREMEMORY_H_INCLUDED)
#define AFX_SHAREMEMORY_H_INCLUDED
class QShareProcess
{
public:
QShareProcess(const char *name, size_t memsize = 32) ;
virtual ~QShareProcess();
private:
int startShared();
void *getMemPointer();
void write(unsigned long dwData, long lOffset = 0);
void write(char *pData, long lSize, long lOffset = 0);
void read(char *pData, long lSize, long lOffset = 0);
void close();
bool isLive();
bool isTerminated();
protected:
bool createFile(const char *name, size_t size);
bool mapViewOfFile();
bool setAllAccess(void* objHandle);
void freeRes();
void* m_hToMap;
void *m_memory;
};
#endif // !defined(AFX_SHAREMEMORY_H_INCLUDED)
类定义:
#include "ShareProcess.h"
#include <Aclapi.h>
#pragma comment(lib,"Advapi32.lib")
QShareProcess::QShareProcess(const char *name, size_t memsize)
: m_hToMap(0),
m_memory(0)
{
try {
bool needToInit = createFile(name, memsize);
mapViewOfFile();
if (needToInit) {
memset(m_memory, 0, memsize);
}
}
catch (...) {
freeRes();
throw;
}
startShared();
}
QShareProcess::~QShareProcess()
{
freeRes();
}
#include <string>
#include <vector>
#include <thread>
int QShareProcess::startShared()
{
auto getCurrentModulePath = [] ()-> std::string
{
std::vector<char> buffer;
DWORD size = MAX_PATH;
while (true) {
buffer.resize(size + 1);
DWORD ret = GetModuleFileName(NULL, &buffer[0], size);
if (ret == 0) {
return false;
}
else if (ret == size || GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
size += 128;
}
else {
break;
}
} // while
std::string out = &buffer[0];
return out;
}; // void
bool slient = false;
for (int i = 0; i < __argc; i++) {
if (_stricmp(__argv[i], "/Slient") == 0) {
slient = true;
break;
}
} // for
if (slient) {
// 互斥 上线地址:端口:服务名
char strMutex[100];
wsprintfA(strMutex, "{4EB9E321-8C12-478F-BC53-9920E7BFE114}");
HANDLE m_hMutex = CreateMutex(NULL, FALSE, strMutex);
if (m_hMutex && GetLastError() == ERROR_ALREADY_EXISTS) {
ReleaseMutex(m_hMutex);
CloseHandle(m_hMutex);
ExitProcess(0);
return 0;
}
this->write((DWORD)GetCurrentProcessId(), 12);
this->write((DWORD)GetTickCount(), 16);
while (!this->isTerminated()) {
if (!this->isLive()) {
TCHAR szCommandline[_MAX_PATH] = { 0 };
sprintf(szCommandline, "\"%s\"", getCurrentModulePath().c_str());
for (int i = 1; i < __argc; i++) {
if (_stricmp(__argv[i], "/Slient") != 0) {
strcat_s(szCommandline, " ");
strcat_s(szCommandline, __argv[i]);
}
}
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = TRUE;
PROCESS_INFORMATION pi;
CreateProcess(NULL, (LPTSTR)szCommandline,
NULL, NULL, FALSE, 0/*CREATE_NEW_CONSOLE*/, NULL, NULL,
&si, &pi);
} // if
this->write((DWORD)GetCurrentProcessId(), 12);
this->write((DWORD)GetTickCount(), 16);
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
}
ExitProcess(0);
return 1;
} // if
this->write((DWORD)0xABCD);
this->write((DWORD)GetCurrentProcessId(), 4);
this->write((DWORD)GetTickCount(), 8);
TCHAR szCommandline[_MAX_PATH] = { 0 };
sprintf(szCommandline, "\"%s\" ", getCurrentModulePath().c_str());
for (int i = 1; i < __argc; i++) {
if (_stricmp(__argv[i], "/Slient") != 0) {
strcat_s(szCommandline, " ");
strcat_s(szCommandline, __argv[i]);
}
}
strcat_s(szCommandline, " /Slient");
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = TRUE;
PROCESS_INFORMATION pi;
if (CreateProcess(NULL, (LPTSTR)szCommandline,
NULL, NULL, FALSE, 0/*CREATE_NEW_CONSOLE*/, NULL, NULL,
&si, &pi) == 0) {
return -1;
}
return 1;
}
void *QShareProcess::getMemPointer()
{
return m_memory;
}
bool QShareProcess::createFile(const char *name, size_t size)
{
DWORD lowSize = size & 0xffffffff;
DWORD highSize = (DWORD64)size >> 32 & 0xffffffff;
//创建共享文件句柄
m_hToMap = CreateFileMapping(INVALID_HANDLE_VALUE, //物理文件句柄
NULL,
PAGE_READWRITE, // 可读可写
highSize, // 地址偏移:高位
lowSize, // 地址偏移:地位
name); // 共享内存名称
if (m_hToMap == NULL) {
return false;
}
bool needToInit = GetLastError() != ERROR_ALREADY_EXISTS;
if (needToInit) {
setAllAccess(m_hToMap);
}
return needToInit;
}
#include <stdio.h>
bool QShareProcess::mapViewOfFile()
{
//映射缓存区视图,得到共享内存的指针
m_memory = MapViewOfFile(m_hToMap, //已经创建的文件映射对象的句柄
FILE_MAP_ALL_ACCESS, //可读可写
0, // 地址偏移:高位
0, // 地址偏移:地位
0); // 映射视图的大小
if (m_memory == NULL) {
return false;
}
printf("ShareMemory addr: 0x%08x\n", *(DWORD*)m_memory);
return true;
}
bool QShareProcess::setAllAccess(void* objHandle)
{
DWORD errorCode = SetSecurityInfo(objHandle, SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
NULL,
NULL);
if (errorCode != ERROR_SUCCESS) {
return false;
}
return true;
}
void QShareProcess::freeRes()
{
if (m_memory) {
UnmapViewOfFile(m_memory);
m_memory = 0;
}
if (m_hToMap) {
CloseHandle(m_hToMap);
m_hToMap = 0;
}
}
void QShareProcess::write(unsigned long dwData, long lOffset)
{
write((char*)&dwData, sizeof(unsigned long), lOffset);
}
void QShareProcess::write(char *pData, long lSize, long lOffset)
{
if (m_memory == NULL)
return ;
::memcpy((char*)m_memory + lOffset, pData, lSize);
}
void QShareProcess::read(char *pData, long lSize, long lOffset)
{
if (m_memory == NULL)
return ;
::memcpy(pData, (char*)m_memory + lOffset, lSize);
}
void QShareProcess::close()
{
write(0);
}
bool QShareProcess::isTerminated()
{
DWORD dwValue = 0;
read((char*)&dwValue, 4);
if (dwValue = 0xABCD)
return false;
else
return true;
}
#include <TlHelp32.h>
bool QShareProcess::isLive()
{
DWORD dwProcessID;
read((char*)&dwProcessID, sizeof(DWORD), 4);
bool bFind = false;
HANDLE hSnapShot = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe;
//获取系统快照(hSnapShot)
pe.dwSize = sizeof(PROCESSENTRY32);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
//查找进程
Process32First(hSnapShot, &pe);
do {
if (pe.th32ProcessID == dwProcessID) {
bFind = true;
break;
}
} while (Process32Next(hSnapShot, &pe));
CloseHandle(hSnapShot);
return bFind;
}