Как проверить, какое приложение удерживает буфер обмена?

9

Мы внедряем некоторые виртуальные машины с программным обеспечением роботов, которое выполняет действия в браузере, и у нас возникают проблемы с некоторыми из них при доступе к буферу обмена для чтения или записи. Они показывают «Не удается открыть буфер обмена».

Таким образом, есть любое другое приложение, удерживающее буфер обмена.

Как мы можем отладить это? Есть ли инструмент, который может контролировать это? AFAIK ProcMon не делает работу.

Машины Windows XP.

Аксель Костас Пена
источник
Это происходит в минимальной конфигурации загрузки?
Ramhound
Программное обеспечение роботов не работает в безопасном режиме, это одна из трудностей
Аксель Костас Пена
1
Я не сказал Безопасный режим, я сказал, что в минимальной конфигурации загрузки есть разница.
Ramhound
Ручной буфер обмена: сохранить текст в файл, вызвать текст в этом файле, удалить файл.
Wutnaut
Машина @Ramhound имеет много компонентов, многие из которых необходимы для работы робота. Начиная с чистой машины и устанавливайте программное обеспечение по одному, пока воспроизведение ошибки не будет очень дорогим.
Аксель Костас Пена

Ответы:

9

API буфера обмена появился в Windows 3.0 (или раньше?) И плохо спроектирован. К сожалению, вместо получения / установки примитивов он использует open / close, что позволяет приложениям слишком долго удерживать свой доступ. Vista внесла некоторые улучшения в обработку цепочки зрителей, но не добавила новый API.

С помощью существующего API можно определить владельца буфера обмена, только если у этого владельца есть хотя бы одно открытое окно. Если у владельца нет окон, то ему не повезло.

В теме Почему мой буфер обмена перестал работать? Jay Parzych предоставил следующий vbs-код, где функция GetClipboardLocker возвращает имя файла процесса, содержащего буфер обмена:

<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

Сходная функция C # может быть найдена в посте Получить владельцы буфера обмена Title / Caption .

harrymc
источник
Поскольку в нашем сценарии мы можем гарантировать, что любой процесс, который выполняет, не имеет созданного окна, я отмечу это как правильный ответ. Спасибо.
Аксель Костас Пена