Имя: Пароль:
1C
 
Преобразовать String в byte array
0 detec
 
01.06.11
13:00
Приветствую!

С библиотеки CAPICOM перехожу на .NET-овский класс System.Security.Cryptography.SHA1CryptoServiceProvider, рассчитываю MD5.

Раньше с помощью ADODB.Stream читал нужный мне файл как бинарный поток и на выходе получал тип String, определяемый как COMSafeArray в отладчике. System.Security.Cryptography.SHA1CryptoServiceProvider в методе ComputeHash хочет либо Stream, либо byte array. Кто-то знает, как можно с помощью конструкции Новый COMОбъект преобразовать полученный String в byte array??

Важно! Нельзя использовать Javascript'ные вставки, т.к. код должен работать под x64.
1 Лефмихалыч
 
01.06.11
13:05
а ADODB.Stream туда нельзя прямо как есть всунуть?
2 detec
 
01.06.11
13:12
(1) пробовал, не даёт.
3 detec
 
01.06.11
13:13
Сейчас сменил класс на более подходящий System.Security.Cryptography.MD5CryptoServiceProvider, но там тоже требуется byte array или stream.
4 Serginio1
 
01.06.11
14:07
А что, мешает написать Сом сервер на Net, который бы вернул тебе строку?
5 H A D G E H O G s
 
01.06.11
14:09
Что мешает разобрать строку на массив байт в 1С и запихать его в comsafearray ?
6 H A D G E H O G s
 
01.06.11
14:09
ComSafeArray на то и ComSafeArray, чтобы через него обмениваться.
7 H A D G E H O G s
 
01.06.11
14:10
COMSafeArray (COMSafeArray)
COMSafeArray (COMSafeArray)
Методы:
GetDimensions (GetDimensions)
GetLength (GetLength)
GetLowerBound (GetLowerBound)
GetType (GetType)
GetUpperBound (GetUpperBound)
GetValue (GetValue)
IsResizable (IsResizable)
Resize (Resize)
SetValue (SetValue)
Выгрузить (Unload)

Конструкторы:
Из COMSafeArray
Из массива 1
Из массива 2
По типу элемента 1
По типу элемента 2

Описание:
Объектная оболочка над многомерным массивом SAFEARRAY из COM. Позволяет создавать и использовать SAFEARRAY для обмена данными между COM-объектами.
Для передачи массива в качестве параметра метода COM-объекта необходимо построить COMSafeArray нужной размерности с нужным типом элемента и указать построенный COMSafeArray в качестве значения входного параметра. Другие объекты 1С:Предприятия можно использовать в качестве значений входных параметров типа Массив только при наличии исчерпывающей информации о типах параметров в библиотеке типа COM-объекта.
Результат метода COM-объекта или значение выходного параметра типа Массив всегда представляется объектом COMSafeArray.
Пример:
Массив = Новый COMSafeArray("VT_I4", 2);
Массив.SetValue(0, 23);
Массив.SetValue(1, 13.5);
COMОбъект = Новый COMObject("ExampleCOMObject.ECOMClass");
COMОбъект.ProcessSafeArray(Массив);
8 Serginio1
 
01.06.11
14:14
Согласен, только ему нужен VT_I1
9 H A D G E H O G s
 
01.06.11
14:15
(8) Это из примера СП.
10 Serginio1
 
01.06.11
14:28
Кстати был ыесьма удивлен, когда
public object CreateArray(string type, int length)
       {
           return new AutoWrap(Array.CreateInstance(Type.GetType(type), length));
       }
(AutoWrap это оболочка IRflect) вотображается в 1С как COMSafeArray
11 detec
 
01.06.11
14:35
(5)

У меня уже есть возвращённый COMSafeArray. Я смотрел в отладчике - там массив с числами, я так понимаю, байтами. По идее, массив с байтами. CAPICOM на входе в метод шифрования требует тип String, и мой COMSafeArray ошибок не вызывал.

Возможно, всё дело в 8.2.14. Тут где-то пробегала тема, что в 8.2 что-то ухудшили именно в работе с .NET.

(10)

AutoWrap - есть вариант этой компоненты под x64?
12 H A D G E H O G s
 
01.06.11
14:35
(11) ЧТО мешает составить строку из байт?
13 H A D G E H O G s
 
01.06.11
14:36
Данные="";
Для i=0 По Массив.Количество()-1 Цикл
Данные=Данные+Символ(Массив[i]);
КонецЦикла;
14 detec
 
01.06.11
14:42
(13)

Спасибо, сейчас попробую.

У меня код String.GetType() возвращает "VT_UI1", где String - COMSafeArray, полученный из Стрим.Read().
15 detec
 
01.06.11
14:46
Нет, к сожалению, код с передачей переменной Данные из (13) не взлетает ((
16 H A D G E H O G s
 
01.06.11
14:48
(15) Что пишет?
17 detec
 
01.06.11
14:54
(16) пишет "неизвестная ошибка".

Я сейчас попробую сделать свой новый COMSafeArray, как описано в (7) и (8). Если я правильно понимаю, в изначально выгруженном COMSafeArray байты "неправильного" типа.
18 H A D G E H O G s
 
01.06.11
15:02
байты "неправильного" типа

как сказанул!!!
19 Serginio1
 
01.06.11
15:13
(11) Нет Это враппер для преобразования Net объектов в IDispatch v8: Объекты Net в IDispatch
20 detec
 
01.06.11
15:16
(18) )))


А теперь не могу заполнить новосозданный массив

String = СтруктураШифрования.Стрим.Read();

Массив = Новый COMSafeArray("VT_I1", String.getLength());
Для н = 0 По  String.getLength() - 1 Цикл
    Массив.SetValue(н, String.getValue(н));
КонецЦикла;

Спотыкается на 1-м элементе, String.getValue(н) у меня в отладчике показывает тип "число", 255. Я пробовал жёстко вставлять значения в новый COMSafeArray, равные 0; 1; 5. Когда попробовал вставить символ - выругалось в несоответствие типов.

Грешу уже на платформу - использую 8.2.14.460.
21 Serginio1
 
01.06.11
15:17
(19)+ Авыполняться будет взависимоти от среды
22 detec
 
01.06.11
15:19
(19) спасибо. Если ничего не поможет - попробую скомпилировать код из той темы под x64.
23 Serginio1
 
01.06.11
15:21
(20) У тебя уникоде. Поэтому нужно брать % 255 и сдвиг на 8 байт то есть делить на 256,
24 Serginio1
 
01.06.11
15:23
Но вообще можешь попробоать в VT_UI2 по идее он должен кастнуть.
25 Serginio1
 
01.06.11
15:24
Компилируй под any процессор
26 H A D G E H O G s
 
01.06.11
15:25
(23) Причем тут уникод?
Он числа вставляет.
27 Serginio1
 
01.06.11
15:26
(26) в уникоде сколько байтов?
28 H A D G E H O G s
 
01.06.11
15:28
(27) 2, 4, 8?.
29 Serginio1
 
01.06.11
15:29
(22) Тольк регасмь из по 64
@"Microsoft.NET\Framework64\v4.0.30319\regasm.exe";
с ключом /codebase
30 Serginio1
 
01.06.11
15:30
(28) 2 байта то есть до 64 с чем то, в байте макс значеие 255
31 H A D G E H O G s
 
01.06.11
15:30
Скажите мне тока, почему "VT_I1", а не "VT_UI1"
32 H A D G E H O G s
 
01.06.11
15:31
(30) ППЦ.
2, 4, возможно 8 байт на символ (для иероглифов каких-нибудь). Че не понятного?
Про 8 байт - не в курсе.
33 H A D G E H O G s
 
01.06.11
15:33
(30) 65536 вариантов (символов). Поражен, это еще при работе с памятью в бейсике (сегмент:смещение) должно отложиться было.
34 Serginio1
 
01.06.11
15:33
(32) а всовываешь ты 2 байтное значение в однобайтное
35 H A D G E H O G s
 
01.06.11
15:34
(34) Он всовывает ЧИСЛО!

<<А теперь не могу заполнить новосозданный массив

String = СтруктураШифрования.Стрим.Read();

Массив = Новый COMSafeArray("VT_I1", String.getLength());
Для н = 0 По  String.getLength() - 1 Цикл
    Массив.SetValue(н, String.getValue(н));
КонецЦикла;


Спотыкается на 1-м элементе, String.getValue(н) у меня в отладчике показывает тип "число", 255.>>
36 Serginio1
 
01.06.11
15:34
(32) а зачем если это 2 сдвиг влево на 16 -1. Я только так запоминаю. И чего ты завелся?
37 Serginio1
 
01.06.11
15:35
(34 оторое либо обрезано до 255 либо выдаст ошибку если код символа больше 255
38 H A D G E H O G s
 
01.06.11
15:36
Бекоурз, он всовывает значение 255 в знаковую ячейку. Возможно "умный" обработчик COM объектов и говорит - "не больше 128 в меня влезет. И знак.".

Поэтому (31).
39 H A D G E H O G s
 
01.06.11
15:37
(36) Я - спокоен. Скучно.
40 H A D G E H O G s
 
01.06.11
15:37
(38) 128->127
41 H A D G E H O G s
 
01.06.11
15:39
Хотяяяя. Автор! Ты где?
42 Serginio1
 
01.06.11
15:39
(38) Да для VT_I1 128 вроде исключение.
43 detec
 
01.06.11
15:40
Можно по-простому объяснить разницу между VT_I1, VT_UI1 и другими типами, которые провзучали в ветке?
44 Serginio1
 
01.06.11
15:42
(43) Знаковый и безнаковые. Не знаю что у тебя представляет
СтруктураШифрования, но она однозначно беззнаковая, но если у нее есть символы больше 255 то данное значение либо обрежется, либо вызовет исключение.
45 H A D G E H O G s
 
01.06.11
15:43
У меня при попытке
мас=Новый COMSafeArray("VT_I1",1);
мас.SetValue(0,255);
Ошибка при вызове метода контекста (SetValue): Выход за пределы диапазона.

мас=Новый COMSafeArray("VT_UI1",1);
мас.SetValue(0,255);
Срабатывает

мас=Новый COMSafeArray("VT_I1",1);
мас.SetValue(0,127);
Срабатывает


ЧЯДНТ?
46 H A D G E H O G s
 
01.06.11
15:44
(44) Исключение. У него тупо однобайтный массив походу.
47 detec
 
01.06.11
15:46
Массив.SetValue(н, 127);

Отрабатывает. Не отрабатывает Массив.SetValue(н, 128); и выше.
48 detec
 
01.06.11
15:47
(45) Да-да, именно такая ошибка. Придётся тупо перебирать типы.
49 H A D G E H O G s
 
01.06.11
15:48
**facepalm
50 H A D G E H O G s
 
01.06.11
15:48
Измени
Массив = Новый COMSafeArray("VT_I1", String.getLength());
на
Массив = Новый COMSafeArray("VT_UI1", String.getLength());
51 detec
 
01.06.11
15:52
(50) Переделал, новый COMSafeArray заполняется. Но класс .NET выдаёт Неизвестная ошибка.
52 H A D G E H O G s
 
01.06.11
15:55
(51) Ну, а что ему (NET-классу надо то)?
53 detec
 
01.06.11
15:56
Может нужно заполнить новый массив символами ASCII? Ведь код Массив.SetValue(н, Символ(String.getValue(н))) по идее, даст символы в Unicode.

.NET класс требует для функции ComputeHash(Byte())  Computes the hash value for the specified byte array.
54 H A D G E H O G s
 
01.06.11
15:59
(53) ППЦ.
http://msdn.microsoft.com/ru-ru/library/s02tk69a.aspx

Ну вот где там написано, что он comsafearray сожрет, этот
ComputeHash() ?

Там, в компоненте, надо вырезать данные из переданного comsafearray и сделать на их основе System.Byte()
55 Serginio1
 
01.06.11
16:01
(53) 45 правильно он начинает кастить по значению, а не по физическому расположению битов как в нормальных языках.
56 detec
 
01.06.11
16:03
(54) Это я видел. Можно как-то в 1С 8 сделать аналог

       ' Convert the input string to a byte array and compute the hash.
       Dim data As Byte() = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input))


?
57 detec
 
01.06.11
16:05
(55) Можно по-русски или по 1С-ному ))) ?
58 Serginio1
 
01.06.11
16:13
(57) Не суть (что знаковый байт что беззнаковый это 8 бит). Я так понимаю СтруктураШифрования.Стрим.Read(); возвращает safearray() VT_UI1 Посмотри в отладчике.
По идее ты его и должен обратно передать.
А проще написать ком сервер и сделать все, что ты хочешь без переконвертаций структур
59 Serginio1
 
01.06.11
16:17
Или воспользуйся моей приблудой. По идее должно получиться.
60 detec
 
01.06.11
16:18
(58) Да, отладчик показывает именно это.

С нестандартными компонентами я зарёкся работать. У меня x64 и платформа 8.2.14. Код должен отрабатывать как в x32, так и при исполнении на 64-битном сервере 1С:Предприятие. С NativeAPI-компонентами, как я понял, глухо, как в танке.

(59) спасибо.
61 Serginio1
 
01.06.11
16:21
(60) У тебя нетовский код скомпилированный под any процессор будет работать под любой платформой. При этом если ты COM сервер нужно зарегить как по 64 @"Microsoft.NET\Framework64\v4.0.30319\regasm.exe";
с ключом /codebase
так и под обычным регасмом. Все это прекрасно работает на сервере. И никаких C Native API не надо
62 Serginio1
 
01.06.11
16:29
(60) Я у себя вызываю метод
SearchDetailItem[] DetailSearch(string APIkey, string[] PartNumbers, string ChangePart)

Вызываю его
Массивассив=объект.СоздатьМассив("System.String",1);
       Массив.SetValue(Артикул,0);
       резулт=Езоко.DetailSearch("ЧЧЧЧЧЧЧЧЧ",массив,"No");
       для Каждого стр из резулт цикл
               ........
               КонецЦикла;

Внутри каждый объект обернут через AutoWrap
63 detec
 
01.06.11
18:17
Рассказываю, как я решил эту задачу. ))

Есть у MS такая утилитка как Microsoft File Checksum Integrity Verifier (FCIV) Utility

Простейший синтаксис, консольный режим - и программулина выдаёт хэш MD5.

Я добавил её в общие макеты, а при необходимости вычислить хэш - программно вызываю через COM-объект командную строку, считываю консольный вывод и регулярным выражением вытягиваю хэш. Благо, наработки по сабджу были.

А так как код выполняется на севрере 1С:Предприятие - нет никаких выпрыгивающих чёрных окошек. И не нужно трахать мозги всякими компонентами и преобразованиями, x32, x64.
64 H A D G E H O G s
 
01.06.11
18:23
(63) Мдать.
65 H A D G E H O G s
 
01.06.11
18:24
Даже в дремучем Дельфи 6 есть типовая компонента получения MD5.
Там делов написать ВК, либо COMсервер на 15 минут.
66 H A D G E H O G s
 
01.06.11
18:24
Вот те делать нечего.
67 Serginio1
 
01.06.11
18:28
(63) Не знаю, у меня нет никаких проблем с черными окошками (Это когда сервер долго занят? помню было такое и писал приложение которое гасило это окошко) и x32, x64.
Так или иначе в итоге ты используешь ком объект.
Используй обертку нетовских объектов. Правда нужно там дописать GetType с именем
http://msdn.microsoft.com/ru-ru/library/z7aahsb8.aspx
или
http://msdn.microsoft.com/ru-ru/library/system.reflection.assembly.gettype.aspx
68 detec
 
01.06.11
18:30
(64) Это всё классно, если где-то стоит установленная IDE, есть навыки программирования на этом языке, какие-то базовые знания.

А когда есть отлаженная лично библитоечка функций, то проще добавить в конкретную конфу несколько функций.

Мне приходилось работать с консольными утилитами, альтернативы которым просто не было, и только регулярными выражениями можно было пропарсить их ответ и вернуть результат в 1С.

Но спасибо вам за помощь, ребята. Много нового узнал.

Чёрное окошко - это когда вызываешь из 1С:Предприятие wscript.shell - чёрное окошко командной строки. Видно только при запуске с клиента или в файловой базе.
69 Serginio1
 
01.06.11
18:30
(65) Да изменил я Delphi. В основном Net. И связано это в том числе и с написанием приложений для КПК. Да и если честно, NET развивается семимильными шагами
70 Serginio1
 
01.06.11
18:41
(68) Изучай. Пригодиться однозначно.
71 Serginio1
 
02.06.11
12:28
Исправил посмотри новый вариант с примером
Пример использования
объект=Новый COMОбъект("NetObjectToIDispatch");
   Типмд5= объект.ПолучитьТип("System.Security.Cryptography.MD5CryptoServiceProvider","");
   Активатор=объект.Activator;
   мд5=Активатор.CreateInstance(Типмд5);
   типЭнкодинг=объект.ПолучитьТип("System.Text.Encoding","");
   рез=мд5.ComputeHash(типЭнкодинг.Default.GetBytes("Строка"));
   для каждого стр из рез Цикл
       Сообщить(стр);
       КонецЦикла;