Вход | Регистрация
    1  2   
1С:Предприятие :: 1С:Предприятие 8 общая

v8: Использование сборок .NET в 1С 7.x и 8.x

v8: Использование сборок .NET в 1С 7.x и 8.x
Я
   Serginio1
 
28.11.13 - 16:13
Это продолжение темы
v8: Объекты Net в IDispatch
v8: Вопрос по NetObjectToIDispatch
v8: soap:Header

выложил статью и файлы http://infostart.ru/public/238584/
Суть статьи использование сборок на примере доступа к вэб сервису
   Serginio1
 
1 - 28.11.13 - 16:13
Данная разработка создана для использования сборок .Net в 1С через преобразование объектов и классов в COM объекты которые можно использовать в 1С. Достигается это путем создания класса реализующим методы интерфейса IReflect public class AutoWrap : IReflect
Внутри него есть метод который оборачивает объекты не поддерживаемые в 1С в экземпляр класса AutoWrap.
Для облегчения работы с этим классом создан другой класс NetObjectToIDispatch
У него есть следующие методы
public object ПолучитьТип(string type)
Получает тип используя типы загруженных сборок
полученный объект позволяет использовать статические методы класса
и члены перечислений
примеры взятые отсюда v8: Вопрос по NetObjectToIDispatch
v8: soap:Header

и созданные oleg_km
обСокет = Плагин.СоздатьОбъект(Плагин.ПолучитьТип("System.Net.Sockets.Socket", "System"),
        Плагин.ПолучитьТип("System.Net.Sockets.AddressFamily", "System").InterNetwork,
        Плагин.ПолучитьТип("System.Net.Sockets.SocketType", "System").Stream,
        Плагин.ПолучитьТип("System.Net.Sockets.ProtocolType", "System").Tcp);

Но есть один мисус для типа нельзя вызвать методы типа. Для этого существует метод
public object ТипКакОбъект(object Тип)
из которого можно использовать методы и свойства Type (Например AssemblyQualifiedName)
public object СоздатьОбъект(object Тип, params object[] args)

Создает объект по типу или по строке используя параметры которые можно перечислять через запятую. Например
сервер=врап.СоздатьОбъект(тип,парам1,парам2);
public Object ChangeType(string type, object value)
Используя для преобразования типа в нужный тип. В C# используется перегрузка по параметрам. В .Net для чисел много типов, а  1С только один тип.
public object ПолучитьИнтерфейс(object obj, string InterfaseName)
получить интерфейс  объекта.
public object ЗагрузитьСборку(string ПутьКСборке)
загружает сборку и возвращает ссылку на нё.

В Net особенно в WCF активно используются конфигурационные файлы.
Для использования их в 1С можно создать такой файл в директории запускаемой программы под именем ИмяЗапускаемойПрограммы.exe.config например
 C:\Program Files (x86)\1Cv77\BIN\1cv7s.exe.config
Или
C:\Program Files (x86)\1cv8\8.3.4.317\bin\1cv8.exe.config

Иногда стоит заменить этот файл на другой. Для этого есть метод
ЗаменитьConfigFile(string имяФайла)
Если имяФайла=”” тогда берется файл typeof(NetObjectToIDispatch45).Assembly.Location + ".config"

Как пример показано программное изменение настроек 
УстановитьDefaultProxy()

Другие методы созданы для отладки.

Также заложена возможность использования итераторов в 1С например
рез = сервер.GetForms("Ваяся Пупкин");
Для каждого стр  Из рез Цикл
   сообщить(стр) 
КонецЦикла;
Для использования в 1С 7.7 предусмотрено установка УстЭтоСемерка() так как в ней не поддерживается беззнаковые, Decimal и ограничена DateTime без времени.

Приведены примеры для 1С 7.7 и 8.3
Использующие сборку для доступа к Веб Сервису http://www.morpher.ru/WebServices/Morpher.asmx

Использующие загрузку сборок, замену м модификацию конфигурационных файлов.
Вы можете создавать любые сборки или использовать стандартные библиотеки без регистрации.

NestNet45.dll для иестирования 4.5 TestWebServices.dll для тестов 2.0

В папке NetObjetToIDispatch содержатся файлы для доступа к Net 2.0
NetObjetToIDispatch45 соответсвенно к 4.5

Пример для 7.7
Процедура ПодключитьсякМорферЧерез45()
    
    врап=СоздатьОбъект("NetObjectToIDispatch45");
    врап.УстЭтоСемерка();
    // Можно указать место конфигурационного файла
    //    врап.ЗаменитьConfigFile("");
    // Устанавливаю в конфигурацию DefaultProxy
    Если ИспользоватьDefaultProxy=1 Тогда
        
        Сообщить(врап.УстановитьDefaultProxy());
    КонецЕсли;
    
    //Сборка=врап.загрузитьСборку("d:\MyPrograms\Test\NestNet45\NestNet45\bin\Debug\NestNet45.dll");
    // Загружаю сборку содержащую классы и методы доступа в Вэб сервису
    Сборка=врап.загрузитьСборку(ИмяФайла);
    
    // Получаю текущие установки прокси
    прокси=врап.ПолучитьТип("System.Configuration.ConfigurationSettings").GetConfig("system.net/defaultProxy");
    Сообщить("прокси.Enabled="+прокси.Enabled);
    Сообщить("прокси.UseDefaultCredentials="+прокси.UseDefaultCredentials);
    
    
    true=врап.ChangeType("System.Boolean","true");
        
    //Создаю экземляр NestNet45.ServiceReference1.MorpherSoapClient используя BasicHttpBinding
    //и remoteAddress
    типСервера=Сборка.GetType("NestNet45.ServiceReference1.MorpherSoapClient");
    типСервера=врап.ПолучитьТип("NestNet45.ServiceReference1.MorpherSoapClient");
    
    remoteAddress =врап.СоздатьОбъект("System.ServiceModel.EndpointAddress",
    врап.СоздатьОбъект("System.Uri","http://www.morpher.ru/WebServices/Morpher.asmx";));
    привязка = врап.СоздатьОбъект("System.ServiceModel.BasicHttpBinding");

    сервер=врап.СоздатьОбъект(типСервера,привязка,remoteAddress);
    //сервер=врап.СоздатьОбъект(типСервера);
    
    
    // Вызываю метод и вывожу результат
    рез = сервер.GetForms("Ваяся Пупкин");
    
    Для сч=0 по рез.Length-1 Цикл
        Сообщить(рез.GetValue(Инт(сч)));
    КонецЦикла;
    
    врап="";
КонецПроцедуры





Для 83

Процедура ТестВызоваСервисаНажатие(Элемент)
    // Вставить содержимое обработчика.
    врап=новый COMОбъект("NetObjectToIDispatch45");
// Можно использовать внешний конфигурационный фай    
//    врап.ЗаменитьConfigFile("");
Если ИспользоватьDefaultProxy Тогда
Сообщить(врап.УстановитьDefaultProxy());    
КонецЕсли;

//Сборка=врап.загрузитьСборку("d:\MyPrograms\Test\NestNet45\NestNet45\bin\Debug\NestNet45.dll");
Сборка=врап.загрузитьСборку(ИмяФайлаСборки);
// Можно получить тип и используя сборку, что будет правильным
//Сборка GetType("NestNet45.ServiceReference1.MorpherSoapClient");
//Но в данном примере используется поиск в загруженных сборках
типСервера=Сборка.GetType("NestNet45.ServiceReference1.MorpherSoapClient");

типСервера=врап.ПолучитьТип("NestNet45.ServiceReference1.MorpherSoapClient");

//Создаю экземляр NestNet45.ServiceReference1.MorpherSoapClient используя BasicHttpBinding
    //и remoteAddress
    
remoteAddress =врап.СоздатьОбъект("System.ServiceModel.EndpointAddress",
                        врап.СоздатьОбъект("System.Uri","http://www.morpher.ru/WebServices/Morpher.asmx";));
привязка = врап.СоздатьОбъект("System.ServiceModel.BasicHttpBinding");

прокси=врап.ПолучитьТип("System.Configuration.ConfigurationSettings").GetConfig("system.net/defaultProxy");
Сообщить("прокси.Enabled="+прокси.Enabled);
Сообщить("прокси.UseDefaultCredentials="+прокси.UseDefaultCredentials);
сервер=врап.СоздатьОбъект(типСервера,привязка,remoteAddress);



// Вызываю метод и вывожу результат
рез = сервер.GetForms("Ваяся Пупкин");

Для каждого стр  Из рез Цикл
    сообщить(стр)
КонецЦикла;

КонецПроцедуры
   oleg_km
 
2 - 28.11.13 - 17:33
Молодец, осилил. У меня не хватило пороху.

Докину примеры использования из своей копилки:

// Системные

Процедура Приостановить(ВремяПаузы) Экспорт
    ПолучитьТип("System.Threading.Thread").Sleep(ВремяПаузы);
КонецПроцедуры

Функция ПолучитьКоманднуюСтроку() Экспорт 
    Возврат ПолучитьТип("System.Environment").CommandLine;
КонецФункции

Функция ПолучитьТекущийПринтер() Экспорт 
    Возврат СоздатьОбъект(ПолучитьТип("System.Drawing.Printing.PrinterSettings", "System.Drawing")).PrinterName;
КонецФункции

Функция ПолучитьТекущийПроцесс() Экспорт 
    Возврат ПолучитьТип("System.Diagnostics.Process", "System").GetCurrentProcess().Id;
КонецФункции

Процедура СкопироватьПоток(вхПоток, исхПоток, РазмерПорции = 100000) Экспорт 
    Пока Истина Цикл
        мсДанные = СоздатьМассив(ПолучитьТип("System.Byte"), РазмерПорции);
        число = вхПоток.Read(мсДанные, 0, мсДанные.Length);
        Если число = 0 Тогда Прервать; КонецЕсли; 
        исхПоток.Write(мсДанные, 0, число);
    КонецЦикла;     
КонецПроцедуры

// Компрессия

Процедура GZIPУпаковать(вхФайл, исхФайл) Экспорт
    УдалитьФайлы(исхФайл);
    
    типФайл         = ПолучитьТип("System.IO.FileStream");
    типРежим         = ПолучитьТип("System.IO.FileMode");
    типДоступ         = ПолучитьТип("System.IO.FileAccess");
    типРазделение     = ПолучитьТип("System.IO.FileShare");
    
    обФайлИсходный     = СоздатьОбъект(типФайл, вхФайл, типРежим.Open, типДоступ.Read, типРазделение.ReadWrite);
    обФайлАрхив        = СоздатьОбъект(типФайл, исхФайл, типРежим.CreateNew, типДоступ.Write);
    обПотокКомпр     = СоздатьОбъект(ПолучитьТип("System.IO.Compression.GZipStream", "System"), 
                        обФайлАрхив, ПолучитьТип("System.IO.Compression.CompressionMode", "System").Compress);
                        
    СкопироватьПоток(обФайлИсходный, обПотокКомпр);
    
    обПотокКомпр.Close();
    обФайлАрхив.Close();
    обФайлИсходный.Close();
КонецПроцедуры
 
Процедура GZIPРаспаковать(вхФайл, исхФайл) Экспорт
    УдалитьФайлы(исхФайл);
    
    типФайл         = ПолучитьТип("System.IO.FileStream");
    типРежим         = ПолучитьТип("System.IO.FileMode");
    типДоступ         = ПолучитьТип("System.IO.FileAccess");
    типРазделение     = ПолучитьТип("System.IO.FileShare");
    
    обФайлАрхив     = СоздатьОбъект(типФайл, вхФайл, типРежим.Open, типДоступ.Read, типРазделение.ReadWrite);
    обФайлНовый        = СоздатьОбъект(типФайл, исхФайл, типРежим.CreateNew, типДоступ.Write);
    обПотокКомпр     = СоздатьОбъект(ПолучитьТип("System.IO.Compression.GZipStream", "System"), 
                        обФайлАрхив, ПолучитьТип("System.IO.Compression.CompressionMode", "System").Decompress);
                        
    СкопироватьПоток(обПотокКомпр, обФайлНовый);
    
    обПотокКомпр.Close();
    обФайлАрхив.Close();
    обФайлНовый.Close();
КонецПроцедуры

// Получение хеша

Функция ПолучитьХешСтроки(текСтрока, Провайдер = "MD5") Экспорт
    мсДанные = ПолучитьКодировку().GetBytes(текСтрока);
    Возврат Хеш2Строка(СоздатьКриптоПровайдер(Провайдер).ComputeHash(мсДанные));
КонецФункции

Функция ПолучитьХешФайла(ИмяФайла, Провайдер = "MD5") Экспорт
    обФайл = СоздатьОбъект(ПолучитьТип("System.IO.FileStream"), ИмяФайла, 
        ПолучитьТип("System.IO.FileMode").Open, 
        ПолучитьТип("System.IO.FileAccess").Read, 
        ПолучитьТип("System.IO.FileShare").ReadWrite);
        
    Рез = Хеш2Строка(СоздатьКриптоПровайдер(Провайдер).ComputeHash(обФайл));
    обФайл.Close();
        
    Возврат Рез;
КонецФункции

Функция СоздатьКриптоПровайдер(Провайдер)
//SHA                                        SHA1CryptoServiceProvider 

//SHA1                                       SHA1CryptoServiceProvider 
//System.Security.Cryptography.SHA1          SHA1CryptoServiceProvider 

//System.Security.Cryptography.HashAlgorithm SHA1CryptoServiceProvider 
//MD5                                        MD5CryptoServiceProvider 

//System.Security.Cryptography.MD5           MD5CryptoServiceProvider 
//SHA256                                     SHA256Managed 

//SHA-256                                    SHA256Managed 
//System.Security.Cryptography.SHA256        SHA256Managed 

//SHA384                                     SHA384Managed 
//SHA-384                                    SHA384Managed 

//System.Security.Cryptography.SHA384        SHA384Managed 
//SHA512                                     SHA512Managed 

//SHA-512                                    SHA512Managed 
//System.Security.Cryptography.SHA512        SHA512Managed 

    
    КлючПровайдера = "Hash_" + Провайдер;
    обПровайдер = КешОбъектов[КлючПровайдера];
    
    Если обПровайдер = Неопределено Тогда
        обПровайдер = ПолучитьТип("System.Security.Cryptography.HashAlgorithm").Create(Провайдер);
        КешОбъектов.Вставить(КлючПровайдера, обПровайдер);
    КонецЕсли; 
    
    Возврат обПровайдер;
КонецФункции

Функция Хеш2Строка(мсХеш)
    стрРез = СоздатьОбъект(ПолучитьТип("System.Text.StringBuilder"), мсХеш.Length * 2);
    Для ии = 0 По мсХеш.Length - 1 Цикл
        стрРез.AppendFormat("{0:X2}", мсХеш.GetValue(ии));
    КонецЦикла; 
    Возврат СокрЛП(стрРез.ToString());
КонецФункции
   Asmody
 
3 - 28.11.13 - 17:39
фигня. вот кто бы научил 1Ску ассинхронным запросам…
   H A D G E H O G s
 
4 - 28.11.13 - 17:40
Вы нереально круты, круче только яйца.

Получите мне простенькую командную строку стороннего приложения, например outlook.exe в моей win64 - тому мое респект и уважуха.
   H A D G E H O G s
 
5 - 28.11.13 - 17:40
(3) пфффф
   Asmody
 
6 - 28.11.13 - 17:40
(5) что "пфффф"?
   H A D G E H O G s
 
7 - 28.11.13 - 17:43
(6) Я делал это. Правда не с запросом, а с множественными вычислениями. Но думаю, и запрос потянет. Надо проверить.
   oleg_km
 
8 - 28.11.13 - 17:46
(3) Ну прямые асинхронные SQL запросы посредством дот.нет вполне доступны. А 1Сные с применением сокетов возможны посредством фоновых заданий. Просто с использованием дот.нета я бы выпилил из 1С всю эту шелуху, типа ИнтернетСоединение, ИнтернетПочта, всякие там вебсервисы, географические схемы и прочие наколенные поделки, регулярно неработающие и всегда не до конца реализаованные, а главное через три года, как оно было нужно и уже было в дот.нете. Еще бы как-нибудь это удалить из СП чтобы не мешалось. Я для себя оставил прикладные объекты: справочники, документы, регистры, перечисления и пр. И сразу легче задышалось
   Asmody
 
9 - 28.11.13 - 17:47
(7) под "запросом" я имел ввиду не только те запросы, которые в 1С, хотя и их тоже, а вообще. те же запросы к внешним веб-сервисам
   Asmody
 
10 - 28.11.13 - 17:47
(8) с дот.нетом тебе 1С не мешает?
   H A D G E H O G s
 
11 - 28.11.13 - 17:48
(8) Это все круто, нереально круто. Давно выпилить этот, как ты сказал, нерабочий мусор, согласен на все 100, вот только как реализуешь (4).
   H A D G E H O G s
 
12 - 28.11.13 - 17:51
(9) Внешние веб-сервисы? Не, не слышал.
   oleg_km
 
13 - 28.11.13 - 17:51
(4) Не совсем понял найти outlook. Именно файл outlook.exe или скажем текущий почтовый клиент по-умолчанию. Первое реализуется средствами самого 1С, делаешь рекурсивный обход всех каталогов. Второе естественно через поиск по регистру можно сделать через это поделие

(9) Асинхронную работу этим компонентом сделать не получается, т.к. не понятно как туда прикрутить делегаты. Может в поделке Elisy это реализовано, там вроде как целые куски кода на шарпе можно запускать
   oleg_km
 
14 - 28.11.13 - 17:57
Вон очередной мученик давится кактусом:

v8: Как правильно передать данные по https ?
   H A D G E H O G s
 
15 - 28.11.13 - 17:57
(13) Командную строку, с помощью которой запущен вот этот вот работающий процесс outlook.exe с PID 1232
   oleg_km
 
16 - 28.11.13 - 18:05
(15) ну у меня это еще через WMI сделано, но можно и через дот.нет. Непричесанный пример (списаок всех процессов на компьютере ОС_Наименование):

    тзПроцессы = Новый ТаблицаЗначений;
    тзПроцессы.Колонки.Добавить("Программа", Новый ОписаниеТипов("Строка"));
    тзПроцессы.Колонки.Добавить("Домен", Новый ОписаниеТипов("Строка"));
    тзПроцессы.Колонки.Добавить("Пользователь", Новый ОписаниеТипов("Строка"));
    тзПроцессы.Колонки.Добавить("Путь", Новый ОписаниеТипов("Строка"));
    тзПроцессы.Колонки.Добавить("Память", Новый ОписаниеТипов("Число"));
    тзПроцессы.Колонки.Добавить("ДатаЗапуска", Новый ОписаниеТипов("Дата"));
    тзПроцессы.Колонки.Добавить("ВремяЯдра", Новый ОписаниеТипов("Строка"));
    тзПроцессы.Колонки.Добавить("ВремяПользователя", Новый ОписаниеТипов("Строка"));
    тзПроцессы.Колонки.Добавить("Прочитано", Новый ОписаниеТипов("Число"));
    тзПроцессы.Колонки.Добавить("Записано", Новый ОписаниеТипов("Число"));
    тзПроцессы.Колонки.Добавить("ИДПроцесса", Новый ОписаниеТипов("Число"));
    тзПроцессы.Колонки.Добавить("ИДСессии", Новый ОписаниеТипов("Число"));
    
     обПроцессы = ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\" + 
        ОС_Наименование + "\root\cimv2").ExecQuery("Select * from Win32_Process");

    Для каждого текПроцесс Из обПроцессы Цикл
        новПроцесс = тзПроцессы.Добавить();
        новПроцесс.Программа = текПроцесс.Caption;
        Попытка                                                       
            новПроцесс.Путь = текПроцесс.CommandLine;
        Исключение
        КонецПопытки; 
        Если ЗначениеЗаполнено(текПроцесс.CreationDate) Тогда
            новПроцесс.ДатаЗапуска = Дата(Лев(текПроцесс.CreationDate, 14));
        КонецЕсли; 
        новПроцесс.ВремяЯдра = БиблАП.Время2Строка(Цел(текПроцесс.KernelModeTime/10000000));
        новПроцесс.ВремяПользователя = БиблАП.Время2Строка(Цел(текПроцесс.UserModeTime/10000000));
        новПроцесс.ИДПроцесса = текПроцесс.ProcessId;
        новПроцесс.ИДСессии = текПроцесс.SessionId;
        новПроцесс.Память = текПроцесс.WorkingSetSize;
        новПроцесс.Прочитано = текПроцесс.ReadTransferCount;
        новПроцесс.Записано = текПроцесс.WriteTransferCount;
        
        Попытка
            текПроцесс.GetOwner(новПроцесс.Пользователь, новПроцесс.Домен);
        Исключение
        КонецПопытки; 
    КонецЦикла; 
    
    тзПроцессы.Сортировать("Домен, Пользователь, Программа");
    ДополнительныеСвойства.Вставить("РезультатПроцессы", тзПроцессы);
   Serginio1
 
17 - 28.11.13 - 18:22
(2)Блин не думал, что народ подойдет.
Я сделал больше для использования загрузки сборок. И поэксперементировал с конфиг файлом.
   Serginio1
 
18 - 28.11.13 - 18:25
(4) Что типа такого
System.Diagnostics.Process p = new System.Diagnostics.Process();
                //    p.EnableRaisingEvents = false;

                //    p.StartInfo.CreateNoWindow = false;

                p.StartInfo.FileName = ИмяФайла;
                p.StartInfo.Arguments = КоманднаяСтрока;//(Аргументы командной строки)

                p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                p.Start();
                p.WaitForExit();
            }
   Serginio1
 
19 - 28.11.13 - 18:40
(4)

Процедура ЗапуститьOutlookНажатие(Элемент)
     ИмяФайла="c:\Program Files (x86)\Microsoft Office\Office12\Outlook.exe";
     КоманднаяСтрока=""; 
    // Вставить содержимое обработчика.

     врап=новый COMОбъект("NetObjectToIDispatch45");
    //System.Diagnostics.Process 

     p = врап.СоздатьОбъект("System.Diagnostics.Process");
                //    p.EnableRaisingEvents = false;


                //    p.StartInfo.CreateNoWindow = false;


                p.StartInfo.FileName = ИмяФайла;
                p.StartInfo.Arguments = КоманднаяСтрока;//(Аргументы командной строки)


                p.StartInfo.WindowStyle = врап.ПолучитьТип("System.Diagnostics.ProcessWindowStyle").Normal;
                p.Start();
              //  p.WaitForExit();

    

 КонецПроцедуры
   Serginio1
 
20 - 28.11.13 - 19:04
(9) А это как раз легко решить через внешние сборки. Там ассинхронность уже заложена. И как правило такие сборки даются ввиде примеров создателями веб сервисов
   Serginio1
 
21 - 29.11.13 - 10:26
(13) Для работы с событиями тебе так или иначе нужно сделать сборку. Динамически или статически. Проще написать сборку хранить её в бд. Сохранять и загружать на клиенте.
При это использовать все возможности RADостей.
Сейчас кстати события прикручу, что бы можно было использовать ДобавитьОбработчик
   MM
 
22 - 29.11.13 - 11:16
(2) А что это за функции ПолучитьТип, СоздатьОбъект и СоздатьМассив, которые не являются методами.
(21) ДобавитьОбработчик и УдалитьОбработчик это будет кстати. А можно проект с инфостарта куда-нибудь в более удобное для загрузки место перенести.
   oleg_km
 
23 - 29.11.13 - 11:46
(22) У меня свой компонент, переделанный из компонента Serginio1. Просто привел как пример полезных функций дот.нета

(21) А обработчики к чему прикручиваются?

Сохранять и загружать на клиенте.
А сборки на клиенте можно использовать без регистрации РегАсмом, а то у пользователей прав администратора нет
   Serginio1
 
24 - 29.11.13 - 12:11
(22) На проф клуб собираюсь.
(23) Хочу просто сделать обертку к нетовским событиям через Com обертку. Пока не получается
http://support.microsoft.com/kb/313891
   oleg_km
 
25 - 29.11.13 - 12:18
(24) Не очень ориентируюсь в нетовской терминологии: нетовские события это случаем не делегаты?
   oleg_km
 
26 - 29.11.13 - 12:20
(24) http://support.microsoft.com/kb/313891
Вот, если бы это сделать универсальным, чтобы описывать со стороны 1С
   MM
 
27 - 29.11.13 - 12:23
(23) и этот компонент размещает свои методы в пространстве имён 1С или это функции обёртки в 1С, для удобства?
   oleg_km
 
28 - 29.11.13 - 12:28
(27) Да, у меня еще есть обработка-обертка на этим компонентом. Мне так удобне, работает подсказка, это немножно база знаний, один раз полученные типы и сборки кешируются в соответствии. У меня даже уже много оберток: работа с графикой GDI+, сокетами, HTTP, прямые SQL-запросы.
   Serginio1
 
29 - 29.11.13 - 12:43
(26) Уже сделал
   [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [Guid("33B45C9D-1AED-41F9-8880-36AB6AE84749")]
    public interface IEventFor1C
    {
        [DispId(0x60020000)]
        void Событие();
    }

  

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [Guid("62F8156C-13B9-4484-B152-82023243E1D3")]
    [ComSourceInterfaces(typeof(IEventFor1C))]
    public class ClassForEvent1C : System.Windows.Forms.UserControl
    {
        [ComVisible(false)]
        public delegate void Событие_Delgate();
        public object ЗначениеСобытия//{get;set;}

        public ClassForEvent1C()
        {
            ЗначениеСобытия = "Тестовая Строка";
        
        }
        public event Событие_Delgate Событие;

       
       public string GetText()
        {
            ЗначениеСобытия = AutoWrap.ОбернутьОбъект("Привет из Класса для событий");
            if (this.Событие != null) Событие();
            return "Эта процедура вызвала Событие";
        }

    


    }

(26) А смысл? Все равно городить сборку так или иначе. И мучится без RAD. Я все равно сначала пишу в студии, а затем переношу в 1С
   Serginio1
 
30 - 29.11.13 - 12:45
29+

Перем ОбъектССобытием;

 Процедура ТестСобытияНажатие(Элемент)
    // Вставить содержимое обработчика.

      врап=новый COMОбъект("NetObjectToIDispatch45");
      ОбъектССобытием=врап.ПолучитьОбъектДляСобытий();
      Сообщить(ОбъектССобытием);
      Сообщить("ЗначениеСобытия="+ОбъектССобытием.ЗначениеСобытия);
//      p = врап.СоздатьОбъект("System.Diagnostics.Process");

//      ДобавитьОбработчик p.Событие, ПриИзмененииДокумента;

      ДобавитьОбработчик ОбъектССобытием.Событие, ПриИзмененииДокумента;

      Сообщить(ОбъектССобытием.GetText());
  КонецПроцедуры
  
    Процедура ПриИзмененииДокумента()
      Сообщить(ОбъектССобытием.ЗначениеСобытия);
  КонецПроцедуры
 
 
   Serginio1
 
31 - 29.11.13 - 12:46
И вот сообщения
COMОбъект
ЗначениеСобытия=Тестовая Строка
Привет из Класса для событий
Эта процедура вызвала Событие
   Serginio1
 
32 - 29.11.13 - 12:47
Сейчас напишу обертку к событию Net, которое будет подключатся к событию объекта и передавать его в 1С
   Serginio1
 
33 - 29.11.13 - 12:58
Добавил
[DispId(0x60020001)]
        void СобытиеСПараметром(object value);

и вызов
ДобавитьОбработчик ОбъектССобытием.СобытиеСПараметром, ПриИзмененииДокументаСПараметром;

  Процедура ПриИзмененииДокументаСПараметром(Парам)
      Сообщить(парам);
  КонецПроцедуры


Но в принципе достаточно события без параметров, а результат передавать в ЗначениеСобытия
   MM
 
34 - 29.11.13 - 13:06
(33) А как в 1С получать события из системных сборок или без исходного кода? Будет переходник?
   Serginio1
 
35 - 29.11.13 - 13:31
(34) Да нужно написать сборку в которой нужно создать классы которые будут предоставлять делегаты для событий. А внутри класса создать событие которое будет вызыватся в делегате.
Сомовская обертка будет над этим классом. Внутри будет через рефлексию GetEvent подключаться к событию
AddEventHandler передавать метод внутри кторого будут запоминаться данные для 1С и передаваться события.

Кстати какие системные события интересуют. Сейчас как раз и хочу написать пример. Желательно с вызовом в отдельном потоке для синхронизации
   Serginio1
 
36 - 29.11.13 - 15:02
Сделал Класс обертку
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;

namespace NetObjectToIDispatch45
{

  
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [Guid("33B45C9D-1AED-41F9-8880-36AB6AE84749")]
    public interface IEventFor1C
    {
        [DispId(0x60020000)]
        void Событие();

        [DispId(0x60020001)]
        void СобытиеСПараметром(object value);
    }

  

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [Guid("62F8156C-13B9-4484-B152-82023243E1D3")]
    [ComSourceInterfaces(typeof(IEventFor1C))]
    public class ClassForEvent1C : System.Windows.Forms.UserControl
    {
        [ComVisible(false)]
        public delegate void Событие_Delgate();
        public delegate void СобытиеСПараметром_Delgate(object value);
        public object Объект;
        private SynchronizationContext Sc;
        public object ЗначениеСобытия//{get;set;}

        public ClassForEvent1C(object Объект,String СобытиеОбъекта)
        {
            this.Объект = Объект;
            BindingFlags bf = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
            EventInfo ei = Объект.GetType().GetEvent(СобытиеОбъекта, bf);
            ei.AddEventHandler(Объект, new System.Action(ВнешнееСобытие));

            SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
            Sc = SynchronizationContext.Current;

        }
        public event Событие_Delgate Событие;
        public event СобытиеСПараметром_Delgate СобытиеСПараметром;
       
        private void ВнешнееСобытие()
        {
          if (this.Событие != null)//Событие();

              Sc.Send(d => Событие(), null);

        
        }
       public string GetText()
        {
            ЗначениеСобытия = AutoWrap.ОбернутьОбъект("Привет из Класса для событий");
            if (this.Событие != null) Событие();

            if (this.СобытиеСПараметром != null) СобытиеСПараметром("Вызов события с Параметром");

            return "Эта процедура вызвала Событие";
        }

    


    }

}
   Serginio1
 
37 - 29.11.13 - 15:04
Сделал Тестовую сборку
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Permissions;


namespace ПроектИспользованияДелегатов
{
    public class КлассДляВнешнихСобытий
    {
        public string ИзмененныйФайл;
        public string ПереименованныйФайл;
        public event System.Action Событие;
        public event System.Action СобытиеПереименованияФайла;
  

        private  void ИзмененияВДиректории(object source, FileSystemEventArgs e)
        {
            // Specify what is done when a file is changed, created, or deleted.

            ИзмененныйФайл = e.FullPath + " " + e.ChangeType;
            if (this.Событие != null) Событие();
     
        }

        public КлассДляВнешнихСобытий(string Директория)
        {
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = Директория;
            /* Watch for changes in LastAccess and LastWrite times, and
               the renaming of files or directories. */
            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
               | NotifyFilters.FileName | NotifyFilters.DirectoryName;
            // Only watch text files.

            watcher.Filter = "*.txt";

            // Add event handlers.

            watcher.Changed += new FileSystemEventHandler(ИзмененияВДиректории);
            watcher.Created += new FileSystemEventHandler(ИзмененияВДиректории);
            watcher.Deleted += new FileSystemEventHandler(ИзмененияВДиректории);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);

            // Begin watching.

            watcher.EnableRaisingEvents = true;


        
        }

        private  void OnRenamed(object source, RenamedEventArgs e)
    {
        // Specify what is done when a file is renamed.

        Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
        ПереименованныйФайл = string.Format("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
        if (this.СобытиеПереименованияФайла != null) СобытиеПереименованияФайла();
    }

    }
}
   Serginio1
 
38 - 29.11.13 - 15:06
И вызов из 1С

ОбъектССобытием
Процедура ТестСобытияНажатие(Элемент)

врап=новый COMОбъект("NetObjectToIDispatch45");
 Сборка=врап.загрузитьСборку("d:\MyPrograms\Test\ПроектИспользованияДелегатов\ПроектИспользованияДелегатов\bin\Debug\ПроектИспользованияДелегатов.dll");
 тип=Сборка.GetType("ПроектИспользованияДелегатов.КлассДляВнешнихСобытий");
 
 ОбъектССобытием=врап.СоздатьОбъект(Тип,"c:\Тест\");
 Событие=Врап.ПолучитьОбъектДляСобытий(ОбъектССобытием,"Событие");
 СобытиеПереименования=Врап.ПолучитьОбъектДляСобытий(ОбъектССобытием,"СобытиеПереименованияФайла");

 ДобавитьОбработчик Событие.Событие, ПриИзмененииДиректории;
 ДобавитьОбработчик СобытиеПереименования.Событие, ПриПереименованииФайла;
 
  КонецПроцедуры
  
  Процедура ПриИзмененииДиректории()
      Сообщить(ОбъектССобытием.ИзмененныйФайл);
  КонецПроцедуры
  
  Процедура ПриПереименованииФайла()
      Сообщить(ОбъектССобытием.ПереименованныйФайл);
  КонецПроцедуры


Работает только почемуто при изменении срабатывает два раза.
   oleg_km
 
39 - 29.11.13 - 15:13
А если приходится делать отдельную сборку, почему бы ее саму не сделать как КОМ и пользовать без всяких оберток? Ну возвращаемые объекты оборачивать в AutoWrap и все.
   Serginio1
 
40 - 29.11.13 - 15:48
Так её регистрировать надо. Опять же AutoWrap добавлять. Намного больше действий
   Serginio1
 
41 - 29.11.13 - 15:49
   Serginio1
 
42 - 29.11.13 - 16:00
40+ Я кстати начал использовать ради доступа к Вэб сервисам.
А там куча типов и замучаешься каждый тип описывать.
А используя AutoWrap все становится элементарно.

Модераторам. Можно ссылочку в 41 перенести в Шапку?
   oleg_km
 
43 - 29.11.13 - 16:08
Еще есть вопрос. Вот этот класс:

public class EnumVariantImpl : IEnumVARIANT

и соответственно этот код:

if (name == "[DISPID=-4]")
{
return new EnumVariantImpl(((IEnumerable)O).GetEnumerator());
}

Это же как я понимаю должны превращать коллекции НЕТ в пригодные для Для каждого 1С? У меня почему то конструкция Для каждого с коллекциями дот.нет не работает. Можно маленький пример, где это у тебя работает?
   Serginio1
 
44 - 29.11.13 - 16:13
Это для Энумераторв для использования
Для каждого стр  Из рез Цикл
   Serginio1
 
45 - 29.11.13 - 16:15
У меня работает все. Например даже из v8: Объекты Net в IDispatch
рез=мд5.ComputeHash(типЭнкодинг.Default.GetBytes("Строка"));
    для каждого стр из рез Цикл
        Сообщить(стр);
        КонецЦикла;
   oleg_km
 
46 - 29.11.13 - 17:33
(46) Я тоже так думаю, но у меня почему-то не работает. У тебя именно в восьмерке работает или они одинаково коллекции "раскручивают"?
   Serginio1
 
47 - 29.11.13 - 17:37
(46) А только в 8 ке есть
для каждого 
в 7.7 только через индексы.
 А посмотри в отладчике, что передается при  
для каждого стр из рез Цикл

Скачай мои примеры из 41
   oleg_km
 
48 - 29.11.13 - 17:42
(47) Индексы тоже не работают
   Serginio1
 
49 - 29.11.13 - 17:44
(48) То есть 45 у тебя не идет? А мои примеры?
   Serginio1
 
50 - 29.11.13 - 17:46
(48) Индексы нужно к Int32 приводить.
Из-за перегрузки методов не работают. Поэтому я и сделал
public Object ChangeType(string type, object value)
        {

            if (value is AutoWrap)
                value = ((AutoWrap)value).O;

            Type result = НайтиТип(type)//Type.GetType(type, false);

            if (result == null)
                throw new Exception("Не найден тип " + type);

            return new AutoWrap(Convert.ChangeType(value, result, CultureInfo.InvariantCulture));

        }
   Serginio1
 
51 - 29.11.13 - 17:48
Функция Инт(стр)
    возврат врап.ToInt(Строка(стр));
    
КонецФункции// Децимал


рез = сервер.GetForms("Ваяся Пупкин");
    
    Для сч=0 по рез.Length-1 Цикл
        Сообщить(рез.GetValue(Инт(сч)));
    КонецЦикла;
   oleg_km
 
52 - 29.11.13 - 17:53
(51) Как раз GetValue прекрасно работает, а вот как в (45) не получается. Я немножко AutoWrap переделал, может что-то там сбилось.
   Serginio1
 
53 - 29.11.13 - 17:54
(52) Скорее всего. Посмотри мои примеры
   Serginio1
 
54 - 02.12.13 - 18:35
Также добавлена возможность использования  внешних событий в 1С, в том числе примеры обмена сообщениями по TCP/IP и Работа со сканером ШК
   Serginio1
 
55 - 02.12.13 - 18:36
Пример использования на сервере

Функция СоздатьСерверTCP(Врап)
      
      Если ЗначениеЗаполнено(ИмяФайлаСборки) Тогда
      предупреждение("Не выбрано Имя Файла Сборки"); 
          
      
      КонецЕсли; 
      
      
       врап=новый COMОбъект("NetObjectToIDispatch45");
 ФайлСборки=ИмяФайлаСборки//"d:\MyPrograms\Test\ОбменПоTCPIP\ОбменПоTCPIP\bin\Debug\ОбменПоTCPIP.dll";

 Сборка=врап.загрузитьСборку(ФайлСборки);//ПроектИспользованияДелегатов.dll

 тип=Сборка.GetType("TCPConnectTo1C.TCPConnector");

 СерверTCP=врап.СоздатьОбъект(Тип);
возврат   СерверTCP
  
  КонецФункции// СоздатьTCP()

   
  Процедура ЗапуститьСерверTCPIPНажатие(Элемент)
      // Вставить содержимое обработчика.

      перем Врап;
 СерверTCP=СоздатьСерверTCP(Врап); 

  Событие=Врап.ПолучитьОбъектДляСобытийСПараметром(СерверTCP,"ПришлоСообщениеПоTCP");

 ДобавитьОбработчик Событие.СобытиеСПараметром, ПолучениеДанныхПоTCP;
 СерверTCP.ОткрытьАйПиПортСНомеромПорта(6891);
 
ЭлементыФормы.ОтправитьКоманду.Видимость=ложь;

КонецПроцедуры

Процедура ПолучениеДанныхПоTCP(Данные)
Сообщить("Команда="+Данные.Команда);
Сообщить("Данные="+Данные.Данные);
Сообщить("ЕстьОтвет="+Данные.ЕстьОтвет);    

Если Данные.ЕстьОтвет Тогда
Ответ="Ответ на команду "+Данные.Команда+"
|Данные "+Данные.Данные+"
|ВремяНаСервере="+XmlСтрока(ТекущаяДата());
СерверTCP.Ответить(Ответ);
    

КонецЕсли; 

КонецПроцедуры
   Serginio1
 
56 - 02.12.13 - 18:37
На Клиенте 

Процедура ОтправитьКомандуНажатие(Элемент)
перем Врап;

    КлиентTCP=СоздатьСерверTCP(Врап);

    ServerAdress="127.0.0.1";
    порт=6891;
    Команда="Тест Отправки Сообщения";
    ДанныеДляКоманды=XmlСтрока(ТекущаяДата());
    
    ЕстьОтвет=истина;
    ЗакрытьСоединение=истина;
    ОшибкаСоединения=false;
    
    резулт=КлиентTCP.ОтправитьКоманду(ServerAdress,порт,Команда,ДанныеДляКоманды,ЕстьОтвет,ЗакрытьСоединение);
    Сообщить(резулт.Данные);    
        Если резулт.ОшибкаСоединения Тогда
            СтрОшибки="ОшибкаСоединения
            |"+резулт.Данные;
        Предупреждение(СтрОшибки);
        КонецЕсли;
КонецПроцедуры
   Serginio1
 
57 - 02.12.13 - 18:39
Ну и работа со сканером ШК
Процедура ОткрытьПортСканераНажатие(Элемент)
    перем Врап;
    // Вставить содержимое обработчика.

    НомерПорта=0;
    Если не ВвестиЧисло(НомерПорта,"Введите номе COM порта",4,0) Тогда
        возврат
    КонецЕсли;
     СерверTCP=СоздатьСерверTCP(Врап);
    Событие=Врап.ПолучитьОбъектДляСобытийСПараметром(СерверTCP,"ДанныеОтСканера");
    ДобавитьОбработчик Событие.СобытиеСПараметром, ПолучениеДанныхПоTCP;
    
    СерверTCP.ПодключитьСканер(НомерПорта);
    
КонецПроцедуры

Процедура ПолучениеДанныхОтСканераШК(Данные)
Сообщить("ИмяПорта="+Данные.ИмяПорта);
Сообщить("ШтрихКод="+Данные.Данные);
    

КонецПроцедуры
   Serginio1
 
58 - 03.12.13 - 11:42
Для упрощения регистрации добавил интерактивную регистрацию
   Serginio1
 
59 - 03.12.13 - 16:01
Кстати часто спрашивают как загрузить СОМ Объект без регистрации

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Reflection;


namespace WindowsFormsApplication3
{
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(false), Guid("00000001-0000-0000-C000-000000000046")]
    internal interface IClassFactory
    {
        [return: MarshalAs(UnmanagedType.Interface)]
        object CreateInstance([In, MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
        void LockServer([In, MarshalAs(UnmanagedType.Bool)] bool fLock);
    }





    [ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IDispatch
    {
        void GetTypeInfoCount(out uint pctinfo);
        void GetTypeInfo(uint iTInfo, int lcid, out IntPtr info);

        void GetIDsOfNames(ref Guid iid, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] names, uint cNames, int lcid, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)] int[] rgDispId);

        void Invoke(int dispIdMember, ref Guid riid, int lcid, System.Runtime.InteropServices.ComTypes.INVOKEKIND wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, IntPtr pvarResult, IntPtr pExcepInfo, IntPtr puArgErr);
    }




    public class Win32NativeMethods
    {

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr LoadLibrary(
        [MarshalAs(UnmanagedType.LPWStr)] string lpFileName);

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern IntPtr LoadLibraryEx(string libFilename, IntPtr reserved, int flags);


        [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr GetProcAddress(
            IntPtr hModule,
            [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

        public delegate uint DllGetClassObjectDelegate(
            [MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
            [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            [MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 1)] out object pUnknown);

        [DllImport("oleaut32", CharSet = CharSet.Unicode)]
        public extern static void LoadTypeLib(string dllFilePath, out
 UCOMITypeLib typeLibrary);

    }

    public class ЗагрузкаComОбъекта
    {

        public static object ЗагрузитьОбъект(string ИмяФайла, string clsid)
        {
            return ЗагрузитьОбъект(ИмяФайла, new Guid(clsid));
        }

        public static object ЗагрузитьОбъект(string ИмяФайла, Guid clsid)
        {
            var module = Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 0);
            var proc = Win32NativeMethods.GetProcAddress(module, "DllGetClassObject");
            var gco = Marshal.GetDelegateForFunctionPointer(proc,
                typeof(Win32NativeMethods.DllGetClassObjectDelegate))
                as Win32NativeMethods.DllGetClassObjectDelegate;

        
            object unknown;
            gco(clsid, typeof(IClassFactory).GUID, out unknown);
            var factory = unknown as IClassFactory;

            //var iid = typeof(IFilter).GUID;

            //var filter = factory.CreateInstance(null, ref iid) as IFilter;


            var iid = typeof(IDispatch).GUID;
            return factory.CreateInstance(null, iid);


        }

        public static object ЗагрузитьОбъектПоИнформацииОТипе(string ИмяФайла)
        {

            UCOMITypeLib typeLibrary;
            Win32NativeMethods.LoadTypeLib(ИмяФайла, out typeLibrary);

            string typeName, typeDocumentation, typeHelpFile;
            int typeHelpContext;
            for (int i = 0; i < typeLibrary.GetTypeInfoCount(); i++)
            {
                typeLibrary.GetDocumentation(i, out typeName, out
typeDocumentation, out typeHelpContext, out typeHelpFile);


                System.Runtime.InteropServices.TYPEKIND tk;
                typeLibrary.GetTypeInfoType(i, out tk);

                if (tk == System.Runtime.InteropServices.TYPEKIND.TKIND_COCLASS)
                {
                    UCOMITypeInfo typeInformation;
                    typeLibrary.GetTypeInfo(i, out typeInformation);

        
                    //IntPtr ptr;

                    // typeInformation.GetTypeAttr(out ptr);

                    // System.Runtime.InteropServices.TYPEATTR pta =(System.Runtime.InteropServices.TYPEATTR) Marshal.PtrToStructure(ptr, typeof(System.Runtime.InteropServices.TYPEATTR));


                    // return ЗагрузитьОбъект(ИмяФайла, pta.guid);

                   
                    object classInstance;
                    var IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");

                    
                    typeInformation.CreateInstance(null, ref IID_IUnknown, out classInstance);
                    return classInstance;
                    
                    //method.Invoke(classInstance, new object[0]);


                }
            }
            return null;
        }
    }
}
   Serginio1
 
60 - 03.12.13 - 16:02
И пример использования
dynamic res = ЗагрузкаComОбъекта.ЗагрузитьОбъектПоИнформацииОТипе(@"c:\Program Files (x86)\1cv8\8.3.4.317\bin\comcntr.dll");
            MessageBox.Show(res.HighBoundDefault.ToString());
 
 
   Serginio1
 
61 - 03.12.13 - 16:17
Загружать DLL нужно с параметром 8
var module = Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8);

что бы исказ зависимые DLL в каталоге имени файла

http://wm-help.net/books-online/print-page/59464/59464-14.html
LOAD_WITH_ALTERED_SEARCH_PATH

Этот флаг изменяет алгоритм, используемый LoadLibraryEx при поиске DLL-файла. Обычно поиск осуществляется так, как я рассказывал в главе 19 Однако, если данный флаг установлен, функция ищет файл, просматривая каталоги в таком порядке
1.Каталог, заданный в napaмeтре pszDLLPathName.
2.Текущий каталог процесса.
3.Системный каталог Windows.
4.Основной каталог Windows.
5.Каталоги, перечисленные в переменной окружения PATH
   Serginio1
 
62 - 03.12.13 - 18:13
Немного изменил загркзку. Добавив загрузку по имени класса

public static object ЗагрузитьОбъектПоИнформацииОТипе(string ИмяФайла,String ИмяКласса="")
        {
            UCOMITypeLib typeLibrary;
            Win32NativeMethods.LoadTypeLib(ИмяФайла, out typeLibrary);

            string typeName, typeDocumentation, typeHelpFile;
            int typeHelpContext;
            for (int i = 0; i < typeLibrary.GetTypeInfoCount(); i++)
            {
                typeLibrary.GetDocumentation(i, out typeName, out
typeDocumentation, out typeHelpContext, out typeHelpFile);


                System.Runtime.InteropServices.TYPEKIND tk;
                typeLibrary.GetTypeInfoType(i, out tk);

                if (tk == System.Runtime.InteropServices.TYPEKIND.TKIND_COCLASS)
                {

                    if (!string.IsNullOrEmpty(ИмяКласса) && (string.Compare(typeName,ИмяКласса,true)!=0))
                         continue;

                    UCOMITypeInfo typeInformation;
                    typeLibrary.GetTypeInfo(i, out typeInformation);

        
                    IntPtr ptr;
                     typeInformation.GetTypeAttr(out ptr);
                     System.Runtime.InteropServices.TYPEATTR pta =(System.Runtime.InteropServices.TYPEATTR) Marshal.PtrToStructure(ptr, typeof(System.Runtime.InteropServices.TYPEATTR));

                     return ЗагрузитьОбъект(ИмяФайла, pta.guid);
                   
                    object classInstance;
                    var IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");

                    
                    typeInformation.CreateInstance(null, ref IID_IUnknown, out classInstance);
                    return classInstance;
                    
                    //method.Invoke(classInstance, new object[0]);


                }
            }
            return null;
        }
   Serginio1
 
63 - 03.12.13 - 18:14
И соответственно вызов
dynamic res = ЗагрузкаComОбъекта.ЗагрузитьОбъектПоИнформацииОТипе(@"c:\Program Files (x86)\1cv8\8.3.4.317\bin\comcntr.dll", "COMConnector".ToUpper());
            MessageBox.Show(res.HighBoundDefault.ToString());

Таким способом можно загружать нужные версии comcntr.dll
   H A D G E H O G s
 
64 - 03.12.13 - 18:23
(62) GUID фабрики есть в библиотеке типов?
   H A D G E H O G s
 
65 - 03.12.13 - 18:24
(61) Неа. Версия ядра core82 не соответствует версии библиотеки, как то так.
Этот метод возможен только для работы одинаковых версия 1cv8.exe и comcntrl.dll
   Serginio1
 
66 - 03.12.13 - 18:28
(64) Да можно загрузить так 
IntPtr ptr;
                     typeInformation.GetTypeAttr(out ptr);
                     System.Runtime.InteropServices.TYPEATTR pta =(System.Runtime.InteropServices.TYPEATTR) Marshal.PtrToStructure(ptr, typeof(System.Runtime.InteropServices.TYPEATTR));

                     return ЗагрузитьОбъект(ИмяФайла, pta.guid);

 При этом она вызывает var module = Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8); 
и находит все связанные библиотеки.

Сделан просто для использование через LoadLibraryEx 

но лучше сразу

object classInstance;
                    var IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");

                    
                    typeInformation.CreateInstance(null, ref IID_IUnknown, out classInstance);
                    return classInstance;
   H A D G E H O G s
 
67 - 03.12.13 - 18:28
(65) Тут только - перехват getmodulehandle(), ручной loadlibraryex() по нужному пути и возврат handle загруженных dll в перехваченный getmodulehandle()

Вернее не getmodulehandle() а его native предок zwgetmodulehandle() из winnt.dll. Вот чую это.
   Serginio1
 
68 - 03.12.13 - 18:31
(67) Я выкладываю рабочий вариант. При использовании
 Win32NativeMethods.LoadLibrary(ИмяФайла); 
 или
 Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 0); 

Вылетает твоя ошибка. Но при 
 Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8); 
все чики пики
   H A D G E H O G s
 
69 - 03.12.13 - 18:32
(66) Стоп. Тпрррр.

1) 1C загружает dll
2) Из StringTable 100 она берет ProgID
3) Вызывает DllRegisterServer
4) DllregisterServer регистрирует в реестре само, пиша туда ProgID и CLSID
5) 1C по ProgID получает CLSID
6) Создает фабрику COM
7) Создает Инстансы.
   H A D G E H O G s
 
70 - 03.12.13 - 18:32
(68) Я пробовал.

У меня в процесс загружалось по 2 dll из разных папок
   Serginio1
 
71 - 03.12.13 - 18:33
Но я загружаю не через 1С. Завтра попробую через 1С
   Serginio1
 
72 - 03.12.13 - 18:34
(69) Это для ВК
   H A D G E H O G s
 
73 - 03.12.13 - 18:35
(69) У меня идея - перехват DllregisterServer.
В нем - включение перехвата работы с реестром, и возврат годного CLSID по ProgID. Но там такая каша с zw(nt) работы с реестром, пока не разобрался.
   H A D G E H O G s
 
74 - 03.12.13 - 18:37
(71) Естественно. Comcntlr требует для себя core82.dll
А оно уже загружено при загрузке 1cv8.exe

Он получает его handle по имени и видит кривую версию. Фэйл.
   Serginio1
 
75 - 03.12.13 - 18:39
(73) Зачем? Посмотри внимательно 62.
(74) При использовании Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8); будет грузить библиотеку из директории
таком порядке 
1.Каталог, заданный в napaмeтре pszDLLPathName. 
А уже потом из
2.Текущий каталог процесса.
3.Системный каталог Windows.
4.Основной каталог Windows.
5.Каталоги, перечисленные в переменной окружения PATH
   Serginio1
 
76 - 03.12.13 - 18:39
Давай сейчас и проверю.
   H A D G E H O G s
 
77 - 03.12.13 - 18:40
Сколько я мучения провел с этим перехватом dllregisterserver

2 дня убил на то, что обваливался процесс в мертвую при установке перехвата реестра.
Оказалось, что 1С выгружала dll, так как в dllregisterserver не всенено записей в реестр и дальше не вызывался dllgetclassobject и не было ссылок на эту dll.
   H A D G E H O G s
 
78 - 03.12.13 - 18:42
(75) Зачем? Посмотри внимательно 62.

У меня нет библиотеки типов.
   Serginio1
 
79 - 03.12.13 - 19:03
(78) Я про библиотеку типов
Кстати проверил на 1С все грузится

Процедура ЗагрузкаComОбъектаБезРегистрацииНажатие(Элемент)
    // Вставить содержимое обработчика.

    врап=новый COMОбъект("NetObjectToIDispatch45");
//    ФайлСборки=ИмяФайлаСборки;//"d:\MyPrograms\Test\ОбменПоTCPIP\ОбменПоTCPIP\bin\Debug\ОбменПоTCPIP.dll";

    ФайлСборки="d:\MyPrograms\Test\ЗагрузкаCOMОбъектаБезРегистрации\ЗагрузкаCOMОбъектаБезРегистрации\bin\Debug\ЗагрузкаCOMОбъектаБезРегистрации.dll";
    Сборка=врап.загрузитьСборку(ФайлСборки);
    ЗагрузкаComОбъекта=Сборка.GetType("ЗагрузкаCOMОбъектаБезРегистрации.ЗагрузкаComОбъекта");
    res = ЗагрузкаComОбъекта.ЗагрузитьОбъектПоИнформацииОТипе("c:\Program Files (x86)\1cv8\8.3.3.715\bin\comcntr.dll", "COMConnector");
    Сообщить(res.HighBoundDefault);

КонецПроцедуры
   Serginio1
 
80 - 03.12.13 - 19:05
(78) Но она и без
public class Win32NativeMethods
    {

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr LoadLibrary(
        [MarshalAs(UnmanagedType.LPWStr)] string lpFileName);

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern IntPtr LoadLibraryEx(string libFilename, IntPtr reserved, int flags);


        [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr GetProcAddress(
            IntPtr hModule,
            [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

        public delegate uint DllGetClassObjectDelegate(
            [MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
            [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            [MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 1)] out object pUnknown);

        [DllImport("oleaut32", CharSet = CharSet.Unicode)]
        public extern static void LoadTypeLib(string dllFilePath, out
 UCOMITypeLib typeLibrary);

    }

    public class ЗагрузкаComОбъекта
    {

        public static object ЗагрузитьОбъект(string ИмяФайла, string clsid)
        {
            return ЗагрузитьОбъект(ИмяФайла, new Guid(clsid));
        }

        public static object ЗагрузитьОбъект(string ИмяФайла, Guid clsid)
        {
            var module = Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8);
            var proc = Win32NativeMethods.GetProcAddress(module, "DllGetClassObject");
            var gco = Marshal.GetDelegateForFunctionPointer(proc,
                typeof(Win32NativeMethods.DllGetClassObjectDelegate))
                as Win32NativeMethods.DllGetClassObjectDelegate;

        
            object unknown;
            gco(clsid, typeof(IClassFactory).GUID, out unknown);
            var factory = unknown as IClassFactory;

            //var iid = typeof(IFilter).GUID;

            //var filter = factory.CreateInstance(null, ref iid) as IFilter;


            var iid = typeof(IDispatch).GUID;
            return factory.CreateInstance(null, iid);


        }
   Serginio1
 
81 - 03.12.13 - 19:06
(78) А в какой библиотеке у тебя нет информации о типе. Это надо на чистом С++ писать.
   Serginio1
 
82 - 04.12.13 - 17:55
И добавлен приер загрузки объекта из DLL без регистрации на примере загрузки
Из comcntr.dll класс COMConnector. Для примера когда нужно подключиться к Базе  с версией отличной от текущей 


К сожалению иногда не все методы выполняются. Например ToArray() для List<T>
Или методы с параметром типа GUID (сам метод выполняется, но при передаче результата в 1С выдается ошибка «типы не совпадают» )
Для этого добавлен метод
public object ВыполнитьМетод(object obj, string ИмяМетода, params object[] args)

И вызов из 1С
//Ком=ЗагрузкаComОбъекта.ЗагрузитьОбъект(ИмяФайла,стр.Гуид); ошибка  типа

            Ком=Врап.ВыполнитьМетод(ЗагрузкаComОбъекта,"ЗагрузитьОбъект",ИмяФайла,стр.Гуид);
// Выполняется без ошибок
   Serginio1
 
83 - 05.12.13 - 12:52
Решил поэкспериментировать с ExpandoObject
Понятно, что с типом там работать не получится, а переделывать AutoWrap пока лениво.

public static object ПолучитьExpandoObject()
        {
            dynamic res = new ExpandoObject();
            res.Имя = "Тест ExpandoObject";
            res.Число = 456;
            res.ВСтроку = (Func<string>) (() => res.Имя );


            return res;
        
        }
   Serginio1
 
84 - 05.12.13 - 12:53
И соответственно вызов из 1С 
Процедура ТестExpandoObjectНажатие(Элемент)
    // Вставить содержимое обработчика.


    врап=новый COMОбъект("NetObjectToIDispatch45");
    //ФайлСборки="d:\MyPrograms\Test\ЗагрузкаCOMОбъектаБезРегистрации\ЗагрузкаCOMОбъектаБезРегистрации\bin\Debug\ЗагрузкаCOMОбъектаБезРегистрации.dll";

    ФайлСборки=ИмяФайлаСборки;
    Сборка=врап.загрузитьСборку(ФайлСборки);
    ЗагрузкаComОбъекта=Сборка.GetType("ЗагрузкаCOMОбъектаБезРегистрации.ЗагрузкаComОбъекта");
//    врап.GetInfoFromObject(ЗагрузкаComОбъекта);

    Объект=ЗагрузкаComОбъекта.ПолучитьExpandoObject();
//    Сообщить(объект.Имя);


 Для каждого стр Из  Объект Цикл
    Сообщить(""+стр.Key+"="+Стр.Value);
КонецЦикла; 

Для каждого стр Из Врап.ТипКакОбъект(Объект.GetType()).GetInterfaces() Цикл
    Сообщить(Врап.ТипКакОбъект(Стр).Name);

КонецЦикла; 
  Объект=Врап.ПолучитьИнтерфейс(Объект,"IDictionary`2");
  Объект.set_Item("Число",5);
    
  Сообщить(Объект.get_Item("Имя"));
  Сообщить(Объект.get_Item("Число"));
  Объект.set_Item("Имя","Вызов Метода");
  Сообщить(Объект.get_Item("ВСтроку").DynamicInvoke());

КонецПроцедуры
   Serginio1
 
85 - 05.12.13 - 12:57
Но обнаружилась неприятная для меня новость
При вызове свойства или при Установке свойства
Объект.get_Item("Имя"));
в  InvokeMember(
invokeAttr вызывается как GetProperty а вот в параметрах ничего нет. Как такое можно побороть?
   Serginio1
 
86 - 05.12.13 - 12:58
Вернее при вызове свойства Объект.Item["Имя"];
   H A D G E H O G s
 
87 - 05.12.13 - 13:01
(85) Я вот неплохо понимаю в кухне COM, но вот ваши шаманические напевы на C++ вынесли мне мозг. Пишите на Дельфи, пожалуйста :-)
   Serginio1
 
88 - 05.12.13 - 13:37
(87) Это C#. На манагед Delphi будет тоже самое.

Суть в том что например при вызове такой конструкции
Объект.Item[5]=5;

Должен вызываться Метод IDispath Invoke c параметрами
DISPID_PROPERTYPUT и 2 параметра.
А на самом деле
вызывается с DISPATCH_PROPERTYGET и вообще без параметров.

Если просто вызвать Объект.Item["Имя"];

то параметры (Имя) не передается
   Serginio1
 
89 - 05.12.13 - 13:39
(87) Зря ты C# игнорируешь. Подучи. Там после Delphi не так сильно переучиваться, а знание библиотек и устройство Net пригодится.
   Serginio1
 
90 - 05.12.13 - 16:51
Сделал Исправления связанные с параметрами и событиями

        public void ПроверитьНаДоступКПолям(ref System.Reflection.BindingFlags invokeAttr,int КоличествоПараметров)
        {

            if ((
                (
                (invokeAttr & BindingFlags.PutDispProperty) == BindingFlags.PutDispProperty)
                || (invokeAttr.HasFlag(System.Reflection.BindingFlags.PutRefDispProperty))
                )
                && (КоличествоПараметров == 1))
            {
                invokeAttr = invokeAttr | BindingFlags.SetField;

            }



И после вызова метода нужно снва обернуть параметры
// Так как параметры могут изменяться (OUT) и передаются по ссылке

            // нужно обратно обернуть параметры

            if (args.Length > 0)
            {
                if (args != null && args.Length > 0)
                {
                    for (int x = 0; x < args.Length; x++)
                    {
                       args[x]=ОбернутьОбъект(args[x]);
                    }
                }
            }
   H A D G E H O G s
 
91 - 08.12.13 - 22:02
Ищется Serginio1
   Serginio1
 
92 - 09.12.13 - 10:11
(91) Я Здесь
   Serginio1
 
93 - 09.12.13 - 11:05
Нашел как использовать конфигурационнын файлы в WCF клиентах в DLL

public object СоздатьКлиентаWCFConfigFile(string ИмяФайла, object TChannel, string endpointConfigurationName, object endpointAddress)
        {
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = ИмяФайла;

            Configuration newConfiguration = ConfigurationManager.OpenMappedExeConfiguration(
                fileMap,
                ConfigurationUserLevel.None);

            
            Type ТипКанала=ТипДляСоздатьОбъект(TChannel);
            Type type= typeof(ConfigurationChannelFactory<>);
            Type constructed = type.MakeGenericType(ТипКанала);

            dynamic factory1 = System.Activator.CreateInstance(constructed,
                endpointConfigurationName,
                newConfiguration,
                AutoWrap.ПолучитьРеальныйОбъект(endpointAddress)
                );

          //      new ConfigurationChannelFactory<ICalculatorChannel>(
          //          "endpoint1",
          //          newConfiguration,
          //          new EndpointAddress("http://localhost:8000/servicemodelsamples/service";));
            return AutoWrap.ОбернутьОбъект(factory1.CreateChannel());
        
        
        }
   Serginio1
 
94 - 09.12.13 - 11:06
И вызов из 1С
Процедура ВызовСервисаИспользуяConfigFileНажатие(Элемент)
    // Вставить содержимое обработчика.

        врап=новый COMОбъект("NetObjectToIDispatch45");
        
    //Сборка=врап.загрузитьСборку("d:\MyPrograms\Test\NestNet45\NestNet45\bin\Debug\NestNet45.dll");

    Сборка=врап.загрузитьСборку(ИмяФайлаСборки);
    // Можно получить тип и используя сборку, что будет правильным

    //Сборка GetType("NestNet45.ServiceReference1.MorpherSoapClient");

    //Но в данном примере используется поиск в загруженных сборках

    TChannel=Сборка.GetType("NestNet45.ServiceReference1.MorpherSoap");
    ConfigFile=ИмяФайлаСборки+".config";
    endpointConfigurationName="MorpherSoap";
    endpointAddress=Неопределено;
    Клиент=врап.СоздатьКлиентаWCFConfigFile(ConfigFile,TChannel,endpointConfigurationName,endpointAddress);
        
    
    // Вызываю метод и вывожу результат

    рез = Клиент.GetForms("Ваяся Пупкин");
    
    Для каждого стр  Из рез Цикл
        сообщить(стр) 
    КонецЦикла; 


КонецПроцедуры
   H A D G E H O G s
 
95 - 09.12.13 - 11:33
(92) Я готов оплатить ваше время, если вы через team(ammy) покажите, как загружаете comcntrl.dll в 1С. Желательно с включенным отладчиком и списком загруженных в процесс, библиотек. (если такого нет в c# - подойдет и vmmap).
   Serginio1
 
96 - 09.12.13 - 11:42
(95) А у тебя на Delphi не получается?
Наприаер 62. Там через натив достаточно просто.
   Serginio1
 
97 - 09.12.13 - 11:48
Или скачай пример. Там сможешь и сам посмотреть какие библиотеки загружены. Скачиваешь отсюда http://1c.proclub.ru/modules/mydownloads/personal.php?cid=120&lid=9569
проект. Распаковывешь его в куданибуть. Запускаешь РегистрацияКомСервера.exe и выбираешь NetObjetToIDispatch45.dll которая лежит в DLLNetObjetToIDispatch45

Затем запускаешь толстого клиента и ТестNetObjectToIDispatch.epf

Выбираешь Имя Файла сборки 
ФайлыNetObjectToIDispatch\СборкиДляТестов\ЗагрузкаCOMОбъектаБезРегистрации.dll

Выбираешь НадписьКаталогОтличнойОтТекущейВерсии1с
нужный каталог


и жмешь на ЗагрузкаComОбъектаБезРегистрации
или ПолучитьИнформациюОКоКлассах
   H A D G E H O G s
 
98 - 09.12.13 - 11:49
(96)
моя ситуация:

1cv8.exe (8.2.18.109)
при открытии 1С этот процесс загружает из своей же папки
core82.dll (8.2.18.109)

Через ВК, через

LoadLibraryEx(path,0,8);

из другой папки загружаю:
comcntr.dll (8.2.17.169)

При загрузке, comcntr.dll возбуждает ошибку:
"Версия ядра core82.dll (8.2.18.109) отлична от версии comcntr.dll (8.2.17.169)"

И это правильно.
И это логично.
   Serginio1
 
99 - 09.12.13 - 11:51
(98) Еще раз LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8); 
не выдает этой ошибки.
И загрузка через TypeLib тоже.
   Serginio1
 
100 - 09.12.13 - 11:53
99+ прошу прощения не дочитал до конца. Видно с Net другая ситуация
  1  2   

Список тем форума
 
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.