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 #include <QtCore/QList> 00041 #include <QtCore/QtDebug> 00042 00043 static PPERF_OBJECT_TYPE FirstObject( PPERF_DATA_BLOCK PerfData ) 00044 { 00045 return (PPERF_OBJECT_TYPE)( (PBYTE)PerfData + PerfData->HeaderLength ); 00046 } 00047 00048 static PPERF_INSTANCE_DEFINITION FirstInstance( PPERF_OBJECT_TYPE PerfObj ) 00049 { 00050 return (PPERF_INSTANCE_DEFINITION)( (PBYTE)PerfObj + PerfObj->DefinitionLength ); 00051 } 00052 00053 static PPERF_OBJECT_TYPE NextObject( PPERF_OBJECT_TYPE PerfObj ) 00054 { 00055 return (PPERF_OBJECT_TYPE)( (PBYTE)PerfObj + PerfObj->TotalByteLength ); 00056 } 00057 00058 static PPERF_COUNTER_DEFINITION FirstCounter( PPERF_OBJECT_TYPE PerfObj ) 00059 { 00060 return (PPERF_COUNTER_DEFINITION) ( (PBYTE)PerfObj + PerfObj->HeaderLength ); 00061 } 00062 00063 static PPERF_INSTANCE_DEFINITION NextInstance( PPERF_INSTANCE_DEFINITION PerfInst ) 00064 { 00065 PPERF_COUNTER_BLOCK PerfCntrBlk = 00066 (PPERF_COUNTER_BLOCK)( (PBYTE)PerfInst + PerfInst->ByteLength ); 00067 return (PPERF_INSTANCE_DEFINITION)( (PBYTE)PerfCntrBlk + PerfCntrBlk->ByteLength ); 00068 } 00069 00070 static PPERF_COUNTER_DEFINITION NextCounter( PPERF_COUNTER_DEFINITION PerfCntr ) 00071 { 00072 return (PPERF_COUNTER_DEFINITION)( (PBYTE)PerfCntr + PerfCntr->ByteLength ); 00073 } 00074 00075 static PPERF_COUNTER_BLOCK CounterBlock( PPERF_INSTANCE_DEFINITION PerfInst ) 00076 { 00077 return (PPERF_COUNTER_BLOCK) ( (LPBYTE) PerfInst + PerfInst->ByteLength ); 00078 } 00079 00080 #define GETPID_TOTAL 64 * 1024 00081 #define GETPID_BYTEINCREMENT 1024 00082 #define GETPID_PROCESS_OBJECT_INDEX 230 00083 #define GETPID_PROC_ID_COUNTER 784 00084 00085 static QString fromWChar( const wchar_t *string, int size = -1 ) 00086 { 00087 return ( sizeof(wchar_t) == sizeof(QChar) ) ? 00088 QString::fromUtf16( (ushort *)string, size ) 00089 : QString::fromUcs4( (uint *)string, size ); 00090 } 00091 00092 void KPIMUtils::getProcessesIdForName( const QString &processName, QList<int> &pids ) 00093 { 00094 qDebug() << "KPIMUtils::getProcessesIdForName" << processName; 00095 PPERF_OBJECT_TYPE perfObject; 00096 PPERF_INSTANCE_DEFINITION perfInstance; 00097 PPERF_COUNTER_DEFINITION perfCounter, curCounter; 00098 PPERF_COUNTER_BLOCK counterPtr; 00099 DWORD bufSize = GETPID_TOTAL; 00100 PPERF_DATA_BLOCK perfData = (PPERF_DATA_BLOCK) malloc( bufSize ); 00101 00102 char key[64]; 00103 sprintf( key,"%d %d", GETPID_PROCESS_OBJECT_INDEX, GETPID_PROC_ID_COUNTER ); 00104 LONG lRes; 00105 while ( ( lRes = RegQueryValueExA( HKEY_PERFORMANCE_DATA, 00106 key, 00107 0, 00108 0, 00109 (LPBYTE) perfData, 00110 &bufSize ) ) == ERROR_MORE_DATA ) { 00111 // get a buffer that is big enough 00112 bufSize += GETPID_BYTEINCREMENT; 00113 perfData = (PPERF_DATA_BLOCK) realloc( perfData, bufSize ); 00114 } 00115 00116 // Get the first object type. 00117 perfObject = FirstObject( perfData ); 00118 if ( !perfObject ) { 00119 return; 00120 } 00121 00122 // Process all objects. 00123 for ( uint i = 0; i < perfData->NumObjectTypes; i++ ) { 00124 if ( perfObject->ObjectNameTitleIndex != GETPID_PROCESS_OBJECT_INDEX ) { 00125 perfObject = NextObject( perfObject ); 00126 continue; 00127 } 00128 pids.clear(); 00129 perfCounter = FirstCounter( perfObject ); 00130 perfInstance = FirstInstance( perfObject ); 00131 // retrieve the instances 00132 qDebug() << "INSTANCES: " << perfObject->NumInstances; 00133 for ( int instance = 0; instance < perfObject->NumInstances; instance++ ) { 00134 curCounter = perfCounter; 00135 const QString foundProcessName( 00136 fromWChar( ( wchar_t * )( (PBYTE)perfInstance + perfInstance->NameOffset ) ) ); 00137 qDebug() << "foundProcessName: " << foundProcessName; 00138 if ( foundProcessName == processName ) { 00139 // retrieve the counters 00140 for ( uint counter = 0; counter < perfObject->NumCounters; counter++ ) { 00141 if ( curCounter->CounterNameTitleIndex == GETPID_PROC_ID_COUNTER ) { 00142 counterPtr = CounterBlock( perfInstance ); 00143 DWORD *value = (DWORD*)( (LPBYTE) counterPtr + curCounter->CounterOffset ); 00144 pids.append( int( *value ) ); 00145 qDebug() << "found PID: " << int( *value ); 00146 break; 00147 } 00148 curCounter = NextCounter( curCounter ); 00149 } 00150 } 00151 perfInstance = NextInstance( perfInstance ); 00152 } 00153 } 00154 free( perfData ); 00155 RegCloseKey( HKEY_PERFORMANCE_DATA ); 00156 } 00157 00158 bool KPIMUtils::otherProcessesExist( const QString &processName ) 00159 { 00160 QList<int> pids; 00161 getProcessesIdForName( processName, pids ); 00162 int myPid = getpid(); 00163 foreach ( int pid, pids ) { 00164 if ( myPid != pid ) { 00165 // kDebug() << "Process ID is " << pid; 00166 return true; 00167 } 00168 } 00169 return false; 00170 } 00171 00172 bool KPIMUtils::killProcesses( const QString &processName ) 00173 { 00174 QList<int> pids; 00175 getProcessesIdForName( processName, pids ); 00176 if ( pids.empty() ) { 00177 return true; 00178 } 00179 00180 qWarning() << "Killing process \"" << processName << " (pid=" << pids[0] << ").."; 00181 int overallResult = 0; 00182 foreach ( int pid, pids ) { 00183 int result = kill( pid, SIGTERM ); 00184 if ( result == 0 ) { 00185 continue; 00186 } 00187 result = kill( pid, SIGKILL ); 00188 if ( result != 0 ) { 00189 overallResult = result; 00190 } 00191 } 00192 return overallResult == 0; 00193 } 00194 00195 struct EnumWindowsStruct 00196 { 00197 EnumWindowsStruct() : windowId( 0 ) {} 00198 int pid; 00199 HWND windowId; 00200 }; 00201 00202 BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam ) 00203 { 00204 if ( GetWindowLong( hwnd, GWL_STYLE ) & WS_VISIBLE ) { 00205 00206 DWORD pidwin; 00207 00208 GetWindowThreadProcessId( hwnd, &pidwin ); 00209 if ( pidwin == ( (EnumWindowsStruct *)lParam )->pid ) { 00210 ( (EnumWindowsStruct *)lParam )->windowId = hwnd; 00211 return FALSE; //krazy:exclude=captruefalse 00212 } 00213 } 00214 return TRUE; //krazy:exclude=captruefalse 00215 } 00216 00217 void KPIMUtils::activateWindowForProcess( const QString &executableName ) 00218 { 00219 QList<int> pids; 00220 KPIMUtils::getProcessesIdForName( executableName, pids ); 00221 int myPid = getpid(); 00222 int foundPid = 0; 00223 foreach ( int pid, pids ) { 00224 if ( myPid != pid ) { 00225 qDebug() << "activateWindowForProcess(): PID to activate:" << pid; 00226 foundPid = pid; 00227 break; 00228 } 00229 } 00230 if ( foundPid == 0 ) { 00231 return; 00232 } 00233 EnumWindowsStruct winStruct; 00234 winStruct.pid = foundPid; 00235 EnumWindows( EnumWindowsProc, (LPARAM)&winStruct ); 00236 if ( winStruct.windowId == 0 ) { 00237 return; 00238 } 00239 SetForegroundWindow( winStruct.windowId ); 00240 } 00241 00242 #endif // Q_WS_WIN