As I’ve done many times with WinDBG in the past, I spent some time this week trying to use WinDBG Preview as my daily debugger. I’m delighted to report that, although it didn’t seem like it at first, once I dug in, WinDBG Preview really does appear to be usable as an everyday debugger! This is great news for everyone who’s been chafing under Visual Studio’s deteriorating debugger for the past fifteen years.
Since Microsoft has been asking for feedback, I thought I’d take a minute to list all the things I noticed that made it more difficult to use WinDBG than I would like:
There needs to be a keyboard shortcut for re-running an unloaded executable. This is the #1 thing that bothers me about using WinDBG at the moment. If the executable is still loaded, you can hit CTRL-SHIFT-F5 at any time to restart it, and it will preserve everything perfectly: breakpoints, command line arguments, working directory, the whole nine. But once you unload it (SHIFT-F5), presumably to rebuild it with some changes, CTRL-SHIFT-F5 no longer works. This really needs to be fixed, because the only way around it that I have found is to manually go to the File menu, select “Recent”, and then select the executable again. Thankfully, this still brings back your breakpoints and command line arguments, but it’s still way too many steps just to run the executable again. I would suggest doing the same thing Visual Studio does, which is that if the executable is unloaded, hitting F5 (which is normally “continue”) reloads it and starts it running.
There need to be keyboard bindings for automation scripts. WinDBG allows you to script its behavior via a scripting interface. I could see this eventually being useful for customizing the debugger for specific workflows. But at the moment, it seems very limited, because you cannot actually bind scripts to keyboard shortcuts. Instead, you have to manually switch to the command window, type the execution command, and then type the entire name of the script. This is much too cumbersome to make it useful for user interface improvement. If there was some kind of script keybindings file you could create, that would allow you to bind all your keys to scripts you’ve written to perform your common tasks. This would make scripting immediately much more powerful.
Break-command-continue should to be automated. Right now, you cannot invoke most debugger operations when the target is actively running. Even if you want to do a common operation, like set a breakpoint and wait until it is hit, you can’t do it directly. Instead, you must break the target (ALT-DEL),
then set the breakpoint (ALT-B A),
then continue (F5). Not a showstopper, but there’s really no reason for the user to be doing this manually. If the debugger can’t set breakpoints while the target is running, just automatically invoke the break-set-continue for the user when they ask for a new breakpoint.
Setting a new breakpoint by name should be a single keystroke. This is a weird oversight, but for some reason, it doesn’t seem like there’s any way to add a breakpoint by name with a direct keyboard shortcut. Although F9 will set a breakpoint on the current line with a single keystroke, setting a breakpoint by name requires you to open the breakpoints ribbon (ALT-B)
and then hit A to execute the “Add Breakpoint” operation. There should be a dedicated keyboard shortcut for this, as it’s a very common operation (in Visual Studio, both ALT-F9 and CTRL-B will do this).
Unresolved breakpoints should retain their original names. If WinDBG understands the breakpoint you’re trying to set, the breakpoints window will list it with a descriptive name that makes sense. However, if it
doesn’t (like if it’s in a module that hasn’t been loaded yet, so the symbols aren’t there), then it just lists the breakpoint as “0x0”, which makes it impossible to tell which breakpoint is which. It’d be nice if the breakpoint window always listed breakpoints with something user-recognizable, like the original text the user typed in, so it’s clear which breakpoints are which even if some of them can’t be set yet.
Single-stepping shortcuts need to be improved. WinDBG currently has shortcuts for “step in”, “step out”, and “step over”, which is great. But “step in” is unfortunately a broad category, and WinDBG doesn’t seem to support shortcuts for all the variants you might want. Specifically, you want “step to next machine instruction”, “step to next source code line”, “step into first function call on this source code statement”, and “step into last function call on this source code statement”. Ideally these are not modal, they are all always available, just bound to separate keys. In WinDBG at the moment, only “step to next machine instruction” and “step to next source code line” are bound to a key, but they’re bound to the
same key (F11), and you have to use a modal switch to select which one to do.
The register window needs work. Modern processors have a lot of registers. A
lot. The register window can’t be just a giant uncustomizable list, or it’s not really feasible to use it. Ideally, there would be some kind of register view that would allow the user to quickly toggle which registers appear (as Visual Studio does via a right-click menu), and perhaps also has a “locals” section that shows all the registers involved in an n-instruction window around the current IP.
PDB hunting could be a lot better. If you use the /RELEASE and /PDBALTPATH switches to the linker, you will probably not have much trouble getting WinDBG to read your symbols automatically. This is great! But in more complicated scenarios, where the EXE and PDB don’t match exactly (for example, if the PDB has been moved or renamed), WinDBG doesn’t seem to try very hard to find it. This forces the user to do a bunch of busywork to load symbols that the debugger probably could have found itself if it did a little bit of searching.
Loading and saving the window layout should be a separate operation. WinDBG’s persistent configuration is a little hard to understand at the moment. It would be nice if it was more clearly delineated into two pieces:
UI and
target. Ideally, you want to be able to load targets independently of UI layouts and keyboard configurations, because the target is about
what you are debugging, and the layout is about
how you are debugging. In the best possible world, you could make several UI configurations irrespective of the target, and they would be immediately available at all times for rapid switching. Targets, on the other hand, are just configurations of which executables and DLLs to load, where to find the symbols, and how to configure everything (working directory, parameters, etc.) While it’s nice if they save which UI configuration they were last using, that’s about all they should do, and layouts shouldn’t be coupled to targets in any other way.
The file “menu” is cumbersome and weird. Most of the UI in WinDBG is pretty straightforward. I don’t care for “ribbons”, but thankfully you can just collapse the ribbon and use the keyboard shortcuts for everything… well, almost everything. Unfortunately, the File menu is something you do have to use, to set up executables, change settings, etc. And it’s very weird — it doesn’t work the way any of the other UI works, replaces the entire window so you can’t see anything you were doing while you use it, and just generally feels really out of place. I would recommend not going down this path, and replacing the File menu with a regular menu system that doesn’t do anything fancy.
There should be a ZIP-based distribution. Currently, WinDBG preview is only available via the Windows Store. While that might have been a deal killer, fortunately it doesn’t require an account or any fussing. You can just download it directly from the store, then ZIP the resulting directory yourself, creating a nice distribution you can put on any machine quickly. But obviously, it would be an improvement if Microsoft provided such a ZIP directly, and committing to such a deployment would ensure that bloated installer creep couldn’t happen (like it has for Visual Studio).