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