|
Dear Brian
First of all, thanks for the wonderful tutorial u have here and the replies u gave me before.
I have a wierd problem here. I used your code in my program which essentially contains a method which starts the DCOM server, call the DCOM method and finally closes the DCOM server.(I did not use connection points though...) This works perfectly fine, EXCEPT that after a time lapse of about 6-7 seconds, I have to run e.g:"DCOMService /Service" again if I were to call this method repeatedly. However, this problem does not occur if I call this method repeatedly without a time lapse greater than 5-6 sec.
Would gladly appreciate if you could enlighten me on this. Thanks!
|
|
|
|
|
Hi all,
I want to know the way to notify client from server.
I tried to use PostMessage but it didn't work
|
|
|
|
|
Nguyen Duc Thang wrote:
I want to know the way to notify client from server.
I tried to use PostMessage but it didn't work
The way a client is sent events is through Connection Points. Please see the following Steps of this tutorial, in order, for more info. Work through them, don't just "read Shakespeare."
Step 5: http://www.codeproject.com/com/HelloTutorial5.asp[^]
Step 6: http://www.codeproject.com/com/HelloTutorial6.asp[^]
Step 7: http://www.codeproject.com/com/HelloTutorial7.asp[^]
There is no known way to fire events without a method being called. There is also no known way for the server to simulcast events.
You'll have to jury-rig something up which mimics that functionality.
Sincerely Yours,
Brian Hart
Department of Physics and Astronomy
University of California, Irvine
|
|
|
|
|
while I implement the SayHello(BSTR ps) on server side, I found the ps is wide char format. but while I implement the onSayHello on clent, and define the event Func like :
DISP_FUNCTION(CHelloWorldEvents, "SayHello", OnSayHello, VT_EMPTY,VTS_BSTR )
void CHelloWorldEvents::OnSayHello(BSTR lpszHost)
it pass me a string in single char format, even I call Fire_OnSayHello(T2OLE(str)) on serverside. I have to define
DISP_FUNCTION(CHelloWorldEvents, "SayHello", OnSayHello, VT_EMPTY,VTS_WBSTR ) to get a wide char format,
why it is different while transfer from c->s than s->c
|
|
|
|
|
Hi,
I'm a beginer in DCOM programming and I did the whole tutorial but when starting server thru client dialog, this message appears in a message box "Unable to access IHelloWorld because Classe non inscrite".
I used DCOMcnfg.exe to configure TCP/IP as standard prototocol as luenii proposed but nothing happens.
Help please !
tkp
|
|
|
|
|
|
I have a case where one VB client would like to call multiple DCOM servers. In fact they will be identical DCOM servers but running on different locations (PCs). How can I call them from my application if obviously they have the same name ?
|
|
|
|
|
sdaymond wrote:
I have a case where one VB client would like to call multiple DCOM servers. In fact they will be identical DCOM servers but running on different locations (PCs). How can I call them from my application if obviously they have the same name ?
With DCOM, you tell VB what machine to instantiate an object on as well as its ProgID.
Go to Step 7[^] of the tutorial, and look for the line
serverInfo.pwszName = L"\\\\Viz-06";
in Listing 13. You replace "\\\\Viz-06" (for the UNC pathname \\Viz-06) with an Internet address, either IP or like "codeproject.com", or an UNC (i.e. \\Machine) pathname to the machine you want.
This is a little problematic to do from visual Basic, but there must be another parameter to CreateInstance() that let's you tell it the machine name. Look it up in the docs, or try to find a CreateInstanceEx() subroutine.
Sincerely Yours,
Brian Hart
Department of Physics and Astronomy
University of California, Irvine
|
|
|
|
|
Hello Brian,
Thank you for your comment - that put me in the right direction. There is no doubt I have to create object dynamically in VB. For that purpose VB has CreateObject but with CreateObject you cannot specify remote machine. So there must be some other way.
I have done some search on the Web and found an article that directly appears to solve my problem:
"Creating Remote DCOM Objects on Specific Servers" (http://www.avdf.com/apr98/art_vb005.html)
The author - Jim Karabatsos - provides VB code for a function: CreateRemoteObject (that calls a couple of API functions, including CoCreateInstanceEx):
The code is below.
Best regards,
Stan Daymond
London, UK
Private Type SERVER_STRUCTURE
reserved1 As Long
pServer As Long
AuthInfo As Long
reserved2 As Long
End Type
Private Type MULTI_QI
pIID As Long
pInterface As Object
hResult As Long
End Type
Private Declare Function CLSIDFromProgID Lib "ole32.dll" _
(Progid As Any, Clsid As Any) As Long
Private Declare Function OleInitialize Lib "ole32.dll" _
(ByVal Nullptr As Long) As Long
Private Declare Function CoCreateInstanceEx Lib "ole32.dll" _
(Clsid As Any, ByVal pUnkOuter As Long, _
ByVal Context As Long, Server As SERVER_STRUCTURE, _
ByVal nElems As Long, mqi As MULTI_QI) As Long
Private Declare Function GetComputerName Lib "kernel32" _
Alias "GetComputerNameA" (ByVal lpBuffer As String, _
nSize As Long) As Long
' The trick is to call CoCreateInstanceEx to do the dirty work - and get
' an iDispatch interface pointer in one step. This is very efficient,
' You get the IDISPATCH pointer by passing the 'well-known' REFIID of
' IDISPATCH. Unfortunately, not being able to do this as a constant,
' we can hard-code the REFIID into a little routine.
Public LastError As String
Public Function CreateRemoteObject(ObjectName As String, _
Optional ServerName As String) As Object
Dim clsid(256) As Byte
Dim progid() As Byte
Dim server() As Byte
Dim QI As MULTI_QI
Dim SS As SERVER_STRUCTURE
Dim refiid(16) As Byte
Dim lrc As Long
LastError = ""
' We only need to create the object remotely if the server name is not
' the same as our machine (or if it is empty, allowing this function to
' act as a general replacement for CreateObject)
If (Trim$(ServerName) = "") Or (UCase$(ServerName) = UCase$(GetCompName())) Then
On Error Resume Next
Err = 0
Set CreateRemoteObject = CreateObject(ObjectName)
If Err <> 0 Then
LastError = Err.Description 'record last error
End If
On Error GoTo 0
Exit Function
End If
'otherwise, it is genuinely remote.
GetIIDforIDispatch refiid() 'set an IID for IDispatch
QI.pIID = VarPtr(refiid(0)) 'point to the IID
progid = ObjectName & Chr$(0) 'specify the object to be launched
server = ServerName & Chr$(0) 'specify the server
OleInitialize 0 'initialise OLE
lrc = CLSIDFromProgID(progid(0), clsid(0)) 'get the CLSID for the object
If lrc <> 0 Then
LastError = "Unable to obtain CLSID from progid " & ObjectName & vbCrLf _
& "Possibly it is not registered on both this server and server " & ServerName
Exit Function
End If
' point to server name and
' invoke a remote instance of the desired object
SS.pServer = VarPtr(server(0))
lrc = CoCreateInstanceEx(clsid(0), 0, 16, SS, 1, QI)
If lrc <> 0 Then
LastError = "CoCreateInstanceEx failed with error code " & Hex$(lrc)
Exit Function
End If
Set CreateRemoteObject = QI.pInterface ' pass back object ref.
End Function
Public Sub GetIIDforIDispatch(p() As Byte)
' fills in the well-known IID for IDispatch into the byte array p.
p(1) = 4
p(2) = 2
p(8) = &HC0
p(15) = &H46
End Sub
Function GetCompName() As String
' return the computer name
Dim buf As String
Dim rc As Long
buf = String$(256, 0)
rc = GetComputerName(buf, Len(buf))
If InStr(buf, Chr$(0)) > 1 Then
GetCompName = UCase$(Left$(buf, InStr(buf, Chr$(0)) - 1))
End If
End Function
That's it. Just include this module in your project, then create your remote object using this syntax:
Dim O as MyServer.MyObject ' NB - you can use early binding !!!
Set O = CreateRemoteObject("MyServer.MyObject","MyServer")
CreateRemoteObject is pretty much a drop-in replacement for CreateObject.
|
|
|
|
|
sdaymond wrote:
>Thank you for your comment - that put me in the right direction. There is no doubt I have to create object dynamically in VB. For
that purpose VB has CreateObject but with CreateObject you cannot specify remote machine.
Check again. Search the docs for a CreateInstance() function.
Also, I would suggest you go to the MSDN Library
at http://msdn.microsoft.com/library/ and search on DCOM VB
Sincerely Yours,
Brian Hart
Department of Physics and Astronomy
University of California, Irvine
|
|
|
|
|
I am recieving this error message while running HelloCli. (sorry as the last error message is in german). Can anyone tell me what did i do wrong?
Unable to access IHelloWorld because Der RPC-Server ist nicht verfügbar.
|
|
|
|
|
The usual reason is, that the remote server is not reachable via one of the configured protocols. Check if you can even ping the server.
If the ping replies, check with the DCOMcnfg.exe if you have TCP/IP in the list of standard protocols. Has you server enabled DCOM? Check this with the DCOMcnfg.exe tool on your server.
|
|
|
|
|
Hi Brian,
Thanks for your great article!
In step6 I got the idea that for installing these two lines
HelloServ /Service
regsvr32 HelloServps.dll
should be executed both at client and server machine. So client machine also needs the COM service to be installed. But earlier I had the impression that in DCOM, clint machine should only have the information of the server machine (where the COM service is available). Please clarify if I am wrong.
with regards
Manash
|
|
|
|
|
I also don't know, why you need to install the service.
The second line is to install the object description (I guess). The remote interface must be known at the local machine. Instead of registering the whole object, for the client it must be enough to register the server's type library.
|
|
|
|
|
luenii wrote:
I also don't know, why you need to install the service.
The second line is to install the object description (I guess). The remote interface must be known at the local machine. Instead of registering the whole object, for the client it must be enough to register the server's type library.
The service is the executeable code that actually contains the object you are accessing remotely. However, I have tried and tried to only register the Proxy-Stub DLL on the client machine, but Connection Points will only work if the service is installed on both client and server.
Don't worry -- the server-side code is what's running. You can tell because the method asks the machine it's running on, "What's your host name?" and sends this to the client via the connection point. This tells you on which machine the code actually ran that was called.
Sincerely Yours,
Brian Hart
Department of Physics and Astronomy
University of California, Irvine
|
|
|
|
|
Hi,
I have following questions
why do, on client machine, one has to register server (cmd "HelloServ /RegServer") ?
isn't registration of proxy-stub dll (cmd "regsvr32 HelloServps.dll") sufficient ?
If my client is activeX control running in browser,
then, how to I let that activeX control know about
proxy-stub dll and dcom sevrice i.e. how to I do
resigration for proxy-stub dll and service from within the activeX control/application ?
Thanks,
-Manoj
|
|
|
|
|
Dear Sir,
if u found a solution to ur inquiry plz mail me
sincerly
awhossam
|
|
|
|
|
|
Manoj Chaudhari wrote:
why do, on client machine, one has to register server (cmd "HelloServ /RegServer") ?
This is necessary for Connection Points to work.
Manoj Chaudhari wrote:
isn't registration of proxy-stub dll (cmd "regsvr32 HelloServps.dll") sufficient?
Registration only of the Proxy-Stub DLL on the client machine is sufficient, but only if you don't want to use Connection Points. I found that when I registered the Proxy-Stub DLL on the client machine, but not the server EXE too, Connection Points don't work.
I know, this behavior is weird, but it's my work-around that I figured out through lots of testing on a similar system.
I hope this answers your question. Thank you.
Sincerely Yours,
Brian Hart
Department of Physics and Astronomy
University of California, Irvine
|
|
|
|
|
hi,
thanks very much for your tutorials. its really helped me to understand DCOM. but how do i get my compiler to generate both the .dll and .exe as output when it compiles. like u have in your example.
thanks in advance.
Adu-Gyamfi.
|
|
|
|
|
problemcracker wrote:
hi,
thanks very much for your tutorials. its really helped me to understand DCOM. but how do i get my compiler to generate both the .dll and .exe as output when it compiles. like u have in your example.
Hello Adu-Gyamfi:
The way to get the compiler to produce both an EXE server and Proxy-Stub DLL is to run the ATL COM AppWizard in Visual C++ 6. Go to
Step 1 of this Tutorial[^]
to see how to open the ATL COM AppWizard and how to select the proper options.
NOTE: The ATL COM AppWizard produces a file called 'MyProject.mk' as well as the normal Workspace and VC project files. The *.mk file builds the Proxy-Stub DLL. So you add a step to the Build (under Project->Settings->Custom Build Step tab) to run the following command:
'nmake /f MyProject.mk'
Sincerely Yours,
Brian Hart
Department of Physics and Astronomy
University of California, Irvine
|
|
|
|
|
Does anyone have a client implemented with ATL instead MFC ?
Could you show an example how to implement it.
I tried to create one but it doesn't work properly.
Thanx
Vld
|
|
|
|
|
Hi there, first of all I must say that this is an excellent example. It got me started on DCOM very quickly.
I have implemented both client and server (both .exe files) based on this example and it works just fine. What I am trying to do now is to port the client code so that I can use it from a Web Browser such ad IE6.0. I got this to work by building an ActiveX compoent (.ocx) . The only thing that does not wotk is the Connection Points. For some reason that I don't know, the ActiveX client is not recieving event fired from the Server (ie: OnSayHello)
I have looked throught documentations but could not find an explanation. Could you pls help with this one.
thank you very much.
Ron.
|
|
|
|
|
hi,
I hope this will help you
http://codeguru.earthweb.com/atl/events.html
I think the answer of your question is at the very end of this (interesting) article.
Dim
|
|
|
|
|