Debugging Using PTVS (Part 2)

I received a comment on yesterday’s post, Debugging Using PTVS, that I thought I should explore in a bit more detail than a simple answer to the comment would allow. I want to extend my thanks to Dino Viehland for making me aware of this particular issue.

The first thing you need to know is that the version of PTVS that comes with IronPython 2.7 is outdated. So, when you’re asked whether to install PTVS with IronPython 2.7, you want to clear the selection. Simply set the Tools for Visual Studio option shown below not to be available.

IP2702

After you install IronPython 2.7, download and install PTVS from the CodePlex site instead. If you already have IronPython 2.7 installed with PTVS, I’ve found that the only way to truly get rid of the PTVS support is to uninstall it and start from scratch.

OK, on to the debugging part of this post. It turns out that you can change the debugging mode of PTVS by modifying the project properties. To perform this task, you choose Project > ProjectName Properties. If your Project Properties window looks like the one shown here, then you truly do have the old PTVS installed.

PTVSDebug201

However, if you see this version:

PTVSDebug202

you’re ready to go. Notice that the Debug tab has a Launch Mode field. This field controls how PTVS debugs your application. My initial post, Debugging Using PTVS, shows the IronPython (.NET) Launcher side of things. It turns out that you can change this setting to Standard Python Launcher, which significantly changes the behavior of the debugger.

The down side firstyou lose the ability to debug other .NET code. All you see when using this launcher is the Python world.

Now for the good part. My previous post showed how the call stack looks. It’s barely readable, but only if you squint a bit and think about it for a second or two. When working with the Standard Python Launcher, the call stack is significantly easier to read. Check it out:

PTVSDebug203

In addition, you’ll find that the Immediate window is a bit more cooperative too. Remember that it wasn’t possible to type ? args[0] without generating an error in yesterday’s post. When working with the Standard Python Launcher you get the expected result as shown here:

PTVSDebug204

In fact, you’ll find that debugging Python-specific code becomes easier when using the Standard Python Launcher. So, using the newer version of PTVS gives you some significant debugging flexibility that developers really need to create great IronPython applications. Let me know your thoughts on the updating debugging functionality at John@JohnMuellerBooks.com.

 

Debugging Using PTVS

A reader recently wrote to ask about the debugging features provided by PTVS. In Chapter 12 of Professional IronPython you discover techniques for debugging your IronPython application. This chapter doesn’t include any information about PTVS because the product wasn’t available at the time of writing. However, the techniques described in the chapter work just fine in Visual Studio too. What PTVS does provide is some additional debugging functionality that isn’t available to IronPython developers normally and that’s the topic of this post.

This post begins with the example created in the Using the PTVS for a Windows Forms Project post so that you can easily follow along. Of course, the techniques I describe are useful for any application you might be working on at the moment.

One of the first things you should look at is the Output window. It shows you everything that IronPython is loading in order to run your application. This information can help you locate potential issues in running an application on a client system and help you create the appropriate installation support for your application as shown here.

PTVSDebug01

As with any other Visual Studio application, you can set breakpoints for your IronPython application to stop execution at a particular point. To set a breakpoint you can click in the left margin. It’s also possible to right click a particular line, select the Breakpoint menu entry, and choose from the options on the menu. PTVS even provides full support for the usual assortment of conditional breakpoint offerings as shown here. (For the purposes of this post, I set a breakpoint on the MessageBox.Show(‘Hello!’) line of code.

PTVSDebug02

When your application stops at a breakpoint, you have access to many, but not all of the Visual Studio features. So far I haven’t been able to get the Autos window to work. (If anyone has a trick to make it work, let me know.) The Locals window does work though and provides the full range of information you’d expect. Here’s an example of the information you’ll typically see.

PTVSDebug03

Notice that you can drill down into the arguments as needed. It’s also possible to change values using the Locals window, just as you can with Visual Studio normally. Changes to many properties and variables work fine. However, you might not be able to count on this behavior for all value types. Visualizer support is there as well. At least, the Text, XML, and HTML visualizers seem to work. There may not be any support for custom visualizers.

The Call Stack window works much like it does for any Visual Studio application. Of course, the information is IronPython-specific as shown here.

PTVSDebug04

One bothersome aspect is that the window doesn’t tell you the correct language. Instead, you see that the language is marked as Unknown. The debugger does get the line numbers correct and it’s easy enough to decipher the remaining information in this window. You’ll find that the Call Stack window correctly marks any arguments to methods for you.

The Immediate window only partially works. At least, I found it worked only partially for me. For example, if you type ? args and press Enter, you’ll find that the Immediate window correctly tells you that it’s a tuple containing two items. However, it appears to be impossible to access the elements within tuple. For example, if you type ? args[0] and press Enter, you’ll find that the Immediate window responds with an error message as shown here.

PTVSDebug05

Making things a bit more difficult is the fact that you can type ? $function and press Enter to obtain the function-specific information and type ? $function.__name__ and press Enter to obtain the function name. In this case, everything works as expected. The debugging support provided by the Immediate window seems spotty. You may find yourself limited to performing certain tasks using it and then relying on the Locals window to perform other tasks.

There are other windows supported by the debugger that appear to work as you think they should. For example, you can set watches and view them using the Watch window, just like any other language that Visual Studio supports. The Breakpoints window also seems to work as it should.

This has been a whirlwind overview of the debugging features provided by PTVS to IronPython developers. Let me know if you have any specific questions at John@JohnMuellerBooks.com and I’ll do my best to research them.

 

Creating Sensible Error Trapping

Errors in software happen. A file is missing on the hard drive or the user presses an unexpected key combination. There are errors of all shapes and sizes; expected and unexpected. The sources of errors are almost limitless. Some developers look at this vastness, become overwhelmed, and handle all errors the same wayby generating an ambiguous exception for absolutely every error that doesn’t help anyone solve anything. This is the worst case scenario that’s all too common in software today. I’ve talked with any number of people who have had to employ extreme effort just to figure the source of the exception out; many people simply give up and hope that someone has already discovered the source of the error.

At one time, error handling functionality in application development languages was so poor that it was possible to give the developer the benefit of a doubt. However, with the development tools that developers have at their disposal today, there is never a reason to provide an ambiguous “one size fits all” exception. For one thing, developers should make a distinction between the expected and the unexpected. Any expected errora missing file for example—should be handled directly and specifically. If the application absolutely must have the file and can’t recreate it, then it should display a message saying which file is missing, where it is missing from, and possibly how to obtain another copy.

Even more than simply shoving the burden onto the user, however, modern applications have significantly more resources available for handling the error automatically. For example, it’s quite possible to use an Internet connection to access the vendor’s Web site and automatically download a missing application file. Except to tell the user what’s happening when the repair will take a few minutes, the application shouldn’t even bother the user with this particular kind of errorthe repair should be automatic.

My book, C# Design and Development,” discusses a number of expected error scenarios that the developer can easily handle. For example, a user could press the wrong key combination. Instead of simply beeping it’s discontent, the application should tell the user that the key combination won’t do anything and provide a list of acceptable key combinations. The use of friendly controls can also help. Don’t use a textbox when a drop down listbox will work better. In fact, the textbox is the worst possible control to use in many circumstancesit should be the option of last choice. Chapters 4 through 7 of my book discusses a wealth of design issues, including the selection of a proper interface type (such as a dialog box versus an SDI or MDI form). It divides these decisions into those that affect application speed, reliability, and security, which is the smart approach to use in developing any application.

Exceptional conditions do occur. However, even in these situations the developer must avoid the generic exception at all costs. If an application experiences an unexpected error and there isn’t any way to recover from it automatically, the user requires as much information as possible about the error in order to fix it. This means that the application should diagnose the problem as much as possible. Don’t tell the user that the application simply has to endthere is never a good reason to include this sort of message. Instead, tell the user that the application can’t locate a required resource and specify the resource in as much detail as possible. If possible, let the user fix the resource access problem and then retry access before you simply let the application die an ignoble death. Remember this! Any exception that your application displays means that you’ve failed as a developer to locate and repair the errors, so exceptions should be reserved for truly exceptional conditions.

Not everyone agrees with my approach to error trapping, but I have yet to hear a convincing argument to provide unreliable, non-specific error trapping in an application. Poor error trapping always translates into increased user dissatisfaction, increased support costs, and a reduction in profitability. Let me know your thoughts on the issue of creating a sensible error trapping strategy at John@JohnMuellerBooks.com.

 

Using CodeBlocks 10.05 – Part 3

As previously mentioned, C++ All-In-One Desk Reference For Dummies is currently designed around CodeBlocks 8.02. However, a number of readers have written to ask about the latest version of CodeBlocks, 10.05. I introduced this new version in Using CodeBlocks 10.05 – Part 1, where I discussed the general look of the new version. Since that time, I’ve tried out more of the book’s source code with this new version and still haven’t encountered any problems except the one described in Using CodeBlocks 10.05 – Part 2 on my test systems. Of course, that doesn’t mean the new version will run flawlessly on your system, so I’m still looking for input from readers about it.

Today’s post focuses on the debugger, which has changed a bit since the CodeBlocks 8.02 release. Book III, starting on page 349, discusses errors in programming. Chapter 2, page 361, discusses debugging techniques. Figure 2-1 shows the Debugging toolbar with callouts for each button. There isn’t any difference in this toolbar for CodeBlocks 10.05. You can also press F8 to start the debugger, just as in previous versions.

This post works with the example found in the \Author\BookIII\Chapter02\BuggyProgram folder of the source code. There is actually a small error in the example code supplied with the book in that example. Look at the following line of code:

// system("PAUSE”); // add this for Windows

There is an odd looking double quote after the word PAUSE. If you uncomment this line so the code pauses, the compiler will register a warning: missing terminating ” character error. Make sure you change that odd looking double quote to an actual double quote when you run the code. The resulting change should look like this:

system("PAUSE"); // add this for Windows

when you remove the comment.

Page 363 tells you about breakpoints. To use the sample, you set a breakpoint at line 22. If you want, you can click on the left side, as described in the book. You also have the option of right clicking on the line number to display a context menu that contains options for setting or removing a breakpoint. Here’s how the context menu appears when you want to set a breakpoint.

CodeBlocks10_05Part2_1

Simply choose Add Breakpoint to set the breakpoint on that line. If a breakpoint is already on the line, you’ll see these options instead.

CodeBlocks10_05Part2_2

To clear a breakpoint, simply choose the Remove Breakpoint option. It’s also possible to change how a breakpoint works. Click Edit Breakpoint and you’ll see the Edit Breakpoint dialog box shown here.

CodeBlocks10_05Part2_3

If you clear the Enabled checkbox, the IDE retains the breakpoint, but ignores it during debugging. The breakpoint appearance doesn’t change (many IDEs display the breakpoint as a hollow circle when the breakpoint is disabled). This means that you must actually check the breakpoint status before you assume something has gone wrong.

It’s also possible to set conditional breakpoints. For example, if you’re working in a loop, you can tell the IDE to ignore the breakpoint until the loop has executed a certain number of times by checking the Ignore Count Before Break option and setting the number of times the IDE should ignore the breakpoint before it actually stops.

As an alternative, you can set a condition the code must meet before the breakpoint executes. For example, you might set a breakpoint that says result = 15. If result is any other value, the IDE ignores the breakpoint. In order to use this kind of conditional breakpoint, you check the Break When Expression Is True option and enter the expression you want to check.

If you have some extremely odd condition to check, you can combine both conditional features. The breakpoint seems to work only if both conditions are true. In other words, you can’t check for one condition or the other, but must instead look for both conditions. If someone has a different experience with this feature, please be sure to let me know.

I tried the debugging steps in Chapter 2 and didn’t encounter any issues. I encourage you to try the various conditional breakpoint features as you work through other examples in the book, especially examples that employ looping. If you find any debugging features that fail to work, please be sure to let me know at John@JohnMuellerBooks.com.

 

Using the FindStr Utility to Locate Errors in Visual Studio

There are cases where the error message that you obtain from Visual Studio is less than helpful. Let’s begin the scenario by saying a coworker wants you to test some code. According to the code worker, the application works fine, but when you try it on your system, you get an odd sort of error message like the one shown here:

Error: Could not find a part of the path ‘C:\MyProj\Projects\TestMe\TestMe\Properties\MyManifest.xml’.

Here’s the frustrating part. You look in Solution Explorer and MyManifest.xml is in plain sight. So, now you start to wonder what’s going on because the IDE should be able to find the file. Here’s the key for this particular example. Instead of putting the project in C:\MyProj, you placed it in C:\MyFriendsProj. In this case, you don’t have a C:\MyProj folder on your machine.  So, when the IDE looked for MyManifest.xml in that particular folder, it couldn’t find it and displayed an error.  What to do?  You could search for this problem all day long and never find it. Often, the problem is one where the path has been hard coded into one or more of the Visual Studio support files.

The answer is to use the FindStr utility at the command line to find files that have the MyProj folder hard coded in them.  You open a command prompt and type FindStr /m /s /C:”MyProj” *.* and press Enter (where the /m command line switch tells FindStr to supply only filenames, the /s command line switch searches subdirectories, and the /C: command line switch performs a literal search).  Here’s some typical output.

Projects\TestMe\Bin\Debug\TestMe.dll
Projects\TestMe\Bin\Debug\TestMe.pdb
Projects\TestMe\obj\Debug\App.g.cs
Projects\TestMe\obj\Debug\App.g.i.cs
Projects\TestMe\obj\Debug\DesignTimeResolveAssemblyReferences.cache
Projects\TestMe\obj\Debug\DesignTimeResolveAssemblyReferencesInput.cache
Projects\TestMe\obj\Debug\Form1.g.cs
Projects\TestMe\obj\Debug\Form1.g.i.cs
Projects\TestMe\obj\Debug\TestMe.csproj.FileListAbsolute.txt
Projects\TestMe\obj\Debug\TestMe.dll
Projects\TestMe\obj\Debug\TestMe.pdb
Projects\TestMe\obj\Debug\XapCacheFile.xml
Projects\TestMe.suo

All of these files have the MyProj folder hard coded in them.  By deleting these files and rebuilding the project, you can get rid of the error.  You can’t use the Visual Studio search features to find this problem because Visual Studio doesn’t look inside all of the files that it should—it only looks in source code files for the most part and only the source code files that are actually part of your project.  FindStr looks inside every file, no matter what its purpose might be.

What unique uses have you found for FindStr in managing your application development? Let me know at John@JohnMuellerBooks.com.