Pull to refresh
24
0
Антон Миронов @mviorno

Developer

Send message
Можно. Но, потеряем тогда оригинал, а он бывает важен. Может оно и специфика, но во всех больших контролах, что лично мне пришлось разрабатывать (RichEdit, Spreadsheet, Scheduler), обработка клавиатуры и мышки полностью кастомная. И при любых подозрениях на эту часть кода, я бы обязательно взглянул на неоптимизированный оригинал. Плюс, см. аргументы выше.
Кольцевой буфер, по дефолту на 1000 элементов, размер настраивается в коде/конфиге. Размер элемента переменный (json), в ориентировочно десятки-сотни байт. Если всё это вместе превышает ~3Mb, отправляются самые свежие по времени данные, поместившиеся в 3Mb.
Спасибо кэп, см. первую картинку в статье. В случае двойного клика восстанавливать ничего и не надо, напротив, стОит убрать/свернуть «лишние» сообщения, предшествующие (и следующие за) WM_LBUTTONDBLCLK. Выкинуть их «превентивно» нельзя, ибо в таком случае не отловишь одиночный клик. А еще, сюрприз, сообщения WM_LBUTTONSINGLECLICK в винде не существует, и таки придётся анализировать соответствующие пары Down/Up. Аналогичная ситуация и с KeyDown, KeyPress, KeyUp.

Может возникнуть соблазн сделать обработку не на сервере, а на клиентах, типа ближе к телу, сразу учесть особенности платформы и т.п. Но есть один ньюанс) Выпущенную версию клиента обратно не воротишь, улучшить что-то или поправить косяк получится только в следующей версии клиента. Пока будешь делать новую версию, «плохой» клиент успеет распространиться в природе, и попробуй теперь замени его на более новый, стильный, модный и молодёжный. А логика обработки и показа на сервере может быть быстро/легко исправлена и расширена, полностью независимо от клиентов и их версий.
Приучать — вообще бесполезняк, грамотные люди и сами проект прилагают, у остальных приходится его выцарапывать. Мне больше всего нравится подход, когда на заявление «у меня падает», мы сами отдаём клиенту работающий тестовый проект с комментарем в духе «вот это у нас работает, попробуй у себя и, если не валится, добавь код, чтобы упало». Очень часто после такого ответа человек самостоятельно находит и фиксит проблему в своём коде. И это всё за один раунд переписки.

А больше всего радуют (но нечасто) реально продвинутые ребята, которые приходят с проблемой типа «в методе X класса Y у вас в N-ной строке косяк, надо исправить вот так. поправьте плиз, чтобы мне из исходников ваши компоненты не собирать». Или, «я хочу что-то этакое закастомизить, почти всё сделал, но не хватает virtual в методe X класса Y, чтобы перекрыть и получить искомое. впишите, не сочтите за труд.»
Бывают именно такие ситуации, не каждый день, конечно. Когда к нам приходят с обоснованными подозрениями, что виноваты наши компоненты (например, перекомпилили с новой их версией и стало ломаться; но не воспроизводится ни у автора программы, ни у нас), нам по-любому надо докопаться до причины и уже править или на нашей стороне, и/или объяснить автору, как поправить на его стороне.

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

Логировать было бы неплохо, но тут надо волевое политическое решение принимать, на уровне фирмы.
Насчёт штатного функционала сложной системы — эх, если бы всё было так радужно, не было бы у службы поддержки проблем.

Наша ситуаций такова. Мы разрабатываем компоненты, продаём их нашим клиентам, программистам. Те, в свою очередь, пишут с их использованием софт для своих заказчиков. Далее, довольно типовая тупиковая ситуация. Из 50 заказчиков у одного софт подпадывает. Заказчик жалуется своему поставщику, тот в свою очередь жалуется нам в саппорт. При этом проблема не поспроизводится нигде, кроме как на машине у того самого заказчика. Teamviewer к машине не дают, студию и прочие нужные тулзы поставить тоже нельзя, передеплоить новую версию приложения или нельзя вообще или не получается сделать быстро, а разобраться и пофиксить надо уже вчера.

В наших общих интересах, в создавшихся условиях, собрать максимально объективную информацию о возникновении проблемы и максимально быстро её поправить. Наша служба поддержки в таких случаях пытается объяснить, какая инфа нужна, и как её собрать (те же дампы и прочее). Это все занимает время, и немало. Для экономии времени, они просили нас сделать им тулзу, которая автоматически сделает всё, что необходимо. От программиста лишь требуется дописать батник для запуска его приложения и отправить заказчику вместе с тулзой. От заказчика требуется лишь скачать и запустить в один клик.

Предлагаемые вами сбор дампов руками заказчика и прочие манипуляции, которые надо провести его силами, вполне применимы и возможны, но обычно уходит довольно много времени, чтобы объяснить заказчику, что и как ему делать. А наша служба подддержки тут в лучшем случае 3я в цепочке заказчик <-> программист <-> devexpress.
Очень сомневаюсь, обратная совместимость постоянно будет тянуть обратно в трясину. Тут тот самый случай, когда сделать новое будет проще, чем починить старое. А у чего-то нового будут большие проблемы с тем чтобы взлететь.
Ваш вариант, несмотря на простоту, потенциально опасен тем, что кардинально меняет процесс запуска приложения.

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

Второе, те самые конфиги. Приложение будет пытаться подхватить не свой конфиг, а конфиг загрузчика. Решение (не уверен, что полноценное) — заменить конфиг загрузчика копией конфига приложения.

Третье — точки входа в приложение часто помечаются атрибутами, задающими COM threading model, например STAThread. «Решение» — писать по отдельному загрузчику на каждую threading model. Какой из них использовать, выбирать или вручную, или писать ещё один, головной загрузчик.

Четвёртое. Если приложение где-то в своих потрохах использует Assembly.GetEntryAssembly, то его может ждать большой сюрприз.

Будут ещё технические моменты по правильному определению точки входа приложения (а они разные бывают, взять хотя бы приложение на VB). По запуску приложения через reflection, передаче ему командной строки — но это всё решаемо в рабочем порядке.

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

PS:
Есть хорошая статья, описывающая, что делает CLR, перед тем как стартовать приложение. Не так уж и мало мест, где что-то ещё может пойти не совсем так, как ожидалось.
Да, с битностью, как ни крути, ни верти — 2 сборки где-нибудь да получаются. Интересно, если, экспортировать функцию из managed-сборки — вылезут ли те же самые грабли с подпиской на UnhandledException. Если не вылезут, это хороший плюс такому подходу и потенциальная работоспособность тулзы в консольном приложении.
Интересная штука, не знал. В нашем конкретном случае всё равно её не получилось бы использовать — нужна поддержка .net framework 4.0
С использованием ThreadStatic/TLS проблематично сделать вот такую тотальную зачистку хуков:

protected void RemoveHooks() {
    lock (hooks) {
        foreach (int threadId in hooks.Keys)
            UninstallHook(threadId, hooks[threadId]);
        hooks.Clear();
    }
}
Используется, конечно, микросервисов много, если глазками за каждым из них приглядывать, то у разработчиков ручки отвалятся :) Одно из внутренних внедрений как раз к себе в проект и было.
Все возможные антивирусы не проверяли. Те что в наличии есть — не паникуют. По логике вещей и не должны бы, т.к. приложение установило хуки самостоятельно, при помощи кода из подписанной dll-ки, явно прописанной в зависимостях. Т.е. сборка вполне легально попала в процесс.

Более того, антивири не ругались даже в тех случаях, когда сборка в процесс внедрялась гораздо более противоестественным образом. Делал такое для техподдержки, для тех случаев, когда клиент по различным причинам не может или не хочет пересобирать/перевыкладывать приложение только ради включения в него крэш-репортера. А подробная информация о падении критично важна для воспроизведения и фикса.
То что raw-отчёт по событиям слишком подробный — факт. Поэтому мы на сервере при показе его сильно «упрощаем» (см. по ссылке), а для мудрёных случаев сохранили возможность посмотреть исходный вариант. У меня про процесс упрощения в загашнике статья полуготовая лежит.
Как раз сегодня запилили такую фичу в Web-клиенте — возможность исключить security-sensitive информацию из репорта ещё из до отправки его на сервер. См. файл, свойства IgnoreFormFields, IgnoreHeaders, IgnoreCookies, IgnoreServerVariables. Через запятую задаются маски имён ключей, которые на сервер отправлять не надо.
Андрей, ИМХО, подобная проверка уже на грани абсурда. Следующий шаг — запретить напрямую обращаться к свойствам объекта, а разрешить только брать значения в локальную переменную — вдруг свойство из соседней нитки кто-нить занулит между обращениями. Принцип разумной достаточности никто не отменял.
Спасибо, поправили (кроме лока на тип — оно так надёжнее будет, чем на статическую переменную полагаться в многопоточной среде).
Вот тут насчет индралина поподробнее. Вкратце, штука далеко не безобидная, кроме того, надо хорошо соображать, как правильно его применять.
1) Появится конечно, просто не получается сделать всё и сразу.

Information

Rating
Does not participate
Location
Тула, Тульская обл., Россия
Date of birth
Registered
Activity