 So if your code is perfect and there's nothing wrong with it, don't watch this episode of Visual Studio Toolbox, where Leslie Richardson will show us debugger tips and tricks. I envy that person. Hi, welcome to Visual Studio Toolbox. I'm your host, Robert Green, and joining me today is Leslie Richardson. Hey, Leslie. Hi. Thanks for coming on the show. Thanks for having me. Leslie is a PM in Visual Studio Land. Sure am. We're going to talk about debugging tips and tricks. Yes, we are. So there's obviously a lot to cover in the debugging space that sadly a lot of people don't know about. You can spend countless hours debugging that one bug and going through the most tedious steps possible when at the end of the day, you just want to get back to writing code, right? Yes. Yes. So hopefully some of these tips that I show you will help you out in the long run. Cool. A lot of these have been in the product for a while, some are new to 2019. Yes. So if you can remember to when there's something that's brand new in 2019, let's call that out. Okay. Otherwise, this is just stuff in Visual Studio. Awesome. Yeah, definitely. So I'm going to be focusing more on the.NET space today, but a lot of these features overlap into C++ as well. So I'm in Visual Studio 2019 right now, and I'm using an ASP.NET core application. Because I love to read so much, this is an app that randomly gives me a list of books that I can choose to read and add to my shelf or reject and they won't be added to my shelf. Okay. So this app also has a lot of problems with it. So hopefully we can use some of the debugging tools available to us in order to figure them out. Cool. All right. So first up, I have a breakpoint already set in this Book Manager constructor here, and this happens pretty early on in my programs at Secution where it takes in a JSON file containing a bunch of different book related information, converts each piece of that into a book object, and then stores each of those in a list. So I'm at the start of my function here, but I actually want to navigate to the bottom here instead. So normally that would be when I start spamming F10 or step over in order to get down there, but that can be tiresome, especially because I have this for loop right in the middle, so that can take a lot of time and that's not very productive of me. So the other option of course is to just set a breakpoint at the end and then hit F5, but then if I do that, I have to remember to delete the breakpoint afterward. Right. Because the next time you run the app and you get up and go for coffee or something you come back, it's sitting on that breakpoint, you forgot to remove. It's like, okay. It's like, I thought it was going to run without me while I get my coffee, but nope. So another alternative is something called run to click, which I can perform by hovering over the line I want to navigate to next. When I do that, you'll notice there's this little green Glyph icon that shows up, and I can click on that and it'll run all of my code up to that particular line. Easier than going down there right clicking and then set next statement or whatever it was. This is just quicker. Exactly. It's like having a remote control for your code and being able to fast forward to where you want to go. Yeah. So from there, the reason why I want to go to the end of this function is because I wanted to hone in on that book list, which stores a hundred different books because I want to quickly inspect each one. When I hover over it, I get a data tip. But one of my problems I have with data tips from time to time is that the moment I hover away from it, it disappears. So if I want to keep it for a while longer, what I can do instead is pin it. When I pin it, this data tip will stick around for as long as I decide to leave it until I ultimately close it. You can drag that to a second monitor. Yeah. I haven't actually tried. Good question. I feel like that should be possible. Okay. But good question. Yeah. The good news about this is that when I close out of my debugging session here, it'll still be present even when I start a new one. So now, if I wanted to inspect all the contents of this list here, at first glance, this isn't really helpful. Let's say I wanted to inspect each book by their names. It would be a little tedious to expand each of these out until I find the title property and then keep going to the next one and so forth until I find what I'm needing. So this also goes for if I were in the locals window as well or watch or autos. Ideally, it would be a lot nicer if instead of getting the type of object under the value column, I could see particular properties that I'm interested in, so I can just quickly skim through this list. So thankfully, there is a feature that you can use in Visual Studio that's one of my favorites, and it's an attribute called DebuggerDisplay, and that is an attribute that allows you to customize how you view your objects in the watch, autos, locals, and data tip windows. So to do that, I can go into where I defined my class, and at the top of that class definition, I can write in some DebuggerDisplay syntax, and the curly brackets will return the value of any property or properties because I can go plural with it. I can also use expressions if I wanted of whatever property that I specify. In this case, I want to view books by their title property so I'm going to type in title, and I'm also going to have to restart the debugging session. But hopefully, this is where the magic happens. So this is an attribute that exists currently in F-sharp, C-sharp, and Visual Basic. So this is for managed users, but if you're a C++ user, the equivalent that you can use that performs the same function is something called NATViz, where the difference mainly is that you have to create a separate NATViz file inside your project, and then that contains some XML that you can add to or modify in order to perform the thing that I'm about to show you. So I need to go back to the end of this function again. I'm going to use run to click, and I have my data tip that I pinned earlier that's still here because I never closed it. This is my favorite. This is my ad. Yeah. Cool. So cool. I love it a lot. Now, this is the part where we have fun. How long has this been in the project? Yeah. Longer than 2015 and longer than 2015. Yeah. It's been around for a while, longer than me. I love that. That's my favorite part of the show. I get asked that all the time. So is this a 2017, 2019 exclusive? No. Oh, no. Awesome. Yeah. So that's one of my favorites. So another thing that I like- And you can do expressions, so you can concatenate a couple of fields. Yeah. Exactly. Yep. If you wanted to do some simple type of expressions, then you can do that as well if you're interested in seeing what one property plus another is equal to. Could you do something like a function that says if these three fields are missing, just display incomplete. Then if they're there, just like complete. Can you do stuff like that? You can. Yeah. You can do some simple if conditional type statements as well. Yep. But kind of do it at your own risk. My recommendation for when things start to get very complicated in your debugger display syntax is to create another property or function within that class first. Called like debugger display or something like that. Right. Include all that logic and then you can write the function name inside the debugger display. Oh, that makes sense. Okay. Cool. Yeah. So from there, another feature that I like are the text visualizers and visual studios. So for instance, I have this JSON variable here that stores all my JSON contents. And if I'm looking at it, oh, first I need to actually navigate back to it because this is earlier on in my code and I'm currently out of scope. So what I can use for that is something called set to net statement, which I think you mentioned earlier. Right. So to do that, I can pretend as if I were doing another run to click, except I can hold down the control key and that green glyph will turn into the yellow icon, which will automatically move my execution pointer up to that particular line. So that's nice, especially if you want to try out what different execution paths are going to be looking like or if you want to go back and reinspect a previous variable. But you kind of have to use it at your own risk because since you're changing the execution flow in a way that is not necessarily intended, it has the potential to mess with the rest of your code's execution unless you restart and make a new debugging session. So from there, I have the JSON variable and looking at it, it's not very readable right off the bat because it's formatted for JSON in particular. That and it cuts off the screen. So if I'm looking at it in the locals window, for instance, there's this magnifying glass icon that's next to that, and I can click this dropdown to get a list of different visualizers I can use. So I'm going to use the JSON visualizer because this is JSON. And this time I get a lot better of a formatted view so I can quickly view this giant string in its proper format, which is great. So again, if you had a string that's cater for HTML or XML, then you can do that as well. Or if you have something that's catered for something completely different, you can also make your own visualizers. So that's pretty neat. And also if you just have a giant paragraph of text being stored in a variable, you can just use the regular text visualizer as well. Yep, cool. Yeah, so from there, now I kind of want to start looking into some problems with my application itself. So I'm going to hit continue. And so this is the general application and again I can go to this rate books page where it'll randomly give me a list of books that I can read to add to my shelf or not read and they won't be added. So in my case, I just want to read everything so I'm going to add. 100 books. Yep, I'm going to read all 100 of them. You know, it depends. It depends on how big it is. I have the goal every year of reading like 25 books. So I'm not quite at the 100 a year thing so let's go with four years for 100. So, but I'm noticing that of the 100 books that are supposed to be added to the shelf when I do that, it looks like there's only around half of them. So if I go into Visual Studio, I want to double check that out but also I should receive a notification if I click on the rate books page telling me that all the books are gone. Instead I get a lovely exception error instead. So let's try to solve this issue. So I'm going to navigate to my add all to shelf function and this is my function that will take each book on the rate books page and move them into my shelf. And I'm thinking the problem lies within this for loop here. So I want to see what's going on here. So before I, when I first started coding I was really big on print statements everywhere. Yeah, I don't know how many people in the audience out there love print statements as much as I did but they're great. I graduated to writing things to a text file. Yeah, that's great too, counts logging. Yeah. But I guess the problem with that at least for me is that it would be all over my code even when it's not needed. I forget to delete it when I'm done. So I prefer to not modify my code nowadays. So if you do like to log your information to the output window, an alternative you can use is a trace point which is an offshoot of a regular break point. So that will allow me to essentially perform a print statement without having to modify my code in the process. So I'm going to set a normal break point inside this for loop first and then I can hover over the break point to get little settings icon. When I click on that I'm going to select actions and here I'll get a prompt telling me what I want to log to the output window. In this case, I want to see how many indices this for loop goes through before it stops because I feel like it's stopping prematurely. So I'm going to do index, colon and then curly brackets and return the value of variable I. Hit enter and I'm going to leave continue execution checked but if you wanted your code to stop when a trace point's about to be printed you can do that as well. You get a diamond icon instead of the circle as well. So I'm going to boot up the program again. So it would come in handy if you, also come in handy if you wanted to watch the progress of something like I was working on some code yesterday that goes through looks in GitHub repositories and it loops through a large number of them and on some of them it was, there was an exception and I just wanted to know which ones through the exception without watching this program go that could take hours. So I wrote it to a file which worked but it seemed like this way I could just write that information out to the console window and then I don't have this printing, the saving to a file in my code which I could accidentally release to production and then it would blow up because someone didn't have, didn't have the directory that this is writing to, right? See, the big risk to modifying the code to do debugging is to leave that stuff in there. Yeah, because I'm pretty sure I've done a demo in school at one point where I left some arbitrary console.log something or other and I always like write weird quotes in it when I'm frustrated and trying to debug so it had said like a random, ugh, right in the middle of the demo. Or what idiot wrote this code, how come this doesn't work? Yeah, so from here I'm gonna perform that same add all books to my shelf option and this time I should see some print statements to go with it. All right, so going back into VS I can go to the output window and scroll up a little bit and here you'll notice that there's a bunch of related print statements going back with the trace point that I created. So this is one way to check out your trace points but also the problem with this is that these can easily get buried in the sea of stuff in the output window. So the other place where you can check them out that I like is in the diagnostics tools window. This is a window that I have a bad habit of closing usually when I'm debugging but one of the perks of keeping it open is this because you can filter out events that you see. I have a bad habit of leaving open and watching the pretty pictures. Yeah, that's true too, I do love the CPU graphs. Yeah, but then what are you doing with that? Right. But it makes you look official when somebody's walking past like what is that person doing? Although I did use it in this application I was working on to tell if there was a problem because the exceptions and there's like 10 exceptions that just happen but then when I noticed that there were 20,000 exceptions or 50 or 150,000 exceptions, that was my clue because the way this code works if it hits an exception it just sits in a loop because it's assuming that it just needs to keep trying. Exactly. And then when I got to 400,000 exceptions that was my clue that, hell, hold on a second. It's like, well, okay, maybe I should do something. Yeah. Yeah, so you can view your trace points here as well which might make things a little easier too. So from there I'm noticing that my index value I only goes up to 49 when it should go up to 99. So at this point I just want to step through like that last iteration of my for loop just to see what's going on with each piece of it. So I'm gonna go back to where I set this trace point and now the new problem is I want to go through this for loop but I don't wanna start from the very beginning of it like from when I is equal to zero because I'll be there for days and chances are I'm not gonna pay attention and I'm gonna skip when I equals 49 and then I have to rinse and repeat. So I can use a conditional break point instead which will allow me to halt my code only under a specific scenario that I give it. So where I set the trace point I'm gonna go back to settings and I'm gonna uncheck actions because I'm done with this trace point and check conditions. And from there I want my code to halt when I is equal to 49. Hit enter and close out and the conditional break points been created based off of this little plus icon inside the standard icon. And I'm gonna have to restart again. Now those, the conditional break points and things have been in there pretty much all or I don't even remember when those were created. I have no idea, like I feel like I started hearing about Visual Studio around 2013 or whichever one was before 2015. 13. Yeah, yeah, so 13. So anything past that, no idea. Cool, so again for forming that same add all books to my shelf action, my code halts this time and you'll notice that the value of I is set to 49 instead of zero. So from there if I step through this for loop I'm noticing that I used my neutral books dot count here as my loop condition and at the same time a book is being removed from neutral books at the end of each iteration which is causing the count to decrease at the start of each new iteration. So I think I found the problem here. So I'm gonna stop debugging and we're gonna comment out this line and then just clear all the books at the very end of the function instead. Okay. And that should solve the issue, give it a that. Now is there a way, let's say you thought that was the issue. You could add neutral books dot count to the watch window, right? Right. But correct me if I'm wrong but it doesn't update in real time as the application's running, is that true? Oh, it does update in real time. If you add it to the watch window. Okay. Yeah, and you're stepping then if it changes it will let you know that it changed because it usually highlights in red in either the watch autos in local's windows, so. All right, good. Cool. So from there adding all books it's time it looks like there's a lot more books that have been added. Yes. And just to double check turns out, yeah, I've rated all the books in the library already. Okay. So that was conditional break points and trace points to awesome alternatives to regular break points that you can use in your everyday debugging environment. Cool. So I think what we'll do is stop here and call this part one. Awesome. And then next week we'll do part two and see more debugging trips. People want to learn more about that. You wrote a blog post on this, right? I did. People can check out at aka.ms forward slash debugger display. Yeah, it goes through a lot more of the different scenarios that you can use with it and you can go check it out for more examples. And we will see you next time on Visual Studio Toolbox.