none
Conseguir el HWnd de una aplicacion lanzada con ShellExecute??? RRS feed

  • Pregunta

  • Hola, a ver si me pueden ayudar porque estoy ya desesperado.

    En un primer paso abria cualquier documento con ShellExecute, pero el ShellExecute me devuelve casi siempre el valor 42, investigue y llegué a la conclusión que lo que me devolvía ShellExecute no me valía para usar la funcion SendMessage a la app abierta, ya que necesitaba el HWnd de la app lanzada. Incluso siguiendo este articulo http://support.microsoft.com/default.aspx/kb/242308 no podía hacerlo.

    El caso que pase a utilizar la API ShellExecuteEx, con la esperanza que en la estructura SHELLEXECUTEINFO, que devuelve el campo HProcess, me pudiese servir, incluso quizás así el anterior articulo me serviría. Pero no, al debugear me voy fijando en el nombre de cada proceso. Cuando llego al proceso que quiero, siguen sin coincidir. Osea en el articulo este, dicen de usar GetWindowThreadProcessId para cada HWnd de entre los procesos del sistema, lo que me devuelve un IdProcess, pero yo en el SHELLEXECUTEINFO tengo un HProcess, no un IdProcess.

    HProcess e IdProcess paracen son diferentes, por tanto hago usando EnumProcesses y OpenProcess para obtener en un array todos los Id's, si uso GetWindowThreadProcessId  por cada IdProcess tengo el HWnd, pero que tampoco me coinciden con el HProcess.

    Otra opción que he estado barajando es hacer un CreateProcess que esa API  ya me devuelve en HWnd. Pero ¿al CreateProcess hay que pasarle un ejecutable? Yo no tengo ejecutables, yo tengo documentos, y dependiendo del programa asociado a la extensión del archivo del documento abre un ejecutable u otro.

    Todo esto había estado funcionando bien porque lo hacia por la descripción de la ventana, donde estaba incluido el nombre del documento en casi todos los programas. Unos con extensión o sin extensión del archivo en el texto de la ventana abierta. El problema es que si el nombre del archivo es "a", cualquier proceso coincide sin asegurarme que sea el que yo abrí.

    .... tela marinela ... para mi que algo no estoy haciendo bien....
    Public Declare Function GetWindowThreadProcessId Lib "user32" _
      (ByVal hwnd As Long, lpdwprocessid As Long) As Long
    
    Private Function ProcIDFromWnd(ByVal hwnd As Long) As Long
       Dim idProc As Long, lngtest As Long
       
       ' Get PID for this HWnd
       lngtest = GetWindowThreadProcessId(hwnd, idProc)
       
       ' Return PID
       ProcIDFromWnd = idProc
    End Function
    
    
    Public Function SearchInTaskList(ByVal hwnd As Long, ByVal lngTarget As Long) As Long
    'Hwnd de mi ventana, y el valor HProcess que deberia ser idProcess que busco
    
    Dim CurrWnd As Long, Length As Long, ListItem As String
    Dim LoadTaskList As String, blnFound As Boolean
    
    'pruebas de otras opciones....
    'ExecuteAndReturnHWnd lngTarget 
      
    
      blnFound = False
      ' Recoge el primer handle del primer programa en proceso
      ' solo los de primer nivel
      CurrWnd = GetWindow(hwnd, GW_HWNDFIRST)
    
      ' Bucle mientras el handle devuelto por GetWindow sea valido
      If CurrWnd <> 0 Then
        Do
          ' Devuelve la longitud del nombre de la tarea para crear el buffer
          Length = GetWindowTextLength(CurrWnd)
          If Length > 0 Then
          'Recoge el nombre de la aplicación
          ListItem = Space$(Length + 1)
          Length = GetWindowText(CurrWnd, ListItem, Length + 1)
          
          If GetParent(CurrWnd) = 0 Then
    '''''AQUI PARO A VER SI COINCIDEN, MIRANDO EL NOMBRE LISTITEM SE CUAL TIENE QUE COINCIDIR Y NUNCA COINCIDEN.
            If lngTarget = ProcIDFromWnd(CurrWnd) Then
              Call SendMessage(CurrWnd, &H10, 0, 1)
              CurrWnd = GetWindow(hwnd, GW_HWNDFIRST)
              Exit Do
            End If
          End If
          End If
          CurrWnd = GetWindow(CurrWnd, GW_HWNDNEXT)
        Loop While CurrWnd <> 0
    
      End If
    
    ''''''ESTO ES LO VIEJO, LO HACIA POR DESCRIPCION
          ' Si devuelve un valor valido, se incluye en la lista
    ''      If Length > 0 Then
    ''        If ListItem Like ("*" & strTargetSearch & "*") Then
    ''          Call SendMessage(CurrWnd, &H10, 0, 1)
    ''          CurrWnd = GetWindow(hwnd, GW_HWNDFIRST)
    ''        ElseIf InStr(strTargetSearch, ".") > 0 Then
    ''          If ListItem Like ("*" & Left(strTargetSearch, InStr(strTargetSearch, ".") - 1) & "*") Then
    ''            Call SendMessage(CurrWnd, &H10, 0, 1)
    ''            CurrWnd = GetWindow(hwnd, GW_HWNDFIRST)
    ''            Exit Do
    ''          End If
    ''
    ''        End If
    ''      End If
    
    End Function
    

    Ese codigo era para buscar el HWnd, Al SearchTaskInList le paso ....¿? ya no se ni lo que pasarle para que me coincidan......le tengo que pasar algo que me sirva para que coincida con el IdProcess y obtener el HWnd, eso es el valor devuelto por ShellExecuteA o el HProcess del SHELLEXECUTEINFO devuelto por ShellExecuteEx o numerando todos los procesos de Id, el Handle del cual coincida el HProcess con el Hwnd OpenProcess

    Public Function flngGetIdProcess(ByVal HProcessTarget As Long) As Long
    Dim lngNumElements As Long
    Dim lngProcessIDs() As Long
    Dim lngReturn As Long
    Dim lngCBSize As Long 'Specifies the size, In bytes, of the lpidProcess array
    Dim lngCBSizeReturned As Long 'Receives the number of bytes returned
    Dim lngLoop As Long
    Dim lngHwndProcess As Long
    Dim blnFound As Boolean
    Dim pmc As PROCESS_MEMORY_COUNTERS
    Dim strModuleName As String
    Dim lret As Long
    Dim strProcName2 As String
    Dim strProcName As String
    Dim lngModules(1 To 200) As Long
    Dim lngCBSize2 As Long
    Dim lngSize As Long
    Dim strProcessName As String
    
      lngCBSize = 8 ' Really needs To be 16, but Loop will increment prior to calling API
      lngCBSizeReturned = 96
      
      Do While lngCBSize <= lngCBSizeReturned
          DoEvents
          'Increment Size
          lngCBSize = lngCBSize * 2
          'Allocate Memory for Array
          ReDim lngProcessIDs(lngCBSize / 4) As Long
          'Get Process ID's
          lngReturn = EnumProcesses(lngProcessIDs(1), lngCBSize, lngCBSizeReturned)
      Loop
      'Count number of processes returned
      lngNumElements = lngCBSizeReturned / 4
      'Loop thru each process
    
      For lngLoop = 1 To lngNumElements
        DoEvents
        'Get a handle to the Process and Open
        lngHwndProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, lngProcessIDs(lngLoop))
        Debug.Print lngHwndProcess
    
    ''''''AQUI DEBERIAN COINDIRME, SALIR DEL BUCLE Y DEVOLVER EL IDPROCEES PARA QUE LUEGO EN LA FUNCION SEARCHTASKINLIST LO PUEDA USAR.....¿?¿?
        If HProcessTarget = lngHwndProcess Then
          blnFound = True
          Exit For
        End If
      'Next lngLoop
      
      If lngHwndProcess <> 0 Then
          'Get an array of the module handles for the specified process
          lngReturn = EnumProcessModules(lngHwndProcess, lngModules(1), 200, lngCBSize2)
    
          'If the Module Array is retrieved, Get the ModuleFileName
          If lngReturn <> 0 Then
    
              'Buffer with spaces first to allocate memory for byte array
              strModuleName = Space(MAX_PATH)
    
              'Must be set prior to calling API
              lngSize = 500
    
              'Get Process Name
              lngReturn = GetModuleFileNameExA(lngHwndProcess, lngModules(1), strModuleName, lngSize)
    
              'Remove trailing spaces
              strProcessName = Left(strModuleName, lngReturn)
    
              'Check for Matching Upper case result
              strProcessName = UCase$(Trim$(strProcessName))
    
              strProcName2 = GetElement(Trim(Replace(strProcessName, Chr$(0), "")), "\", 0, 0, GetNumElements(Trim(Replace(strProcessName, Chr$(0), "")), "\") - 1)
    
              
    
              'Get the Site of the Memory Structure
              pmc.cb = LenB(pmc)
    
              lret = GetProcessMemoryInfo(lngHwndProcess, pmc, pmc.cb)
    
              Debug.Print strProcName2 & "::" & CStr(pmc.WorkingSetSize / 1024)
    
              
          End If
      End If
      Next lngLoop
      
      
      If blnFound Then
        flngGetIdProcess = lngProcessIDs(lngLoop)
      Else
        flngGetIdProcess = 0
      End If
      
    End Function


    jueves, 4 de junio de 2009 11:17

Todas las respuestas

  • Bueno, usando la funcion API GetProcessID tengo una parte solucionada, asi consigo el IdProcess a traves del HProcess. En la API-GUIDE 3.7 no veia esa función y me ha costado darme cuenta de su existencia.

    Pero tengo otro problema, los documentos word que abro con ShellExecuteEx, en la estructura SHELLEXECUTEINFO el campo HProcess me devuelve valor 0 ¿Por que? Como consigo el IdProcesss o HProcess si SHELLEXECUTEINFO no me los da.

    Recordad que los documentos a tratar pueden ser un doc, jpg, avi, pdf, etc .... por lo que CreateProcess no creo que me sirva a no ser que me digan como....
    martes, 9 de junio de 2009 10:33