Задачка для размышлений

Здравствуйте. Попалась тут очень забавная задачка.
Есть софт и некий аппарат. Софт написан немцами давным давно на VB. Так вот проблема в том что этот софт адекватно видит прибор и может с ним работать только на винде с установленным форматом даты Немецкий (Германия). Если его поменять на русский то прога в упор не видит прибора. Причем в декомпилированных текстах формата даты который бы учавствовал в обмене я не увидел.
Как думаете это баг или фича??

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

перехваченный дамп:
55 0E 21 20 80 07 00 00 00 EB AA D3 5B AA

формат тут такой:

[55 0E 21 20] [80 07 00 00 00] [EB AA D3 5B AA]

cзапрос - еще чего то, думал длина но нет - в конце CRC того что посередине.

суть в том что немцы производят невероятное количество лишних манипуляций но суть в том что.
есть строка “8007000000” далее она по 2 символа переводится в число и затем в символ char.
Далее полученная строка преобразуется в массив байт кодом:

stringBuilder.Insert(0, (char)(Convert.ToInt32(text2, 16))); // каждые 2 символа в число и символ

byte[] bytes = Encoding.GetEncoding(1252).GetBytes(strInput);

так вот у меня из строки 80 07 всегда получается 3f 07
Как это вообще возможно то?? в данном случае формат даты не имеет значения.
Че за цыганские шутки???

Ну про 07 всё понятно вроде бы.

А вот почему '\u0080' превравращается в 3f хз.
Можно посмотреть исходник примерно тут но там чот сложно :confounded:

может компилятор VB как то по другому работает?? Исходная сборка на 2,0 вообще написана была … но у меня и на 2,0 тоже 3f. мистика какая то

А куда можно пожаловаться в майкрософт с этой проблемой??

Жаловаться можно например тут https://developercommunity.visualstudio.com/spaces/61/index.html, но кто сказал, что это проблема. Может кодировки так и должны преобразовываться.

Тут же надо помнить, что в .NET char это 2 байта, а string это Юникод/UTF-16.
И Encoding.GetBytes пытается преобразовать эти юникодные символы в нужную кодировку.

Например, Encoding.GetEncoding(1251).GetBytes("абвг") вернет e0 e1 e2 e3 cp1251(7) - Linux manual page

0080 это что-то странное вряд ли существующее в 1252 кодировке &#57472; - <Control>: U+0080 - Unicode Character Table
Так что хз по каким правилам оно конвертирует в таких случаях.

Так прога на VB при немецком языке выдает 80 07 а при русском языке дает 3f 07
Где то же проблема существует. Допустим если взять кодировку 950 то она возвращает 80 07 правда с ней другие символы неправильно переводит.

В любом случае даже если и не глюк то пусть сам МС это подтвердит.

а, 3f это ж ? в ASCII. Видимо оно используется для всех неконвертируемых символов.

в исходнике выше:

                   byte bReplacement = mapUnicodeToBytes[fallback.DefaultString[0]];

                   ...

                    while (chars < charEnd)
                    {
                        char ch2 = *chars;
                        chars++;
 
                        byte bTemp = mapUnicodeToBytes[ch2];
 
                        if (bTemp == 0 && ch2 != (char)0)
                            *bytes = bReplacement;
                        else
                            *bytes = bTemp;
 
                        bytes++;
                    }

Непонятно правда почему это зависит от языка системы. По идее ж в любом случае юникодный 0080 не преобразовать в символ из 1252 :thinking:

Вот вот … и каким образом решить эту задачу тоже не ясно. На форумах МС пока молчат

А язык где именно выставлен? У меня и с немецким форматом то же самое.

Гугл говорит, что там есть функция для создания char по текущей однобайтовой кодировке.
Может она используется?

Chr, ChrW Functions | Microsoft Docs
Why Encoding.Default.GetBytes() returns different results in VB.NET and C#? - Stack Overflow

Если пишете на C# то язык не имеет значения. Всегда и везде получается 3F. Подобный глюк наблюдается только в программе которая разработана на VB.

Может компилятор VB ее где то внутри и использует но визуально в коде этого не видно. Использую ILSpy.


ХексСтр2АСКИ дает правильный результат 80070000 и при русском языке VB делает из этого тоже самое в байтах.
То есть проблема только в шарпе.

Просто задача то стоит чтобы пропатчить как то прогу чтобы она работала на всех версиях одинаково.

Если я правильно понял то мне нужно в этой функции

Заменить String.Chr на String.ChrB


Чтобы в системах с расширенным чаром всегда был один байт. Правильно??

Эти функции в новом .net не поддерживаются… что же делать то ((
Поставил принудительно культуру для потока и приложения но все равно не работает.

Так может просто не конвертировать в char?)
Сразу в массив байтов.

Да там весь протокол завязан на обработке строк. Гоняют туда сюда. То в байты то из байт в строку потом складывают и опять в байты. Все места изменения этой строки сложно отследить.

Пытаюсь сейчас внедрить свою функцию в код. Но тоже как то не очень …

У меня работает.

using Microsoft.VisualBasic;
using System;
using System.Globalization;
using System.Text;
using System.Threading;

public class Program
{
    public static void Main()
    {
        Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");

        var sb = new StringBuilder();
        sb.Insert(0, Strings.Chr(Convert.ToInt32("80", 16)));

        string strInput = sb.ToString();
        
        var bytes = Encoding.GetEncoding(1252).GetBytes(strInput);
    }
}

Ну да … работает.
Внедрил через ILSpy код локализации. MessageBox сообщает что стоит de-De а все равно не работает.

код внедрял такой:

            Application.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("de-DE");
            System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("de-DE");
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo("de-DE");

Тут само взаимодествие происходит в дополнительной библиотеке. Но ведь культура должна распространятся и на нее??


Хоть тресни … Хотя в конструкторе формы 8007 тоже правильно преобразовалось

В общем с C# все понятно. Если использовать Strings.Chr то она какое то свое значение возвращает в char.
А у меня было упаковка в char не работало.
Теперь осталось понять как задать нужную культуру для основной проги на VB. Инъекции с культурой не помогают.

Может там другие потоки создаются?

https://stackoverflow.com/a/7536117/964478

Да тут 2.0. Вроде распихал везде где только можно. Также впихнул туда мессаджбокс он выдает что там de-DE локализация. Непонятно совсем.

Подвязываю библиотеку к студии, запускаю отладчик, создаю экземпляр класса из либы и там внутри встроен код локализации. Код показывается немецкий, закидываю туда данные 80070000 и получаю в ответ что что надо в кодировке 1252.

В оригинальной программе также после загрузки показывается немецкий, а в порт сыпется кривые данные. Ну как так то … ((

Может быть как-то связано с форматом даты, и язык не при чем…

Русский формат даты

Немецкий формат даты

Если дата участвует в обмене данными с устройством, то формат может иметь значение.