В истории буфера обмена копится мусор от операций turboconf

tormozit Закрыто

Понимаю, почему в turboconf используется буфер обмена как ячейка для чтения/записи текста в окна UIAutomation. Но многие пользователи и я в их числе использует ведение истории буфера обмена для повторного использования клипов. После обновления где то с начала февраля к сожалению даже всякие защитные меры писателей истории буфера не спасают от регистрации мусора от турбоконфа в этой истории.

Предлагаю описать тут способы, которыми turboconf изменяет содержимое буфера обмена. Попробуем найти оптимальное решение, включая возможную адаптацию представителя второй стороны - ClipAngel.

Комментарии

bolsun
#1, ред. 23 марта 2021 20:15

Добавить TurboConf в исключения, не помогает?


tormozit
#2, ред. 23 марта 2021 20:14

Так отправляет же не только turboconf, но и сам процесс конфигуратора после получения команды CTRL+C от turboconfа.


tormozit
#3, 23 марта 2021 20:19

К тому же у буфера обмена нет атрибута "Процесс-источник" к сожалению. Поэтому программы для ведения истории считают отправителем клипа активное окно. А оно уже может измениться в момент обработки события обновления буфера обмена подписантом. Поэтому 100% определять отправителя клипа невозможно. Особенно в случае с турбоконфом который свои окна быстро скрывает после завершения команды.


bolsun
#4, 23 марта 2021 20:21

(2) tormozit, CTRL+C для получения данных не используется для платформы >= 8.3.8. Раньше да только через буфер получались данные.


tormozit
#5, ред. 23 марта 2021 20:24

Если в буфер помещает непосредственно turboconf, то можно ставить специальный флаг типа "не добавлять в историю". Это неофициальный стандарт среди менеджеров буфера обмена . Подробнее тут http://www.clipboardextender.com/developing-clipboard-aware-programs-for-windows/ignoring-clipboard-updates-with-the-cf_clipboard_viewer_ignore-clipboard-format


tormozit
#6, 23 марта 2021 20:27

У меня чаще всего в историю попадает список методов модуля, т.к. я вызываю скрипт "Процедуры и функции". Я думал ты как раз через буфер обмена из штатного окна получаешь список. Раз ты получаешь оттуда текст напрямую, то непонятно почему он в буфер обмена попадает.


bolsun
#7, 23 марта 2021 20:27

(6) tormozit, согласен, не везде через UIAutomation, в таких списках через буфер.


bolsun
#8, 23 марта 2021 20:28

(5) tormozit, у тебя же на C# ClipAngel, ты используешь этот флаг при вставке?


bolsun
#9, ред. 23 марта 2021 20:30

Опять же как это поможет при Ctrl+C, там же 1С помещает в буфер и флага не будет никакого.


tormozit
#10, 23 марта 2021 20:32

(8) bolsun, при вставке флаг не использую, т.к. я не делаю временного изменения содержимого буфера. А при захвате я его проверяю.


tormozit
#11, ред. 23 марта 2021 20:37

(7) bolsun, насколько сложно будет избавиться от использования буфера обмена для чтения текста из окон конфигуратора хотя бы в этом месте?


bolsun
#12, ред. 23 марта 2021 20:40

(11) tormozit, кроме как через буфер список не получить. Тут только типа какого-то костыля можно сделать.
Обычно сразу после копирования в буфер, идет восстановление буфера предыдущим значением.
Может удалять эти 2 операции если они идут вместе.


bolsun
#13, ред. 23 марта 2021 20:55

2-й вариант зарегистрировать свой формат, говорящий что нужно удалить это и предыдущее значение. И когда я восстанавливаю буфер, добавлять этот флаг.


tormozit
#14, ред. 24 марта 2021 10:54

Предлагаю следующую систему сигнализации. Перед изменением текстового содержимого буфера обмена устанавливай в буфер обмена единственный формат с именем "ClipboardTempChange" и текстовым значением "Begin.<PID>" c ID процесса окна, которое будет слать временные данные в буфер. При восстановлении содержимого буфера обмена вместе с установкой туда оригинальных форматов добавляй формат с именем "ClipboardTempChange" и текстовым значением "End.<PID>" c ID процесса окна, которое завершило слать временные данные в буфер.


tormozit
#15, 24 марта 2021 10:42

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


bolsun
#16, 24 марта 2021 11:43

(14) tormozit, не знаю даже, работа с буфером и так нестабильна, приходится делать задержки, даже что бы одно значение установить, а тут придется на 2 операции больше делать.


tormozit
#17, ред. 24 марта 2021 11:49

(16) bolsun, на 1 обновление буфера больше, а не на 2. Согласен, что лишнее изменение буфера обмена - относительно высокая плата за такое исправление. Тогда предлагаю начать с добавления только второго сигнала -

При восстановлении содержимого буфера обмена вместе с установкой туда оригинальных форматов добавляй формат с именем "ClipboardTempChange" и текстовым значением "End.<PID>" c ID процесса окна, которое завершило слать временные данные в буфер.


bolsun
#18, 24 марта 2021 12:25

(17) tormozit, флаг добавить можно, но что даст ID процесса? Ведь копирований при выполнении скрипта может быть несколько. Как понять какие отменять, а какие нет. Причем есть скрипты, которые по времени могут занимать достаточно продолжительное время.


bolsun
#19, 24 марта 2021 12:26

"Clipboard Viewer Ignore" я попробовал добавить, вроде работает. Твоя программа не регистрирует такие изменения буфера.


tormozit
#20, ред. 24 марта 2021 12:45

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

При восстановлении содержимого буфера обмена вместе с установкой туда оригинальных форматов добавляй формат с именем "RemoveClipsFromHistory" и текстовым значением JSON:
PID=<PID>
TimeStart=<TimeBeginWithMiliseconds>
TimeEnd=<TimeEndWithMiliseconds>
где TimeStart - момент времени непосредственно перед отправкой в окно 1С первой команды CTRL+C из серии, а TimeEnd - момент времени сразу после считывания помещенного окном 1С текста в буфер после последней команды серии.


tormozit
#21, 24 марта 2021 12:39

(19) bolsun, Так вроде уже много раз мы установили, что ты отправляешь в окно 1С CTRL+C и уже непосредственно оно отправляет данные в буфер обмена. Там ты не сможешь повлиять на установленные форматы. Их состав полностью определяет процесс конфигуратора.


bolsun
#22, 24 марта 2021 13:49

(20) tormozit, слишком сложно и также без гарантированного результата из-за задержек. Что если я нажал Ctrl+C и через 100 мс, сразу запустил скрипт, который тоже нажал Ctrl+C.

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


bolsun
#23, ред. 24 марта 2021 13:53

ИМХО просто отменять предыдущую вставку (после получения CF_CLIPBOARD_VIEWER_IGNORE от ТК), если время между ними в пределах какого-то небольшого интервала (200-300 мс). Во время выполнения скриптов, я блокирую ввод. Поэтому вероятность, что какие-то полезные данные будут скопированы пользователем в это время - минимальная.


bolsun
#24, 24 марта 2021 13:53

Настройку можно сделать опциональной во вьювере.


tormozit
#25, 24 марта 2021 14:20

(22) bolsun, видимо я просто чего то не знаю или не достаточно подробно описал.
Ты запускаешь скрипт по команде пользователя и сразу блокируешь ввод в окне конфигуратора. В какой то момент в скрипте идет отправка первой команды CTRL+C в конфигуратор. Вот перед ней нужно зафиксировать отметку времени. Дальше скрипт делает много всего и с буфером обмена в том числе, но ввод пользовательских команд заблокирован. В конце скрипт перед восстановлением буфера обмена и разблокировкой ввода пользователя также фиксирует отметку времени. Затем он восстанавливает содержимое буфера обмена и при этом добавляет новый формат с данными о периоде замусоривания буфера обмена. Мне схема кажется простой и понятной и достаточно надежной. Дополнительных обновлений буфера обмена не вызывает. Сложных алгоритмов не добавляет. Твоя программа будет предоставлять все нужные данные для наблюдателей за буфером, чтобы они могли убрать мусор из своей истории.

По поводу пользовательских скриптов - ну тут конечно можно нагородить что угодно и сломать что угодно. Поэтому принимать их в расчет не нужно, чтобы не добавлять 10-кратной сложности ради 10% случаев у 10% пользователей.


tormozit
#26, ред. 24 марта 2021 14:25

(23) bolsun, Использовать флаг CF_CLIPBOARD_VIEWER_IGNORE для удаления создаваемых твоей программой мусорных клипов - нехорошо, ведь этот флаг как я объяснял ранее является неофициальным стандартом и взводится многими программами, которые имеют другую логику работы и например там вредно будет удалять предыдущий клип. Если делать самый простой вариант, то все равно нужно свой флаг делать - например "RemoveLastClipFromHistory" и очень желательно PID все равно предоставлять, т.к. юзер мог переключиться на другое приложение, пока твой скрипт работал и там поместить что то полезное в буфер обмена.


bolsun
#27, 24 марта 2021 15:06

(25) tormozit, со стороны задача кажется всегда проще чем есть на самом деле. Я как минимум несколько проблем вижу и изменения в алгоритмах достаточно существенные.


tormozit
#28, ред. 24 марта 2021 15:11

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


bolsun
#29, 24 марта 2021 15:28

(28) tormozit, тут еще нужно подумать хорошенько.

RemoveLastClipFromHistory - не очень хорошо, а если копирования по какой-то причине не было, что будет удалено?


bolsun
#30, 24 марта 2021 15:28

или интервал будет учитываться?


bolsun
#31, 24 марта 2021 15:38

Предлагаю попробовать флаг сделать 'RemoveClipsFromHistory', а значение которого - период в ms. Я сам могу тогда задавать интервал за который удалить.


bolsun
#32, ред. 24 марта 2021 15:39

Можешь сделать мне тестовую сборку с этим флагом? Я попробую как это работает.


tormozit
#33, ред. 24 марта 2021 15:49

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


bolsun
#34, ред. 24 марта 2021 15:52

(33) tormozit, ну давай значит в том формате

PID=<PID>
TimeStart=<TimeBeginWithMiliseconds>
TimeEnd=<TimeEndWithMiliseconds>

если PID = 0 то значит удалять от всех процессов за этот период.


bolsun
#35, ред. 24 марта 2021 15:54

и еще уточни время локальное или UTC и в каком формате.


tormozit
#36, 24 марта 2021 16:04

(35) bolsun, предлагаю взять локальное время по формату из примера

string format = "dd/MM/yyyy HH:mm:ss.ff";
string str = DateTime.Now.ToString(format, CultureInfo.InvariantCulture);
DateTime date = DateTime.ParseExact(str, format, CultureInfo.InvariantCulture);
string str1 = date.ToString(format, CultureInfo.InvariantCulture);


bolsun
#37, 24 марта 2021 16:08

(36) tormozit, ок, жду тогда сборку.


tormozit
#38, ред. 24 марта 2021 18:39

Готово. Формат буфера назвал - RemoveTempClipsFromHistory. Сериализацию все таки сделал через JSON формат - и тебе и мне меньше забот по сериализации/десериализации.
Рекомендую добавить в проект пакет Newtonsoft.Json (лицензия MIT). Тогда сформировать транспортную строку будет очень просто - пример

        public struct removeClipsFilter
        {
            public int PID;
            public DateTime TimeStart;
            public DateTime TimeEnd;
        }
				...
                removeClipsFilter removeClipsFilter = new removeClipsFilter
                {
                    PID = 54635
                    TimeStart = DateTime.Now.AddMilliseconds(-1000),
                    TimeEnd = DateTime.Now
                };
                dataString = JsonConvert.SerializeObject(removeClipsFilter);

ClipAngel 1.95.zip


bolsun
#39, 24 марта 2021 18:41

(38) tormozit, посмотрю. Конечно я использую Newtonsoft.Json. Все сишарперы его используют ))


bolsun
#40, 24 марта 2021 18:43

посмотрел ради интереса Newtonsoft.Json - 936 000 000 установок ))


bolsun
#41, 24 марта 2021 19:01

(38) tormozit, PID = 0 поддерживается?


tormozit
#42, 24 марта 2021 19:02

(41) bolsun, да


bolsun
#43, 24 марта 2021 19:05

(41) bolsun, тогда что-то не работает.
Как у тебя выглядит RegisterClipboardFormat? какая строка?


bolsun
#44, ред. 24 марта 2021 19:06

Имя формата 'RemoveTempClipsFromHistory' ?


tormozit
#45, 24 марта 2021 19:06

(44) bolsun, у меня ее нет. Это должен звать создатель клипов этого формата.


bolsun
#46, 24 марта 2021 19:07

(45) tormozit, я регистрирую "RemoveTempClipsFromHistory"


bolsun
#47, 24 марта 2021 19:07

но ничего не удаляется,
"Clipboard Viewer Ignore" работает


bolsun
#48, ред. 24 марта 2021 19:09

Ты можешь вывести алерт, если есть RemoveTempClipsFromHistory и параметры?


tormozit
#49, 24 марта 2021 19:10

(48) bolsun, поставь CLCL - там удобно смотреть текущие форматы в буфере Clip_222181.png


tormozit
#50, 24 марта 2021 19:12

Виноват. Отправил тебе из релизной папки сброку. А тестил на дебаге. Сейчас исправлюсь.


tormozit
#51, ред. 24 марта 2021 19:16

af7a0d54633f495a8ddd87eaf84c2235_ClipAngel 1.95.zip


bolsun
#52, ред. 24 марта 2021 19:20

del


bolsun
#53, 24 марта 2021 19:21

(51) tormozit, 2021-03-24_211912.png


tormozit
#54, 24 марта 2021 19:22

(53) bolsun, Может ты null вместо 0 передал в PID?


bolsun
#55, 24 марта 2021 19:28

(54) tormozit, мой косяк, не то передал. Но падать все равно не нужно )


tormozit
#56, 24 марта 2021 19:30

(55) bolsun, ну если бы я не показал ошибку, то мы тут еще бы 3 часа разбирались. Поэтому я за "здоровое" падение.


bolsun
#57, 24 марта 2021 19:32

Теперь удаляет, но есть проблема. Не удаляет тот текст, который приходит при восстановлении буфера.
Если добавить флаг ClipboardIgnoreFormatString, то игнорирует текст, но не удаляет предыдущие.


tormozit
#58, 24 марта 2021 19:36

А зачем удалять текст, который приходит при восстановлении буфера? Об этом речи не шло. Можешь на примере текстом пояснить?


bolsun
#59, 24 марта 2021 19:51

(58) tormozit, ну да, согласен, похоже не нужно.


bolsun
#60, 02 апреля 2021 16:25

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


tormozit
#61, 13 апреля 2021 23:12

При захвате мусорных клипов в локальном сеансе из дистанционного (например RDP), время локальное и дистанционное может сильно отличаться даже в одном часовом поясе. Поэтому в структуре, которую ты кидаешь в буфер для удаления мусорных клипов прошу добавить CurrentTime (текущее время), чтобы я мог хоть как то сориентироваться в смещении времени. А PID в связи с этим можно удалить (только сообщи мне, чтобы я у себя продублировал).


bolsun
#62, 14 апреля 2021 07:53

bolsun изменил статус на Открыто


bolsun
#63, 22 апреля 2021 11:46

(61) tormozit, CurrentTime получается будет совпадать с TimeEnd


tormozit
#64, 22 апреля 2021 12:25

Ты всегда сразу после последнего мусорного клипа отправляешь этот служебный клип? Если да, то я сделаю расчет смещения времени через TimeEnd.


bolsun
#65, 22 апреля 2021 12:49

(64) tormozit, я при каждой вставке, которую нужно исключить добавляю эти служебные данные.


tormozit
#66, 25 апреля 2021 15:45

Да. TimeEnd оказалось вполне достаточно чтобы смещение считать.


bolsun
#67, 25 апреля 2021 16:06

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


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