FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

More Windows COM problems... :-)
Goto page 1, 2  Next
 
Post new topic   Reply to topic     Forum Index -> Juno
View previous topic :: View next topic  
Author Message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Mon Oct 08, 2007 11:41 pm    Post subject: More Windows COM problems... :-) Reply with quote

Greetings...

I have this program, copied right from a working JScript program commented inside the D program,
Code:
import std.stdio;
import juno.com.core;
import juno.com.client;

void main()
{
  //var w = WScript;
  //var wa = w.Arguments;

  //var te = w.CreateObject("TagEditor.Application");
  scope te = new DispatchObject("TagEditor.Application");

  //var f = "C:\\temp\\test.htm";
  char[] f = "C:\\temp\\test.htm";

  //var INIFile = "D:\\Projects\\_DTD-INI-Files\\HTML4.ini";
  char[] INIFile = "D:\\Projects\\_DTD-INI-Files\\HTML4.ini";

  //var DTD = te.DtdSettingsFiles;
  scope DTD = new DispatchObject(te.get("DtdSettingsFiles"));

  //var oDTD = DTD.Add(INIFile);
  scope oDTD = DTD.call("Add", INIFile);

  //w.Echo(DTD.Count);
  writefln(DTD.get!(long)("Count"));

  //var teDocs = te.Documents;
  scope teDocs = new DispatchObject(te.get("Documents"));

  //teDocs.Open(f,oDTD);
  teDocs.call("Open",f,oDTD);

  //w.Echo(teDocs.Count);
  writefln(teDocs.get!(long)("Count"));

  //var teDoc = te.ActiveDocument;
  scope teDoc = new DispatchObject(te.get("ActiveDocument"));

  //teDoc.SaveBilingual();
  teDoc.call("SaveBilingual");

  //w.Echo(teDoc.FullName);
  writefln(teDoc.get!(char[])("FullName"));

  //te.Quit();
  te.call("Quit");
}

a complete execution of the JScript program outputs these strings,
Quote:

8
1
C:\temp\test.htm.ttx


But, though the D program is compiling, it fails with this output,
Quote:

8
0
Error: ArgumentNullException: Value cannot be null.

I know what the problem is. The open command,
Code:

  //teDocs.Open(f,oDTD);
  teDocs.call("Open",f,oDTD);

is failing. But why? I tried a few changes, but it still does not work. Any ideas?

Thanks,

jose
Back to top
View user's profile Send private message
John



Joined: 17 Jan 2006
Posts: 75

PostPosted: Wed Oct 17, 2007 4:17 am    Post subject: Reply with quote

Without owning the software you're automating, it's hard to diagnose the problem. A quick glance at the code suggests that oDTD is a null reference. DTD.call("Add", INIFile) might be failing.
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Wed Oct 17, 2007 2:52 pm    Post subject: Reply with quote

John wrote:
Without owning the software you're automating, it's hard to diagnose the problem.


Yeah, I understand. The hardest part is to be able to understand why it is failing.

John wrote:
A quick glance at the code suggests that oDTD is a null reference. DTD.call("Add", INIFile) might be failing.


Well, that part works fine. I tested it. The part that fails is line 2, below.
Code:
  //var teDocs = te.Documents;
1.  auto teDocs = new DispatchObject(te.get("Documents"));

  //teDocs.Open(f,oDTD);
2.  teDocs.call("Open",f,oDTD);

  //w.Echo(teDocs.Count);
3.  writefln(teDocs.get!(long)("Count"));


Somehow, it does not want to open the file which is line 2. I know that teDocs works because it gives me a number on line 3. The item oDTD on number 2 is an object. How does juno passes an object to a COM call?

Are there differences in COM objects?
Back to top
View user's profile Send private message
John



Joined: 17 Jan 2006
Posts: 75

PostPosted: Thu Oct 18, 2007 10:10 am    Post subject: Reply with quote

Quote:
The item oDTD on number 2 is an object. How does juno passes an object to a COM call?


DTD.call() returns a VARIANT. I think this has uncovered a bug. If you're comfortable changing the source code, try adding the following two lines to juno/com/client.d, starting at line 130:

Code:
else if (arg == typeid(VARIANT))
  list ~= va_arg!(VARIANT)(argptr);
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Thu Oct 18, 2007 11:35 am    Post subject: Reply with quote

ok, I will give this a try.

thanks.
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Thu Oct 18, 2007 9:46 pm    Post subject: Reply with quote

Ok, made the changes and still the same way. Here is the new code after the change,
Code:
private VARIANT invokeMemberById(int dispId, DispatchFlags flags, IDispatch target, ...) {

  VARIANT[] argsToVariants(TypeInfo[] args, va_list argptr) {
    VARIANT[] list;

    foreach (arg; args) {
      if (arg == typeid(bool))
        list ~= VARIANT(va_arg!(bool)(argptr));
      else if (arg == typeid(ubyte))
        list ~= VARIANT(va_arg!(ubyte)(argptr));
      else if (arg == typeid(byte))
        list ~= VARIANT(va_arg!(byte)(argptr));
      else if (arg == typeid(ushort))
        list ~= VARIANT(va_arg!(ushort)(argptr));
      else if (arg == typeid(short))
        list ~= VARIANT(va_arg!(short)(argptr));
      else if (arg == typeid(uint))
        list ~= VARIANT(va_arg!(uint)(argptr));
      else if (arg == typeid(int))
        list ~= VARIANT(va_arg!(int)(argptr));
      else if (arg == typeid(ulong))
        list ~= VARIANT(va_arg!(ulong)(argptr));
      else if (arg == typeid(long))
        list ~= VARIANT(va_arg!(long)(argptr));
      else if (arg == typeid(float))
        list ~= VARIANT(va_arg!(float)(argptr));
      else if (arg == typeid(double))
        list ~= VARIANT(va_arg!(double)(argptr));
      else if (arg == typeid(string))
        list ~= VARIANT(va_arg!(string)(argptr));
      else if (arg == typeid(IDispatch))
        list ~= VARIANT(va_arg!(IDispatch)(argptr));
      else if (arg == typeid(IUnknown))
        list ~= VARIANT(va_arg!(IUnknown)(argptr));
      else if (arg == typeid(Object))
        list ~= VARIANT(va_arg!(Object)(argptr));
      else if (arg == typeid(VARIANT*)) {
        VARIANT v;
        v.vt = cast(VARTYPE)(VARTYPE.VT_BYREF | VARTYPE.VT_VARIANT);
        v.pvarVal = va_arg!(VARIANT*)(argptr);
        list ~= v;
      }
      else if (arg == typeid(SAFEARRAY*)) {
        VARIANT v;
        v.vt = cast(VARTYPE)(VARTYPE.VT_ARRAY | VARTYPE.VT_VARIANT);
        v.parray = va_arg!(SAFEARRAY*)(argptr);
        list ~= v;
      }
      else if (arg == typeid(VARIANT))
        list ~= va_arg!(VARIANT)(argptr);
    }

    return list.reverse;
  }


Is there a way to get what the function Open wants for input?
Back to top
View user's profile Send private message
John



Joined: 17 Jan 2006
Posts: 75

PostPosted: Fri Oct 19, 2007 2:09 am    Post subject: Reply with quote

Quote:
Ok, made the changes and still the same way


Crying or Very sad

Quote:
Is there a way to get what the function Open wants for input?


The documentation would be my first port of call. If you haven't got access to that, you should be able to examine the type library for the argument types. Download OleView from Microsoft for that.

Out of interest, what application is it for?
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Fri Oct 19, 2007 6:42 am    Post subject: Reply with quote

the application is Trados Tag Editor. It is a translation software that we use. Most of the libraries are in .net, but I have translated most of the code to D, but I am having problem with this one. I need to continue with this, since I want to show the folks where I work that .net is not the only solution. .-)

I will give this Oleview a try. I may have to return for more help.

thanks.

jose
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Sat Jan 05, 2008 12:19 am    Post subject: Reply with quote

Happy new 2008 to everyone dealing with Juno. Smile

Sorry about the wait, but as we all know, time is not what it used to be... Ok, so I had a few hours and went and downloaded the OLE package from MS and I found out that the Open statements for the Document call is defined this way,
Code:
Open(
                    [in] BSTR FileName,
                    [in] IDtdSettingsFile* DtdSettings,
                    [out, retval] IDocument** pVal);

So, in my code above,
Code:
  //teDocs.Open(f,oDTD);
2.  teDocs.call("Open",f,oDTD);

I am passing the object and not the pointer of the object. How do I pass the pointer of the object to the call? I tried passing the *oDTD, but I get "TTXd.d(65): Error: can only * a pointer, not a 'juno.com.client.DispatchObject'".

Any help would be greatly appreciated.

thanks,

jic
Back to top
View user's profile Send private message
John



Joined: 17 Jan 2006
Posts: 75

PostPosted: Tue Jan 08, 2008 6:04 am    Post subject: Reply with quote

Quote:
So, in my code ... I am passing the object and not the pointer of the object.


No, you are passing a VARIANT instance - oDTD - which holds a reference to the IDtdSettingsFile object.

OleView's output is misleading - it's showing you IDL code, which (like C++) adds the pointer notation, while D doesn't need it. That code is also really only relevant for early binding. In late binding, which is what you're doing, function arguments get wrapped in a VARIANT. And oDTD is a VARIANT anyway.

But you could always unwrap it and pass the object reference (which will eventually get wrapped again):

Code:
auto dtdSettings = com_cast!(IDtdSettingsFile)(oDTD);
scope(exit) tryRelease(dtdSettings);
teDocs.call("Open", f, dtdSettings);


Also, might be worth checking the value of the oDTD's vt field - it should be either VARTYPE.VT_UNKNOWN (13) or VARTYPE.VT_DISPATCH (9) (depending on which interface IDtdSettingsFile derives from). If it's neither, then something's amiss.
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Thu Jan 10, 2008 11:22 pm    Post subject: Reply with quote

John wrote:

But you could always unwrap it and pass the object reference (which will eventually get wrapped again):

Code:
auto dtdSettings = com_cast!(IDtdSettingsFile)(oDTD);
scope(exit) tryRelease(dtdSettings);
teDocs.call("Open", f, dtdSettings);



I am getting,

Code:

TTXd.d(65): Error: identifier 'IDtdSettingsFile' is not defined
TTXd.d(65): Error: template instance 'com_cast!(int)' is not a variable
TTXd.d(65): Error: function expected before (), not com_cast!(int) of type int


John wrote:

Also, might be worth checking the value of the oDTD's vt field - it should be either VARTYPE.VT_UNKNOWN (13) or VARTYPE.VT_DISPATCH (9) (depending on which interface IDtdSettingsFile derives from). If it's neither, then something's amiss.


Sorry about my lack of knowledge, but how do I do this? I tried oDTD.vt and I get "Error: no property 'vt' for type 'juno.com.client.DispatchObject'".

thanks for the help. I have gotten all of the classes to work with D, but this one. Any help will be greatly appreciate it.

thanks,

jose
Back to top
View user's profile Send private message
John



Joined: 17 Jan 2006
Posts: 75

PostPosted: Fri Jan 11, 2008 5:09 am    Post subject: Reply with quote

Quote:
Error: identifier 'IDtdSettingsFile' is not defined


Of course - silly me. Ignore that idea.

Quote:
Error: no property 'vt' for type 'juno.com.client.DispatchObject'


When did oDTD become a DispatchObject? Looking at your original code

Code:
scope oDTD = DTD.call("Add", INIFile);


it would be a VARIANT, because the "call" method returns a VARIANT unless you specify otherwise (and you haven't). Please post the current version of your code.

And if you're trying to pass a DispatchObject to teDocs.Open, then that would explain why it's failing - it's expecting an instance of IDtdSettingsFile (in the case of early binding) or a VARIANT (when late binding, as we're doing here).
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Sun Jan 13, 2008 11:31 pm    Post subject: Reply with quote

This is the actual code,
Code:
import std.stdio;
import juno.com.client;
import juno.com.core;
//import xtranslate;

void main()
{
  //var w = WScript;
  //var wa = w.Arguments;

  //var te = w.CreateObject("TagEditor.Application");
  auto te = new DispatchObject("TagEditor.Application");

  //var f = "C:\\temp\\test.htm";
  char[] f = "C:\\temp\\test.htm";

  //var INIFile = "D:\\Projects\\_DTD-INI-Files\\HTML4.ini";
  char[] INIFile = "D:\\Projects\\_DTD-INI-Files\\HTML4.ini";

  //var DTD = te.DtdSettingsFiles;
  auto DTD = new DispatchObject(te.call("DtdSettingsFiles"));

  //w.Echo(DTD.Count);
  writefln(DTD.get!(long)("Count"));

  //var oDTD = DTD.Add(INIFile);
  auto oDTD = DTD.call("Add", INIFile);

  //w.Echo(DTD.Count);
  writefln(DTD.get!(long)("Count"));

  //var teDocs = te.Documents;
  auto teDocs = new DispatchObject(te.get("Documents"));

  //teDocs.Open(f,oDTD);
  teDocs.call("Open",f,oDTD);

  //w.Echo(teDocs.Count);
  writefln(teDocs.get!(long)("Count"));

  //var teDoc = te.ActiveDocument;
  auto teDoc = new DispatchObject(te.get("ActiveDocument"));

  //teDoc.SaveBilingual();
  teDoc.call("SaveBilingual");

  //w.Echo(teDoc.FullName);
  writefln(teDoc.get("FullName"));

  //te.Quit();
  te.call("Quit");
}
Back to top
View user's profile Send private message
John



Joined: 17 Jan 2006
Posts: 75

PostPosted: Mon Jan 14, 2008 4:26 am    Post subject: Reply with quote

The code looks OK. From the error you reported earlier, I thought you might have wrapped oDTD in DispatchObject, but you haven't. Which begs the question - why are you even getting this error:

Quote:
Error: no property 'vt' for type 'juno.com.client.DispatchObject'


Are you sure you typed oDTD.vt and not DTD.vt by mistake? You see, oDTD isn't a DispatchObject, so the error couldn't possibly have occurred.

Code:
// auto oDTD = DTD.call("Add", INIFile);
VARIANT oDTD = DTD.call("Add", INIFile);
writefln(oDTD.vt);


I don't really know what else to suggest.
Back to top
View user's profile Send private message
jicman



Joined: 22 Dec 2004
Posts: 298
Location: Rochester, NY

PostPosted: Mon Jan 14, 2008 10:05 pm    Post subject: Reply with quote

Thanks for helping. I have now made changes where it works. Here is the working code
Code:
import std.stdio;
import juno.com.client;
import juno.com.core;
//import xtranslate;

void main()
{
  //var w = WScript;
  //var wa = w.Arguments;

  //var te = w.CreateObject("TagEditor.Application");
  auto te = new DispatchObject("TagEditor.Application");

  //var f = "C:\\temp\\test.htm";
  char[] f = "C:\\temp\\test.htm";

  //var INIFile = "D:\\Projects\\_DTD-INI-Files\\HTML4.ini";
  char[] INIFile = "D:\\Projects\\_DTD-INI-Files\\HTML4.ini";

  //var DTD = te.DtdSettingsFiles;
  auto DTD = new DispatchObject(te.get("DtdSettingsFiles"));

  //w.Echo(DTD.Count);
  writefln(DTD.get!(long)("Count"));

  //var oDTD = DTD.Add(INIFile);
  auto oDTD = DTD.call("Add", INIFile);
  writefln(oDTD.vt);

  //w.Echo(DTD.Count);
  writefln(DTD.get!(long)("Count"));

  //var teDocs = te.Documents;
  auto teDocs = new DispatchObject(te.get("Documents"));

  //teDocs.Open(f,oDTD);
  teDocs.call("Open",f,oDTD);

  //w.Echo(teDocs.Count);
  writefln(teDocs.get!(long)("Count"));

  //var teDoc = te.ActiveDocument;
  auto teDoc = new DispatchObject(te.get("ActiveDocument"));

  //teDoc.SaveBilingual();
  teDoc.call("SaveBilingual");

  //w.Echo(teDoc.FullName);
  writefln(teDoc.get("FullName"));

  //te.Quit();
  te.call("Quit");
}


I made the changes you suggested, and it was still failing, but then I switched this line,
Code:

  //var DTD = te.DtdSettingsFiles;
  auto DTD = new DispatchObject(te.call("DtdSettingsFiles"));


to this,
Code:

  //var DTD = te.DtdSettingsFiles;
  auto DTD = new DispatchObject(te.get("DtdSettingsFiles"));


and somehow, now it works. So, thanks a lot. I am now totally D'ed. Smile

jose
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> Juno All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group