Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: интеграция с 1С (создание COM компонента)  (Прочитано 44880 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 22-07-2011 10:59 » 

Может кто помнит, я задавал кучу вопросов, когда делал программу для удалённого администрирования. Так вот, поделка сия готова, и заказчик задал вопрос - как это чудо познакомить с одинэской, то есть чтобы программу можно было запустить из 1C-ного кода, а также управлять запущенной программой оттуда (управлять - максимум вызывать определённые функции).

Как это делается ? О_о
« Последнее редактирование: 28-07-2011 16:38 от Алексей1153++ » Записан

Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 22-07-2011 11:30 » 

1С умеет работать с OLE объектами. Ты можешь в своей программе сделать OLE (COM) интерфейс для управления?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 22-07-2011 16:13 » 

если подскажешь, как это делается, то смогу Улыбаюсь

Добавлено через 1 день, 23 часа, 57 минут и 24 секунды:
А правильно ли я понимаю, что в 1С основная проблема - трудности с вызовом WinAPI, и поэтому написание и использование DLL необходимо именно для того, что 1C умеет подгрузить DLL и вызывать из него функции ?

То есть, по сути, DLL у меня должно быть тупо посредником между 1С и WinAPI , который будет передавать команды управляемой программе (через экспортируемые функции)?
« Последнее редактирование: 24-07-2011 16:10 от Алексей1153 » Записан

Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 25-07-2011 12:51 » 

В принципе уже есть "универсальный" посредник для вызова WinAPI - это DynamicWrapper, так что можно обойтись WinAPI. Но по стандарту 1С имеет свой формат интерфейсов, через которые ведет общение с программой. Причем поскольку с выходом 8.2 стало возможным работать через веб-клиент не только в среде Windows, то в 8.2 добавлена переработанная версия работы с внешними компонентами: Native API.
На сайте 1С описание находится в закрытой области (точнее его можно загрузить со страницы загрузки платформы), но поиск дает возможность найти его в просторах интернета
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 25-07-2011 14:59 » 

Kivals, спасибо, вот мне нечто вроде того, что по первой ссылке, и надо, судя по всему сделать. Я сегодня телегу по COM читал, вроде понятно, как это сделать. Потом отпишусь, что вышло )

Добавлено через 1 день, 1 час, 35 минут и 11 секунд:
Kivals, глянь, пожалуйста, мои метания вот тут )
https://forum.shelek.ru/index.php/topic,11352
« Последнее редактирование: 26-07-2011 16:34 от Алексей1153 » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 28-07-2011 07:22 » 

Kivals, я тут поразбирался с визардом в студии и, вроде, родил DLL с COM-объектом внутри. Но не могу понять, в чём его протестировать. А также - кто должен регистрировать компонент, или же вручную надо вызывать regsvr32 ?

Можешь попробовать?

DLL в аттаче, название компонента "MyLIBR.My1Component" , там сейчас единственный метод

Код:
__show_dlg(VARIANT_BOOL show);

должен показывать и скрывать диалог

(проект тоже пристегну на всякий случай)

* DLL.rar (13.5 Кб - загружено 926 раз.)
* MyLIBR.rar (22.5 Кб - загружено 918 раз.)
« Последнее редактирование: 28-07-2011 14:06 от Алексей1153++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 28-07-2011 11:20 » 

Да, в системе его регистрируют (и разрегистрируют) посредством regsrv32. Не важно, руками или посредством вызова из другой программы. Иначе COM не будет недоступен.

Протестить COM-объект легче всего в VB - для него это родной дом.

Код: (Visual Basic)
Dim o As Object

' Создание объекта
Set o = CreateObject("MyLIBR.My1Component")

' Вызов метода
Call o.__show_dig(True)
' Альтернативный способ вызова
' o.__show_dig True

' Удаление объекта
Set o = Nothing
« Последнее редактирование: 28-07-2011 20:30 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 28-07-2011 12:48 » 

Из 1С: Ошибок не вызывает, но и ничего не делает. В атачах тестовые обработки для 1С

* TestDLL77.ert (24 Кб - загружено 935 раз.)
* TestDLL82.epf (6.14 Кб - загружено 923 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 28-07-2011 13:56 » 

Ром,  VB  щас поищу. VB6 сойдёт же ?

Слав, у меня нет 1C Жаль

Добавлено через 44 минуты и 35 секунд:
вспомнил, что в экселе есть VBA  , сделал модуль - а выполняться он не желает, эксель пишет, что макросы не разрешено выполнять

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

Добавлено через 4 часа, 50 минут и 51 секунду:
происходит вот что: не создаётся диалог. Имеется в виду - хендл его окна

Код:
My1Component::My1Component()
{
m_pDlg=new CSomeDlg(0);
BOOL b=m_pDlg->Create(IDD_DIALOG1,0);

CString txt;
txt.Format(
L"Create=%d\n\r"
L"GetLastError=%d\n\r"
L"HWND=0x%08X"
,b
,GetLastError()
,m_pDlg->m_hWnd
);


MessageBox(0,txt,L"345",MB_SYSTEMMODAL);
ShowDialod(0);
}

выводится
Create=0
GetLastError=0
HWND=0

почему окно не создаётся ?

Добавлено через 4 часа, 27 минут и 57 секунд:
догадался, однако Улыбаюсь)

Код:
My1Component::My1Component()
{
m_pApp= new CWinApp;          // <<<<<<<<<
m_pApp->InitInstance();           // <<<<<<<<<

m_pDlg=new CSomeDlg(0);
m_pDlg->Create(IDD_DIALOG1,0);

ShowDialod(0);
}

My1Component::~My1Component()
{
delete m_pDlg;
delete m_pApp;                  // <<<<<<<<<
}


* DLL.rar (85.02 Кб - загружено 906 раз.)
« Последнее редактирование: 28-07-2011 19:31 от Алексей1153 » Записан

Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 28-07-2011 16:29 » 

Слав, у меня нет 1C Жаль
Я помню - это как пример кода, возможно - для твоего клиента

Однако как размерчик dll сразу поменялся... Похоже студия даже не вкомпилила ресурсы в первый раз

Добавлено через 9 минут и 27 секунд:
Все Ок - в 1С 7.7 и 8.2 (толстый и тонкий клиенты) все работает
« Последнее редактирование: 28-07-2011 16:38 от Kivals » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 28-07-2011 16:39 » 

Kivals, насчёт размера -  я теперь статически слинковал с библиотекой MFC. До этого пропустил этот момент (но на работоспособность в данном случая это не влияло)

Добавлено через 52 секунды:
Все Ок - в 1С 7.7 и 8.2 (толстый и тонкий клиенты) все работает
это хорошо )) Сейчас встраиваю полученные знания в проект )

Добавлено через 13 часов, 55 минут и 23 секунды:
Зак пишет:

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

вот могу только батник предложить. Или ещё как-то можно ? ))))
« Последнее редактирование: 29-07-2011 06:35 от Алексей1153 » Записан

zubr
Гость
« Ответ #11 : 29-07-2011 11:55 » 

CreateProcess(NULL, L"regsvr32.exe /s MyComLib.dll", NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, si, pi);
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 29-07-2011 16:45 » 

zubr,  не не, как в студии это сделать я знаю. А там, как выразился зак, сидят бабушки-пользователи 1С . По моему, тут только батник самое удобное
Записан

zubr
Гость
« Ответ #13 : 29-07-2011 17:03 » 

Алексей1153++, причем здесь студия? WinAPI для любой программной платформы одинаково, будь то VS C++, VBA, Delphi, BCB и т. п.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 29-07-2011 17:06 » 

речь про 1С вообще-то Улыбаюсь
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 29-07-2011 17:11 » 

пытаюсь протестировать COM класс,  следующие методы  

Код:
slavedclient_ConnectToServe)(BSTR* ServerAddress, LONG TcpPort);
slavedclient_GetID(LONG* ID);
slavedclient_GetPassword(BSTR* Password, LONG max_chars_count_with_zero);


пробую на VBA в экселе 2000. Вопросы – в комментариях
  

Код:
Public Sub f1()

Dim o As Object

Set o = CreateObject("TMV1C_Component.SlavedClient")


'тут нужна юникодная строка, как объявить ?
Dim str(10) As Byte
str(0) = 48 + 0
str(1) = 48 + 1
Call o.slavedclient_ConnectToServer(str, 80)


'правильно ли ? (нужна юникодная строка, передаваться должен указатель на буфер)
Dim LL As Long
LL = 77
Call o.slavedclient_GetID(LL)


'тоже нужна юникодная строка
Dim pass(100 * 2) As Byte
Call o.slavedclient_GetPassword(pass, 100)



Set o = Nothing
End Sub
Записан

zubr
Гость
« Ответ #16 : 29-07-2011 17:24 » 

речь про 1С вообще-то Улыбаюсь
Ну так из 1С функции API можно вызывать.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 29-07-2011 18:11 » 

zubr, если речь про этот вроппер
 
В принципе уже есть "универсальный" посредник для вызова WinAPI - это DynamicWrapper
то он заказчику не подошёл почему то
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 30-07-2011 07:12 » 

Леш, строка задается не массивом байт, а типом String - с указанием длины или без.

Код: (Visual Basic)
Dim str1 As String(80)
Dim str2 As String

Насчет юникодности пока ничего не могу сказать.
Из того, что прочел, я вынес, что строки VBA юникодные, а проблема заключена в строковых константах и встроенных функциях типа MsgBox.
http://teaandbiscuits.org.uk/drupal/node/77

Указателей в VBA нет, но есть передача по ссылке. Данный момент указывается в прототипе импортируемой функции. Для COM, думаю (не уверен), ByRef автоматом указывается.
« Последнее редактирование: 30-07-2011 07:29 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 30-07-2011 11:01 » 

VBA ругается на

Dim str1 As String(80)


Добавлено через 19 минут и 5 секунд:
попробовал вот так, но явно что-то не то

(click to show)

* widechar.PNG (17.23 Кб - загружено 3745 раз.)
« Последнее редактирование: 02-08-2011 21:23 от Алексей1153++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 30-07-2011 13:38 » 

Не связано с предыдущим постом (но тот тоже пока ещё не решился), в общем, по какой я грабле прогулялся! Запишу, кому-то спасёт много времени и нервов Отлично

Если в COM-ном проект добавить ссылку из другого, рабочего проекта, в частности на создаваемый MFC-шный стандартный файл "MyProjectApp.cpp" , а там объявлена глобальная переменная CMyProjectApp theApp, то при сборке DLL+COM:

первый признак ерунды
(click to show)
в консоли вывода:
Цитата
1>Компиляция...
1>CMyProjectApp.cpp
1>Компоновка...
1>Внедрение манифеста...
1>Осуществляется регистрация выхода...
на этом происходит затык - ждать можно до талого снега, либо нажать отмену компиляции.

зависает конкретно regsvr32.exe (студия сразу пытается зарегить COM объект) - его видно в диспетчере. Такая же фигня происходит и при попытке зарегить уже созданную DLL из командной строки

второй признак ерунды
(click to show)
если из того же VBA попытаться создать объект, то выхода из CreateObject уже не произойдёт - висим.

Если для глобальной переменной поставить тип CWinApp вместо CMyProjectApp (для этого эксперимента придётся заремарить extern CMyProjectApp theApp из "MyProjectApp.h"), либо вовсе убрать эту переменную, то затыков не происходит

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

В принципе, я избавился от ссылки в DLL на этот файл, но всё равно хотелось бы узнать, где сябака
« Последнее редактирование: 30-07-2011 13:46 от Алексей1153++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #21 : 30-07-2011 14:49 » 

Чей-то ты, Леш, мудришь...

При регистрации происходит запуск DLL и вызов некой функции в ней (см. MSDN). Соотв., срабатывают зависимости и прочее.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 30-07-2011 15:04 » 

Я в курсе - вызывается DllRegisterServer

Но глобальная переменная то создаётся при этом тоже. Но это ладно, я без неё обошёлся. Тут вот чего ещё:
с передачей строк разобрался - дело в том, что BSTR - это уже указатель на WCHAR. Ещё раз разыменовал - и всё стало нормально с передачей.

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


Код:
str1 = String(100, 0)
Call o.slavedclient_GetPassword( str1, 100)

передаться то он передаётся, но при попытке изменить содержимое строки программа валится, а васик показывает окно

(click to show)

* 111.PNG (9.94 Кб - загружено 3616 раз.)
« Последнее редактирование: 02-08-2011 21:23 от Алексей1153++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #23 : 30-07-2011 15:12 » 

Попробуй

Код: (Visual Basic)
Dim str1 As String(100)
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #24 : 30-07-2011 15:30 » 

VBA ругается на

Dim str1 As String(80)


Улыбаюсь

я кое что уже обнаружил, проверяю щас

Добавлено через 15 минут и 59 секунд:
в общем, в IDL файле я неправильно указал свойства параметра


Цитата
   [id(5), helpstring("метод slavedclient_GetPassword")] HRESULT slavedclient_GetPassword([in,out] BSTR* Password, [in] LONG max_buffer_length);


вместо "[in,out]" у меня было "[out]"
« Последнее редактирование: 30-07-2011 15:46 от Алексей1153 » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #25 : 30-07-2011 16:36 » 

Код: (Visual Basic)
Dim str1 As String * 80
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #26 : 30-07-2011 18:25 » 

RXL, ага, так тоже выделяется. Но я уже вот так делал

Код:
str1 = String(100, 0)


а я тут 2 часа мозгового сексу отхватил - оказалось, что фаервол отличился. Ну не создавался сокет, и всё тут! Потом вдруг думаю - отрублю ка я фаер... Хоп - открылся сокет! Запускаю фаер, смотрю правила - екселька то у меня весь запрещённый Отлично

Остался ещё один момент - при закрытии компонента эксель вылетает. Щас буду рыться

Добавлено через 1 час, 2 минуты и 58 секунд:
Охренеть. Я столько мучался без отладчика, а студия-то позволяет отлаживать DLL ! Совершенно случайно это сейчас открыл для себя

Сразу увидел, где ошибка, а так бы ни в жисть. Осталось ещё придумать, как исправить ))

Добавлено через 34 минуты и 1 секунду:
усё, силы зла побеждены )

Одно только беспокоит - где-то два потока остаются висеть после закрытия объекта. Что очень странно. Проверил с MyLIBR.My1Component (тестовый проект из аттача вверху) - там всё ок, ничего не остаётся висеть

Добавлено через 13 часов, 13 минут и 8 секунд:
выяснил, что дело в CWinThread - я их первый раз применил для потоков ради эксперимента. Если делать выход из процедуры потока сразу (для теста), то счётчик потоков не увеличивается. Причину пока не понял и пока забил (частых перезапусков всё равно не будет). Подозреваю, что если использовать обычные АПИшные потоки, то всё будет ок , но переделывать сейчас не буду ))
« Последнее редактирование: 31-07-2011 09:15 от Алексей1153 » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #27 : 02-08-2011 10:30 » 

Если в COM-ном проект добавить ссылку из другого, рабочего проекта, в частности на создаваемый MFC-шный стандартный файл "MyProjectApp.cpp" , а там объявлена глобальная переменная CMyProjectApp theApp, то при сборке DLL+COM:

выдалась свободная минутка, поэкспериментировал . Выявлен более "глубокий" виновник затыкания (но дальше я пока не стал разбираться)

(click to show)

Поскольку у меня MFC-проект, основанный на диалоге, то внутри InitInstance открывается модальный диалог, после закрывания которого происходит возврат 0 (завершение приложения)

С тестовым кодом, где взят чистый CDialog, которому подсунут ресурс моего диалога, затыкания не происходит. После строки вывода "1>Осуществляется регистрация выхода..." появляется диалог-зомби, его закрываем, компиляция удачно завершается.

А вот эта корявая надпись как раз выводится из-за того, что возвращается 0. Если вернуть 1, то надписи нет. Интересно, возможно ли как-то узнать, как "запустили приложение" - штатно, или только для регистрации DLL ?

* 1.PNG (32.5 Кб - загружено 3748 раз.)
« Последнее редактирование: 02-08-2011 21:23 от Алексей1153++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #28 : 02-08-2011 11:52 » 

Вызов DllRegisterServer разве не информативно?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #29 : 02-08-2011 17:47 » 

не понимаю вопроса
Записан

Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines