【发布时间】:2015-07-23 23:50:07
【问题描述】:
如何从 Qt/Windows 代码中等待然后捕获外部进程的工作目录(可能尚未运行)?
【问题讨论】:
如何从 Qt/Windows 代码中等待然后捕获外部进程的工作目录(可能尚未运行)?
【问题讨论】:
我以前做过类似的事情,这里是相关部分。只是为了展示它是如何工作的。
WaitForProcess 类将每刷新毫秒搜索 exe,作为参数传递给start。
如果你使用这个sn-p,并启动notepad.exe,它将在控制台中显示它的路径。一旦你有了这些信息,你就可以发出一个信号或任何你喜欢的东西。
main.cpp
#include <QApplication>
#include "waitforprocess.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
WaitForProcess wfp;
wfp.start("notepad.exe", 1000);
return a.exec();
}
waitforprocess.h
#ifndef WAITFORPROCESS_H
#define WAITFORPROCESS_H
#include <QObject>
#include <QString>
#include <QTimer>
class WaitForProcess : public QObject
{
Q_OBJECT
public:
explicit WaitForProcess(QObject *parent = 0);
~WaitForProcess();
signals:
public slots:
void start(const QString& processName, int refresh);
private slots:
void onTimeout();
private:
QString _processName;
QTimer* _timer;
bool FindWin32Process();
};
#endif // WAITFORPROCESS_H
waitforprocess.cpp
#include "waitforprocess.h"
#include <Windows.h>
#include <TlHelp32.h>
#include <QFileInfo>
#include <QDebug>
WaitForProcess::WaitForProcess(QObject *parent) : QObject(parent)
{
_timer = new QTimer(this);
connect(_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
WaitForProcess::~WaitForProcess()
{
}
void WaitForProcess::onTimeout()
{
if(FindWin32Process()) {
_timer->stop();
}
}
void WaitForProcess::start(const QString& processName, int refresh)
{
_processName = processName;
_timer->start(refresh);
}
std::string utf8_encode(const std::wstring &wstr)
{
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo( size_needed, 0 );
WideCharToMultiByte (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
bool WaitForProcess::FindWin32Process()
{
QString otherProcess;
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return false;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
// clean the snapshot object
CloseHandle(hProcessSnap);
return false;
}
// loop through all running processes looking for process
do
{
otherProcess = QString(utf8_encode(std::wstring(pe32.szExeFile)).c_str());
if (_processName.compare(otherProcess)==0)
{
// Find Path
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
wchar_t lpExeName[1024];
DWORD lpdwSize = 1024;
if(hProcess != NULL)
{
QueryFullProcessImageName(hProcess, 0, lpExeName, &lpdwSize);
QString fullPath = QString(utf8_encode(std::wstring(lpExeName)).c_str());
// HERE I'VE FOUND THE PATH OF THE EXE
QFileInfo info(fullPath);
QString path = info.path();
QString name = info.fileName();
qDebug() << "Found: " << name;
qDebug() << "PATH: " << path;
}
// clean the snapshot object
CloseHandle(hProcess);
CloseHandle(hProcessSnap);
return true;
}
} while(Process32Next(hProcessSnap, &pe32));
// clean the snapshot object
CloseHandle(hProcessSnap);
return false;
}
【讨论】:
您可以使用 Qprocess 以编程方式运行 vbs/batch (.bat) 文件..
【讨论】:
好的,我最后解决的方法如下:
void Widget::waitForExe() //#
{
HWND hWnd;
do{
hWnd = ::FindWindow(NULL, L"TARGETWINDOW!");
}while(!hWnd);
// will loop a goto FindWindow() till hWnd captured (window opened/found)
// better use above in another thread as it will freeze the GUI otherwise.
qDebug() << "target window found in waitForExe()";
DWORD pid = 0x0;
GetWindowThreadProcessId( hWnd, &PID );
qDebug() << "PID: " << pid;
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,pid);
if(handle == 0)
qDebug()<<"no handle after openProcess() :(";
else{
wchar_t exe_path[2048] = {};
if (GetModuleFileNameEx(handle, 0, exe_path, sizeof(exe_path)-1))
qDebug() << "exe_path" << QString::fromWCharArray(exe_path);
else
qDebug() << "GetModuleFileNameEx() failed: " << GetLastError();
CloseHandle(handle);
}
}
【讨论】: