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.