 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Ian Boyd Guest
|
Posted: Thu Aug 17, 2006 7:27 am Post subject: QueryInterface reports E_NOINTERFACE with called from a serv |
|
|
i have a COM object written in Delphi, that we can instantiate fine from an
app:
procedure TForm1.Button1Click(Sender: TObject);
var
ClassID: TGUID;
o: IUnknown;
s: IExam;
const
IID_IExam: TGUID = '{7A794786-7C05-4EB4-A071-3D9B170B663A}';
CLSID_TestPaper: TGUID = '{4A75D28A-BCD3-46BF-BE91-361F2F207A10}';
begin
ClassID := CLSID_TestPaper;
o := CreateComObject(ClassID);
// s := o as IExam;
// if Failed(o.QueryInterface(IID_IExam, s) then
// if not Supports(o, IID_IExam, s) then
if Supports(o, IExam, s) then
ShowMessage(' ')
else
ShowMessage(' ');
end;
But if similar code is done from a service, then a call to Supports fails,
as does "as", and using QueryInterface directly returns 0x80004002
(E_NOINTERFACE)
i think the problem has to do with differing apartment models, and so COM is
trying to find some IMarshall interface, but it cannot. But before you think
about that, i'll confuse you with two other theories.
1. You just can't use Delphi COM dll's from a service. Maybe Delphi and it's
global variables (which make accessing visual controls from anything but the
main thread make impossible) make construcing COM objects from a service
impossible. There are global unit level routines, and singleton class
factories.
2. i create my objects during TService.OnStart event. i don't take advantage
of the OnExecute event and spawn worker threads. So, my service is single
threaded; and i STILL call CoInitialize/CoUninitialize during
OnStart/OnStop. So there's no problem there - but at least it can serve to
distract you from what the real problem probably is.
Now back to trying to figure it out. Overriding TComObject's
ObjQueryInterface method, i get to see all the interfaces being asked for by
COM when i try to load the object:
{00000000-0000-0000-C000-000000000046}: SUCCEEDED
{00000003-0000-0000-C000-000000000046}: FAILED
{0000001B-0000-0000-C000-000000000046}: FAILED
{00000000-0000-0000-C000-000000000046}: SUCCEEDED
{00000018-0000-0000-C000-000000000046}: FAILED
{00000019-0000-0000-C000-000000000046}: FAILED
{4C1E39E1-E3E3-4296-AA86-EC938D896E92}: FAILED
{7A794786-7C05-4EB4-A071-3D9B170B663A}: SUCCEEDED
Well that's quite a hodge-podge, but in the end it asks for my own IID, and
it returns.
So what's the rest?
IUnknown: SUCCEEDED
IMarshall: FAILED
"IdentityUnmarshal?": FAILED
IUnknown: SUCCEEDED
IStdMarshallInfo: FAILED
IExternalConnection: FAILED
???: FAILED
IExam: SUCCEEDED
So obviously COM is trying to do some cross apartment stuff. So my question
is, what do i have to do to my COM object so that it is compatible with the
apartment setup by a service?
My COM object is registered with Delphi as:
initialization
ComObjectFactory.Create(ComServer,
TTestPaper, CLSID_TestPaper, 'EyeExam', 'Dummy values changed for
the newgroup post',
ciMultiInstance,
tmApartment);
The last two are of course my concern. Also, my dll has no type library;
which has not been a problem when there was no marshalling. Does Delphi need
me to make a type library in order to automatically support marshalling? Can
Delphi EVER automtically support marshalling? Does TComObject ever get
marshalling ability? Should i be descending from some other type?
Or, more to the point, how can i get my DLL to be truly loaded into the
process space of the service application calling it? What specifically is
the cross-apartment issue? |
|
| Back to top |
|
 |
Dennis Passmore Guest
|
Posted: Thu Aug 17, 2006 4:18 pm Post subject: Re: QueryInterface reports E_NOINTERFACE with called from a |
|
|
I have been using Delphi COM dlls in Delphi NT services for years. I have one Delphi NT Service
project that loads and uses a Delphi COM object that in itself loads and uses MsSql OLEDB as a COM
object and uses QueryInterface with no problems at all.
Dennis Passmore
"Think it might be a new experience and
if you can not Pull then at least Push
the job will get done" |
|
| Back to top |
|
 |
Ian Boyd Guest
|
Posted: Thu Aug 17, 2006 5:54 pm Post subject: Re: QueryInterface reports E_NOINTERFACE with called from a |
|
|
Do your dll's have type libraries?
"Dennis Passmore" <dennisp (AT) nospam_dpassmore (DOT) com> wrote in message
news:g2k8e25hf4g8ab5atr2ujup1osqg06q14u (AT) 4ax (DOT) com...
| Quote: | I have been using Delphi COM dlls in Delphi NT services for years. I have
one Delphi NT Service
project that loads and uses a Delphi COM object that in itself loads and
uses MsSql OLEDB as a COM
object and uses QueryInterface with no problems at all.
Dennis Passmore
"Think it might be a new experience and
if you can not Pull then at least Push
the job will get done" |
|
|
| Back to top |
|
 |
Dennis Passmore Guest
|
Posted: Sat Aug 19, 2006 9:16 pm Post subject: Re: QueryInterface reports E_NOINTERFACE with called from a |
|
|
| Quote: | Do your dll's have type libraries?
|
Sure they do but you have to use LoadRegTypeLib() to load the typelib into the NT service memory
space and then you can create the referenced forward interface functions you need access to.
Example:
type
TProgressFunc = class(TAutoIntfObject, IProgressfuncIntf)
private
fOwner: TObject;
protected
constructor Create;
procedure ProgressInfo(const Message: WideString); safecall;
end;
constructor TProgressFunc.Create;
var
ifTypeLib: ITypeLib;
begin
OleCheck(LoadRegTypeLib(LIBID_MyCalcs, 1, 0, 0, ifTypeLib));
inherited Create(ifTypeLib, IProgressfuncIntf);
end;
LIBID_MyCalcs is the GUID to the COM library declared in MyCalcs_TLB.pas and
IProgressfuncIntf is a Forward declaration defined in the same file.
Dennis Passmore
"Think it might be a new experience and
if you can not Pull then at least Push
the job will get done" |
|
| Back to top |
|
 |
Ian Boyd Guest
|
Posted: Fri Aug 25, 2006 6:18 pm Post subject: Re: QueryInterface reports E_NOINTERFACE with called from a |
|
|
| Quote: | Sure they do but you have to use LoadRegTypeLib() to load the typelib into
the NT service memory space and then you can create the referenced forward
interface functions you need access to.
|
Why?
What problem is this solving, how is it solving it, what am i doing to have
this problem, and why hasn't this problem happened before?
Windows already loads type libraries by itself. Why do it again? |
|
| Back to top |
|
 |
Dennis Passmore Guest
|
Posted: Fri Aug 25, 2006 8:41 pm Post subject: Re: QueryInterface reports E_NOINTERFACE with called from a |
|
|
| Quote: | Why?
What problem is this solving, how is it solving it, what am i doing to have
this problem, and why hasn't this problem happened before?
|
It is done so the calling application (a Nt Service in your case ) can create and use a interface
defined in a typelibrary without ever knowing how the interface is defined or implemented. Just
create a local case wrapper and call LoadRegTypeLib to load the typelib and create the interface
without ever knowing how it was implemented and built in the COM library.
I have a small example I can post if you need a sample. |
|
| Back to top |
|
 |
Ian Boyd Guest
|
Posted: Fri Aug 25, 2006 10:24 pm Post subject: Re: QueryInterface reports E_NOINTERFACE with called from a |
|
|
| Quote: | It is done so the calling application (a Nt Service in your case ) can
create and use a interface
defined in a typelibrary without ever knowing how the interface is defined
or implemented. Just
create a local case wrapper and call LoadRegTypeLib to load the typelib
and create the interface
without ever knowing how it was implemented and built in the COM library.
I have a small example I can post if you need a sample.
|
Yes please.
You can't just "create the interface", interfaces don't get created. |
|
| Back to top |
|
 |
|
|
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
|
|