Jak sprawdzić, która aplikacja ma schowek?

9

Wdrażamy niektóre maszyny wirtualne z oprogramowaniem robotów, które wykonuje działania w przeglądarce, i mamy problemy z niektórymi z nich podczas uzyskiwania dostępu do schowka w celu odczytu lub zapisu. Pokazują „Nie można otworzyć schowka”.

Jest więc inna aplikacja przechowująca schowek.

Jak możemy to debugować? Czy jest jakieś narzędzie, które może to monitorować? AFAIK ProcMon nie wykonuje pracy.

Maszyny to Windows XP.

Áxel Costas Pena
źródło
Czy dzieje się tak przy minimalnej konfiguracji rozruchu?
Ramhound
Oprogramowanie robotów nie działa w trybie awaryjnym, co stanowi jedną z trudności
Áxel Costas Pena
1
Nie powiedziałem, że tryb awaryjny powiedziałem, że przy minimalnej konfiguracji rozruchu jest różnica.
Ramhound
Ręczny schowek: zapisz tekst do pliku, wywołaj tekst w tym pliku, usuń plik.
Wutnaut
@Ramhound ma wiele komponentów, z których wiele jest potrzebnych do działania robota. Począwszy od czystej maszyny i instalując oprogramowanie jeden po drugim, aż odtworzenie błędu będzie bardzo kosztowne.
Áxel Costas Pena

Odpowiedzi:

9

Clipboard API pochodzi z systemu Windows 3.0 (lub wcześniej?) I jest źle zaprojektowany. Niestety zamiast prymitywów get / set korzysta z funkcji open / close, co umożliwia aplikacjom zbyt długo utrzymywać dostęp. Vista wprowadziła pewne usprawnienia w obsłudze łańcucha przeglądających, ale nie ma nowego API.

Dzięki istniejącemu interfejsowi API można zidentyfikować właściciela schowka tylko wtedy, gdy ten właściciel ma również co najmniej jedno otwarte okno. Jeśli właściciel nie ma okien, jedno nie ma szczęścia.

W wątku Dlaczego mój schowek przestał działać? Jay Parzych napisał następujący kod vbs, w którym funkcja GetClipboardLocker zwraca nazwę pliku procesu przechowującego schowek:

<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

Podobną funkcję C # można znaleźć w poście Uzyskaj właściciela tytułu / podpisu ze schowka .

harrymc
źródło
Ponieważ w naszym scenariuszu możemy zapewnić, że każdy przebiegający proces, który nie ma utworzonego okna, oznaczę go jako prawidłową odpowiedź. Dziękuję Ci.
Áxel Costas Pena