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

时间:2015-03-22 01:28:38

标签: c++ windows keyboard-hook

我是C ++的新手,我自己制作了一个程序,可以通过在键盘上输入命令来启动程序。为了能够随时启动程序,我决定设置一个低级键盘钩,它可以跟踪击键并在检测到特定命令时启动特定程序。简单的windows程序用于安装钩子,窗口没有显示,因为我需要的是在后台监听的钩子。

到目前为止,它工作正常,但是,这个小问题但是我必须通过Windows任务管理器来终止程序,这非常不方便。我已经设法通过按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.
    }
    }
}

1 个答案:

答案 0 :(得分:0)

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

<强>加了: 如果您想将退出消息从一个进程发送到另一个进程,那么您的朋友是PostThreadMessage(dwThreadId, WM_DESTROY, 0, 0);