Hola, espero me puedan ayudar necesito hacer una mini aplicación en C++ que me muestre todos los procesos que están activos en windows y los servicios que usa cada proceso algo así como lo que hace el process explorer según he investigado la forma de poder lograrlo es por el WMI pero no he podido encontrar mucha información encontré un código en C++ donde hacen la conexión COM y verifican el nombre de la computadora no se si alguien me puede decir si este código me sirve y que líneas puedo agregar para que me consulte los procesos y los servicios asociados a cada proceso.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
int main(int argc, char **argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_OperatingSystem"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
wcout << " OS Name : " << vtProp.bstrVal << endl;
VariantClear(&vtProp);
pclsObj->Release();
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
pclsObj->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
No hace falta WMI.
CreateToolhelp32Snapshot
Process32First
Process32Next
CloseHandle
Ejemplo de MSDN:
Taking a Snapshot and Viewing Processes (http://msdn.microsoft.com/en-us/library/windows/desktop/ms686701(v=vs.85).aspx)
Hola Eternal Idol estaba viendo el link que pones utiliza la función GetProcessList pero tanbién me mostrará los procesos que son propios del sistema operativo como por ejemplo svchost.exe y como puedo saber los servicios asociados a cada proceso?
Mira EnumServicesStatusEx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682640(v=vs.85).aspx).
PD. GetProcessList es parte del ejemplo, las funciones que usa son las que puse antes.
Disculpa Eternal Idol como podría hacer para vicular cada proceso que me devuelve GetProcessList a su respectivo servicios
Esta en la documentacion:
The lpServices parameter is a pointer to a buffer that receives an array of ENUM_SERVICE_STATUS_PROCESS structures.
typedef struct _ENUM_SERVICE_STATUS_PROCESS {
LPTSTR lpServiceName;
LPTSTR lpDisplayName;
SERVICE_STATUS_PROCESS ServiceStatusProcess;
} ENUM_SERVICE_STATUS_PROCESS, *LPENUM_SERVICE_STATUS_PROCESS;
typedef struct _SERVICE_STATUS_PROCESS {
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
DWORD dwProcessId;
DWORD dwServiceFlags;
} SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;
Hola Eternal Idol podrías ayudarme con algún ejemplo para utilizar la función EnumServicesStatusEx
Siguiendo exactamente la misma logica que con GetExtendedTcpTable (comproba los valores de retorno, libera la memoria, cerra el SC_HANDLE, etc. en este extracto de ejemplo no se hace):
SC_HANDLE scm = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE);
DWORD bSize = 0;
DWORD services = 0;
EnumServicesStatusEx(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, NULL, bSize, &bSize, &services, 0, 0);
LPBYTE sdata = new BYTE[bSize];
EnumServicesStatusEx(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, sdata, bSize, &bSize, &services, 0, 0);
LPENUM_SERVICE_STATUS_PROCESS service = (LPENUM_SERVICE_STATUS_PROCESS)sdata;
for (int x = 0; x < services; ++x)
{
cout << service->lpServiceName << " (" << service->lpDisplayName << ") pid: " << service->ServiceStatusProcess.dwProcessId << endl;
++service;
}
...
Gracias Eternal disculpa, y para obtener el string del lpServiceName osea guardarlo en una variable
string sname = service->lpServiceName;
Hola Eternal retomando este tema tengo una consulta sabes si hay alguna manera de saber el nombre del dll que usa un servicio determinado, no he podido encontrar nada referente a esto por ejemplo para el svchost.exe este utiliza diversos servicios digamos el SessionEnv tenemos el nombre del servicio y el display name pero para saber el dll asociado a este servicio que para este servicio sería sessenv.dll hay alguna función que me permita saber el dll de este servicio?
No se, tal vez haya una funcion en la API de Windows, fijate:
Service Reference (http://msdn.microsoft.com/en-us/library/windows/desktop/ms685974(v=vs.85).aspx)
Sino de acuerdo a:
http://en.wikipedia.org/wiki/Svchost
Services run in SvcHost are implemented as dynamically-linked libraries (DLLs). Such service's registry key must have a value named ServiceDll under the Parameters subkey, pointing to the respective service's DLL file.
Hola Eternal Idol otra vez retomando el tema pues buscando en la documentación MSDN hay una función que sirve para mi cometido pero al ejecutar la función esta falla y no he podido encontrar donde está el error, se compila bien y todo pero no devuelve nada pongo el código si me haces el favor de darle una revisión puedas ver que he hecho mal.
hscManager = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE);
while( EnumServicesStatusEx( hscManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, service, bufSize,
&bufSize, &numOfService, 0, 0) == 0 )
delete [] service, service = new BYTE[bufSize *= 2];
LPENUM_SERVICE_STATUS_PROCESS services = (LPENUM_SERVICE_STATUS_PROCESS) service;
for(int i = 0; i < numOfService; i++){
val.pid = services->ServiceStatusProcess.dwProcessId;
CopyString(services->lpServiceName, val.service, MAX_PATH);
GetServiceDisplayName (hscManager, services->lpServiceName, NULL, &buffer);
if (buffer)
{
lpDisplayName = new TCHAR[buffer +1];
ZeroMemory (lpDisplayName, buffer + 1);
if (GetServiceDisplayName (hscManager, services->lpServiceName, lpDisplayName, &buffer))
{
CopyString (lpDisplayName, displayName, MAX_PATH);
}
}
services++;
initialRunxes->push_back(val);
}
el problema es en la función GetServiceDisplayName que no me devuelve el valor de lpDisplayName nunca entra en el If lo que significa que esta fallando la función no se si he definido mal los parámetros o que pasa.
De base no tenes ninguna necesidad de hacer esto, en services->lpDisplayName ya tenes lo que buscas. En cuanto al problema en si tal vez se deba a que buffer no es 0 en el momento de la primera llamada, depuralo, fijate que devuelven las funciones y si no es el resultado correcto mira GetLastError.
lo que sucede que lpDisplayName de la función GetServiceDisplayName me devuelve el path del servicio pero le concatena el nombre de la dll según la documentación
Supongo que lo diras por esto:
This parameter can specify a localized string using the following format:
En fin, en mi Windows 7 x64 TODOS los servicios tienen exactamente el mismo resultado llamando a GetServiceDisplayName o a EnumServicesStatusEx. Igual fijate que buffer tenga valor 0 siempre que llames para averiguar el tamaño ...
Ya lo solucione el problema estaba que no aumentaba en 1 el tamaño del buffer para el parámetro sólo en la asignación de lpDisplay pero bueno lo malo es que está función no me da el valor esperado tal como lo dijiste retorna el mismo valor que EnumServicesStatusEx :-\