Microsoft KB Archive/117558

{|
 * width="100%"|

Tutorial: Debugging OLE Client-Server Combinations

 * }

Q117558

-

The information in this article applies to:


 * The Visual Workbench Integrated Debugger
 * Microsoft Visual C++, version 1.5

-

SUMMARY
When building object linking and embedding (OLE) servers, you may want to debug them in the context of being activated by an OLE container or to debug both the container and the server at the same time. The "Tutorial" in the "MORE INFORMATION" section, below, shows you how to debug and set breakpoints in an OLE server when the main debuggee is an OLE container.

Because Windows NT does not allow hard-mode debugging, and because you cannot run CodeView under Windows NT, you cannot perform simultaneous OLE client-server debugging using Visual C++, version 1.5, on Windows NT. However, you can still debug clients and servers under Windows NT as single applications on a standalone basis using the integrated debugger.

MORE INFORMATION
This tutorial guides you through a simple debugging session using the samples that come with Visual C++:

Tutorial
 Build debug versions of the Microsoft Foundation Classes (MFC) samples in the following directories:

 \MSVC\MFC\SAMPLES\CONTAIN\STEP2 \MSVC\MFC\SAMPLES\SCRIBBLE\STEP7  Run the SCRIBBLE.EXE file, built in step 1, to update the Windows registry to point to this executable file. From File Manager, choose Run from the File menu and type REGEDIT in the Command Line field. When REGEDIT comes up, double-click the SCRIB File Type entry to verify that the path points to the debug version of SCRIBBLE.EXE you just built. If not, modify the path accordingly. Load the OLE container project into the Visual C++ Workbench. If you are debugging an SDI server application, you should set the Program Arguments line of the Debug Options dialog box to "/Embedding" or "/Automation" so that the debugger can launch the server application as though it were launched from a container. Starting the container from Program Manager or File Manager now causes the container to use the instance of the server started in the debugger. Choose Debug from the Options menu and enter the full path to the debug version of the OLE server in the Additional DLLs field (be sure to include the .EXE extension). This tells the debugger to load the symbolic debug information for the server.

NOTE: This path must exactly match the path to the server entered in the Windows system registry. If it does not, attempts to debug the OLE server will fail. You can check or modify the path in the registry by using the REGEDIT tool provided with Windows.</li> While in the Visual C++ Debug dialog box, also choose the hard-mode button. This is just as important as the path-matching requirement mentioned earlier. If you try to debug in soft mode, the OLE lightweight remote procedure call (LRPC) mechanism will most likely cause unexpected behavior. For example, if you have breakpoints set in the server[ASCII 146]s initialization code, when the first breakpoint is hit the server will stop in the debugger before it is completely "created". The container[ASCII 146]s call to OleCreate will continue to run, eventually timing out and returning FALSE because the item was not properly created. You will then get a Message Box stating "Failed to create object. Make sure the object is entered in the system registry." Once you have received this message, a copy of the server is left stranded in memory, and subsequent attempts to debug it will fail (i.e. breakpoints will be missed). Restarting Windows will remove the server from memory and allow you to start a fresh debug session.</li> Open CONTAIN\STEP2[ASCII 146]s CONTRVW.CPP file and set a breakpoint on line 168.</li> Open SCRIBBLE\STEP7[ASCII 146]s SCRIBBLE.CPP file and set a breakpoint on line 68.</li> Press F5 to start the CONTAIN.EXE file. In the CONTAIN main menu, choose Insert New Object from the Edit menu.</li> From the resulting Object Type list, choose SCRIB File Type and choose the "OK" button. At this point, the debugger should have stopped at your breakpoint in the SCRIBBLE.CPP file. You can now debug the SCRIBBLE server.

NOTE: We could have set the breakpoint anywhere, including within the SCRIBBLE class constructors.</li> Press F5 again. The SCRIBBLE server continues its initialization, and then control returns to CONTAIN.EXE. The debugger should stop at the breakpoint in the CONTRVW.CPP file.</li> Step through CONTRVW's code, using F8 to see the embedded SCRIBBLE object become active.</li> Press F5 to continue running the SCRIBBLE.EXE file, activated in place within the CONTAIN.EXE file. If you do not readily see CONTAIN.EXE on your screen, you may need to switch focus to CONTAIN.EXE manually. You can also arrange Visual C++ and CONTAIN.EXE so that their windows do not overlap.</li>  Close the CONTAIN.EXE file.

When debugging OLE clients and servers simultaneously, remember that if both the client and the server(s) were statically linked using the MFC libraries, there will be at least two copies of MFC code in memory (perhaps more if you have nested embedded objects supplied by different servers). Therefore, if you set a breakpoint in MFC library code through its sources in \MSVC\MFC\SRC, you may get unexpected behavior. For example, if you set a breakpoint within AfxOleInit in file \MSVC\MFC\SRC\OLEINIT.CPP, the debugger may not be able to tell whether you want to break at the breakpoint under the following conditions:

 When the container's InitInstance calls AfxOleInit

-or-</li> When the server's InitInstance calls AfxOleInit

-or-</li> When the container's and server's InitInstances both call AfxOleInit</li></ul>

Therefore, the breakpoint may not occur in the place that you want.

To tell the debugger where you want it to break, you must use the context operator to specify in which module the breakpoint should be set. For the AfxOleInit example just mentioned, you could use the following expression to set the breakpoint in the server: <pre class="CODESAMP">     {,oleinit.cpp,server.exe} AfxOleInit This expression names the source file and module (in memory) where the debugger inserts the int 3 that sets the breakpoint. If the Integrated Development Environment (IDE) debugger is used, you need to type this expression into the Location field in the dialog box you get from choosing Breakpoints from the Debug menu. (The above breakpoint has AfxOleInit as the location, which causes a break on the opening brace of AfxOleInit. A line number can just as well be used in this case.) If Codeview is used, type the expression into the Location field in the dialog box you get from choosing Breakpoints from the Data menu. </li> Set a breakpoint at AfxOleInit in the SCRIBBLE server as described above.</li> Restart the CONTAIN.EXE file and observe that this breakpoint is only hit when the SCRIBBLE.EXE file calls AfxOleInit, not when CONTAIN.EXE calls AfxOleInit.</li></ol>

As an alternative, CodeView for Windows allows you to differentiate between multiple module copies by choosing Open Module from the File menu. Use this command to select in which module you want to set the breakpoint (CodeView lists all copies of each of the MFC modules in memory).

The Visual C++ IDE debugger is somewhat limited in its ability to handle complex debugging sessions, such as containers calling multiple servers. If you find you are experiencing problems, try using CodeView instead.

If you want to use CodeView for Windows as the debugger, load debugging information for your servers and/or DLLs by running the following command (without quotes) from the Program Manager or by choosing Run from the File Manager File menu:

"'CVW <options, if any> [/Loleserver.exe] oleclient.exe'" The square brackets indicate that the enclosed parameter can be specified 0 or more times, allowing you to load (/L) symbolic information for several servers or DLLs (or both). Unless the OLE client, server(s), and DLLs reside in the current directory (or in the directories listed in the PATH environment or in the Windows directories), the full path to these files is needed on the command line above this command.