Сниппет вставки из буфера обмена для ZennoPoster (многопоточный, с блокировками) [Дон шампиньон]

У меня метод из старто поста уже сколько лет работает. Встявляет картинки в пост на ФБ. В конкурсах где то есть этот шаблон с этим методом.
 
  • Оценить
Реакции: Pierre Paul Jacques
Хз как под локом он может пересечся. Или речь идет о пересечении при работе человека за пк?
 
Хз как под локом он может пересечся. Или речь идет о пересечении при работе человека за пк?
запросто... просто посмотри какой лок используется в коде и сразу будет ясно в каких случаях он не будет работать. ;-)
не то что всегда не будет работать... но как всегда есть НО...
 
  • Оценить
Реакции: Pierre Paul Jacques
запросто... просто посмотри какой лок используется в коде и сразу будет ясно в каких случаях он не будет работать. ;-)
не то что всегда не будет работать... но как всегда есть НО...
Не врублюсь, а чем этот лок не подходит?
 
  • Оценить
Реакции: Pierre Paul Jacques
  • Оценить
Реакции: Pierre Paul Jacques
Видимо лок распределяется на один проект, а у людишек проекты одновременно работают с одним и тем же функционалом.
Нет, этот лок не работает на один проект.
 
  • Оценить
Реакции: Pierre Paul Jacques
Воскресенье - время для отдыха, поэтому это Zenno:bo.

Использование буфера обмена в автоматизации следует избегать, но в некоторых случаях я использую его, потому что:

Эмуляция текста занимает слишком много времени (если установлен быстрый режим, текст не распознается/область текста не активирована). Для целей SEO, когда я не могу отправить HTML/разметку в качестве гостя. Чтобы избежать конфликтов в многопоточном использовании буфера обмена, я использую: lock(SyncObjects.InputSyncer), но это работает только во время выполнения блока C#.

Однако в некоторых случаях я выполняю операции копирования и вставки, между которыми есть несколько блоков, которые не являются пользовательскими блоками C# (и которые я не могу/не хочу преобразовывать). Поэтому на данный момент я использую простое решение: внешний файл, который действует как "блокировка" с булевым выбором, управляющим доступом к буферу обмена! Цель состоит в том, чтобы убедиться, что когда элемент копируется в буфер обмена, это не другой поток вставляет его, потому что между блоками есть задержка в несколько секунд, и может быть переплетение.

Я создал нижеуказанный код, что вы думаете об использованном методе?

Могло ли быть более простое/надежное решение?

C#:
Развернуть Свернуть Копировать
// Блокировка: True

// Построить путь к файлу

var lockFilePath = Path.Combine(project.Directory, "01 - The Base\01 - Cookies\The Lock.txt");

// Проверить, доступен ли буфер обмена

if (File.ReadAllText(lockFilePath) == "False")

{

// Буфер обмена доступен, записать "True", чтобы заблокировать его

File.WriteAllText(lockFilePath, "True");

}

else

{

// Подождите, пока буфер обмена не станет доступным

while (File.ReadAllText(lockFilePath) != "False")

{

// Подождите 1 секунду перед повторной попыткой

Thread.Sleep(1000);

}

// Как только буфер обмена станет доступным, записать "True", чтобы заблокировать его

File.WriteAllText(lockFilePath, "True");

}

Затем в конце процесса мы записываем "False" в текстовый файл.

Заранее спасибо за ваш совет!
image.png


PS :

Прошу прощения за возможные странности в моем русском тексте, я использую сервис перевода для своих сообщений. На данный момент я не владею русским языком, но с большим интересом и вниманием читаю русскую часть форума благодаря сервису перевода. Все ясно, что именно здесь, в русскоязычном сообществе, скрывается больше всего ценной информации. Так что, если я хочу продвинуться с Zenno, мне нужно отправиться на сторону русского сообщества!
На данный момент, единственное слово, которое я знаю на русском, это 'здоровье'
 
  • Оценить
Реакции: Morti
Воскресенье - время для отдыха, поэтому это Zenno:bo.

Использование буфера обмена в автоматизации следует избегать, но в некоторых случаях я использую его, потому что:

Эмуляция текста занимает слишком много времени (если установлен быстрый режим, текст не распознается/область текста не активирована). Для целей SEO, когда я не могу отправить HTML/разметку в качестве гостя. Чтобы избежать конфликтов в многопоточном использовании буфера обмена, я использую: lock(SyncObjects.InputSyncer), но это работает только во время выполнения блока C#.

Однако в некоторых случаях я выполняю операции копирования и вставки, между которыми есть несколько блоков, которые не являются пользовательскими блоками C# (и которые я не могу/не хочу преобразовывать). Поэтому на данный момент я использую простое решение: внешний файл, который действует как "блокировка" с булевым выбором, управляющим доступом к буферу обмена! Цель состоит в том, чтобы убедиться, что когда элемент копируется в буфер обмена, это не другой поток вставляет его, потому что между блоками есть задержка в несколько секунд, и может быть переплетение.

Я создал нижеуказанный код, что вы думаете об использованном методе?

Могло ли быть более простое/надежное решение?

C#:
Развернуть Свернуть Копировать
// Блокировка: True

// Построить путь к файлу

var lockFilePath = Path.Combine(project.Directory, "01 - The Base\01 - Cookies\The Lock.txt");

// Проверить, доступен ли буфер обмена

if (File.ReadAllText(lockFilePath) == "False")

{

// Буфер обмена доступен, записать "True", чтобы заблокировать его

File.WriteAllText(lockFilePath, "True");

}

else

{

// Подождите, пока буфер обмена не станет доступным

while (File.ReadAllText(lockFilePath) != "False")

{

// Подождите 1 секунду перед повторной попыткой

Thread.Sleep(1000);

}

// Как только буфер обмена станет доступным, записать "True", чтобы заблокировать его

File.WriteAllText(lockFilePath, "True");

}

Затем в конце процесса мы записываем "False" в текстовый файл.

Заранее спасибо за ваш совет!
image.png


PS :

Прошу прощения за возможные странности в моем русском тексте, я использую сервис перевода для своих сообщений. На данный момент я не владею русским языком, но с большим интересом и вниманием читаю русскую часть форума благодаря сервису перевода. Все ясно, что именно здесь, в русскоязычном сообществе, скрывается больше всего ценной информации. Так что, если я хочу продвинуться с Zenno, мне нужно отправиться на сторону русского сообщества!
На данный момент, единственное слово, которое я знаю на русском, это 'здоровье'
Есть большая вероятность что при больших объемах потоков проект зациклиться и станет работать медленно, разумнее всего при итерации попыток вставки пробовать другие методы, такие как SET, либо эмуляцию клавиатуры на крайний вариант:dd:
 
  • Оценить
Реакции: Pierre Paul Jacques
Друзья, появилась новая инфа на счет вставки, но с помощью хот кеев. По сути метод прост: Устанавливаете софт который биндит хоткеи и эмулируете для каждого отдельного проекта с буфером обмена свой отдельный метод вставки. Так же возможно напрямую менять файл с вариацией вставки текста.:dt:
 
  • Оценить
Реакции: Pierre Paul Jacques
Друзья, появилась новая инфа на счет вставки, но с помощью хот кеев. По сути метод прост: Устанавливаете софт который биндит хоткеи и эмулируете для каждого отдельного проекта с буфером обмена свой отдельный метод вставки. Так же возможно напрямую менять файл с вариацией вставки текста.:dt:
а буфер обмена как был один и не предназначеный для работы в многопотоке, так и остался :bk:
 
  • Оценить
Реакции: Pierre Paul Jacques
Друзья, появилась новая инфа на счет вставки, но с помощью хот кеев. По сути метод прост: Устанавливаете софт который биндит хоткеи и эмулируете для каждого отдельного проекта с буфером обмена свой отдельный метод вставки. Так же возможно напрямую менять файл с вариацией вставки текста.:dt:
Напитонил софт для вас, работает как с буфером так и с методом быстрой прописи текста, а так же есть настройка и пример. Не забудьте установить python с несколькими библиотеками, которые найдете в коде:bt:
Чтобы применить в инстансе необходима команда:

instance.ActiveTab.KeyEvent("Горячая клавиша", "press", "Клавиша с которой начинается комбинация");
 

Вложения

Последнее редактирование:
  • Оценить
Реакции: Pierre Paul Jacques
Напитонил софт для вас, работает как с буфером так и с методом быстрой прописи текста, а так же есть настройка и пример. Не забудьте установить python с несколькими библиотеками, которые найдете в коде:bt:
Чтобы применить в инстансе необходима команда:

instance.ActiveTab.KeyEvent("Горячая клавиша", "press", "Клавиша с которой начинается комбинация");
что это меняет в глобальном смысле кроме того, что появился дополнительный костыль?
 
что это меняет в глобальном смысле кроме того, что появился дополнительный костыль?
ничего не меняет... просто глянь его историю сообщений ;-)

думаю он тебе ответит примерно так :bk:хотя может преды научили общаться...

121190
 
что это меняет в глобальном смысле кроме того, что появился дополнительный костыль?
Меняет то что теперь работает одна программа через которую проходит весь буфер обмена, вам теперь не нужно постоянно выполнять в каждом проекте и потоке кусок кода который отвечает за прерывание потока и установку текста в буфер. Все работает уже скомпилированным и тем является быстрым решением для многопоточного многопроектного проектища)

вы просто братья по несчастью, которые хотят быстрой и правильной работы от чего то одного. Так вот я предоставил вам несколько вариаций обхода неправильной логики дабы прийти к одному годному варианту.

вы просто братья по несчастью, которые хотят быстрой и правильной работы от чего то одного. Так вот я предоставил вам несколько вариаций обхода неправильной логики дабы прийти к одному годному варианту.
Единственный костыль с которым вы столкнетесь, это спам горячей клавиши если питон не включен.
 
Выдано очередное предупреждение.
будто нейронка пишет
любой код=часть природы
нейронка исправляет ошибки и смазывает углы а так же расписывает каждое действие
нет нашей инициации=нет кода
логика решения не от нейронки а от переваренных нами ошибок и действий которые их сопроводили
 
Буфер обмена можно выбрать из броузера в переменную. Не затрагивая буфер Windows
 
  • Оценить
Реакции: Dmitriy_Zenno
Существует профессиональное и полностью изолированное решение. Создание виртуального буфера обмена с помощью нативного JavaScript API.

Скрипт ниже берет значение из переменной ZennoPoster и применяет браузерную команду insertText к активному (выделенному) элементу. Для сайта (включая сложные фреймворки вроде React или Vue) это выглядит в точности как вставка из буфера обмена единым блоком. При этом:

  1. Системный буфер обмена Windows вообще не используется.
  2. Потоки работают на 100% независимо и никогда не пересекаются.
  3. Корректно срабатывают все события input и change на сайте.
C#:
Развернуть Свернуть Копировать
// Имя переменной ZennoPoster, содержимое которой нужно вставить
string variableName = "text";

try
{
    // 1. Получаем текст
    string text = project.Variables[variableName].Value;

    if (string.IsNullOrEmpty(text))
    {
        project.SendWarningToLog("[VirtualClipboard] Переменная пуста. Нечего вставлять.");
        return "empty";
    }

    if (instance.ActiveTab.IsVoid)
    {
        throw new System.Exception("Активная вкладка недоступна.");
    }

    // 2. ЖЕСТКАЯ НОРМАЛИЗАЦИЯ: Убираем конфликты Windows-переносов (\r\n) и Mac/Linux (\n)
    text = text.Replace("\r\n", "\n").Replace("\r", "\n");

    // 3. Кодируем в Base64 для безопасной передачи
    byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(text);
    string base64Text = System.Convert.ToBase64String(textBytes);

    // 4. Формируем усовершенствованный JS-код
    string jsCode = @"
    (function() {
        function decodeB64Utf8(b64) {
            var bin = window.atob(b64);
            var bytes = new Uint8Array(bin.length);
            for (var i = 0; i < bin.length; i++) {
                bytes[i] = bin.charCodeAt(i);
            }
            return new TextDecoder('utf-8').decode(bytes);
        }

        var activeEl = document.activeElement;
       
        if (!activeEl || activeEl.tagName === 'BODY') {
            return 'no_focus';
        }

        var textToPaste = decodeB64Utf8('" + base64Text + @"');

        if (activeEl.hasAttribute('maxlength')) {
            activeEl.removeAttribute('maxlength');
        }

        // --- УРОВЕНЬ 1: Эмуляция события Ctrl+V (Paste Event) ---
        // Идеально для сложных сайтов. Мы заставляем сайт думать, что произошла реальная вставка.
        try {
            var dataTransfer = new DataTransfer();
            dataTransfer.setData('text/plain', textToPaste);
           
            var pasteEvent = new ClipboardEvent('paste', {
                clipboardData: dataTransfer,
                bubbles: true,
                cancelable: true
            });
           
            // Если сайт перехватил событие (вернул false), значит он сам обработал текст
            var handledBySite = !activeEl.dispatchEvent(pasteEvent);
            if (handledBySite) {
                activeEl.dispatchEvent(new Event('input', { bubbles: true }));
                activeEl.dispatchEvent(new Event('change', { bubbles: true }));
                return 'ok';
            }
        } catch (e) {
            // Игнорируем ошибку, переходим к следующему методу
        }

        var success = false;

        // --- УРОВЕНЬ 2: Нативная команда браузера ---
        try {
            success = document.execCommand('insertText', false, textToPaste);
        } catch(e) {
            success = false;
        }

        // --- УРОВЕНЬ 3: Глубокий Fallback ---
        // Проверяем, вставился ли текст. Если нет — вставляем вручную с учетом структуры.
        if (!success || (activeEl.value !== undefined && activeEl.value.indexOf(textToPaste) === -1)) {
           
            // Для классических <input> и <textarea>
            if (activeEl.tagName === 'INPUT' || activeEl.tagName === 'TEXTAREA') {
                var start = activeEl.selectionStart;
                var end = activeEl.selectionEnd;
                var val = activeEl.value;
               
                activeEl.value = val.substring(0, start) + textToPaste + val.substring(end);
                activeEl.selectionStart = activeEl.selectionEnd = start + textToPaste.length;
                success = true;
            }
            // Для сложных редакторов (contenteditable)
            else if (activeEl.isContentEditable) {
                var sel = window.getSelection();
                if (sel.rangeCount > 0) {
                    var range = sel.getRangeAt(0);
                    range.deleteContents();
                   
                    // Разбиваем текст по строкам и создаем правильную HTML-структуру с тегами <br>
                    var lines = textToPaste.split('\n');
                    var frag = document.createDocumentFragment();
                   
                    for (var i = 0; i < lines.length; i++) {
                        frag.appendChild(document.createTextNode(lines[i]));
                        // Добавляем перенос строки, если это не последняя строка
                        if (i < lines.length - 1) {
                            frag.appendChild(document.createElement('br'));
                        }
                    }
                   
                    range.insertNode(frag);
                    range.collapse(false); // Сдвигаем курсор в конец
                    success = true;
                } else {
                    activeEl.innerText += textToPaste;
                    success = true;
                }
            }
        }
       
        // Триггерим события изменения для активации кнопок 'Отправить'
        if (success) {
            activeEl.dispatchEvent(new Event('input', { bubbles: true }));
            activeEl.dispatchEvent(new Event('change', { bubbles: true }));
        }
       
        return success ? 'ok' : 'fail';
    })();
    ";

    // 5. Выполняем скрипт
    string result = instance.ActiveTab.MainDocument.EvaluateScript(jsCode);

    // 6. Обработка результатов
    if (result == "no_focus")
    {
        throw new System.Exception("Ни один элемент на странице не находится в фокусе.");
    }
    if (result == "fail")
    {
        throw new System.Exception("Браузер отклонил вставку текста всеми 3 методами.");
    }

    project.SendInfoToLog("[VirtualClipboard] Мультистрочный текст успешно вставлен.");
    return "ok";
}
catch (System.Threading.ThreadAbortException)
{
    project.SendWarningToLog("[VirtualClipboard] Выполнение прервано пользователем.");
    return "aborted";
}
catch (System.Exception ex)
{
    project.SendErrorToLog("[VirtualClipboard] Ошибка: " + ex.Message);
    return "error";
}
 
Последнее редактирование:
Существует профессиональное и полностью изолированное решение. Создание виртуального буфера обмена с помощью нативного JavaScript API.

Скрипт ниже берет значение из переменной ZennoPoster и применяет браузерную команду insertText к активному (выделенному) элементу. Для сайта (включая сложные фреймворки вроде React или Vue) это выглядит в точности как вставка из буфера обмена единым блоком. При этом:

  1. Системный буфер обмена Windows вообще не используется.
  2. Потоки работают на 100% независимо и никогда не пересекаются.
  3. Корректно срабатывают все события input и change на сайте.
C#:
Развернуть Свернуть Копировать
// Имя переменной ZennoPoster, содержимое которой нужно "вставить"
string variableName = "text_to_paste";

try
{
    // 1. Получаем текст
    string text = project.Variables[variableName].Value;

    if (string.IsNullOrEmpty(text))
    {
        project.SendWarningToLog("[VirtualClipboard] Переменная пуста. Нечего вставлять.");
        return "empty";
    }

    if (instance.ActiveTab.IsVoid)
    {
        throw new System.Exception("Активная вкладка недоступна.");
    }

    // 2. Безопасное экранирование текста для передачи в JavaScript
    // Это гарантирует, что переносы строк, кавычки и слэши не сломают JS-код
    string escapedText = text.Replace("\\", "\\\\")
                             .Replace("\"", "\\\"")
                             .Replace("\r", "")
                             .Replace("\n", "\\n");

    // 3. Формируем JS-код виртуальной вставки
    // Используем конкатенацию вместо string.Format, чтобы избежать ошибки с { и }
    string jsCode = @"
    (function() {
        var textToPaste = """ + escapedText + @""";
        var activeEl = document.activeElement;
       
        // Проверяем, установлен ли фокус на какой-либо элемент ввода
        if (!activeEl || activeEl.tagName === 'BODY') {
            return 'no_focus';
        }

        // Основной метод: Нативная команда браузера.
        // Вставляет текст единым куском (как Ctrl+V), не затрагивая буфер ОС
        // и сохраняя возможность отмены (Undo/Ctrl+Z) в браузере.
        var success = document.execCommand('insertText', false, textToPaste);
       
        // Fallback-метод: Если сайт блокирует execCommand, симулируем вставку вручную
        if (!success) {
            var start = activeEl.selectionStart;
            var end = activeEl.selectionEnd;
           
            // Если это стандартное поле input или textarea
            if (typeof start === 'number') {
                var val = activeEl.value;
                activeEl.value = val.slice(0, start) + textToPaste + val.slice(end);
                activeEl.selectionStart = activeEl.selectionEnd = start + textToPaste.length;
               
                // Триггерим события для активации React/Vue обработчиков
                activeEl.dispatchEvent(new Event('input', { bubbles: true }));
                activeEl.dispatchEvent(new Event('change', { bubbles: true }));
                success = true;
            }
            // Если это contenteditable элемент (например, WhatsApp Web, WYSIWYG редакторы)
            else if (activeEl.isContentEditable) {
                activeEl.innerText += textToPaste;
                activeEl.dispatchEvent(new Event('input', { bubbles: true }));
                success = true;
            }
        }
       
        return success ? 'ok' : 'fail';
    })();
    ";

    // 4. Выполняем скрипт внутри контекста браузера текущего потока
    string result = instance.ActiveTab.MainDocument.EvaluateScript(jsCode);

    // 5. Обработка результатов
    if (result == "no_focus")
    {
        throw new System.Exception("Ни один элемент на странице не находится в фокусе. Перед вставкой необходимо кликнуть в нужное поле.");
    }
    if (result == "fail")
    {
        throw new System.Exception("Браузер отклонил виртуальную вставку. Возможно, активный элемент не поддерживает текстовый ввод.");
    }

    project.SendInfoToLog("[VirtualClipboard] Текст успешно вставлен (Изолированно от ОС).");
    return "ok";
}
catch (System.Threading.ThreadAbortException)
{
    project.SendWarningToLog("[VirtualClipboard] Выполнение прервано пользователем.");
    return "aborted";
}
catch (System.Exception ex)
{
    project.SendErrorToLog("[VirtualClipboard] Критическая ошибка: " + ex.Message);
    return "error";
}
А чем это профессиональное решение отличается кардинально например от вот этого?
 
А чем это профессиональное решение отличается кардинально например от вот этого?
Оба скрипта решают одну глобальную задачу — изоляцию потоков от системного буфера обмена ОС Windows.Но первый скрипт нужен для безопасного ЧТЕНИЯ с сайта (копирование), а второй — для безопасной ЗАПИСИ на сайт (вставка). Используя их вместе, вы получаете полностью замкнутый и независимый буфер обмена внутри конкретного потока браузера.
 
  • Оценить
Реакции: BAZAg

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)