¿Cómo verificar qué aplicación tiene el portapapeles?

9

Estamos implementando algunas máquinas virtuales con software de robots que realiza acciones en un navegador, y estamos teniendo problemas con algunas de ellas al acceder al portapapeles para leer o escribir. Muestran un "No se puede abrir el portapapeles".

Entonces, hay otra aplicación que sostiene el portapapeles.

¿Cómo podemos depurar eso? ¿Hay alguna herramienta que pueda monitorear eso? AFAIK ProcMon no hace el trabajo.

Las máquinas son Windows XP.

Áxel Costas Pena
fuente
¿Esto sucede en una configuración de arranque mínima?
Ramhound
El software de los robots no funciona en modo seguro, esa es una de las dificultades
Áxel Costas Pena
1
No dije Modo seguro. Dije que en una configuración de arranque mínima hay una diferencia.
Ramhound
Portapapeles manual: guarde el texto en un archivo, llame al texto en ese archivo, elimine el archivo.
Wutnaut
La máquina @Ramhound tiene muchos componentes, muchos de los cuales son necesarios para la actividad del robot. Comenzar desde una máquina limpia e instalar el software uno por uno hasta que la reproducción del error sea muy costosa.
Áxel Costas Pena

Respuestas:

9

La API del Portapapeles data de Windows 3.0 (¿o anterior?) Y está mal diseñada. Desafortunadamente, en lugar de tener primitivas get / set, usa open / close, lo que hace posible que las aplicaciones mantengan su acceso durante demasiado tiempo. Vista aportó algunas mejoras al manejo de la cadena de televidentes, pero no una nueva API.

Con la API existente, es posible identificar al propietario del portapapeles solo si ese propietario también tiene al menos una ventana abierta. Si el propietario no tiene ventanas, entonces uno no tiene suerte.

En el hilo ¿Por qué mi portapapeles dejó de funcionar? , Jay Parzych ha contribuido con el siguiente código vbs donde la función GetClipboardLocker devuelve el nombre de archivo del proceso que contiene el portapapeles:

<DllImport("user32.dll")> _
Public Function GetOpenClipboardWindow() As IntPtr
   End Function
 <DllImport("user32.dll", SetLastError:=True)> _
   Public Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
   End Function
Public Function GetClipboardLocker() As String
       Dim hwnd As IntPtr = GetOpenClipboardWindow()
       If hwnd <> IntPtr.Zero Then
           Dim processId As Integer
           GetWindowThreadProcessId(hwnd, processId)
           Dim p As Process = Process.GetProcessById(processId)
           GetClipboardLocker = p.Modules(0).FileName
       Else
           GetClipboardLocker = String.Empty
       End If
   End Function

Se puede encontrar una función C # similar en la publicación Obtener título / título de los propietarios del Portapapeles .

harrymc
fuente
Dado que en nuestro escenario, podemos asegurar que cualquier proceso que esté haciendo que no tenga una ventana creada, lo marcaré como la respuesta correcta. Gracias.
Áxel Costas Pena