Setting up client machines in a distributed application is fairly tedious. Each client computer must have the client application's EXE, one or more type libraries, and a significant number of Registry settings. The client-side Registry must contain the same set of keys required for a local out-of-process server, including CLSIDs, IIDs, and the GUID for any type library.
While you can set up client computers by hand, it makes more sense to create a setup program that automates the task. The Visual Basic IDE offers some assistance in configuring the client-side Registry. If you select the Remote Server Files option on your server project's Components tab, Visual Basic creates a remote setup file with a .vbr extension when you choose the Make command from the File menu. A .vbr file contains a list of Registry entries that must be written to the client machine. Visual Basic also ships with a utility named CliReg32.EXE, which accepts a .vbr file as a parameter and writes the appropriate settings to the client's Registry.
A client application that uses remote objects needs a way to redirect activation requests to the target computer running the distributed application. You can accomplish this in a few different ways. One way is to configure the application's CLSIDs on the client computer to use an AppID to point to the target server. Another way is to select the target computer at run time using the CreateObject function.
If you want to configure a CLSID to activate remotely, you must provide a custom AppID key with the RemoteServerName named value. As long as there isn't a more efficient server type available for the CLSID, the SCM manager will initiate a remote activation request to the target server. This means that the CLSID can't have a valid InProcServer32 or a LocalServer32 subkey. The remote server name can be the name of a computer on a Windows NT network, a dotted-decimal TCP/IP address, or a DNS address (for example, www.microsoft.com). After you set up the AppID, you must also add an AppID named value to each of the application's CLSIDs.
After you configure the AppID, you can easily redirect activation requests to any remote server by using Dcomcnfg.exe, as shown in Figure 8-10. If you select a remote server after a local version of the server has been registered, Dcomcnfg.exe temporarily disables the LocalServer32 subkey for every CLSID associated with the AppID by renaming it _LocalServer32. If you then reconfigure the AppID using the Run Application On This Computer option, Dcomcnfg.exe returns the LocalServer32 subkey to its original state.
It's often advantageous for a client to choose a target computer at run time. This allows applications to provide sophisticated features such as load balancing and fail-over support. The easiest way to select a remote computer programmatically is to use Visual Basic's CreateObject function. Visual Basic 6 has a second optional parameter to CreateObject that accepts the name of a remote computer. Note that the client machine still requires a type library and various Registry settings, including the ProgID, which is passed to CreateObject.
Figure 8-10. You can use the Location tab to redirect client activation requests to a computer across the network.
Another approach is to rely on remote activation code written in C++. For teams with C++ expertise, it can be helpful to create thin C++ DLLs that extend the remote capabilities of a Visual Basic application. For example, you can write code in C++ that makes a direct call to a function in the COM Library named CoCreateInstanceEx. This function accepts parameters for a CLSID and a remote host name. It also lets the caller pass a Windows NT user account name and password at run time. Note that this technique is the best way to redirect activation programmatically in versions of Visual Basic prior to version 6.
No description of client-side configuration would be complete without our noting an important setting that has stumped many developers and administrators who try to run their applications in a network environment. Any client application that receives events or connects to a callback interface requires access permissions for the security principal of the server application. This means that the client computer must be configured to include access permissions for the user account that represents the server's identity. You can solve this problem by modifying the access permissions for either the correct AppID or the machinewide default security profile.
A more subtle and troublesome problem can occur when the client and the server are in different domains. Often the server's domain controller will trust the client's domain controller to authenticate the client via a one-way trust relationship so that calls from the client to the server succeed without a hitch. However, for authenticated callbacks to succeed, the client's domain controller must trust the server's domain controller to authenticate the server.