Como verificar qual aplicativo contém a área de transferência?

9

Estamos implantando algumas máquinas virtuais com software de robôs que executam ações em um navegador e estamos tendo problemas com algumas delas ao acessar a área de transferência para leitura ou gravação. Eles mostram uma "Não é possível abrir a área de transferência".

Portanto, há qualquer outro aplicativo segurando a área de transferência.

Como podemos depurar isso? Existe alguma ferramenta que possa monitorar isso? O AFAIK ProcMon não faz o trabalho.

Máquinas são Windows XP.

Áxel Costas Pena
fonte
Isso acontece em uma configuração mínima de inicialização?
Ramhound 18/06
O software robôs não funciona em modo de segurança, que é uma das dificuldades
Axel Costas Pena
1
Eu não disse o Modo de Segurança. Eu disse que em uma configuração mínima de inicialização, há uma diferença.
Ramhound
Área de transferência manual: salve o texto em um arquivo, chame o texto nesse arquivo, exclua o arquivo.
Wutnaut
A máquina @ Ramhound possui muitos componentes, muitos dos quais são necessários para a atividade do robô. A partir de uma máquina limpa e instale o software um por um até a reprodução do bug ser muito cara.
Áxel Costas Pena

Respostas:

9

A API da área de transferência é do Windows 3.0 (ou antes?) E é mal projetada. Infelizmente, em vez de ter primitivas get / set, ele usa abrir / fechar, o que possibilita que os aplicativos mantenham seu acesso por muito tempo. Algumas melhorias foram trazidas pelo Vista para o manuseio da cadeia de visualizadores, mas nenhuma nova API.

Com a API existente, é possível identificar o proprietário da área de transferência apenas se esse proprietário também tiver pelo menos uma janela aberta. Se o proprietário não tiver janelas, uma delas estará sem sorte.

No tópico Por que minha área de transferência parou de funcionar? , Jay Parzych contribuiu com o seguinte código vbs em que a função GetClipboardLocker retorna o nome do arquivo do processo que contém a área de transferência:

<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

Uma função C # semelhante pode ser encontrada na publicação Título / Legenda dos proprietários da área de transferência .

harrymc
fonte
Como em nosso cenário, podemos garantir que qualquer processo que esteja executando e que não tenha janela seja criada, marcarei como resposta correta. Obrigado.
Áxel Costas Pena