Команда "ФорматироватьТекст" ИР адаптера всегда ждет в конце больше секунды на попытке записать в буфер обмена

tormozit Закрыто

Проблема старинная (больше года). Но раз уж мы буфер обмена ковыряем, предлагаю взглянуть и на это мелкое неудобство. После секунды ожидания метод записи в буфер обмена выдает ошибку

SetClipboard error. System.Runtime.InteropServices.ExternalException (0x800401D0): Сбой при выполнении запрошенной операции с буфером обмена.
в System.Windows.Forms.Clipboard.ThrowIfFailed(Int32 hr)
в System.Windows.Forms.Clipboard.SetDataObject(Object data, Boolean copy, Int32 retryTimes, Int32 retryDelay)
в TurboConf.Core.Helpers.SetClipboard(String oldClipboard, ClipboardOptions options)

Ссылка скрыта

При этом остальная часть команды выполняется за 200мс примерно, т.е. она удлиняется во много раз. Дополнительным неприятным фактором является заморозка движения указателя мыши во время ожидания на записи в буфер обмена.

Комментарии

tormozit
#1, 13 сентября 2025 18:22

Может быть еще и запись в буфер через WinAPI попробовать?


bolsun
#2, 13 сентября 2025 20:42

Метод SetDataObject() делает 5 попыток установки текста в буфер обмена, поэтому и 1 секунда ожидания. Почему он не может установить буфер, нужно смотреть скрипт.


tormozit
#3, ред. 13 сентября 2025 22:32

(2) bolsun, в скрипте в конце - явное восстановление буфера обмена. Оно выполняется без ошибки.
УстановитьБуферОбмена(СтароеЗначениеБуфераОбмена);
А вот сразу после выхода из обработчика команды Турбоконф из-за аннотации &ВосстанавливатьБуферОбмена делает тоже самое еще раз. Но у него уже не выходит почему то - возникает ожидание и ошибка.


tormozit
#4, ред. 13 сентября 2025 22:37

(3) tormozit, я явное восстановление буфера конечно уже отключил там, где вызов идет из обработчиков с аннотацией &ВосстанавливатьБуферОбмена. Проблема в этих местах ушла. Но сам факт наличия такой сложно понимаемой беды расстраивает.
Нужно хотя бы при выводе этой ошибки Турбоконфом в самом начале написать, что выполняется восстановление буфера обмена из-за аннотации &ВосстанавливатьБуферОбмена. Тогда бы я намного быстрее нашел и устранил причину в скрипте.


bolsun
#5, ред. 13 сентября 2025 22:52

(4) tormozit, буфер может восстанавливаться по разным причинам (аннотация, некоторые обработчики, настройка в шапке скрипта). Буду выводить в логе

"Восстанавливаем буфер обмена автоматически..."

В ошибку добавлю.
Произошла ошибка при автоматическом восстановлении буфера обмена.


bolsun
#6, ред. 13 сентября 2025 22:57

(5) Update. Нет, метод установки буфера находится в другом пространстве имен и сам логирует ошибки, не зная от том почему вызывался.

Поэтому просто в лог добавлю "Восстанавливаем буфер обмена автоматически..." перед установкой буфера.


tormozit
#7, ред. 14 сентября 2025 08:29

Если двигать указателем мыши во время выполнения восстановления буфера обмена Турбоконфом в том же тесте, то исходная проблема все равно возникает даже без предварительной установки буфера в обработчике скрипта. Так что идея (1) не теряет актуальности.

[14.09.25 08:08:54:435] SetClipboard()
[14.09.25 08:08:54:435] removeClips=True
[14.09.25 08:08:54:446] Delay 50 ms
[14.09.25 08:08:55:508] Error: SetClipboard error. System.Runtime.InteropServices.ExternalException (0x800401D0): Сбой при выполнении запрошенной операции с буфером обмена.
   в System.Windows.Forms.Clipboard.ThrowIfFailed(Int32 hr)
   в System.Windows.Forms.Clipboard.SetDataObject(Object data, Boolean copy, Int32 retryTimes, Int32 retryDelay)
   в TurboConf.Core.Helpers.SetClipboard(String oldClipboard, ClipboardOptions options)

Ссылка скрыта
BcEsMvHZLs.mp4


bolsun
#8, 14 сентября 2025 14:05

(7) tormozit, пришли твою версию скрипта.


tormozit
#9, 14 сентября 2025 14:08

RDT.os


bolsun
#10, 14 сентября 2025 14:28

(7) tormozit, у меня не воспроизводится.


tormozit
#11, ред. 14 сентября 2025 14:45

(10) bolsun, пробуй в модуле из ролика см. ОбработкаОбъект.ирКлсПолеТекстаПрограммы.ОткрытьПоискВМодулях


bolsun
#12, 14 сентября 2025 15:07

Попробуй этот вариант, заменил вставку текста в буфер при восстановлении значения на реализацию через WinAPI.
Метод устанавливает простой текст, никаких дополнительных флагов типа clipignore не устанавливает.

6.4.9388.30354
https://disk.yandex.ru/d/XRPUNWQtrbwBUw


tormozit
#13, 14 сентября 2025 16:52

(12) bolsun, в этой версии не удалось вызвать такую ошибку и значительное замирание указателя мыши. Похоже что помогло.


bolsun
#14, ред. 14 сентября 2025 17:08

(13) tormozit, посмотрел реализацию Clipboar.SetText() и SetDataObject() в NET, опять она какая-то странная, для установки буфера используется метод

[DllImport("ole32.dll", CharSet = CharSet.Auto)]
public static extern int OleSetClipboard(System.Runtime.InteropServices.ComTypes.IDataObject pDataObj);

а не


[DllImport("user32.dll")]
    static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);


bolsun
#15, 14 сентября 2025 17:13

Хорошо бы протестировать как ведет себя новый метод если буфер занят другим приложением и не даст выполнить OpenClipboard()


bolsun
#16, 14 сентября 2025 17:15

Можно будет добавить в него несколько попыток повторной вставки с интервалом ожидания, как в методе .NET.


bolsun
#17, 15 сентября 2025 16:51

6.4.9389.32901

  • Все методы установки данных в буфер обмена заменил на свою реализацию. Добавил отслеживание ошибок совместного доступа к буферу и повторные попытки установки.

https://disk.yandex.ru/d/-tKjlTZDvE2Lxg


tormozit
#18, 15 сентября 2025 16:55

tormozit изменил статус на Закрыто


bolsun
#19, 16 сентября 2025 14:10

6.4.9390.28891

  • Заменил вызовы еще в некоторых местах, которые упустил.

https://disk.yandex.ru/d/XRPUNWQtrbwBUw


Для вставки изображения или файла, перетащите его в поле редактора или вставьте файл из буфера