Уфх, заработало!
Вся проблема, как и предполагал, состояла в правильном заполнении передаваемых параметров, которые помечены как [opt]:
Ниже приведен прототип LoadFromSQLServer:
Код: Выделить всё
LoadFromSQLServer Procedure (Bstring ServerName,Bstring ServerUserName,Bstring ServerPassword,DTSSQLServerStorageFlags Flags,Bstring
PackagePassword,Bstring PackageGuid,Bstring PackageVersionGuid,Bstring PackageName,*tVariant pVarPersistStgOfHost),hresult,raw,proc
OleView описывает прототип следующим образом:
Код: Выделить всё
!Function[IN],[IN][OPT],[IN][OPT],[IN][OPT][HasDefault],[IN][OPT],[IN][OPT],[IN][OPT],[IN][OPT],[IN][OPT][HasDefault]
Вся загвоздка состояла в том, что нужно было правильно инициализировать [OPT] параметры, чтобы COM опознал их как "пропущенные":
Код: Выделить всё
...
bstrServerName pwBStr
bstrServerUserName pwBStr
bstrServerPassword pwBStr
bstrPackagePassword pwBStr
bstrPackageGuid pwBStr
bstrPackageVersionGuid pwBStr
bstrPackageName pwBStr
lpBstrServerName long
lpBstrServerUserName long
lpBstrServerPassword long
lpBstrPackagePassword long
lpBstrPackageGuid long
lpBstrPackageVersionGuid long
lpBstrPackageName long
szParam cstring(256)
pVtMissing &tVariant
code
...
!- for ommitable BString (e.g. lpBstrServerUserName):
szParam = ''
bstrServerUserName.init(szParam)
lpBstrServerUserName = bstrServerUserName.GetStr()
...
!- for ommitable *tVariant pVarPersistStgOfHost:
pVtMissing &= _vt(VtMissing)
hr = self.I_Package2.LoadFromSQLServer(lpBstrServerName, !
lpBstrServerUserName, !
lpBstrServerPassword, !
par_Flags, !
lpBstrPackagePassword, !
lpBstrPackageGuid, !
lpBstrPackageVersionGuid, !
lpBstrPackageName, !
pVtMissing)
!--------------------------------------------------------------------------------
Без указанной инициализации "пустых" [OPT] параметров LoadFromSQLServer умирал с неинтерпретируемым кодом завершения (hr)!
Следующая преграда - использование COM collections из Clarion. Есть у кого-нибудь опыт работы с коллекциями?
С уважением,
Сергей Смирнов
Привет, Сергей.
Следующая преграда - использование COM collections из Clarion. Есть у кого-нибудь опыт работы с коллекциями?
Глянь класс RegExp (есть на
http://www.clarionlife.net/ и в EasyCom2Inc у ingasoftplus), там реализована IMatchCollection
С уважением,
Михаил
(Добавление)
Hello Дуга Михаил,
Спасибо, Михаил, что не оставили в одиночестве в борьбе с Clarion за доступ к COM.
Я бы избегал "опущенных" аргументов, и все методы в описании интерфейса переписал бы без угловых скобок <Bstring ServerUserName>, так как был негативный опыт...
- Действительно, нужно было честно заполнить все [OPT] параметры, именно в этом и была проблема.
Мой опыт оказался таким же как и Ваш.
Параметры опускать никак нельзя, нельзя, также, передавать 0 вместо пропущенных параметров BSTring или Variant.
Пропущенные BSTR передал бы как пустые строки, а VARIANT создал бы из пустой строки.
- Я сделал так: явно заполнил пропускаемые [OPT] параметры BSTring из пустых cstring, для Variant параметра поступил почти также (в PWCOM есть для этого VtMissing), заполнение Variant "пустышкой" выполняется так:
Код: Выделить всё
...
bstrServerUserName pwBStr
lpBstrServerName long
szParam cstring(256)
pVtMissing &tVariant
...
code
...
if omitted(3) !Ommitable Parameter #2: ServerUserName
szParam = ''
else
szParam = clip(par_ServerUserName)
.
bstrServerUserName.init(szParam)
lpBstrServerUserName = bstrServerUserName.GetStr()
pVtMissing &= _vt(VtMissing) !Parameter #9: pVarPersistStgOfHost
после этого _Package2.LoadFromSQLServer задышал. Жаль, что я не получил эту подсказку раньше. Впрочем то, что дело в параметрах я понял. Но пока шел по дороге от "понял" до "решил" для данной проблемы я потратил непристойно много времени, пока смог из Clarion объяснить COM, что передаю "пропущенные" параметры.
Код: Выделить всё
hr = self.I_Package2.LoadFromSQLServer(lpBstrServerName, !
lpBstrServerPassword, !
par_Flags, !
lpBstrPackagePassword, !
lpBstrPackageGuid, !
lpBstrPackageVersionGuid, !
lpBstrPackageName, !
pVtMissing)
После этого LoadFromSQLServer задышал.
С коллекциями тоже справился.
Остались вопросы о некоторых мной обнаруженных, но непонятых хитростях (я описал их в SofVelocity.public.clarion6 Discussion group).
Привожу их здесь, прошу меня простить, на обратный перевод сил нету.
Если есть ответы, подскажите, пожалуйста.
Ну, а следующая проблема, которую мне потребуется решить - перехват в Clarion приложении сообщений об ошибках из выполняемых dts package. Надеюсь, что и это возможно.
С уважением,
Сергей Смирнов.
--------------------------------------------------------------------------------------
Hi Clarioners,
I hope that COM gurus in the Clarion world, could help me to understand 2
following questions:
Q1. About the interface reference counter.
I know about the rule, that when I get the reference to an interface (e.g.
using QueryInterface) then later, I have to use the .Release method to
decrement an internall reference counter of that interface. Working with COM
collections I use the following code to get from _Package2 coclass object the
reference to the IGlobalVariables interface. So, in the CPackage2.destruct
procedure I try to call self.IGlobalVariables.release(). If I do this, then I
get GPF finishing my application. If I don't, then aplication finishes
correctly. I know also, that pwCOMObject releases the IUnknown in its destruct
method...
Код: Выделить всё
!------------------------------------------------
CPackage2 class(PWCOMObject), module('dtspkg.clw'),link('dtspkg.clw',
_COMLinkMode_),dll(_COMDllMode_)
I_Package2 &_Package2Type, protected !pointer to the
_Package2 interface. It will be initialized by CoCreateInstance in init method
of this class.
IGlobalVariables &GlobalVariablesType, protected !pointer to the
IGlobalVariables interface
IsInitialazed byte,private !True - CPackage2 is initialized
construct procedure()
destruct procedure(), virtual
init procedure(), proc, HRESULT, virtual !Here is the internal
CoCreateInstance call
GetDTSVersionInfo procedure(*LONG VersionMajor,*LONG VersionMinor,*LONG
VersionBuild,*Bstring VersionComments),proc,HRESULT
LoadFromSQLServer procedure(string
par_ServerName, !
string
par_ServerUserName, !
string
par_ServerPassword, !
DTSSQLServerStorageFlags
par_Flags=DTSSQLStgFlag_UseTrustedConnection, !
string
par_PackagePassword, !
string
par_PackageGuid, !
string
par_PackageVersionGuid, !
string
par_PackageName, !
<*tVariant par_pVarPersistStgOfHost>),proc, HRESULT
ExecuteIt procedure(),proc, HRESULT, virtual
PutGlobalVariableValue procedure(string par_VarName, string
par_VarValue),proc, HRESULT, virtual
UnInitialize procedure(),proc, HRESULT !The Uninitialize method
clears all state information and releases all related objects, allowing the
Package object to be reused
.
...
!------------------------------------------------
...
!Getting IGlobalVariables interface
hr = self.I_Package2.GetGlobalVariables(pgvs) !GetGlobalVariables
Procedure(*LONG lpGlobalVariables),hresult,raw,proc !PropGet[OUT][RETVAL]
if hr = S_OK
self.IGlobalVariables &= (pgvs) !<-- it is a trick (type customizing)
.
Is it right, that the I_Package2.GetGlobalVariables method increments
internally the reference counter of IGlobalVariables interface like
QueryInterface? If so, then I should explicitly call somewhere later the
IGlobalVariables.Release. I do that using following code in CPackage2.destruct
procedure:
Код: Выделить всё
!------------------------------------------------
CPackage2.destruct procedure()
nCnt long
code
!
! nCnt = self.IGlobalVariables.release() !<-- Q1. If it is uncommented
then I get GPF right here at the end of the application
! if nCnt = 0
! self.IGlobalVariables &= null
! .
!
!-----------------------------------------------
Q2. About repeatable calling of the I_Package2.LoadFromSQLServer method.
It is a specific question, not a common one, I know.
there is the calling statement in my code:
Код: Выделить всё
hr = self.I_Package2.LoadFromSQLServer(lpBstrServerName, !
lpBstrServerUserName, !
lpBstrServerPassword, !
par_Flags, !
lpBstrPackagePassword, !
lpBstrPackageGuid, !
lpBstrPackageVersionGuid, !
lpBstrPackageName, !
pVtMissing)
hr = self.IGlobalVariables.GetCount(count) !<-- A TRICK. I do this only to
avoid bad hr (COM: Error Unknown, hr = -2147220500 (0x800403EC)) on repeated
calling the previous hr = self.I_Package2.LoadFromSQLServer statement. ???
!What does that mean? Why do I need call hr =
self.IGlobalVariables.GetCount(count) ???
!-----------------------------------------------
I found this solution accidentally and I do not understand this trick
(
Regards,
Sergey Smirnoff.
--------------------------------------
P.S. I use Clarion v.6.1 (9026) + PWCOM classes by PlugwareSolutions.com Ltd
delivered with XMLFuse by ThinkData.com + RTLib.exe by Jim Kane
Написал: ClaList(2)