繁体   English   中英

C ++-如何退出没有窗口的程序?

[英]C++ - How can I exit a program that has no window?

我是C ++的新手,我为自己制作了一个小程序,可以通过在键盘上键入命令来启动程序。 为了能够在需要时启动程序,我决定设置一个低级键盘挂钩,该键盘挂钩可以跟踪按键并在检测到特定命令时启动特定程序。 简单的Windows程序用于安装该钩子,未显示Windows,因为我只需要在后台监听钩子即可。

到目前为止,它仍然可以正常工作,但是,一个较小但烦人的问题是我必须通过Windows Task Manager终止程序,这非常不方便。 我已经设法通过按F7键卸载了该挂钩,但是似乎未显示的Windows程序是该挂钩的父项,因此该挂钩无法退出Windows程序。 当我希望它们都通过按键终止时。 希望我已经说清楚了。

有什么方法可以将消息从挂钩发送到Windows程序以要求其退出? 或者以某种方式可以在钩子程序中终止它们两者?

提前致谢。

这是窗口程序的代码:

#include <windows.h>
#include "shortcut.h"

#pragma comment( lib, "libhook.dll.a")          // Link Hook.lib to the project

long WINAPI WndProc(HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam)
{
    switch(wMessage)
    {
        case WM_DESTROY:
            InstallHook(FALSE);     // Unhook
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd, wMessage, wParam, lParam);
    }
    return 0;

}
BOOL FileExists(LPCTSTR szPath)
{
  DWORD dwAttrib = GetFileAttributes(szPath);

  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
         !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASS wndclass;
    HANDLE hMutex = NULL;
    char szAppName[20] = "shortcut";

    hMutex = CreateMutex(NULL,TRUE,szAppName); //启动多线程
    int dwRet = GetLastError();
    if (hMutex)
    {
        if (dwRet == ERROR_ALREADY_EXISTS)
        {
            MessageBox(NULL, "Program is already runing.", "Oops!", MB_OK | MB_ICONINFORMATION);
            CloseHandle(hMutex);
            return FALSE;
        }
    }
    wndclass.style=0;
    wndclass.lpfnWndProc=(WNDPROC)WndProc;
    wndclass.cbClsExtra=0;
    wndclass.cbWndExtra=0;
    wndclass.hInstance=hInstance;
    wndclass.hIcon=NULL;
    wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);
    wndclass.lpszMenuName=NULL;
    wndclass.lpszClassName=(LPSTR)szAppName;

    if(!RegisterClass(&wndclass))
        return FALSE;
    if (!FileExists("\\ShortCuts.txt"))
    {
        MessageBox(NULL, "Missing file: cannot load shortcut settings file.(Shortcuts.txt)", "ERROR",MB_OK|MB_ICONINFORMATION);
        exit(1);
    }
    if (!InstallHook(TRUE))
        exit(1);

    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

这是钩子程序的代码:

// Hook- a project to create the DLL and LIB files.
// Microsoft Visual C++ 6.0 and above steps:
// 1. Create a new Win32 Dynamic Link - Library project.
// 2. Add hook.cpp and hook.h to the project.
// 3. There is no step 3 :-). Just build your project and you will find
// a Hook.dll and Hook.lib file in your map.

#include <windows.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <ctime>
#include <map>
#include <process.h>
using namespace std;


HHOOK hHook;
HINSTANCE ghDLLInst=0;
const char startChar = ';';
bool bChecking = false;
string cmd;
typedef map<string,string> COMMANDMAP;
COMMANDMAP mShortcut;
string logfilename="log.txt";
ofstream LOG;

__declspec(dllexport)int InstallHook(BOOL bCode);

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwFunction, LPVOID lpNot)
{
    ghDLLInst=(HINSTANCE)hModule;
    return TRUE;
}

DWORD WINAPI Runsystem(LPVOID lpParam)
{
    WinExec((LPCSTR)lpParam, SW_SHOW);
}

string gettime()
{
    time_t curTime;
    struct tm *locTime;
    char buf[80];
    time(&curTime);
    locTime=localtime(&curTime);
    strftime(buf,80,"%Y-%m-%d %H:%M:%S",locTime);
    string s=buf;
    return s;
}

ostream& tout()
{
    return LOG<< gettime()<< ": ";
}

void StartCheck()
{
    bChecking=true;
    cmd.clear();
}
void EndCheck()
{
    bChecking=false;
    cmd.clear();
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{

    if ((wParam == WM_KEYDOWN) && (nCode >= HC_ACTION))                         // Only record when key pressed
    {
    KBDLLHOOKSTRUCT *pStruct = (KBDLLHOOKSTRUCT*)lParam;
    switch (pStruct->vkCode)
    {
        case VK_RETURN:
        {
            if (bChecking)
            {
            COMMANDMAP::iterator it;
            it=mShortcut.find(cmd);
            if (it!=mShortcut.end())
            {
                tout()<<"received command \'"<<cmd<<"\', executing \'"<<it->second.c_str()<<endl;
                CreateThread(NULL, 0, Runsystem, (void*)it->second.c_str(),0,NULL);
            }
            else {
                tout()<<"received command \'" <<cmd<<"\', no matching."<<endl;
            }
            }
            EndCheck();
            break;
        }
        case VK_F7:
        {
            InstallHook(false);
            break;
        }
        default:            // Normal keys, convert them
        {
            BYTE KeyboardState[256];
            GetKeyboardState(KeyboardState);
            WORD CharValue;
            if(ToAscii(pStruct->vkCode, pStruct->scanCode,KeyboardState,&CharValue,0) > 0)      // Convert to char.
            {
            char character=char(CharValue);
//          tout()<<"received keyCode: "<<pStruct->vkCode<< " char: "<< character<<endl;
            if (bChecking)
            {
                cmd+=character;
            }
            if (!bChecking && (character == startChar))
            {
//              tout()<<"Start checking..."<<endl;
                StartCheck();
            }
            }
            break;
        }
    }
    }
    return (int)CallNextHookEx(hHook, nCode, wParam, lParam);
}

bool readline(ifstream &fin,string &sline)
{
    do
    {
    getline(fin,sline);
    } while (!fin.eof() && ((sline[0]=='/' && sline[1]=='/') || sline.empty()));

    return fin.eof()?false:true;
}

// __declspec(dllexport) means that this function must be exported to a dll file.
__declspec(dllexport)int InstallHook(BOOL bCode)
{
    if(bCode)
    {
    // initialize shortcuts
    ifstream fin;
    LOG.open(logfilename.c_str(),ios_base::app);
    tout()<<"Reading config file."<<endl;
    fin.open("ShortCuts.txt");
    if (fin)
    {
        string scmd,spath;
        char oneline[256];
        while(readline(fin,scmd)&&readline(fin,spath))
        {
        mShortcut[scmd]=spath;
//      LOG<<scmd<<','<<spath<<endl;
        }
        fin.close();
        tout()<<"OK, "<<mShortcut.size()<<" shortcuts loaded."<<endl;
    }
    else
    {
        tout()<<"ERROR"<<endl;
        LOG.close();
        exit(0);
    }


    hHook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc,   // Start the keyboard hook.
        (HINSTANCE)GetModuleHandle(NULL), NULL);

    if(!hHook)
    {
        tout()<<"Install hook failed."<<endl;
        return 0;
    }
    else
    {
        tout()<<"Install hook successful."<<endl;
        return 1;
    }
    }
    else
    {
    if (MessageBox(NULL,"Are you sure to exit KeyShortcut?","Exit",MB_YESNO|MB_ICONWARNING)==IDYES)
    {
        tout()<<"Uninstall hook successful."<<endl;
        LOG.close();
        return UnhookWindowsHookEx(hHook); // Unhook the keyboardhook.
    }
    }
}

例如,您可以使用RegisterHotKey API函数将自己的热键设置为系统,然后在程序中处理此热键的消息(无窗口)

补充:如果您想从一个进程向另一个进程发送退出消息,那么您的朋友就是PostThreadMessage(dwThreadId,WM_DESTROY,0,0);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM