Commit a6600a2d authored by Thomas Hartmann's avatar Thomas Hartmann Committed by hjk
Browse files

Add support for Windows in LocalProcessList



The call to handleWindowsUpdate is asynchronous to keep a
unified behaivour.

Change-Id: I2e422a203955aa84317f29531f6c259dc3ab823c
Reviewed-by: default avatarhjk <qthjk@ovi.com>
parent 33f37b43
......@@ -29,6 +29,7 @@
#include "localprocesslist.h"
#include <QLibrary>
#include <QProcess>
#include <QTimer>
......@@ -40,24 +41,79 @@
#include <signal.h>
#endif
#ifdef Q_OS_WIN
// Enable Win API of XP SP1 and later
#define _WIN32_WINNT 0x0502
#include <windows.h>
#include <utils/winutils.h>
#include <tlhelp32.h>
#include <psapi.h>
#endif // Q_OS_WIN
namespace ProjectExplorer {
namespace Internal {
const int PsFieldWidth = 50;
#ifdef Q_OS_WIN
// Resolve QueryFullProcessImageNameW out of kernel32.dll due
// to incomplete MinGW import libs and it not being present
// on Windows XP.
static BOOL queryFullProcessImageName(HANDLE h, DWORD flags, LPWSTR buffer, DWORD *size)
{
// Resolve required symbols from the kernel32.dll
typedef BOOL (WINAPI *QueryFullProcessImageNameWProtoType)
(HANDLE, DWORD, LPWSTR, PDWORD);
static QueryFullProcessImageNameWProtoType queryFullProcessImageNameW = 0;
if (!queryFullProcessImageNameW) {
QLibrary kernel32Lib(QLatin1String("kernel32.dll"), 0);
if (kernel32Lib.isLoaded() || kernel32Lib.load())
queryFullProcessImageNameW = (QueryFullProcessImageNameWProtoType)kernel32Lib.resolve("QueryFullProcessImageNameW");
}
if (!queryFullProcessImageNameW)
return FALSE;
// Read out process
return (*queryFullProcessImageNameW)(h, flags, buffer, size);
}
static QString imageName(DWORD processId)
{
QString rc;
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, processId);
if (handle == INVALID_HANDLE_VALUE)
return rc;
WCHAR buffer[MAX_PATH];
DWORD bufSize = MAX_PATH;
if (queryFullProcessImageName(handle, 0, buffer, &bufSize))
rc = QString::fromUtf16(reinterpret_cast<const ushort*>(buffer));
CloseHandle(handle);
return rc;
}
#endif //Q_OS_WIN
LocalProcessList::LocalProcessList(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcessList(device, parent),
m_psProcess(new QProcess(this))
{
#ifdef Q_OS_UNIX
connect(m_psProcess, SIGNAL(error(QProcess::ProcessError)), SLOT(handlePsError()));
connect(m_psProcess, SIGNAL(finished(int)), SLOT(handlePsFinished()));
#endif //Q_OS_UNIX
}
void LocalProcessList::doUpdate()
{
#ifdef Q_OS_UNIX
// We assume Desktop Unix systems to have a POSIX-compliant ps.
// We need the padding because the command field can contain spaces, so we cannot split on those.
m_psProcess->start(QString::fromLocal8Bit("ps -e -o pid=%1 -o comm=%1 -o args=%1")
.arg(QString(PsFieldWidth, QChar('x'))));
#endif
#ifdef Q_OS_WIN
QTimer::singleShot(0, this, SLOT(handleWindowsUpdate()));
#endif
}
void LocalProcessList::handlePsFinished()
......@@ -95,6 +151,30 @@ void LocalProcessList::handlePsFinished()
reportError(errorString);
}
void LocalProcessList::handleWindowsUpdate()
{
QList<DeviceProcess> processes;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE)
return;
for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
DeviceProcess p;
p.pid = pe.th32ProcessID;
p.exe = QString::fromUtf16(reinterpret_cast<ushort*>(pe.szExeFile));
p.cmdLine = imageName(pe.th32ProcessID);
if (p.cmdLine.isEmpty())
p.cmdLine = p.exe;
processes << p;
}
CloseHandle(snapshot);
reportProcessListUpdated(processes);
}
void LocalProcessList::handlePsError()
{
// Other errors are handled in the finished() handler.
......
......@@ -51,6 +51,7 @@ public:
private slots:
void handlePsError();
void handlePsFinished();
void handleWindowsUpdate();
void reportDelayedKillStatus();
private:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment