Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
tormozit opened this issue Jun 7, 2024 · 18 comments

Comments

@tormozit
Copy link

tormozit commented Jun 7, 2024

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

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

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

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

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

Окружение

  • Версия: ОСкрипт 1.9
@tormozit
Copy link
Author

tormozit commented Jun 7, 2024

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

@bolsun
Copy link

bolsun commented Jun 7, 2024

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

if (rawValue == textEncodingEnum.Ansi)

@EvilBeaver
Copy link
Owner

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

@bolsun
Copy link

bolsun commented Jun 9, 2024

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

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)

@Mr-Rm
Copy link
Collaborator

Mr-Rm commented Jun 11, 2024

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

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

@bolsun
Copy link

bolsun commented Jun 11, 2024

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

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

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

@bolsun
Copy link

bolsun commented Jun 11, 2024

Воспроизвел

image

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

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

@Mr-Rm
Copy link
Collaborator

Mr-Rm commented Jun 11, 2024

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

@bolsun
Copy link

bolsun commented Jun 11, 2024

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

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

@bolsun
Copy link

bolsun commented Jun 11, 2024

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

@bolsun
Copy link

bolsun commented Jun 11, 2024

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

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

@bolsun
Copy link

bolsun commented Jun 11, 2024

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

@EvilBeaver
Copy link
Owner

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

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

@bolsun
Copy link

bolsun commented Jun 13, 2024

ContextDiscoverer

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

@Mr-Rm
Copy link
Collaborator

Mr-Rm commented Jun 13, 2024

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

В TextEncodingEnum CreateInstance()

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

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

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

@akpaevj
Copy link
Contributor

akpaevj commented Jun 18, 2024

ContextDiscoverer

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

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

@bolsun
Copy link

bolsun commented Jun 18, 2024

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

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

@Mr-Rm
Copy link
Collaborator

Mr-Rm commented Jun 18, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants