|
v8: Использование сборок .NET в 1С 7.x и 8.x | ☑ | ||
---|---|---|---|---|
0
Serginio1
28.11.13
✎
16:13
|
Это продолжение темы
v8: Объекты Net в IDispatch v8: Вопрос по NetObjectToIDispatch v8: soap:Header выложил статью и файлы http://infostart.ru/public/238584/ Суть статьи использование сборок на примере доступа к вэб сервису |
|||
71
Serginio1
03.12.13
✎
18:33
|
Но я загружаю не через 1С. Завтра попробую через 1С
|
|||
72
Serginio1
03.12.13
✎
18:34
|
(69) Это для ВК
|
|||
73
H A D G E H O G s
03.12.13
✎
18:35
|
(69) У меня идея - перехват DllregisterServer.
В нем - включение перехвата работы с реестром, и возврат годного CLSID по ProgID. Но там такая каша с zw(nt) работы с реестром, пока не разобрался. |
|||
74
H A D G E H O G s
03.12.13
✎
18:37
|
(71) Естественно. Comcntlr требует для себя core82.dll
А оно уже загружено при загрузке 1cv8.exe Он получает его handle по имени и видит кривую версию. Фэйл. |
|||
75
Serginio1
03.12.13
✎
18:39
|
(73) Зачем? Посмотри внимательно 62.
(74) При использовании Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8); будет грузить библиотеку из директории таком порядке 1.Каталог, заданный в napaмeтре pszDLLPathName. А уже потом из 2.Текущий каталог процесса. 3.Системный каталог Windows. 4.Основной каталог Windows. 5.Каталоги, перечисленные в переменной окружения PATH |
|||
76
Serginio1
03.12.13
✎
18:39
|
Давай сейчас и проверю.
|
|||
77
H A D G E H O G s
03.12.13
✎
18:40
|
Сколько я мучения провел с этим перехватом dllregisterserver
2 дня убил на то, что обваливался процесс в мертвую при установке перехвата реестра. Оказалось, что 1С выгружала dll, так как в dllregisterserver не всенено записей в реестр и дальше не вызывался dllgetclassobject и не было ссылок на эту dll. |
|||
78
H A D G E H O G s
03.12.13
✎
18:42
|
(75) Зачем? Посмотри внимательно 62.
У меня нет библиотеки типов. |
|||
79
Serginio1
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); КонецПроцедуры |
|||
80
Serginio1
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); } |
|||
81
Serginio1
03.12.13
✎
19:06
|
(78) А в какой библиотеке у тебя нет информации о типе. Это надо на чистом С++ писать.
|
|||
82
Serginio1
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Объекта,"ЗагрузитьОбъект",ИмяФайла,стр.Гуид); // Выполняется без ошибок |
|||
83
Serginio1
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; } |
|||
84
Serginio1
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()); КонецПроцедуры |
|||
85
Serginio1
05.12.13
✎
12:57
|
Но обнаружилась неприятная для меня новость
При вызове свойства или при Установке свойства Объект.get_Item("Имя")); в InvokeMember( invokeAttr вызывается как GetProperty а вот в параметрах ничего нет. Как такое можно побороть? |
|||
86
Serginio1
05.12.13
✎
12:58
|
Вернее при вызове свойства Объект.Item["Имя"];
|
|||
87
H A D G E H O G s
05.12.13
✎
13:01
|
(85) Я вот неплохо понимаю в кухне COM, но вот ваши шаманические напевы на C++ вынесли мне мозг. Пишите на Дельфи, пожалуйста :-)
|
|||
88
Serginio1
05.12.13
✎
13:37
|
(87) Это C#. На манагед Delphi будет тоже самое.
Суть в том что например при вызове такой конструкции Объект.Item[5]=5; Должен вызываться Метод IDispath Invoke c параметрами DISPID_PROPERTYPUT и 2 параметра. А на самом деле вызывается с DISPATCH_PROPERTYGET и вообще без параметров. Если просто вызвать Объект.Item["Имя"]; то параметры (Имя) не передается |
|||
89
Serginio1
05.12.13
✎
13:39
|
(87) Зря ты C# игнорируешь. Подучи. Там после Delphi не так сильно переучиваться, а знание библиотек и устройство Net пригодится.
|
|||
90
Serginio1
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]); } } } |
|||
91
H A D G E H O G s
08.12.13
✎
22:02
|
Ищется Serginio1
|
|||
92
Serginio1
09.12.13
✎
10:11
|
(91) Я Здесь
|
|||
93
Serginio1
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()); } |
|||
94
Serginio1
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("Ваяся Пупкин"); Для каждого стр Из рез Цикл сообщить(стр) КонецЦикла; КонецПроцедуры |
|||
95
H A D G E H O G s
09.12.13
✎
11:33
|
(92) Я готов оплатить ваше время, если вы через team(ammy) покажите, как загружаете comcntrl.dll в 1С. Желательно с включенным отладчиком и списком загруженных в процесс, библиотек. (если такого нет в c# - подойдет и vmmap).
|
|||
96
Serginio1
09.12.13
✎
11:42
|
(95) А у тебя на Delphi не получается?
Наприаер 62. Там через натив достаточно просто. |
|||
97
Serginio1
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ОбъектаБезРегистрации или ПолучитьИнформациюОКоКлассах |
|||
98
H A D G E H O G s
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)" И это правильно. И это логично. |
|||
99
Serginio1
09.12.13
✎
11:51
|
(98) Еще раз LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8);
не выдает этой ошибки. И загрузка через TypeLib тоже. |
|||
100
Serginio1
09.12.13
✎
11:53
|
99+ прошу прощения не дочитал до конца. Видно с Net другая ситуация
|
|||
101
sapphire
09.12.13
✎
12:05
|
(3) что именно ты имеешь ввиду?
ADO DB умеет делать асинхронный запросы. Или ты имеешь ввиду запросы по сети? |
|||
102
sapphire
09.12.13
✎
12:06
|
(87) не надо дельфи
|
|||
103
Serginio1
09.12.13
✎
12:10
|
(98) Посмотрел vmmap в процессах две библиотеки.
|
|||
104
H A D G E H O G s
09.12.13
✎
12:17
|
(103) Можно мне подключиться?
|
|||
105
Serginio1
09.12.13
✎
12:19
|
Давай я тебе скрин куда нибудь выложу.
|
|||
106
Serginio1
09.12.13
✎
12:24
|
Но я использую в обеих случаях LoadTypeLib
в первом используя загрузку через typeInformation.CreateInstance а во втором случае нахожу GUID и LoadLibraryEx |
|||
107
H A D G E H O G s
09.12.13
✎
12:28
|
(105) Да любой фотохостинг. Но вряд ли мне от этого легче будет.
|
|||
108
H A D G E H O G s
09.12.13
✎
12:30
|
||||
109
Serginio1
09.12.13
✎
12:35
|
||||
110
Serginio1
09.12.13
✎
12:36
|
||||
111
Serginio1
09.12.13
✎
12:51
|
(108) А почему ты не хочешь скачать разработку?
|
|||
112
H A D G E H O G s
09.12.13
✎
13:44
|
(109) гхм...
Может это фишка 8.3 Дома вечером попробую. А можно увидеть, какая core82.dll загружена. И одна ли она? |
|||
113
Serginio1
09.12.13
✎
13:53
|
(112) core82.dll одна из запускаемой программы
|
|||
114
Serginio1
10.12.13
✎
17:00
|
(112) http://msdn.microsoft.com/en-us/library/windows/desktop/ms684179.aspx
относительный путь. SetDllDirectory функция может быть использована для изменения пути поиска. Это решение лучше, чем пользоваться SetCurrentDirectory или жесткого кодирования полный путь к DLL. Однако следует помнить, что использование SetDllDirectory эффективно отключает безопасный режим поиска DLL в то время как указанный каталог находится в пути поиска, и это не является потокобезопасным. Если это возможно, то лучше использовать AddDllDirectory изменить путь поиска технологическую умолчанию. Для получения дополнительной информации см. динамически подключаемых библиотек порядок поиска . Windows 7, Windows Server 2008 R2, Windows Vista и Windows Server 2008: LOAD_LIBRARY_SEARCH_ * флаги доступны на системах, которые KB2533623 установленных. Чтобы определить, доступны ли флаги, используйте GetProcAddress , чтобы получить адрес AddDllDirectory , RemoveDllDirectory или SetDefaultDllDirectories функции. Если GetProcAddress успешно, то LOAD_LIBRARY_SEARCH_ * флаги могут быть использованы с LoadLibraryEx. |
|||
115
H A D G E H O G s
10.12.13
✎
17:09
|
(114) Ах тыж елкин кот.
Ну отказывется у меня грузица comcntrl.dll нижней версии в более верхнюю 1cv8.exe. Это в версии 8.2.18.109 и 8.2.16.x Это логично, правильно и понятно. А 8.3 я вчера не смог проверить, ибо сдох дома комп с синим экраном. |
|||
116
Serginio1
10.12.13
✎
17:18
|
(115) Да не логично. Зарегистрируй Regsvr32 нижнюю версию и посмотри что у тебя грузится в процесс
|
|||
117
Serginio1
10.12.13
✎
17:19
|
||||
118
H A D G E H O G s
10.12.13
✎
17:23
|
(116) Даже смотреть не надо.
Загрузиться нижняя версия и пошлет меня лесом. И будет права. |
|||
119
H A D G E H O G s
10.12.13
✎
17:24
|
(117) Можно коннект?
Или я сам дам коннект и ты глянешь |
|||
120
H A D G E H O G s
10.12.13
✎
17:24
|
А лучше в аську выйди.
|
|||
121
Serginio1
10.12.13
✎
17:30
|
Да у меня тим вьювера нет. С админом нужно согласовывать. Лениво.
Сейчас аску поставлю. |
|||
122
H A D G E H O G s
10.12.13
✎
17:32
|
(121) ammy admin
Не требует регистрации. |
|||
123
Serginio1
11.12.13
✎
11:38
|
На 8.3 Все работает. При чем на версию \8.3.2.172\ и ниже ругается на отсутствие DllGetClassObject.
Короче вежзде заменил LoadLibraryEx на LoadLibrary ЗагрузкаComОбъекта.ЗагрузитьБиблиотекуВПроцесс(Путь+"bin\stl83.dll"); ЗагрузкаComОбъекта.ЗагрузитьБиблиотекуВПроцесс(Путь+"bin\core83.dll"); Ком=ЗагрузкаComОбъекта.ЗагрузитьОбъект(ИмяФайла,стр.Гуид); public static void ЗагрузитьБиблиотекуВПроцесс(string ИмяФайла) { // var module = Win32NativeMethods.LoadLibraryEx(ИмяФайла, IntPtr.Zero, 8); var module = Win32NativeMethods.LoadLibrary(ИмяФайла); if (module == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error()); } Попробуй на 8.2 на Delphi |
|||
124
H A D G E H O G s
11.12.13
✎
12:24
|
Не все так однозначно, бой еще идет.
|
|||
125
Serginio1
11.12.13
✎
13:52
|
Прошу извинить меня за дачу ложной информации по поводу возможности подключения к базе, созданной в другой веерсии программы. Впервую очередь у H A D G E H O G s
Веренее comcntr.dll загружается, но вот core83.dll использует текущего процесса. Ошибка была скрыта использованием информации из библиотеки типов. В ней вызов typeInformation.CreateInstance(null, ref IID_IUnknown, out classInstance); приводил к поиску Гуида в реестре и запуск зарегистрированной библиотеки. В 8.3 обратная совместимость с предыдущими версиями. Через COMОбъект("V83.COMConnector") можно подключиться к версии созданоой в более поздней версии. |
|||
126
H A D G E H O G s
11.12.13
✎
14:03
|
(125) Да фигня.
Я уж думал - все, здравый смысл покинул этот мир. Выход - параллельная загрузка полного ядра 1С предыдущей версии (как это делается в не1С процесс при Com.Connect()) и перенаправление в него вызовов. |
|||
127
Serginio1
11.12.13
✎
14:07
|
Но из 7ки загружается
Процедура Подключитьсяк8ке() ИмяФайла="c:\Program Files (x86)\1cv8\8.3.3.715\bin\comcntr.dll"; ИмяФайлаСборки="D:\MyPrograms\Test\ЗагрузкаCOMОбъектаБезРегистрации\ЗагрузкаCOMОбъектаБезРегистрации\bin\Debug\ЗагрузкаCOMОбъектаБезРегистрации.dll"; врап=СоздатьОбъект("NetObjectToIDispatch45"); //ФайлСборки="d:\MyPrograms\Test\ЗагрузкаCOMОбъектаБезРегистрации\ЗагрузкаCOMОбъектаБезРегистрации\bin\Debug\ЗагрузкаCOMОбъектаБезРегистрации.dll"; ФайлСборки=ИмяФайлаСборки; Сборка=врап.загрузитьСборку(ФайлСборки); ЗагрузкаComОбъекта=Сборка.GetType("ЗагрузкаCOMОбъектаБезРегистрации.ЗагрузкаComОбъекта"); //Путь=КаталогПрограммы(); res=ЗагрузкаComОбъекта.ЗагрузитьОбъект(ИмяФайла,"181E893D-73A4-4722-B61D-D604B3D67D47"); Сообщить(res.HighBoundDefault); ком=res.Connect("File=""C:\Тест\ТестоваяБаза"";"); Сообщить(ком.ВнешнееСоединение1.Тест1()); Сообщить(ком.КаталогПрограммы()); Сообщить(Ком.СтрокаСоединенияИнформационнойБазы()); Сообщить(Ком.ПредставлениеПриложения("COMConnection")); КонецПроцедуры при этом выдает c:\Program Files (x86)\1cv8\8.3.3.715\bin\ File="C:\Тест\ТестоваяБаза"; При зарегистрированной C:\Program Files (x86)\1cv8\8.3.4.365\bin\comcntr.dll |
|||
128
H A D G E H O G s
11.12.13
✎
14:09
|
(127) Конечно.
В семерку загружается полноценное ядро из восьмерки. Посмотри список библиотек процесса 1cv7 из восьмерочной папки после вызова ком=res.Connect("File=""C:\Тест\ТестоваяБаза"";"); Все логично. |
|||
129
Serginio1
11.12.13
✎
14:13
|
Но вот в
Процедура ПодключитьИВывестиИнформацию(ИмяФайла) ИмяФайлаСборки="D:\MyPrograms\Test\ЗагрузкаCOMОбъектаБезРегистрации\ЗагрузкаCOMОбъектаБезРегистрации\bin\Debug\ЗагрузкаCOMОбъектаБезРегистрации.dll"; врап=СоздатьОбъект("NetObjectToIDispatch45"); //ФайлСборки="d:\MyPrograms\Test\ЗагрузкаCOMОбъектаБезРегистрации\ЗагрузкаCOMОбъектаБезРегистрации\bin\Debug\ЗагрузкаCOMОбъектаБезРегистрации.dll"; ФайлСборки=ИмяФайлаСборки; Сборка=врап.загрузитьСборку(ФайлСборки); ЗагрузкаComОбъекта=Сборка.GetType("ЗагрузкаCOMОбъектаБезРегистрации.ЗагрузкаComОбъекта"); //Путь=КаталогПрограммы(); res=ЗагрузкаComОбъекта.ЗагрузитьОбъект(ИмяФайла,"181E893D-73A4-4722-B61D-D604B3D67D47"); Сообщить(res.HighBoundDefault); ком=res.Connect("File=""C:\Тест\ТестоваяБаза"";"); Сообщить(ком.ВнешнееСоединение1.Тест1()); Сообщить(ком.КаталогПрограммы()); Сообщить(Ком.СтрокаСоединенияИнформационнойБазы()); Сообщить(Ком.ПредставлениеПриложения("COMConnection")); КонецПроцедуры // ПодключитьИВывестиИнформацию Процедура Подключитьсяк8ке() ИмяФайла="c:\Program Files (x86)\1cv8\8.3.3.715\bin\comcntr.dll"; ПодключитьИВывестиИнформацию(ИмяФайла); ИмяФайла="c:\Program Files (x86)\1cv8\1cv8\8.3.4.365\bin\comcntr.dll"; ПодключитьИВывестиИнформацию(ИмяФайла); КонецПроцедуры Выдает ошибку "не найден указанный модуль" |
|||
130
Serginio1
11.12.13
✎
14:18
|
Прошу прощения
ком=res.Connect("File=""C:\Тест\ТестоваяБаза"";"); {C:\НОВЫЕОТЧЕТЫ\ТЕСТNETOBJETTOIDISPATCH20.ERT(183)}: V83.COMConnector.1: Версия компоненты 'comcntr' (8.3.4.365) отличается от версии корневого модуля 'core83' (8.3.3.715) То есть она берет уже загруженный core83 |
|||
131
Serginio1
11.12.13
✎
14:52
|
Если lpModuleName не включает в себя путь и имеется больше, чем один загруженный модуль с тем же самым базовым именем и расширением, функция извлекает дескриптор модуля, который был загружен сначала.
|
|||
132
Serginio1
13.12.13
✎
10:49
|
У меня есть еще вопрос. Каким образом 1С обращается к объекту через индексаторы?
Хочу подключить свойства по умолчанию, но мне нужно узнать как 1С обращается через [] Или запращивает интерфейс Который можно вытянуть через QueryInterface или метод который можно выцепить черeз GetIdsOfNames Например как здесь http://delphiworld.narod.ru/base/delphi_and_mapinfo2.html TEvent = class(TInterfacedObject,IUnknown,IDispatch) К сожалению на работе Delphi нет. |
|||
133
Serginio1
13.12.13
✎
11:35
|
Надо понимать, что при обращении к массиву она проверяет на поддежку COMSafeArray, иначе просто обращение к свойсву через GetIdsOfNames
|
|||
134
Serginio1
13.12.13
✎
12:12
|
COMSafeArray gj по индексатору не дает. Да и ..
|
|||
135
Serginio1
16.12.13
✎
11:07
|
Вообще можно было бы увеличить функциональность за счет поддержки ExpandoObject. Например http://www.codeproject.com/Articles/461677/Creating-a-dynamic-object-from-XML-using-ExpandoOb
Так же можно расширить за счет использования свойсв-индексаторов у которых сигнатура this[string] о которых можно узнать динамически у типа через GetDefaultMembers(). Но испотлзуя IReflect нужно знать заранее все значения, что бы сгенерить нужный массив PropertyInfo[] GetProperties. Но вот здесьб проблематично. А вот через ВК это уже намного проще. Например http://www.rsdn.ru/forum/dotnet/3471534.1 |
|||
136
Serginio1
16.12.13
✎
11:10
|
135+ Но у ВК есть проблемы с перегрузками методов
|
|||
137
Serginio1
16.12.13
✎
11:26
|
||||
138
Serginio1
17.12.13
✎
11:54
|
Подправил обертку объектов. Теперь массивы примитивных типов строки, дата, Decimal возвращаются как родные для 1С COMSafeArray.
Для массива объектов нужно отдельно преобразовать через функция ПолучитьSafeArrayИзЭнумератора(Object Массив) |
|||
139
Serginio1
17.12.13
✎
15:52
|
Исправил содержимое папки DLLNetObjetToIDispatch45
|
|||
140
Serginio1
23.12.13
✎
14:09
|
135 Вообще было бы здорово если можно было бы договориться с 1С, что если не находит свойство для Idispatch через GetIdsOfNames, то передавало по аналогии с запросом Энумератора Invoke c [DISPID=-4] что то типа DISPID=-777 или другие значения для понимания, что вызывается свойства по умолчанию
|
|||
141
H A D G E H O G s
23.12.13
✎
15:34
|
(140) Было бы здорово, если бы 1С добавили в каждый объект элемента интерфейса - дескриптор Windows. Больше мне от них ничего не нужно.
|
|||
142
Serginio1
23.12.13
✎
15:43
|
(141) Ну ты их можешь найти, а вот вызвать свойсва индексаторы по другому никак.
Ну и это тоже. Вообще им лучше дать по максимуму возможность расширения за счет сторонних средств. |
|||
143
H A D G E H O G s
23.12.13
✎
15:49
|
(142) Нет. Я их не могу найти. Никак.
|
|||
144
Serginio1
23.12.13
✎
16:02
|
(143) То есть такие конструкции не работают? Хендл главного окна ты через ВК можешь получить
IntPtr hWnd = Win32Window.FindWindow(null, "Set WLAN Power"); while (hWnd == IntPtr.Zero) { Thread.Sleep(100); hWnd = Win32Window.FindWindow(null, "Set WLAN Power"); } IntPtr gg; IntPtr OKHandle = IntPtr.Zero; IntPtr WLHandle = IntPtr.Zero; IntPtr CancelHandle = IntPtr.Zero; // MessageBox.Show(Win32Window.GetWindowText(hEdit)); gg = Win32Window.GetWindow(hWnd, GW.CHILD).Handle; while (gg != IntPtr.Zero) { if (Win32Window.GetWindowText(gg) == "OK") OKHandle = gg; if (Win32Window.GetWindowText(gg) == "WirelessLAN ON") WLHandle = gg; if (Win32Window.GetWindowText(gg) == "Cancel") CancelHandle = gg; // MessageBox.Show(Win32Window.GetWindowText(gg)); // MessageBox.Show(gg.Text); gg = Win32Window.GetWindow(gg, GW.HWNDNEXT).Handle; // gg = Win32Window.GetWindow(gg, GW.CHILD).Handle; } // MessageBox.Show(isChecked(WLHandle).ToString()); if (isChecked(WLHandle)!=state) { emulPress(WLHandle); emulPress(OKHandle); } else emulPress(CancelHandle); WaitForSingleObject(pi.hProcess, INFINITE); |
|||
145
H A D G E H O G s
23.12.13
✎
16:03
|
(144) Аххх.
Сюрприз, сюрприз. В элементах форм, а также в формах Тонкого клиента нет текста. Пуст. |
|||
146
H A D G E H O G s
23.12.13
✎
16:05
|
Искать в Толстом по заголовку формы - фуфуфу, моветон.
Можно его конечно менять на GUIDСтрока, искать GUIDСтрока, возвращать обратно, но только в отдельном потоке, 1С установить заголовок Windows потом, когда твой код окончиться. |
|||
147
H A D G E H O G s
23.12.13
✎
16:07
|
Вообще что то искать по тексту - моветон. Бррр. Корежит всего. Нельзя по тексту ничего искать.
Я текстам недоверяю еще со времен войны кодировок, когда юникодом в винде и не пахло. |
|||
148
Serginio1
23.12.13
✎
16:18
|
(147) Согласен. При чем ХЭНДЛ окна и AppDispatch можно получить только через ВК. Хотя при появлении событий многие вещи можно делать и из ActiveX.
|
|||
149
AaNnDdRrEeYy
23.12.13
✎
16:32
|
Когда сборшик мусора уничтожит созданный объект из сборки NET и полученный в 1С?
Вопрос возник потому что я не видел явного использования интерфейса IDispose. т.е вызова Объект.Dispose() не явно метод вызывается при уничтожении объекта, вот когда происходит это унижтожение? |
|||
150
oleg_km
23.12.13
✎
16:47
|
(149) Как и любой объект без явного вызова Dispose - через какое-то время. Поэтому, если хочу, чтобы был немедленный эффект - сам вызываю Dispose.
|
|||
151
Serginio1
23.12.13
✎
16:48
|
(149) Если объект использует ресурсы, то лучше сразу закрыть его по окончании использования. Как это сделано для соетов и портов
Процедура ПриЗакрытии() // Вставить содержимое обработчика. Если СерверTCP<>неопределено Тогда СерверTCP.Закрыть(); КонецЕсли; КонецПроцедуры А что касается уничтожения объектов, то GC всю работу сделает сам. |
|||
152
Serginio1
23.12.13
✎
16:50
|
(149) IDispose хорош при использовании конструкции using
. В 1С нужно явно закрывать хэндлы |
|||
153
AaNnDdRrEeYy
23.12.13
✎
17:02
|
(152) есть подозрение что GC не тронет объект пока висит рабочий процесс 1сv8.exe. у мня так было, но не с маршалингом а с обычным ком объектом. воощем сборшик мусора не видит когда 1с его отпускает или 1с его просто не отпускает.
|
|||
154
Serginio1
23.12.13
✎
17:30
|
(153) Здесь может быть проблема с подсчетом ссылок. Но ты всегда можешь принудительно запустить сборку мусора и посмотреть.
GC.Collect(); // Wait for all finalizers to complete before continuing. // Without this call to GC.WaitForPendingFinalizers, // the worker loop below might execute at the same time // as the finalizers. // With this call, the worker loop executes only after // all finalizers have been called. GC.WaitForPendingFinalizers(); |
|||
155
oleg_km
23.12.13
✎
17:37
|
(153) ну счетчик должен нормально работать, когда переменная в 1С утрачивает видимость. А дальше уже сработает сборщик мусора
|
|||
156
MM
23.12.13
✎
18:39
|
(141) так они оконные ресурсы экономят. У Реймонда Чена написано, что по соображениям совместимости, оконные дескрипторы штука дефицитная, в пределах оконной станции. В 7.7 можно было истратить все дескрипторы запустив 6-7 приложений на компьютере с windows 2000.
(148) Платформа 1С поддерживает массу языков, так что рассчитывать на постоянство текстов окон наивно, как и приводить типы к строке для проверки их значения. (155) так при наличии достаточного количества памяти сборка мусора совсем не обязательна, и системный ресурс (файл, сокет) может долго не освобождаться. |
|||
157
H A D G E H O G s
23.12.13
✎
18:41
|
(156) так они оконные ресурсы экономят. Хрень полная.
Каждая надпись, поле ввода - это полноценный элемент окна Windows, имеющий дескриптор, не имеющий текста, с переписанной отрисовкой и перехватом событий. |
|||
158
Serginio1
23.12.13
✎
19:02
|
(156) Я не про тексты. В Net есть Control у которого есть свойство Handle. То есть выдать наружу то, что нужно стороннему разработчику.
Они пошли по увеличению функциональности, но вот по части интеграции не очень. А можно и Net по максимуму внедрить, и тд. |
|||
159
MM
23.12.13
✎
19:36
|
(157) Посмотрел, точно, видимо недоделали. IE такую технику использует.
(142) А как они это монетизируют? Благотворительность им не свойственна, потому и запрещают всё, что может сэкономить лицензии, особенно инеграцию. Я ошибся отвечал не на (148), а (147). |
|||
160
xReason
23.12.13
✎
19:45
|
в 8.3 использовать .Net - НЕЛЬЗЯ
Так как решение не полноценное будет |
|||
161
MM
23.12.13
✎
19:48
|
(160) и всё из-за Линукса? Там вроде Mono есть, пусть и без СОМ?
|
|||
162
xReason
23.12.13
✎
19:56
|
(161) ага, вообще чем дальше, тем больше я понимаю. Что все должно быть внутри 1С , в крайнем случае с использованием кросс-платформеных решений
|
|||
163
Serginio1
23.12.13
✎
20:24
|
(162) Угу на серверах и клиентах под Win ну никак нельзя использовать?
Опять же есть Java. Просто к нему нужно делать враппер самой 1С .Данная разработка к работает и без участия 1С просто через СОМ. Просто 1С не поддерживает свойства массивы. Кроме всего прочего в C# есть свойства индексаторы, где некая поддержка 1С возможна через вызов Invoke c заранее оговоренным DISPID |
|||
164
Serginio1
23.12.13
✎
20:25
|
(160) А COM тоже нельзя?
|
|||
165
xReason
23.12.13
✎
20:26
|
(164) как нафиг COM в линуксе или в OSX
|
|||
166
oleg_km
23.12.13
✎
20:51
|
(164) По крайней мере в 8.3.4 можно. Наверное, нельзя в клиенте, запущеном под Linux
|
|||
167
xReason
23.12.13
✎
21:07
|
(166) И самое главное также нельзя это сделать на сервере "запущеном под Linux"
|
|||
168
oleg_km
23.12.13
✎
21:34
|
(167) Каждый может сделать осознанный выбор: или Линукс без .НЕТ или Винда с .НЕТом. Для меня выбор очевиден.
|
|||
169
Serginio1
23.12.13
✎
21:44
|
(165) Но такая возможность в языке существует и великолепно используется. А вот выбирая линукс и прочие оси ты ССЗБ и знаешь на что идешь уменьшая свой функционал. Любое универсальное решение это удар по объему возможностей. Та же поддержка вэб сервисов в 1С 8.3 далека от идеала итд. Зачем тратить ресурсы на поддержку кросс платформенности, если можно их потратить с умом на другие участки.
|
|||
170
Serginio1
25.12.13
✎
15:30
|
140 + Вообще для свойств по умолчанию есть DISPID_VALUE
то есть 0. Странно, что 1С этим не пользуется http://www.rsdn.ru/forum/com/4459556.all |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |