OneScript icon indicating copy to clipboard operation
OneScript copied to clipboard

Неверное значение аргумента ТекстовыйДокумент.Записать(Ч, КодировкаТекста.ANSI)

Open tormozit opened this issue 1 year ago • 20 comments

В среде Турбоконф выполняю скрипт обращающийся к системному перечислению КодировкаТекста. Довольно часто (бывает по 20 раз в день) после каких то действий его значения портятся и стабильно возникает ошибка при их использовании. https://turboconf.ru/Tasks/9510

Воспроизведение ошибки

  1. Неизвестные действия
  2. Выполнить код
ТД = Новый ТекстовыйДокумент;
ИмяФайла = ПолучитьИмяВременногоФайла();
ТД.Записать(ИмяФайла, КодировкаТекста.ANSI);

Возникает ошибка Неверное значение аргумента ТекстовыйДокумент.Записать(ИмяФайла, КодировкаТекста.ANSI)

Ожидаемое поведение Ошибки не возникает

Окружение

  • Версия: ОСкрипт 1.9

tormozit avatar Jun 07 '24 18:06 tormozit

Ранее @bolsun обсуждал это с @EvilBeaver https://t.me/oscript_library/115250 Ошибка пропадает, если заменить перечисление на строку "utf-8". При замене на "ansi" пишет "Неверное имя кодировки".

tormozit avatar Jun 07 '24 18:06 tormozit

Вот еще информация, которая может быть полезна: Не срабатывает условие в строке

if (rawValue == textEncodingEnum.Ansi)

bolsun avatar Jun 07 '24 19:06 bolsun

Коллеги, без вашей помощи не обойтись. Нужно отловить момент выброса исключения и получить хотя бы стектрейс.

EvilBeaver avatar Jun 09 '24 04:06 EvilBeaver

Коллеги, без вашей помощи не обойтись. Нужно отловить момент выброса исключения и получить хотя бы стектрейс.

ScriptEngine.HostedScript.Library.TextEncodingEnum.GetEncoding(IValue encoding, Boolean addBOM) в ScriptEngine.HostedScript.Library.TextDocumentContext.GetDefaultWriter(String path, IValue encoding) в ScriptEngine.HostedScript.Library.TextDocumentContext.Write(String path, IValue encoding, String lineSeparator) в lambda_method(Closure , TextDocumentContext , IValue[] ) в ScriptEngine.Machine.Contexts.AutoContext`1.CallAsProcedure(Int32 methodNumber, IValue[] arguments) в ScriptEngine.Machine.MachineInstance.ResolveMethodProc(Int32 arg) в ScriptEngine.Machine.MachineInstance.MainCommandLoop() в ScriptEngine.Machine.MachineInstance.ExecuteCode() в ScriptEngine.Machine.MachineInstance.ExecuteMethod(IRunnable sdo, Int32 methodIndex, IValue[] arguments) в ScriptEngine.Machine.Contexts.ScriptDrivenObject.CallAsFunction(Int32 methodNumber, IValue[] arguments, IValue& retValue) в TurboConf.HostApplication.HostApplicationForm.ExecuteScript(Script script, Keys ctrl, Keys alt, Keys shift, ScreenForm statusForm, String entryPoint, ScriptOptions options, IVariable[] parameters)

bolsun avatar Jun 09 '24 08:06 bolsun

Воспроизвести вне TurboConf не получается. @bolsun: после того, как начнет появляться ошибка, в выделенной на первом скриншоте строке чему равно textEncodingEnum.Ansi? Появлется ли ошибка при использовании КодировкаТекста.OEM или КодировкаТекста.UTF8?

Строка "ANSI" - недопустимое название кодировки, используйте "windows-1251".

Mr-Rm avatar Jun 11 '24 09:06 Mr-Rm

Как назло, сейчас перестало воспроизводиться.

КодировкаТекста.UTF8

Насколько я помню с этим значением так же возникала ошибка.

bolsun avatar Jun 11 '24 10:06 bolsun

Воспроизвел

image

Пытаюсь понять когда точно возникает ошибка.

Думал, что достаточно было чтобы ИР Адаптер инициализировал COM соединение, но нужно именно чтобы еще подсказка адаптера сработала.

bolsun avatar Jun 11 '24 11:06 bolsun

На вид - одинаково. Но если при этом действительно не срабатывает if (rawValue == textEncodingEnum.Ansi), значит, это разные объекты. Получается, в какой-то момент среда повторно инициализируется, и GlobalsManager создаёт копию перечисления. Как? когда? как поймать? Замена == на Equals не поможет - метод перегружен.

Mr-Rm avatar Jun 11 '24 12:06 Mr-Rm

На вид - одинаково. Но если при этом действительно не срабатывает if (rawValue == textEncodingEnum.Ansi), значит, это разные объекты. Получается, в какой-то момент среда повторно инициализируется, и GlobalsManager создаёт копию перечисления. Как? когда? как поймать?

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

bolsun avatar Jun 11 '24 13:06 bolsun

~и еще важный момент, скрипт вызывается асинхронно через Task, возможно в этот момент выполняется другой скрипт.~

bolsun avatar Jun 11 '24 13:06 bolsun

и еще важный момент, скрипт вызывается асинхронно через Task, возможно в этот момент выполняется другой скрипт.

нет, не асинхронно, перепутал. Никакой другой скрипт в это время не выполняется.

bolsun avatar Jun 11 '24 13:06 bolsun

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

bolsun avatar Jun 11 '24 13:06 bolsun

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

ContextDiscoverer, там 2 метода по поиску перечислений. В обоих поставить бряк

EvilBeaver avatar Jun 12 '24 16:06 EvilBeaver

ContextDiscoverer

Я каждый раз создаю новый движок, при асинхронном вызове скрипта. Вызываю var engine = new HostedScriptEngine(); Там видимо и происходит регистрация перечислений заново. Но тогда архитектура движка непонятна,. Если он использует общие статичные перечисления в разных инстансах движка, то тогда точно сравнивать нужно по ключу.

bolsun avatar Jun 13 '24 11:06 bolsun

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

В TextEncodingEnum CreateInstance()

более надежно сравнивать значения по уникальному строковому идентификатору

Перечисления следовало бы сравнивать по числовому значению enum.

А сейчас в движке есть два существенно разных способа определить перечисления

Mr-Rm avatar Jun 13 '24 11:06 Mr-Rm

ContextDiscoverer

Я каждый раз создаю новый движок, при асинхронном вызове скрипта. Вызываю var engine = new HostedScriptEngine(); Там видимо и происходит регистрация перечислений заново. Но тогда архитектура движка непонятна,. Если он использует общие статичные перечисления в разных инстансах движка, то тогда точно сравнивать нужно по ключу.

В таком сценарии надо смотреть не только на перечисления (они не статичны), а вообще на любые объекты, используемые с врапом. Могу предположить, что в какой-то момент у вас переменная-аргумент с кодировкой оказывается в одном AppDomain, а обернутое для сравнения значение в кишках движка в другом AppDomain.

akpaevj avatar Jun 18 '24 17:06 akpaevj

Вот тестовый проект для воспроизведения https://disk.yandex.ru/d/nQrSRffrbJbnPw

Нажимать кнопку и сразу или через несколько нажатий возникнет эта ошибка.

bolsun avatar Jun 18 '24 18:06 bolsun

Ошибка воспроизводится. Проблема в многопоточности. Достаточно единственного вызова await Task.Run(() => RunScript(true));, и последующие RunScript(false); приводят к падению.

Mr-Rm avatar Jun 18 '24 20:06 Mr-Rm

Я так понял проблему не стали решать. С ростом объема фонового кода я стал сталкиваться с ней все чаще в Турбоконфе. Прошу вернуться к ее рассмотрению. Вот свежий случай https://turboconf.ru/Tasks/10190

tormozit avatar Apr 05 '25 07:04 tormozit

Я бы расчитывал на помощь @bolsun в этом вопросе, у меня нет сейчас возможности активно колупать систему типов в версии 1. Проблема вроде как разобрана, причина найдена, думаю починить сравнение перечислений можно относительно легко

EvilBeaver avatar Apr 07 '25 08:04 EvilBeaver