Olá gente,

encontrei este documento mas confesso que não entendi muito... acho que é 
isso qe eu queria.. quero um servidor para distribuir minhas regras de 
negocios.. nada de Data Module!.. simplemsente objetos


 Creating Remote DCOM Objects on Specific Servers
by Jim Karabatsos - GUI Computing


DCOM is really *hot* technology. The ability to distribute ActiveX servers 
across several machines opens up some very interesting possibilities in 
application architecture. DCOM is ready *now* for use in production 
applications, as long as you are prepared to work within the limits of the 
state of the art.

That's not to say everything is just rosy. One of the problems with using 
DCOM from VB is that the canonical way to set it up is to use DCOMCNFG to 
configure the system registry on the client machine so that a particular COM 
object is associated with a particular server. The client application then 
just creates the COM object in exactly the same way that it would a local 
object, with OLE handling the details of resolving which server is to supply 
the object.

That's OK in many scenarios, but it can be a bit restrictive in others. One 
of the real trends that I am beginning to see is the marked preference to 
minimise the configuration issues on the client. Ideally, the client should 
just be able to load an executable (perhaps from a network share) and run it 
without needing to set anything up on the client machine. To me, this is the 
attraction of "browser-hosted" applications -- not the fact that a browser 
is involved but that deployment is simple.

Well, that's the theory, anyway.

One project I have been working on recently has used a three-tier 
architecture where an ActiveX server object runs on the same machine as an 
SQL Server database. That object communicates with that database and another 
legacy application database using ODBC drivers. The application is not going 
to run on the internet, but we did want to limit access to the legacy 
database to just one connection (for monetary reasons -- do you realise that 
the mainframe guys are still charging megabucks per bum for access to their 
systems?). We also wanted to be able to walk up to any workstation and use 
the application, without "installing" anything. (Well, we did have to 
install DCOM, but that's now part of the OS as far as I'm concerned).

The problem was to allow the client to connect to the server (using DCOM) 
*without* requiring that we run DCOMCNFG on the client to specify the server 
machine. You'd think that this would be pretty fundamental stuff. What I 
wanted was essentially a CreateObject function that took an additional 
parameter - the name of the server to create the object on.

It turns out that this is deemed to be just too complex for us poor 
simple-minded VB programmers, so nobody has bothered to show us how to do 
it. All the literature I could find refered to using DCOMCNFG. Someone (in a 
newsgroup somewhere, I forget where) suggested that we use DCOMCNFG to set 
up the registry entries for a fictitious server and then searching the 
registry for the server name. That would tell us which keys are needed and 
we could change them before calling CreateObject. Of course, you would still 
need to use DCOMCNFG to set up remoting in the first place.

I actually looked at expanding on this idea but it is really ugly. You need 
to register the object first, then change the key. It *can* be done, but 
it's messy.

In desperation, I delved into the revisions to the OLE API introduced with 
DCOM. Guess what, it really isn't that hard, although I still need to do 
something that I would rather not do (at least until I get time to look into 
this a little bit further -- read on).

It turns out that it is really quite easy to create a remote object on any 
arbitrary machine. All you need is it's CLSID, you know, one of those 
128-bit GUIDs that your registry is full of. You will need to find out the 
GUID of your server object. If you don't know how to do this, then you 
really should read "Inside OLE" by Craig Brockschmidt. In a nutshell, use 
RegEdit (carefully!) to look in HKEY_CLASSES_ROOT for your servers name (in 
the form MyServer.MyObject). Under that, you should find a "Clsid" branch 
and the default value for that is the CLSID in the canonical format (ie with 
the braces).

Now in Delphi (or C++ if you really must) you could create a remote server 
based on that GUID using that GUID alone. For example, here is some code 
written by Charles Calvert (of Delphi Unleashed fame) to create a server 
object on the named server (with a few typos fixed, refer to 
http://mix.hive.no/~xman/delphicom.html for the full article).

function CreateRemoteOleObject(ClassID: TGUID; const Server: string): 
Variant;
var
  Unknown: IUnknown;
  ClassFactory: IClassFactory;
  WideCharBuf: array[0..127] of WideChar;
  Info: TCoServerInfo;
  Dest: array[0..127] of WideChar;
begin
  ClassFactory := nil;
  Info.dwSize := SizeOf(Info);
  Info.pszName := StringToWideChar(Server, Dest, SizeOf(Dest) div 2);
  OleCheck(CoGetClassObject(ClassID, CLSCTX_REMOTE_SERVER, @INFO,
                         IID_IClassFactory, ClassFactory));

  if ClassFactory = nil then
    ShowMessage('No Class Factory')
  else
    ClassFactory.CreateInstance(nil, IID_IUnknown, Unknown);
  try
    Result := VarFromInterface(Unknown);
  finally
    ClassFactory.Release;
    Unknown.Release;
  end;
end;

// an example of using the above function:

const
  CLSID_MyObject: TGUID = (
    D1:$7DA2AE60;
    D2:$BFEE;
    D3:$11CF;
    D4:($8C,$CD,$00,$80,$C8,$0C, $F1, $D2));

    //  {7DA2AE60-BFEE-11CF-8CCD0080C80CF1D2}

var
  V: Variant;
  V := CreateRemoteOleObject(CLSID_MyObject, 'MyServer');

Note how in Delphi we can just declare a CLSID as a record of type TGUID. 
Obviously, the number must match that of your server object. Check it. Then 
check it again. Then get your mother to check it...

I'll leave you to read the article to figure out the details about how it 
works. For reasons I won't go into, I could not use this approach as I 
needed to do it all in VB.

The problem was that I had no readily apparent way to convert a 
human-readable format GUID into the appropriate binary structure and to work 
with the UNICODE strings directly across the calls to the OLE libraries 
(Unimess TM strikes again!). I'll get around to figuring it out one of these 
days, but, being pushed against a tight deadline, it was time to don the 
Micky Mouse ears and go into hack mode...

What I ended up doing was to deploy onto the client a cut-down version of my 
server object. I actually used my binary compatibility target, you know, 
that EXE that contains just empty procedures that effectively acts as a type 
library for your VB5 project. I could use standard installation tools (by 
which I mean WISE) to deploy and register this server on the client machine. 
What this does is allow me to use the API to convert the name of the server 
to a binary CLSID using a call to CLSIDFromProgID, as shown below. This uses 
the local registry to return the CLSID, which we can then use in a call to 
CoCreateInstanceEx. This code came (in large part) from a newsgroup posting; 
unfortunately, I have long lost the name of the author.

In a module somewhere, include this code:

   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.

One day, I will look at how to convert the string-format CLID into the 
binary structure. A clue is embedded in this code: look at the 
GetIIDforIDispatch function - it that does that. Problem is, it seems to be 
wrong although it does work. When I get a spare hour with a debugger I'll 
look into it and nut it out, but for now other deadlines beckon and this 
works well enough.





--------------------------------------------------------------------------------
Written by: Jim Karabatsos
April '98

--------------------------------------------------------------------------------


[HOME] [TABLE OF CONTENTS] [SEARCH]

----- Original Message ----- 
From: "Romulo Oliveira" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Thursday, December 02, 2004 3:57 PM
Subject: Re: [delphi-br] Servidor de Camada de Negócios


>
>
> hoje cedo vi no site.... vou comprar qd sair da firma
> aqui é tudo VB!!!!... eu q estou correndo atrás de Delphi!
>
> vale
>
> ----- Original Message ----- 
> From: "Rubem Rocha" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Thursday, December 02, 2004 2:22 PM
> Subject: RES: [delphi-br] Servidor de Camada de Negócios
>
>
>
> A edição 56 (deste mês) da revista ClubeDelphi (www.clubedelphi.net) 
> inicia
> uma série de artigos abordando o assunto.
> []s
>
> -----Mensagem original-----
> De: Danilo Antonio Leite [mailto:[EMAIL PROTECTED]
> Enviada em: quinta-feira, 2 de dezembro de 2004 14:26
> Para: [EMAIL PROTECTED]
> Assunto: Re: [delphi-br] Servidor de Camada de Negócios
>
>
>
> Para criar uma aplicação multicamadas você vai precisar dividir em pelo
> menos uma aplicação servidora, uma aplicação cliente e o banco de dados. A
> aplicação servidora deverá conter pelo menos um módulo de acesso remoto
> (RemoteDataModule). Lá você poderá colocar os seus componentes de acesso a
> dados, como em qualquer aplicação. Para que a aplicação cliente possa
> enxergar as queries, você poderá utilizar o componente DataSetProvider
> associado a cada query. Na aplicação cliente, pode-se utilizar
> TSocketConnection (é necessário o Borland socket server rodando, você o
> encontra na pasta BIN do Delphi) e ClientDataSet´s para acesso e 
> manipulação
> dos dados.
> As classes que você deseja implementar no servidor deverão ser declaradas
> através da opção de menu View/Type Library do delphi, e o código estará
> dentro das units dos RemoteDataModules.
>
> É só uma idéia, tem outras formas de implementar.
>
> Danilo Antônio Leite
> Arcadian Tecnologia SA
> [EMAIL PROTECTED]
>
>
>
>
> -- 
> <<<<< FAVOR REMOVER ESTA PARTE AO RESPONDER ESTA MENSAGEM >>>>>
>
> Para ver as mensagens antigas, acesse:
> http://br.groups.yahoo.com/group/delphi-br/messages
>
> Para falar com o moderador, envie um e-mail para:  [EMAIL PROTECTED]
> ou [EMAIL PROTECTED]
>
> Links do Yahoo! Grupos
>
>
>
>
>
>
>
>
>
> ---
> Incoming mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.799 / Virus Database: 543 - Release Date: 19/11/2004
>
>
>
> -- 
> <<<<< FAVOR REMOVER ESTA PARTE AO RESPONDER ESTA MENSAGEM >>>>>
>
> Para ver as mensagens antigas, acesse:
> http://br.groups.yahoo.com/group/delphi-br/messages
>
> Para falar com o moderador, envie um e-mail para:
> [EMAIL PROTECTED] ou [EMAIL PROTECTED]
>
> Links do Yahoo! Grupos
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> -- 
> <<<<< FAVOR REMOVER ESTA PARTE AO RESPONDER ESTA MENSAGEM >>>>>
>
> Para ver as mensagens antigas, acesse:
> http://br.groups.yahoo.com/group/delphi-br/messages
>
> Para falar com o moderador, envie um e-mail para:
> [EMAIL PROTECTED] ou [EMAIL PROTECTED]
>
> Links do Yahoo! Grupos
>
>
>
>
>
>
>
>
> 






-- 
<<<<< FAVOR REMOVER ESTA PARTE AO RESPONDER ESTA MENSAGEM >>>>>

Para ver as mensagens antigas, acesse:
 http://br.groups.yahoo.com/group/delphi-br/messages

Para falar com o moderador, envie um e-mail para:
 [EMAIL PROTECTED] ou [EMAIL PROTECTED]
 
Links do Yahoo! Grupos

<*> Para visitar o site do seu grupo na web, acesse:
    http://br.groups.yahoo.com/group/delphi-br/

<*> Para sair deste grupo, envie um e-mail para:
    [EMAIL PROTECTED]

<*> O uso que você faz do Yahoo! Grupos está sujeito aos:
    http://br.yahoo.com/info/utos.html

 



Responder a