View mode: basic / threaded / horizontal-split · Log in · Help
March 09, 2005
(help) automation on windows
I fond some reference on how to do late binding and automation (it's 
cool when you know the right terms... at least I hope they're right...), 
so I have this D code right now:

//----------------------------------------
void main()
{
    wchar * prog="InternetExplorer.Application";
    wchar * member="Visible";

    LCID defaultLCID = GetUserDefaultLCID();

    HRESULT hr = CoInitialize(null);
    printf("1:%d\n",hr);

    CLSID bu;
    hr=CLSIDFromProgID(prog, &bu);
    printf("2:%d\n",hr);

    IDispatch* pIDispatch;
    hr = CoCreateInstance(&bu, null, CLSCTX_SERVER, &IID_IDispatch,cast 
(void**)&pIDispatch);
    printf("3:%d\n",hr);

    DISPID dispid;
    hr = pIDispatch.GetIDsOfNames(cast(REFIID) &IID_NULL, &member, 1, 
defaultLCID, &dispid);
    printf("4:%d\n",hr);

    VARIANTARG myArg;
    myArg.n1.n2.vt = VT_I4|VT_BYREF;
    myArg.n1.n2.n3.lVal = 1;

    DISPPARAMS param;
    param.cArgs=1;
    param.rgvarg=&myArg;

    VARIANT * result=new VARIANT;

    hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, defaultLCID, 
DISPATCH_METHOD,
        &param, result, null, null);
    printf("5:%d\n",hr);

    //Sleep(2000);

    CoUninitialize();
}
//----------------------------------------

The idea is to do something like (pseudo-code):

app=new InternetExplorer.Application();
app.Visible=1; //or app.Visible(1), I don't know

But the call to GetIDsOfNames (between printfs 3 and 4) produces an 
access violation. Any ideas?

The C++ version does a bit better: the Invoke call returns -2147024809, 
whatever that means.

(BTW, I'm using the core32 library for all that IDispatch stuff, even if 
the one I have is a bit outdated)

_______________________
Carlos Santander Bernal
March 09, 2005
Re: (help) automation on windows
"Carlos Santander B." <csantander619@gmail.com> wrote in message 
news:d0nuj0$eds$1@digitaldaemon.com...
>I fond some reference on how to do late binding and automation (it's cool 
>when you know the right terms... at least I hope they're right...), so I 
>have this D code right now:
>
> //----------------------------------------
> void main()
> {
>     wchar * prog="InternetExplorer.Application";
>     wchar * member="Visible";
>
>     LCID defaultLCID = GetUserDefaultLCID();
>
>     HRESULT hr = CoInitialize(null);
>     printf("1:%d\n",hr);
>
>     CLSID bu;
>     hr=CLSIDFromProgID(prog, &bu);
>     printf("2:%d\n",hr);
>
>     IDispatch* pIDispatch;
>     hr = CoCreateInstance(&bu, null, CLSCTX_SERVER, &IID_IDispatch,cast 
> (void**)&pIDispatch);
>     printf("3:%d\n",hr);
>
>     DISPID dispid;
>     hr = pIDispatch.GetIDsOfNames(cast(REFIID) &IID_NULL, &member, 1, 
> defaultLCID, &dispid);
>     printf("4:%d\n",hr);

If you create a WebBrowser object instead, with IID_IWebBrowser2, you should 
be able to directly call put_Visible(VARIANT_TRUE).

>
>     VARIANTARG myArg;
>     myArg.n1.n2.vt = VT_I4|VT_BYREF;
>     myArg.n1.n2.n3.lVal = 1;
>
>     DISPPARAMS param;
>     param.cArgs=1;
>     param.rgvarg=&myArg;
>
>     VARIANT * result=new VARIANT;
>
>     hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, defaultLCID, 
> DISPATCH_METHOD,
>         &param, result, null, null);
>     printf("5:%d\n",hr);
>
>     //Sleep(2000);
>
>     CoUninitialize();
> }
> //----------------------------------------
>
> The idea is to do something like (pseudo-code):
>
> app=new InternetExplorer.Application();
> app.Visible=1; //or app.Visible(1), I don't know
>
> But the call to GetIDsOfNames (between printfs 3 and 4) produces an access 
> violation. Any ideas?
>
> The C++ version does a bit better: the Invoke call returns -2147024809, 
> whatever that means.
>
> (BTW, I'm using the core32 library for all that IDispatch stuff, even if 
> the one I have is a bit outdated)
>
> _______________________
> Carlos Santander Bernal
March 09, 2005
Re: (help) automation on windows
John C wrote:
> 
> 
> If you create a WebBrowser object instead, with IID_IWebBrowser2, you should 
> be able to directly call put_Visible(VARIANT_TRUE).
> 
> 

I guess I should've said that: it's supposed to be like that. I mean, if 
later I want to replace "InternetExplorer.Application" with something 
else, that's all I should change, without having to worry about GUIDs. 
Same for "Visible". The goal is late binding. But thanks, though.

_______________________
Carlos Santander Bernal
March 10, 2005
Re: (help) automation on windows
"Carlos Santander B." <csantander619@gmail.com> wrote in message 
news:d0o2ht$i82$1@digitaldaemon.com...
> John C wrote:
>>
>>
>> If you create a WebBrowser object instead, with IID_IWebBrowser2, you 
>> should be able to directly call put_Visible(VARIANT_TRUE).
>>
>>
>
> I guess I should've said that: it's supposed to be like that. I mean, if 
> later I want to replace "InternetExplorer.Application" with something 
> else, that's all I should change, without having to worry about GUIDs. 
> Same for "Visible". The goal is late binding. But thanks, though.
>
> _______________________
> Carlos Santander Bernal

Could this line be the source of the problem?

   IDispatch* pIDispatch;

Change it to

   IDispatch pIDispatch;

It worked for me. By the way, when you call Invoke, try using 
"DISPATCH_PROPERTYPUT" instead of "DISPATCH_METHOD".

Hope this helps.
March 10, 2005
Re: (help) automation on windows
John C wrote:
> 
> Could this line be the source of the problem?
> 
>     IDispatch* pIDispatch;
> 
> Change it to
> 
>     IDispatch pIDispatch;
> 
> It worked for me. By the way, when you call Invoke, try using 
> "DISPATCH_PROPERTYPUT" instead of "DISPATCH_METHOD".
> 
> Hope this helps. 
> 
> 

Thanks, that worked. Partially. "Invoke" returns -1073741819. It doesn't 
matter if I use DISPATCH_METHOD or DISPATCH_PROPERTYPUT.

Regarding that, is there a way to know (automagically, programmatically) 
when to use DISPATCH_PROPERTYPUT, DISPATCH_METHOD, DISPATCH_PROPERTYGET 
or DISPATCH_PROPERTYPUTREF? Maybe by the result of calling GetIDsOfNames?

_______________________
Carlos Santander Bernal
March 10, 2005
Re: (help) automation on windows
"Carlos Santander B." <csantander619@gmail.com> wrote in message 
news:d0o9va$pgh$1@digitaldaemon.com...
> John C wrote:
>>
>> Could this line be the source of the problem?
>>
>>     IDispatch* pIDispatch;
>>
>> Change it to
>>
>>     IDispatch pIDispatch;
>>
>> It worked for me. By the way, when you call Invoke, try using 
>> "DISPATCH_PROPERTYPUT" instead of "DISPATCH_METHOD".
>>
>> Hope this helps.
>
> Thanks, that worked. Partially. "Invoke" returns -1073741819. It doesn't 
> matter if I use DISPATCH_METHOD or DISPATCH_PROPERTYPUT.
>
> Regarding that, is there a way to know (automagically, programmatically) 
> when to use DISPATCH_PROPERTYPUT, DISPATCH_METHOD, DISPATCH_PROPERTYGET or 
> DISPATCH_PROPERTYPUTREF? Maybe by the result of calling GetIDsOfNames?

Conveniently, IDispatch has a GetTypeInfo method that returns an ITypeInfo 
interface. ITypeInfo::GetFuncDesc returns a FUNCDESC structure containing an 
INVOKEKIND enumeration, which is defined as follows:

   typedef enum tagINVOKEKIND {
      INVOKE_FUNC = DISPATCH_METHOD,
      INVOKE_PROPERTYGET = DISPATCH_PROPERTYGET,
      INVOKE_PROPERTYPUT = DISPATCH_PROPERTYPUT,
      INVOKE_PROPERTYPUTREF = DISPATCH_PROPERTYPUTREF
   } INVOKEKIND;

That looks like what you need.

Or you could try calling Invoke() with each flag in turn until you get S_OK. 
If you don't get S_OK after trying all flags, then throw an exception saying 
the method or property doesn't exist. I think this how scripting languages 
do late binding for automation objects.

By the way, MSDN says "when you use IDispatch::Invoke() with 
DISPATCH_PROPERTYPUT you have to specially initialize the cNamedArgs and 
rgdispidNamedArgs elements of your DISPPARAMS structure with the following:

   DISPID dispidNamed = DISPID_PROPERTYPUT;
   dispparams.cNamedArgs = 1;
   dispparams.rgdispidNamedArgs = &dispidNamed;"

I found an example on Microsoft's support site (it's for Excel, but you can 
adapt it for other automation objects): 
http://support.microsoft.com/kb/181473/EN-US/

>
> _______________________
> Carlos Santander Bernal
March 10, 2005
Re: (help) automation on windows
John C wrote:
> 
> Conveniently, IDispatch has a GetTypeInfo method that returns an ITypeInfo 
> interface. ITypeInfo::GetFuncDesc returns a FUNCDESC structure containing an 
> INVOKEKIND enumeration, which is defined as follows:
> 
>     typedef enum tagINVOKEKIND {
>        INVOKE_FUNC = DISPATCH_METHOD,
>        INVOKE_PROPERTYGET = DISPATCH_PROPERTYGET,
>        INVOKE_PROPERTYPUT = DISPATCH_PROPERTYPUT,
>        INVOKE_PROPERTYPUTREF = DISPATCH_PROPERTYPUTREF
>     } INVOKEKIND;
> 
> That looks like what you need.
> 
> Or you could try calling Invoke() with each flag in turn until you get S_OK. 
> If you don't get S_OK after trying all flags, then throw an exception saying 
> the method or property doesn't exist. I think this how scripting languages 
> do late binding for automation objects.
> 
> By the way, MSDN says "when you use IDispatch::Invoke() with 
> DISPATCH_PROPERTYPUT you have to specially initialize the cNamedArgs and 
> rgdispidNamedArgs elements of your DISPPARAMS structure with the following:
> 
>     DISPID dispidNamed = DISPID_PROPERTYPUT;
>     dispparams.cNamedArgs = 1;
>     dispparams.rgdispidNamedArgs = &dispidNamed;"
> 
> I found an example on Microsoft's support site (it's for Excel, but you can 
> adapt it for other automation objects): 
> http://support.microsoft.com/kb/181473/EN-US/
> 
> 
>>_______________________
>>Carlos Santander Bernal 
> 
> 
> 

It works! Thanks, again!

_______________________
Carlos Santander Bernal
March 12, 2005
Re: (help) automation on windows
Carlos Santander B. wrote:
> 
> It works! Thanks, again!
> 

(progress update and another request for help)

PROPERTYGET and PROPERTYPUT work. PROPERTYPUTREF, I don't know, because 
I haven't tried and I don't know how to try. METHOD without parameters 
also works. With parameters, however, it's not as good.

So far, this code works (adapted from Justin's code in 
http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/18805, I hope 
the URL is ok):

//----------------------------------------------------------------
    AXO ie=new AXO("InternetExplorer.Application");

    try
    {
        VARIANTARG a1, a2, a3, a4;
        a1.n1.n2.vt=20;
        a2.n1.n2.vt=6008;
        a3.n1.n2.vt=0;
        a4.n1.n2.vt=17;

        VARIANTARG myArg;
        myArg.n1.n2.vt = VT_BSTR;
        myArg.n1.n2.n3.bstrVal = "about:blank";
        ie.call("Navigate",a4,a3,a2,a1,myArg);

        myArg.n1.n2.vt = VT_UI4;
        myArg.n1.n2.n3.lVal = 850;
        ie.set("Width",myArg);
        myArg.n1.n2.n3.lVal = 710;
        ie.set("Height",myArg);
        myArg.n1.n2.n3.lVal = 10;
        ie.set("Top",myArg);
        myArg.n1.n2.n3.lVal = 10;
        ie.set("Left",myArg);

        myArg.n1.n2.vt = VT_BOOL;
        myArg.n1.n2.n3.boolVal = 0;
        ie.set("ToolBar",myArg);
        ie.set("MenuBar",myArg);
        ie.set("StatusBar",myArg);
        myArg.n1.n2.n3.boolVal = 1;
        ie.set("Visible",myArg);

        VARIANT tmp = ie.get("Visible");
        bool isVisible = cast(bool) tmp.n1.n2.n3.boolVal;
    }
    finally
        ie.call("Quit");
//----------------------------------------------------------------

Works, except for the Navigate call. Going through the parameters I 
found their VARTYPEs, so that's why I set them, but I have no idea what 
they should receive. Also, I'm aware some methods are optional (Navigate 
has 4, I assume the only required is the URL), but only passing one 
doesn't work either.

So, again, some help would be nice.

_______________________
Carlos Santander Bernal
March 12, 2005
Re: (help) automation on windows
"Carlos Santander B." <csantander619@gmail.com> wrote in message 
news:d0tjun$15ie$1@digitaldaemon.com...
> Carlos Santander B. wrote:
>>
>> It works! Thanks, again!
>>
>
> (progress update and another request for help)
>
> PROPERTYGET and PROPERTYPUT work. PROPERTYPUTREF, I don't know, because I 
> haven't tried and I don't know how to try. METHOD without parameters also 
> works. With parameters, however, it's not as good.
>
> So far, this code works (adapted from Justin's code in 
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/18805, I hope the 
> URL is ok):
>
> //----------------------------------------------------------------
>     AXO ie=new AXO("InternetExplorer.Application");
>
>     try
>     {
>         VARIANTARG a1, a2, a3, a4;
>         a1.n1.n2.vt=20;
>         a2.n1.n2.vt=6008;
>         a3.n1.n2.vt=0;
>         a4.n1.n2.vt=17;
>
>         VARIANTARG myArg;
>         myArg.n1.n2.vt = VT_BSTR;
>         myArg.n1.n2.n3.bstrVal = "about:blank";
>         ie.call("Navigate",a4,a3,a2,a1,myArg);
>
>         myArg.n1.n2.vt = VT_UI4;
>         myArg.n1.n2.n3.lVal = 850;
>         ie.set("Width",myArg);
>         myArg.n1.n2.n3.lVal = 710;
>         ie.set("Height",myArg);
>         myArg.n1.n2.n3.lVal = 10;
>         ie.set("Top",myArg);
>         myArg.n1.n2.n3.lVal = 10;
>         ie.set("Left",myArg);
>
>         myArg.n1.n2.vt = VT_BOOL;
>         myArg.n1.n2.n3.boolVal = 0;
>         ie.set("ToolBar",myArg);
>         ie.set("MenuBar",myArg);
>         ie.set("StatusBar",myArg);
>         myArg.n1.n2.n3.boolVal = 1;
>         ie.set("Visible",myArg);
>
>         VARIANT tmp = ie.get("Visible");
>         bool isVisible = cast(bool) tmp.n1.n2.n3.boolVal;
>     }
>     finally
>         ie.call("Quit");
> //----------------------------------------------------------------
>
> Works, except for the Navigate call. Going through the parameters I found 
> their VARTYPEs, so that's why I set them, but I have no idea what they 
> should receive. Also, I'm aware some methods are optional (Navigate has 4, 
> I assume the only required is the URL), but only passing one doesn't work 
> either.
>
> So, again, some help would be nice.

Documentation on this stuff is sparse (as you've no doubt gathered). But if 
I remember correctly, the parameters for Navigate() are as follows:

   url [VT_BSTR, bstrVal]
   flags [VT_UI4, lVal (see BrowserNavConstants)]
   targetFrameName [VT_BSTR, bstrVal]
   postData [VT_ARRAY | VT_VARIANT of VT_UI1, parray]
   headers [VT_BSTR, bstrVal]
   cancel [VT_BOOL | VT_BYREF, pboolVal]

(Note that "cancel" isn't available as a parameter in early binding.)

Without seeing the code behind your set() methods, it's difficult to know 
why it's failing. Your rgvarg array's elements have to be in reverse order, 
but I think you're doing that anyway.

>
> _______________________
> Carlos Santander Bernal
March 12, 2005
Re: (help) automation on windows - COMobjectsSample.zip
Carlos,

I am very interested in this project.  Here is a JScript program that does a lot
with COMs.  It uses IE, Excel and MySQL COM calls.  I wish I can help you more
but I am out of the country on business.  I will keep on watching the posts on
this subject.  Thanks.

josé


Carlos Santander B. says...
>
>Carlos Santander B. wrote:
>> 
>> It works! Thanks, again!
>> 
>
>(progress update and another request for help)
>
>PROPERTYGET and PROPERTYPUT work. PROPERTYPUTREF, I don't know, because 
>I haven't tried and I don't know how to try. METHOD without parameters 
>also works. With parameters, however, it's not as good.
>
>So far, this code works (adapted from Justin's code in 
>http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/18805, I hope 
>the URL is ok):
>
>//----------------------------------------------------------------
>     AXO ie=new AXO("InternetExplorer.Application");
>
>     try
>     {
>         VARIANTARG a1, a2, a3, a4;
>         a1.n1.n2.vt=20;
>         a2.n1.n2.vt=6008;
>         a3.n1.n2.vt=0;
>         a4.n1.n2.vt=17;
>
>         VARIANTARG myArg;
>         myArg.n1.n2.vt = VT_BSTR;
>         myArg.n1.n2.n3.bstrVal = "about:blank";
>         ie.call("Navigate",a4,a3,a2,a1,myArg);
>
>         myArg.n1.n2.vt = VT_UI4;
>         myArg.n1.n2.n3.lVal = 850;
>         ie.set("Width",myArg);
>         myArg.n1.n2.n3.lVal = 710;
>         ie.set("Height",myArg);
>         myArg.n1.n2.n3.lVal = 10;
>         ie.set("Top",myArg);
>         myArg.n1.n2.n3.lVal = 10;
>         ie.set("Left",myArg);
>
>         myArg.n1.n2.vt = VT_BOOL;
>         myArg.n1.n2.n3.boolVal = 0;
>         ie.set("ToolBar",myArg);
>         ie.set("MenuBar",myArg);
>         ie.set("StatusBar",myArg);
>         myArg.n1.n2.n3.boolVal = 1;
>         ie.set("Visible",myArg);
>
>         VARIANT tmp = ie.get("Visible");
>         bool isVisible = cast(bool) tmp.n1.n2.n3.boolVal;
>     }
>     finally
>         ie.call("Quit");
>//----------------------------------------------------------------
>
>Works, except for the Navigate call. Going through the parameters I 
>found their VARTYPEs, so that's why I set them, but I have no idea what 
>they should receive. Also, I'm aware some methods are optional (Navigate 
>has 4, I assume the only required is the URL), but only passing one 
>doesn't work either.
>
>So, again, some help would be nice.
>
>_______________________
>Carlos Santander Bernal
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home