View mode: basic / threaded / horizontal-split · Log in · Help
March 13, 2005
Re: (help) automation on windows
Carlos Santander B. wrote:
> 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):

Not that I should receive any credit for the code which I blantantly 
ripped off of jicman. ;)

...

> 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.

I'm hoping John C's observations are helpful because I don't have any ideas.

I would like to congratulate you, though. It looks to me like you'd 
figured out the truly hard part and only the nagging details remain. 
Good job!

-- 
Justin (a/k/a jcc7)
http://jcc_7.tripod.com/d/
March 13, 2005
Re: (help) automation on windows
J C Calvarese wrote:
> 
> 
> I'm hoping John C's observations are helpful because I don't have any 
> ideas.
> 
> I would like to congratulate you, though. It looks to me like you'd 
> figured out the truly hard part and only the nagging details remain. 
> Good job!
> 

Thanks. "The key is in the details" (or is the problem, or the issue?)

_______________________
Carlos Santander Bernal
March 13, 2005
Re: (help) automation on windows
John C wrote:
> 
> 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.)

Thanks. I'll try that to see how it goes. The problem (still) is being 
generic: I'm just trying with IE, but I want it to be 100% functional 
with any ActiveX object.

> 
> 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.
> 
> 

set() isn't the problem. call() is:

    VARIANT call(char [] member,...)
    {
        INVOKEKIND ik=INVOKE_FUNC;
        DISPID dispid = findMember(member,ik);

        if (!(dispid in methods))
            throw new Exception("can only call methods");

        VARIANTARG [] myArgs = makeArray(_arguments,_argptr);

        DISPPARAMS param;
        param.cArgs=myArgs.length;
        param.rgvarg=myArgs.ptr;

        VARIANT result;
        HRESULT hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, 
defaultLCID, ik, &param, &result, null, null);
        return result;
    }

and makeArray() is:

    VARIANTARG [] makeArray(TypeInfo [] args, void* ptr)
    {
        VARIANTARG [] array;
        array.length = args.length;

        for (uint i;i<args.length;++i)
        {
            if (args[i] == typeid(VARIANTARG))
                array [i] = va_arg!(VARIANTARG)(ptr);
            else
                throw new Exception( "Expected arguments of type 
VARIANTARG" );
        }

        return array;
    }

The problem seems to be after the findMember() call, because calling 
Quit (no parameters) works fine.

_______________________
Carlos Santander Bernal
March 13, 2005
Re: (help) automation on windows - COMobjectsSample.zip
jicman wrote:
> 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é
> 
> 

Thanks, I think that could work as a test case.

_______________________
Carlos Santander Bernal
March 13, 2005
Re: (help) automation on windows
J C Calvarese says...
>
>Carlos Santander B. wrote:
>> 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):
>
>Not that I should receive any credit for the code which I blantantly 
>ripped off of jicman. ;)

Which I, purposely, grab from a Microsoft site.  Though, I did have to suffer
translating it to JScript, since it was VBScript!  But, code it's never stolen.
Just copied and pasted. ja ja ja ja (That's me, laughing in Spanish!  By the
way, it sounds just like ha ha ha ha.  For you see, in Spanish, the j sounds
like an h. Ja ja ja ja ja)


>> 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.
>
>I'm hoping John C's observations are helpful because I don't have any ideas.
>
>I would like to congratulate you, though. It looks to me like you'd 
>figured out the truly hard part and only the nagging details remain. 
>Good job!
>
>-- 
>Justin (a/k/a jcc7)
>http://jcc_7.tripod.com/d/
March 13, 2005
Re: (help) automation on windows
"Carlos Santander B." <csantander619@gmail.com> wrote in message 
news:d10aai$12dk$1@digitaldaemon.com...
> John C wrote:
>>
>> 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.)
>
> Thanks. I'll try that to see how it goes. The problem (still) is being 
> generic: I'm just trying with IE, but I want it to be 100% functional with 
> any ActiveX object.
>
>>
>> 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.
>>
>>
>
> set() isn't the problem. call() is:
>
>     VARIANT call(char [] member,...)
>     {
>         INVOKEKIND ik=INVOKE_FUNC;
>         DISPID dispid = findMember(member,ik);
>
>         if (!(dispid in methods))
>             throw new Exception("can only call methods");
>
>         VARIANTARG [] myArgs = makeArray(_arguments,_argptr);
>
>         DISPPARAMS param;
>         param.cArgs=myArgs.length;
>         param.rgvarg=myArgs.ptr;
>
>         VARIANT result;
>         HRESULT hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, 
> defaultLCID, ik, &param, &result, null, null);
>         return result;
>     }
>
> and makeArray() is:
>
>     VARIANTARG [] makeArray(TypeInfo [] args, void* ptr)
>     {
>         VARIANTARG [] array;
>         array.length = args.length;
>
>         for (uint i;i<args.length;++i)
>         {
>             if (args[i] == typeid(VARIANTARG))
>                 array [i] = va_arg!(VARIANTARG)(ptr);
>             else
>                 throw new Exception( "Expected arguments of type 
> VARIANTARG" );
>         }
>
>         return array;
>     }
>
> The problem seems to be after the findMember() call, because calling Quit 
> (no parameters) works fine.

After a fair amount of trial and error, I've got it working.

   /*------------------------ activex.d -------------------------*/

   module test.activex;

   private import std.stdarg;

   static this() {
       CoInitialize(null);
   }

   static ~this() {
       CoUninitialize();
   }

   public class ActiveXObject {

       private IDispatch disp_;

       public this(char[] progId) {
           CLSID clsid;
           CLSIDFromProgID(toUTF16z(progId), &clsid);
           CoCreateInstance(&clsid, null, CLSCTX_SERVER, &IID_IDispatch, 
(void**)&_disp);
       }

       public VARIANT call(char[] member, ...) {
           DISPID memberId = findMember(member);

           VARIANT[] args = makeArray(_arguments, _argptr);
           DISPPARAMS params;
           params.rgvarg = agrs.ptr;
           params.cArgs = args.length;

           VARIANT result;
           disp_.Invoke(memberId, &IID_NULL, GetUserDefaultLCID(), 
DISPATCH_METHOD, &params, &result, null, null);
           return result;
       }

       public void set(wchar[] member, VARIANT value) // omitted
       public VARIANT get(wchar[] member) // omitted

       private DISPID findMember(char[] member) {
           // Simplified version
           wchar* pszMember = toUTF16z(member);
           DISPID dispidResult;
           disp_.GetIDsOfNames(&IID_NULL, &pszMember, 1, 
GetUserDefaultLCID(), &dispidResult);
           return dispidResult;
       }

       private VARIANT[] makeArray(TypeInfo[] argTypes, void* ptr) {
           int argsLength = argTypes.length;
           VARIANT[] args;
           foreach (TypeInfo argType; argTypes) {
               if (argType == typeid(VARIANT))
                   args ~= va_arg!(VARIANT)(ptr);
           }
           return args;
       }

   }

   /*-------------------------- test.d -------------------------*/

   module test.app;

   private import test.activex;

   int main() {
       ActiveXObject axObject= new 
ActiveXObject("InternetExplorer.Application");

       VARIANT variantTrue;
       variantTrue.vt = VT_BOOL;
       variantTrue.boolVal = -1; // VARIANT_TRUE

       VARIANT variantFalse;
       variantFalse.vt = VT_BOOL;
       variantFalse.boolVal = 0; // VARIANT_FALSE

       axObject.set("ToolBar", variantFalse);
       axObject.set("Visible", variantTrue);

       VARIANT url;
       url.vt = VT_BSTR;
       // Must call SysAllocString() to allocate a BSTR
       url.bstrVal = SysAllocString("about:blank");

       axObject.call("Navigate", VARIANT.init, VARIANT.init, VARIANT.init, 
VARIANT.init, url);

       // Now free the BSTR
       SysFreeString(url.bstrVal);

       return 0;
   }


I can't see that you're doing anything radically different, apart from using 
the wrong value for VARIANT_TRUE and not allocating your BSTRs with 
SysAllocString(). If you're still having problems after trying it, let me 
know and I'll send you my source files.

Good luck.
March 13, 2005
Re: (help) automation on windows
John C wrote:
> 
>     /*------------------------ activex.d -------------------------*/
> 
>     module test.activex;
> 
>     private import std.stdarg;
> 
>     static this() {
>         CoInitialize(null);
>     }
> 
>     static ~this() {
>         CoUninitialize();
>     }
> 
>     public class ActiveXObject {
> 
>         private IDispatch disp_;
> 
>         public this(char[] progId) {
>             CLSID clsid;
>             CLSIDFromProgID(toUTF16z(progId), &clsid);
>             CoCreateInstance(&clsid, null, CLSCTX_SERVER, &IID_IDispatch, 
> (void**)&_disp);
>         }
> 
>         public VARIANT call(char[] member, ...) {
>             DISPID memberId = findMember(member);
> 
>             VARIANT[] args = makeArray(_arguments, _argptr);
>             DISPPARAMS params;
>             params.rgvarg = agrs.ptr;
>             params.cArgs = args.length;
> 
>             VARIANT result;
>             disp_.Invoke(memberId, &IID_NULL, GetUserDefaultLCID(), 
> DISPATCH_METHOD, &params, &result, null, null);
>             return result;
>         }
> 
>         public void set(wchar[] member, VARIANT value) // omitted
>         public VARIANT get(wchar[] member) // omitted
> 
>         private DISPID findMember(char[] member) {
>             // Simplified version
>             wchar* pszMember = toUTF16z(member);
>             DISPID dispidResult;
>             disp_.GetIDsOfNames(&IID_NULL, &pszMember, 1, 
> GetUserDefaultLCID(), &dispidResult);
>             return dispidResult;
>         }
> 
>         private VARIANT[] makeArray(TypeInfo[] argTypes, void* ptr) {
>             int argsLength = argTypes.length;
>             VARIANT[] args;
>             foreach (TypeInfo argType; argTypes) {
>                 if (argType == typeid(VARIANT))
>                     args ~= va_arg!(VARIANT)(ptr);
>             }
>             return args;
>         }
> 
>     }
> 
>     /*-------------------------- test.d -------------------------*/
> 
>     module test.app;
> 
>     private import test.activex;
> 
>     int main() {
>         ActiveXObject axObject= new 
> ActiveXObject("InternetExplorer.Application");
> 
>         VARIANT variantTrue;
>         variantTrue.vt = VT_BOOL;
>         variantTrue.boolVal = -1; // VARIANT_TRUE
> 
>         VARIANT variantFalse;
>         variantFalse.vt = VT_BOOL;
>         variantFalse.boolVal = 0; // VARIANT_FALSE
> 
>         axObject.set("ToolBar", variantFalse);
>         axObject.set("Visible", variantTrue);
> 
>         VARIANT url;
>         url.vt = VT_BSTR;
>         // Must call SysAllocString() to allocate a BSTR
>         url.bstrVal = SysAllocString("about:blank");
> 
>         axObject.call("Navigate", VARIANT.init, VARIANT.init, VARIANT.init, 
> VARIANT.init, url);
> 
>         // Now free the BSTR
>         SysFreeString(url.bstrVal);
> 
>         return 0;
>     }
> 
> 
> I can't see that you're doing anything radically different, apart from using 
> the wrong value for VARIANT_TRUE and not allocating your BSTRs with 
> SysAllocString(). If you're still having problems after trying it, let me 
> know and I'll send you my source files.
> 
> Good luck. 
> 
> 

SysAllocString did the trick. Thanks! Uh, and using 1 instead of -1 does 
work. But thanks again!

It's funny that your activex module is basically identical to what I have.

_______________________
Carlos Santander Bernal
March 13, 2005
Re: (help) automation on windows
"Carlos Santander B." <csantander619@gmail.com> wrote in message 
news:d11n8k$2cd2$1@digitaldaemon.com...
>
> SysAllocString did the trick. Thanks! Uh, and using 1 instead of -1 does 
> work. But thanks again!
>
> It's funny that your activex module is basically identical to what I have.
>

And by clever use of subclassing, the syntax you proposed in your initial 
post is almost possible:

   public final abstract class InternetExplorer {
       public final class Application : ActiveXObject {
           public this() {
               super("InternetExplorer.Application");
           }
       }
   }

   public final abstract class Excel {
       public final class Application : ActiveXObject {
           public this() {
               super("Excel.Application");
           }
       }
   }

   ActiveXObject ieObject = new InternetExplorer.Application;
   ActiveXObject excelObject = new Excel.Application;

Just make the ActiveXObject class abstract and its constructor protected, 
and you've got a fairly safe idiom to guard users from creating invalid 
objects ("Notepad.Application" etc, which doesn't exist).
March 13, 2005
Re: (help) automation on windows
Will you zip these files and post them again?  Sorry and thanks.

jic

John C says...
>
>"Carlos Santander B." <csantander619@gmail.com> wrote in message 
>news:d10aai$12dk$1@digitaldaemon.com...
>> John C wrote:
>>>
>>> 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.)
>>
>> Thanks. I'll try that to see how it goes. The problem (still) is being 
>> generic: I'm just trying with IE, but I want it to be 100% functional with 
>> any ActiveX object.
>>
>>>
>>> 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.
>>>
>>>
>>
>> set() isn't the problem. call() is:
>>
>>     VARIANT call(char [] member,...)
>>     {
>>         INVOKEKIND ik=INVOKE_FUNC;
>>         DISPID dispid = findMember(member,ik);
>>
>>         if (!(dispid in methods))
>>             throw new Exception("can only call methods");
>>
>>         VARIANTARG [] myArgs = makeArray(_arguments,_argptr);
>>
>>         DISPPARAMS param;
>>         param.cArgs=myArgs.length;
>>         param.rgvarg=myArgs.ptr;
>>
>>         VARIANT result;
>>         HRESULT hr = pIDispatch.Invoke(dispid, cast(REFIID) &IID_NULL, 
>> defaultLCID, ik, &param, &result, null, null);
>>         return result;
>>     }
>>
>> and makeArray() is:
>>
>>     VARIANTARG [] makeArray(TypeInfo [] args, void* ptr)
>>     {
>>         VARIANTARG [] array;
>>         array.length = args.length;
>>
>>         for (uint i;i<args.length;++i)
>>         {
>>             if (args[i] == typeid(VARIANTARG))
>>                 array [i] = va_arg!(VARIANTARG)(ptr);
>>             else
>>                 throw new Exception( "Expected arguments of type 
>> VARIANTARG" );
>>         }
>>
>>         return array;
>>     }
>>
>> The problem seems to be after the findMember() call, because calling Quit 
>> (no parameters) works fine.
>
>After a fair amount of trial and error, I've got it working.
>
>    /*------------------------ activex.d -------------------------*/
>
>    module test.activex;
>
>    private import std.stdarg;
>
>    static this() {
>        CoInitialize(null);
>    }
>
>    static ~this() {
>        CoUninitialize();
>    }
>
>    public class ActiveXObject {
>
>        private IDispatch disp_;
>
>        public this(char[] progId) {
>            CLSID clsid;
>            CLSIDFromProgID(toUTF16z(progId), &clsid);
>            CoCreateInstance(&clsid, null, CLSCTX_SERVER, &IID_IDispatch, 
>(void**)&_disp);
>        }
>
>        public VARIANT call(char[] member, ...) {
>            DISPID memberId = findMember(member);
>
>            VARIANT[] args = makeArray(_arguments, _argptr);
>            DISPPARAMS params;
>            params.rgvarg = agrs.ptr;
>            params.cArgs = args.length;
>
>            VARIANT result;
>            disp_.Invoke(memberId, &IID_NULL, GetUserDefaultLCID(), 
>DISPATCH_METHOD, &params, &result, null, null);
>            return result;
>        }
>
>        public void set(wchar[] member, VARIANT value) // omitted
>        public VARIANT get(wchar[] member) // omitted
>
>        private DISPID findMember(char[] member) {
>            // Simplified version
>            wchar* pszMember = toUTF16z(member);
>            DISPID dispidResult;
>            disp_.GetIDsOfNames(&IID_NULL, &pszMember, 1, 
>GetUserDefaultLCID(), &dispidResult);
>            return dispidResult;
>        }
>
>        private VARIANT[] makeArray(TypeInfo[] argTypes, void* ptr) {
>            int argsLength = argTypes.length;
>            VARIANT[] args;
>            foreach (TypeInfo argType; argTypes) {
>                if (argType == typeid(VARIANT))
>                    args ~= va_arg!(VARIANT)(ptr);
>            }
>            return args;
>        }
>
>    }
>
>    /*-------------------------- test.d -------------------------*/
>
>    module test.app;
>
>    private import test.activex;
>
>    int main() {
>        ActiveXObject axObject= new 
>ActiveXObject("InternetExplorer.Application");
>
>        VARIANT variantTrue;
>        variantTrue.vt = VT_BOOL;
>        variantTrue.boolVal = -1; // VARIANT_TRUE
>
>        VARIANT variantFalse;
>        variantFalse.vt = VT_BOOL;
>        variantFalse.boolVal = 0; // VARIANT_FALSE
>
>        axObject.set("ToolBar", variantFalse);
>        axObject.set("Visible", variantTrue);
>
>        VARIANT url;
>        url.vt = VT_BSTR;
>        // Must call SysAllocString() to allocate a BSTR
>        url.bstrVal = SysAllocString("about:blank");
>
>        axObject.call("Navigate", VARIANT.init, VARIANT.init, VARIANT.init, 
>VARIANT.init, url);
>
>        // Now free the BSTR
>        SysFreeString(url.bstrVal);
>
>        return 0;
>    }
>
>
>I can't see that you're doing anything radically different, apart from using 
>the wrong value for VARIANT_TRUE and not allocating your BSTRs with 
>SysAllocString(). If you're still having problems after trying it, let me 
>know and I'll send you my source files.
>
>Good luck. 
>
>
April 07, 2005
Re: (help) automation on windows
On Sun, 13 Mar 2005 20:38:42 +0100, John C <johnch_atms@hotmail.com>  
wrote:

> And by clever use of subclassing, the syntax you proposed in your  
> initial post is almost possible:

Hi, I'm just trying to play using D (version 0.120) for COM  
programming. Can someone please send a complete working example? Or  
send me a ZIP file? That would be great!! I tried fiddling around with  
all pieces here but didn't made it yet.

Thanks a lot.

-- 
Robert M. Münch
Management & IT Freelancer
http://www.robertmuench.de
1 2 3
Top | Discussion index | About this forum | D home