kpimutils
processes.cpp
Go to the documentation of this file.00001
00029 #include "processes.h"
00030 using namespace KPIMUtils;
00031
00032 #ifdef Q_WS_WIN
00033
00034 #include <windows.h>
00035 #include <winperf.h>
00036 #include <psapi.h>
00037 #include <signal.h>
00038 #include <unistd.h>
00039
00040 #ifdef _WIN32_WCE
00041 #include <Tlhelp32.h>
00042 #endif
00043
00044 #include <QtCore/QList>
00045 #include <QtCore/QtDebug>
00046
00047 static PPERF_OBJECT_TYPE FirstObject( PPERF_DATA_BLOCK PerfData )
00048 {
00049 return (PPERF_OBJECT_TYPE)( (PBYTE)PerfData + PerfData->HeaderLength );
00050 }
00051
00052 static PPERF_INSTANCE_DEFINITION FirstInstance( PPERF_OBJECT_TYPE PerfObj )
00053 {
00054 return (PPERF_INSTANCE_DEFINITION)( (PBYTE)PerfObj + PerfObj->DefinitionLength );
00055 }
00056
00057 static PPERF_OBJECT_TYPE NextObject( PPERF_OBJECT_TYPE PerfObj )
00058 {
00059 return (PPERF_OBJECT_TYPE)( (PBYTE)PerfObj + PerfObj->TotalByteLength );
00060 }
00061
00062 static PPERF_COUNTER_DEFINITION FirstCounter( PPERF_OBJECT_TYPE PerfObj )
00063 {
00064 return (PPERF_COUNTER_DEFINITION) ( (PBYTE)PerfObj + PerfObj->HeaderLength );
00065 }
00066
00067 static PPERF_INSTANCE_DEFINITION NextInstance( PPERF_INSTANCE_DEFINITION PerfInst )
00068 {
00069 PPERF_COUNTER_BLOCK PerfCntrBlk =
00070 (PPERF_COUNTER_BLOCK)( (PBYTE)PerfInst + PerfInst->ByteLength );
00071 return (PPERF_INSTANCE_DEFINITION)( (PBYTE)PerfCntrBlk + PerfCntrBlk->ByteLength );
00072 }
00073
00074 static PPERF_COUNTER_DEFINITION NextCounter( PPERF_COUNTER_DEFINITION PerfCntr )
00075 {
00076 return (PPERF_COUNTER_DEFINITION)( (PBYTE)PerfCntr + PerfCntr->ByteLength );
00077 }
00078
00079 static PPERF_COUNTER_BLOCK CounterBlock( PPERF_INSTANCE_DEFINITION PerfInst )
00080 {
00081 return (PPERF_COUNTER_BLOCK) ( (LPBYTE) PerfInst + PerfInst->ByteLength );
00082 }
00083
00084 #define GETPID_TOTAL 64 * 1024
00085 #define GETPID_BYTEINCREMENT 1024
00086 #define GETPID_PROCESS_OBJECT_INDEX 230
00087 #define GETPID_PROC_ID_COUNTER 784
00088
00089 static QString fromWChar( const wchar_t *string, int size = -1 )
00090 {
00091 return ( sizeof(wchar_t) == sizeof(QChar) ) ?
00092 QString::fromUtf16( (ushort *)string, size )
00093 : QString::fromUcs4( (uint *)string, size );
00094 }
00095
00096 void KPIMUtils::getProcessesIdForName( const QString &processName, QList<int> &pids )
00097 {
00098 qDebug() << "KPIMUtils::getProcessesIdForName" << processName;
00099 #ifndef _WIN32_WCE
00100 PPERF_OBJECT_TYPE perfObject;
00101 PPERF_INSTANCE_DEFINITION perfInstance;
00102 PPERF_COUNTER_DEFINITION perfCounter, curCounter;
00103 PPERF_COUNTER_BLOCK counterPtr;
00104 DWORD bufSize = GETPID_TOTAL;
00105 PPERF_DATA_BLOCK perfData = (PPERF_DATA_BLOCK) malloc( bufSize );
00106
00107 char key[64];
00108 sprintf( key,"%d %d", GETPID_PROCESS_OBJECT_INDEX, GETPID_PROC_ID_COUNTER );
00109 LONG lRes;
00110 while ( ( lRes = RegQueryValueExA( HKEY_PERFORMANCE_DATA,
00111 key,
00112 0,
00113 0,
00114 (LPBYTE) perfData,
00115 &bufSize ) ) == ERROR_MORE_DATA ) {
00116
00117 bufSize += GETPID_BYTEINCREMENT;
00118 perfData = (PPERF_DATA_BLOCK) realloc( perfData, bufSize );
00119 }
00120
00121
00122 perfObject = FirstObject( perfData );
00123 if ( !perfObject ) {
00124 return;
00125 }
00126
00127
00128 for ( uint i = 0; i < perfData->NumObjectTypes; i++ ) {
00129 if ( perfObject->ObjectNameTitleIndex != GETPID_PROCESS_OBJECT_INDEX ) {
00130 perfObject = NextObject( perfObject );
00131 continue;
00132 }
00133 pids.clear();
00134 perfCounter = FirstCounter( perfObject );
00135 perfInstance = FirstInstance( perfObject );
00136
00137 qDebug() << "INSTANCES: " << perfObject->NumInstances;
00138 for ( int instance = 0; instance < perfObject->NumInstances; instance++ ) {
00139 curCounter = perfCounter;
00140 const QString foundProcessName(
00141 fromWChar( ( wchar_t * )( (PBYTE)perfInstance + perfInstance->NameOffset ) ) );
00142 qDebug() << "foundProcessName: " << foundProcessName;
00143 if ( foundProcessName == processName ) {
00144
00145 for ( uint counter = 0; counter < perfObject->NumCounters; counter++ ) {
00146 if ( curCounter->CounterNameTitleIndex == GETPID_PROC_ID_COUNTER ) {
00147 counterPtr = CounterBlock( perfInstance );
00148 DWORD *value = (DWORD*)( (LPBYTE) counterPtr + curCounter->CounterOffset );
00149 pids.append( int( *value ) );
00150 qDebug() << "found PID: " << int( *value );
00151 break;
00152 }
00153 curCounter = NextCounter( curCounter );
00154 }
00155 }
00156 perfInstance = NextInstance( perfInstance );
00157 }
00158 }
00159 free( perfData );
00160 RegCloseKey( HKEY_PERFORMANCE_DATA );
00161 #else
00162 HANDLE h;
00163 PROCESSENTRY32 pe32;
00164
00165 h = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
00166 if ( h == INVALID_HANDLE_VALUE ) {
00167 return;
00168 }
00169 pe32.dwSize = sizeof(PROCESSENTRY32);
00170 if ( !Process32First( h, &pe32 ) ) {
00171 return;
00172 }
00173 pids.clear();
00174 do
00175 {
00176 if ( QString::fromWCharArray( pe32.szExeFile ) == processName ) {
00177 pids.append( (int)pe32.th32ProcessID );
00178 qDebug() << "found PID: " << (int)pe32.th32ProcessID;
00179 }
00180
00181 } while( Process32Next( h, &pe32 ) );
00182 CloseToolhelp32Snapshot(h);
00183 #endif
00184 }
00185
00186 bool KPIMUtils::otherProcessesExist( const QString &processName )
00187 {
00188 QList<int> pids;
00189 getProcessesIdForName( processName, pids );
00190 int myPid = getpid();
00191 foreach ( int pid, pids ) {
00192 if ( myPid != pid ) {
00193
00194 return true;
00195 }
00196 }
00197 return false;
00198 }
00199
00200 bool KPIMUtils::killProcesses( const QString &processName )
00201 {
00202 QList<int> pids;
00203 getProcessesIdForName( processName, pids );
00204 if ( pids.empty() ) {
00205 return true;
00206 }
00207
00208 qWarning() << "Killing process \"" << processName << " (pid=" << pids[0] << ")..";
00209 int overallResult = 0;
00210 foreach ( int pid, pids ) {
00211 int result;
00212 #ifndef _WIN32_WCE
00213 result = kill( pid, SIGTERM );
00214 if ( result == 0 ) {
00215 continue;
00216 }
00217 #endif
00218 result = kill( pid, SIGKILL );
00219 if ( result != 0 ) {
00220 overallResult = result;
00221 }
00222 }
00223 return overallResult == 0;
00224 }
00225
00226 struct EnumWindowsStruct
00227 {
00228 EnumWindowsStruct() : windowId( 0 ) {}
00229 int pid;
00230 HWND windowId;
00231 };
00232
00233 BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
00234 {
00235 if ( GetWindowLong( hwnd, GWL_STYLE ) & WS_VISIBLE ) {
00236
00237 DWORD pidwin;
00238
00239 GetWindowThreadProcessId( hwnd, &pidwin );
00240 if ( pidwin == ( (EnumWindowsStruct *)lParam )->pid ) {
00241 ( (EnumWindowsStruct *)lParam )->windowId = hwnd;
00242 return FALSE;
00243 }
00244 }
00245 return TRUE;
00246 }
00247
00248 void KPIMUtils::activateWindowForProcess( const QString &executableName )
00249 {
00250 QList<int> pids;
00251 KPIMUtils::getProcessesIdForName( executableName, pids );
00252 int myPid = getpid();
00253 int foundPid = 0;
00254 foreach ( int pid, pids ) {
00255 if ( myPid != pid ) {
00256 qDebug() << "activateWindowForProcess(): PID to activate:" << pid;
00257 foundPid = pid;
00258 break;
00259 }
00260 }
00261 if ( foundPid == 0 ) {
00262 return;
00263 }
00264 EnumWindowsStruct winStruct;
00265 winStruct.pid = foundPid;
00266 EnumWindows( EnumWindowsProc, (LPARAM)&winStruct );
00267 if ( winStruct.windowId == 0 ) {
00268 return;
00269 }
00270 SetForegroundWindow( winStruct.windowId );
00271 }
00272
00273 #endif // Q_WS_WIN