DOCUMENT:Q157049 03-AUG-1999 [foxpro] TITLE :HOWTO: Debug Remote Automation Servers in Visual FoxPro 5 PRODUCT :Microsoft FoxPro PROD/VER: OPER/SYS: KEYWORDS:kbcode kbinterop kbAutomation kbvfp500 kbvfp600 ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - Microsoft Visual FoxPro for Windows, versions 5.0, 6.0 ------------------------------------------------------------------------------- SUMMARY ======= This article discusses general directions on how to debug remote server applications. MORE INFORMATION ================ Visual FoxPro 5.0 allows you to create remote OLE Automation servers. Unlike servers deployed locally, which can either be an .exe file or a .dll file, remote servers must have an .exe file extension. One of the advantages with .exe type servers is that they have their own event loop, so you can process events. However, in a typical remote situation, your server is non-visual (typically a business object in a three-tier situation). Debugging your .exe servers should be straight forward. For the most part, you should be able to test your servers locally before deploying them remotely. Most of the servers run the same in both situations. The approach you should take in creating and debugging a remote server is as follows: 1. Create your server as an internal Visual FoxPro class. Assuming you have a project called Books, which has a custom class called taxes that calculates the state/province sales tax for your mail order book sales business, you might have your class loosely structured as follows: * TaxLib.PRG DEFINE CLASS taxes AS custom PROCEDURE gettaxes LPARAMETER cState DO CASE CASE m.cState = "CA" RETURN .08 CASE m.cState = "WA" RETURN .07 CASE m.cState = "NY" RETURN .10 OTHERWISE RETURN 0 ENDCASE ENDPROC ENDCLASS Your application can test this class within Visual FoxPro internally with code similar to the following: cState = "CA" nBookPrice = 19.95 SET PROCEDURE TO TaxLib && can also use SET CLASS oTaxes = CreateObject("Taxes") nBookTax = oTaxes.GetTaxes(m.cState) * m.nBookPrice ? "Book total: "+ALLTRIM(STR(m.nBookPrice+m.nBookTax)) The advantage here is that you are working within the Visual FoxPro development environment so you can take advantage of the debugger for common errors such as "Syntax Error." 2. Change your class definitions to OLEPUBLIC and test locally. Theoretically, you have already debugged for most of the common errors. Now, you want to test the class as an OLE Server. In order to do this, update the class definition to make it OLE Public and rebuild the project, selecting the Build EXE option. The following shows this using a class defined in a .prg file: Change: DEFINE CLASS taxes AS custom To: DEFINE CLASS taxes AS custom OLEPUBLIC NOTE: If you are using a visual class created in a .vcx file, you would go into the Class Info dialog box to select the OLE Public check box. Once you have created your OLE Automation Server, you can update your test code as follows (notice that you no longer need a SET CLASSLIB or SET PROC statement--the class is automatically registered in the Registry as an OLE class): cState = "CA" nBookPrice = 19.95 oTaxes = CreateObject("Books.Taxes") nBookTax = oTaxes.GetTaxes(m.cState) * m.nBookPrice ? "Book total: "+ALLTRIM(STR(m.nBookPrice+m.nBookTax)) You should not encounter many problems beyond step 1; however, there are a few things to look out for. Since the OLE Server uses the run-time version, not all the language is supported (especially some of the user interface and designers). Make sure you avoid commands that do not work with the run-time version (these are documented in the Visual FoxPro Professional Features Guide, under "Distributing Applications"). 3. Deploy the OLE Server remotely. You have already created your OLE server. Now, you need to register it remotely. The easiest way to do this is through the Remote Automation Connection Manager (RacMan). RacMan allows you to switch an existing OLE Server, which you already have registered locally, to being registered remotely. In order to do this, make sure your remote machine has that server installed and registered properly and access rights are properly made available to the client. Finally, to create an instance of that server, you must be running DCOM (Distributed COM or Network OLE) between your machines (NT 4.0 or later) or be running the Automation Manager program that ships with Visual FoxPro on the server. See Visual FoxPro documentation for more details on setting up for remote automation and using RacMan. Many of the problems associated with using remote automation servers are not with the servers themselves but rather configuring them properly with valid network address, protocol and access rights. The biggest concern at this stage is checking for wait states that might stop the client. For example, a MessageBox() call that brings up a dialog box on your server can be closed only when someone manually goes over to the server and closes it. Meanwhile, your application is locked in a busy loop waiting for the server to complete the command. Strategies ---------- - Error handlers. Error handling is probably one of the more common problems with remote servers. It is imperative that your error handlers avoid using dialog boxes that can place your server in a modal state. Your error handlers should return an error code (possibly message) to the client for proper handling. Depending on how conservative you are with your code, you can either check after each automation call to the server for an error, or let your error routine handle it. - Wait states. In general, your remote servers should be non-visual. There may be extraneous wait state code such as BROWSE, MODIFY MEMO, WAIT WINDOW that relies on user input. Make sure to avoid this type of code, which can place the client in an endless loop. - Application object properties. There are several properties you can use in your client applications to more effectively handle problems with OLE Servers, including the following: OLEServerBusyTimeout OLERequestPendingTimeout OLEServerBusyRaiseError StartMode - Blocking with OLE Callbacks. Visual FoxPro supports the ability for remote servers to make OLE Callbacks into your clients. An object reference on the client can be passed to a remote server. The remote server can then call a method or set a property on this object. When this happens in a remote situation, the Automation Manager is automatically launched on the client machine. A common problem with OLE Callbacks is when you have the client pass an object reference to a method on the server. This method then tries to make a callback on that object. A blocking problem occurs (Error: Call was rejected by callee) because the client is waiting for the method to complete execution even though the server is trying to call back into the client. Here is a simple example: * Client code x=create("myproj.myserver") y=create("form") x.test(y) &&generates error because of blocking * Server code in project Myproj DEFINE CLASS myserver AS custom OLEPUBLIC PROCEDURE test PARAMETER oForm oForm.Caption = "Hello World" ENDPROC ENDDEFINE There are a number of ways to successfully handle OLE Callbacks. One is with the use of Timers (see the Pool Manager sample located in Samples\Servers). Common Errors with Remote Automation ------------------------------------ - Error: OLE error code 0x800706d9: There are no more endpoints available from the endpoint mapper. Possible causes: Automation Manager/DCOM not started (running) on server. Remedy: If you are using Automation Manager, make sure to launch the program. With DCOM, check DCOM documentation for possible problems configuring it. If a successful connection is made, the Automation Manager window indicates so. - Error: OLE error code 0x800706a7: The RPC protocol sequence is not supported. Possible causes: The Network Protocol specified on the client machine for the remote server is not supported. Remedy: On the client machine, launch the Remote Automation Connection Manager and go into the Server Connection tab. Select a Network Protocol that is supported such as TCP/IP. - Error: OLE error code 0x80070005: Access is denied. Possible causes: This is often due to improper client access set on the server. Remedy: On the server machine, launch the Remote Automation Connection Manager and choose the Client Access tab. Make sure the System Security Policy is set correctly. If this does not work, try using one of the other Policy options such as Allow All Remote Creates. - Error: OLE error code 0x800706e4: The requested operation is not supported. Possible causes: This is often due to improper client access set on the server when the System Security Policy is set to Allow Remote Creates by ACL. Remedy: On the server machine, launch the Remote Automation Connection Manager and choose the Client Access tab. The third option should already be selected (Allow Remote Creates by ACL). Make sure The ACL (Access Control List) privileges are set correctly to allow for client access via the Edit ACL button. If this does not work, try using one of the other Policy options such as Allow All Remote Creates. - Error: OLE error code 0x80010001: Call was rejected by callee. Possible causes: A block in OLE Callback. Remedy: Make sure that callbacks are made independent of the client's actions. Use a timer as in the Pool Manager example. - Error: Server busy or mousepointer endlessly busy Possible causes: This is often due to some wait state in the server such as an error dialog box, message box, browse, and so forth. Remedy: Avoid using code that requires user input. - Error: Feature not available. Possible causes: Command or function is not available in run-time version. Remedy: Do not use these commands. Additional query words: ====================================================================== Keywords : kbcode kbinterop kbAutomation kbvfp500 kbvfp600 Technology : kbVFPsearch kbAudDeveloper kbVFP500 kbVFP600 Issue type : kbhowto ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 1999.