Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   iconos junto a nombres de procesos en timagelist (https://www.clubdelphi.com/foros/showthread.php?t=86970)

aguml 30-10-2014 01:26:33

iconos junto a nombres de procesos en timagelist
 
hola amigos, me he creado una aplicacion la cual me lista todos los procesos que están ejecutandose en mi pc en un listview. Eso va perfecto pero me gustaria mostrar los iconos de los procesos en la primera columna al lado izquierdo del nombre y creo que tengo que añadir un timagelist y asociarlo a smallimagelist pero no tengo ni idea de como obtener el icono del proceso. Para colocarlo creo que tengo que usar imageindex pero no se nada mas. ¿Alguien puede ayudarme?

Neftali [Germán.Estévez] 30-10-2014 10:24:01

En mi web, tienes una aplicación que se llama VProcess, que en su día hice para probar algunas clases de la WMI.
Muestra los procesos que hay funcionando y las características de cada uno.
El código está disponible, así que puedes mirar cómo se obtiene el icono para cada proceso funcionando, a partir del path del ejecutable.

En mi caso utilizo algo así (por si no quieres descargar todo el fuente);

Código Delphi [-]
  //···············································································
  procedure GetFileIconAndDescription(AFileName:string; AIcon: TIcon);
  var
    FileInfo : SHFILEINFO;
  begin

    // Obtener el tipo
    SHGetFileInfo(PChar(AFileName),
                  FILE_ATTRIBUTE_NORMAL,
                  FileInfo,
                  SizeOf(FileInfo),
                  SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES
                  );
    // Obtener el icono y copiarlo en un ImageList
    SHGetFileInfo(PChar(AFileName),
                  FILE_ATTRIBUTE_NORMAL,
                  FileInfo,
                  SizeOf(FileInfo),
                  SHGFI_ICON or SHGFI_SMALLICON or
                  SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES
                  );
    AIcon.Handle := FileInfo.hIcon;
  end;
  //···············································································

escafandra 30-10-2014 11:51:31

Te puede interesar este hilo que estudia la estructura de los iconos, como conocer y cambiar los iconos de ejecutables en la sección de recursos de ejecutables y dlls.

También debes mirar la API ExtractAssociatedIcon.

Si quieres saber la asociación en el shell de un archivo con su icono, te interesa esto

Todo ello en C/C++


Saludos.

Neftali [Germán.Estévez] 30-10-2014 14:05:21

Cita:

Empezado por escafandra (Mensaje 483993)
Todo ello en C/C++

Perdón!!! :o
No me había fijado en el foro. Lo que te he pasado está en Delphi.
Aun así la llamada a la API tal vez te pueda ser de ayuda.

escafandra 30-10-2014 17:44:50

Neftali Claro que sirve de ayuda, al fin y al cabo no hay tanta diferencia, sobre todo cuando se usa API de Windows. :)


Saludos.

aguml 30-10-2014 20:20:03

El principal problema que tenia era obtener las rutas completas de cada proceso pero al final lo he conseguido hacer así:
Código PHP:

TIcon *Icon//Para el icono del proceso

char strPath[MAX_PATH 1];
memset(strPath,0,(MAX_PATH-1));

if(
GetPathFromPID(processInfo.th32ProcessID,strPath))
{  
//SI OBTENGO LA RUTA COMPLETA DEL PROCESO
    // Creo un TIcon temporal
    
Icon = new TIcon;

    
//INTENTO COLOCAR EL ICONO DE CADA PROCESO
    
GetFileIconAndDescription(strPath,Icon);
    
ListItemsProcesos->Item[ListItemsProcesos->Count-1]->ImageIndex Form1->ImageList1->AddIcon(Icon);

    
delete Icon;


Y las funciones:
Código PHP:

// Obtiene el Path de un ID de Proceso (PID) Activo en Memoria.
bool GetPathFromPID(int PIDchar *FullPath)
{
   
HANDLE hProcess;
   
char Path[MAX_PATH 1];
   
bool retval false;
   
HINSTANCE hLib;

   
hProcess OpenProcess(PROCESS_QUERY_INFORMATION PROCESS_VM_READfalsePID);
   if( 
hProcess != ){
      try{
         
hLib LoadLibrary("psapi.dll");
         if(
hLib!=0)
         {
            
pGetModuleFileNameEx = (bool (__stdcall *) (void*, void*, char*, unsigned long)) GetProcAddress(hLib,"GetModuleFileNameExA");
            if(
pGetModuleFileNameEx != NULL)
            {
               if( 
pGetModuleFileNameEx(hProcess0Pathsizeof(Path)) != ){
                  
strcpy(FullPath,Path);
                  
retval true;
               }
            }
         }
      }catch(...){
      }
      
CloseHandle(hProcess);
   }else{
      
//raise Exception.Create('El Programa No Se Encuentra Activo en Memoria');
   
}
   return 
retval;
}
//---------------------------------------------------------------------------

void GetFileIconAndDescription(AnsiString AFileNameTIcon *AIcon)
{
    
SHFILEINFO FileInfo;

    
// Obtener el tipo
    
SHGetFileInfo(AFileName.c_str(),
                  
FILE_ATTRIBUTE_NORMAL,
                  &
FileInfo,
                  
sizeof(FileInfo),
                  
SHGFI_TYPENAME SHGFI_USEFILEATTRIBUTES
                  
);
    
// Obtener el icono y copiarlo en un ImageList
    
SHGetFileInfo(AFileName.c_str(),
                  
FILE_ATTRIBUTE_NORMAL,
                  &
FileInfo,
                  
sizeof(FileInfo),
                  
SHGFI_ICON SHGFI_SMALLICON |
                  
SHGFI_SYSICONINDEX SHGFI_USEFILEATTRIBUTES
                  
);
    
AIcon->Handle FileInfo.hIcon;


Neftali lo del icono lo tenia igual que tu pero solo que yo no lo tenia en una funcion y despues de ver la tuya lo he puesto igual. Gracias.
¿Alguien me dice si hay algo que se me pasa? Funcionar funciona pero no se si hago algo que no deba.
El dolor de cabeza mas grande fue obtener la ruta como ya dije ya que para que pueda hacerlo necesitaba psapi.lib y no pude encontrarlo pero si pude encontrar la dll y usar la funcion dinamicamente jejeje.
Muchas gracias amigos.

escafandra 30-10-2014 21:15:47

Con la API GetModuleFileName o GetModuleFileNameEx obtienes lo que buscas. En tu caso precisas abrir el proceso conociendo su PID. para poder hacer eso necesitar ejecutar el programa como administrador. Para evitar eso, yo uso esta forma:

Código PHP:

bool GetProcessImageFileName(DWORD dwProcessIdcharExePathint Size)
{
  if(
dwProcessId==&& Size){
    *
ExePath 0;
    return 
true;
  }
  
HANDLE hSnapshot;
  
MODULEENTRY32 ModuleEntry;
  
ModuleEntry.dwSize sizeof(MODULEENTRY32);
  
bool Result false;
  if(
Size) *ExePath 0;
  
hSnapshot CreateToolhelp32Snapshot(TH32CS_SNAPMODULEdwProcessId);
  if(
hSnapshot != (HANDLE)-1){
    if(
Module32First(hSnapshot, &ModuleEntry)){
      
Result true;
      
lstrcpyn(ExePathModuleEntry.szExePathSize);
    }
    
CloseHandle(hSnapshot);
  }
  return 
Result;


Si te fijas no usa String. El buffer debe ser un char* y debes pasar el tamaño del mismo. Puedes modificarlo para usar Strings.


Saludos.

aguml 30-10-2014 22:59:33

¿Seguro que eso suelta el path completo? Es que es lo que hago para rellenar el listview con los nombres de procesos, id, id del que ejecuta al proceso, y mas cosillas pero yo no obtengo la ruta completa sino solo el nombre del proceso. Lo que de cabeza no puedo asegurar si uso el Module32First o otra que sele parezca ya que son acabadas en 32first y 32next. Tengo una duda, justo antes de empezar a leer los procesos le doy a mi proceso privilegios de debugger cambiando los token. Si no fuese administrador ¿Daria problemas y no obtendria esos privilegios? Mi aplicacion lo que hace es que lanza un servicio, el servicio cierra a mi aplicacion y lanza otra vez a mi aplicacion y se pausa y entonces mi aplicacion cierra al servicio. Con eso mi aplicacion se crea como system y puedo cargarme cualquier proceso de la lista y tambien ejecutar a otros procesos como system para asi hacer una escalada de privilegios. Esa es la idea.

escafandra 31-10-2014 00:03:34

Ese código devuelve el Path completo con nombre del ejecutable buscado por su ID, sin necesidad de ejecutar como administrador.

Si lo ejecutas como SYSTEM no tendrás problemas pero si no es así, puedes no tener permisos para abrir procesos. Es bueno tener en mente ambos sistemas que por otra parte hacen lo mismo.

Tu código puede tener un desbordamiento de buffer fácil al no pasar el tamaño del mismo y usar strcpy. Puedes pasar el tamaño y usar strncpy o resumirlo de esta otra forma pero siempre teniendo en cuenta ese importante detalle:

Código PHP:

typedef bool (__stdcall PGETMODULEFILENAMEEX)(void*, void*, char*, unsigned long);

bool GetPathFromPID(int PIDchar *FullPathint Size)
{
   
HANDLE hProcess;
   
bool retval false;
   
HINSTANCE hLib;
   
PGETMODULEFILENAMEEX pGetModuleFileNameEx;

   
hProcess OpenProcess(PROCESS_QUERY_INFORMATION PROCESS_VM_READfalsePID);
   if(
hProcess){
      try{
         
hLib LoadLibrary("psapi.dll");
         if(
hLib){
            
pGetModuleFileNameEx = (PGETMODULEFILENAMEEX)GetProcAddress(hLib,"GetModuleFileNameExA");
            if(
pGetModuleFileNameEx)
              
retval pGetModuleFileNameEx(hProcess0FullPathSize);
         }
      }catch(...){}
      
CloseHandle(hProcess);
   }else{
      
//raise Exception.Create('El Programa No Se Encuentra Activo en Memoria');
   
}
   return 
retval;


Otro detalle importante. Si usas WinXP tu código corriendo como SYSTEM va bien. En Win7 o Win8 no verás la ventana, tienen protegido el modo.

Saludos.

aguml 31-10-2014 00:09:40

Va genial gracias. A ver si puedes contestarme a las dudas que comento.

escafandra 31-10-2014 00:24:49

Quizás te interesen estos enlaces:

MiniSystem, una miniaplicación para ejecutar programas con privilegios SYSTEM
Lanzar una aplicación GUI desde un servicio


Saludos.

aguml 31-10-2014 17:40:18

entonces ¿Este truco para escalar privilegios no serviria en win 7 y 8?

escafandra 31-10-2014 22:55:08

Si sirve pero una ventana en modo SYSTEM no puede inreractuar con un usuario, ni ser vista, aunque la aplicación si se esté ejecutando.

Saludos.

aguml 01-11-2014 10:52:31

bueno, entonces si no puedes verlo dificil lo tienes jejeje. Se me ocurre otro modo y es que no se cierre la aplicacion que no tiene privilegios sistem y comunicarte con la que si los tiene usando mensajes por ejemplo y que la que es system haga el trabajo y nos conteste con un mensaje que nos indique si fue bien o no.

escafandra 01-11-2014 12:52:35

Esa es la forma, comunicación no GUI entre aplicaciones.

Saludos.

aguml 01-11-2014 15:56:17

ok, tengo pendiente alguna que otra cosilla mas como mostrar los modulos del proceso y eliminar varios procesos a la vez pero creo que esto no me dará problemas asi que cuando lo tenga a full intentaré hacer lo indicado para que corra en 7 y 8 y funcione a la perfeccion. Muchas gracias a todos.

aguml 03-11-2014 10:51:50

una pregunta ¿Por que algunos procesos me dan la ruta precedida con "\\??\\" ? ¿En 7 y 8 tambien pasaria?


La franja horaria es GMT +2. Ahora son las 16:58:35.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi