Hotkeys for Previous and Next call stack frames in Visual Studio - visual-studio

Visual Studio gives many navigation hotkeys:
F8 for next item in current panel (search results, errors ...),
Control+K, N for bookmarks,
Alt+- for going back and more.
There is one hotkey that I can't find, and I can't even find the menu-command for it, so I can't create the hotkey myself.
I don't know if such exist: Previous and Next call-stack frame.
I try not using the mouse when programming, but when I need to go back the stack, I must use it to double click the previous frame.
Anyone? How about a macro that does it?

I wrote 2 macros to gain it: PreviousStackFrame and NextStackFrame and assigned shortcuts to
Function StackFrameIndex(ByRef aFrames As EnvDTE.StackFrames, ByRef aFrame As EnvDTE.StackFrame) As Long
For StackFrameIndex = 1 To aFrames.Count
If aFrames.Item(StackFrameIndex) Is aFrame Then Exit Function
Next
StackFrameIndex = -1
End Function
Sub NavigateStack(ByVal aShift As Long)
If DTE.Debugger.CurrentProgram Is Nothing Then
DTE.StatusBar.Text = "No program is currently being debugged."
Exit Sub
End If
Dim ind As Long = StackFrameIndex(DTE.Debugger.CurrentThread.StackFrames, DTE.Debugger.CurrentStackFrame)
If ind = -1 Then
DTE.StatusBar.Text = "Stack navigation failed"
Exit Sub
End If
ind = ind + aShift
If ind <= 0 Or ind > DTE.Debugger.CurrentThread.StackFrames.Count Then
DTE.StatusBar.Text = "Stack frame index is out of range"
Exit Sub
End If
DTE.Debugger.CurrentStackFrame = DTE.Debugger.CurrentThread.StackFrames.Item(ind)
DTE.StatusBar.Text = "Stack frame index: " & ind & " of " & DTE.Debugger.CurrentThread.StackFrames.Count
End Sub
Sub PreviousStackFrame()
NavigateStack(1)
End Sub
Sub NextStackFrame()
NavigateStack(-1)
End Sub

I have solved this problem with AutoHotkey. I made this a few months ago.
Suppose you wanted to use Control+1 and Control+2 and that Control+Alt+C is bound to showing the Call Stack window:
^1::SendInput !^c{down}{enter}
^2::SendInput !^c{up}{enter}
It seems to work pretty well. If you aren't already using AutoHotkey to show Visual Studio who's boss, please give it a shot. Your question indicates that you would benefit greatly from it. It's a game changer. Good luck.

I don't think theres an explict next-frame / prev-frame key binding but heres what I do.
CTRL-ALT-C is already bound to "Debug.CallStack"
This will focus you in the Call Stack Tool Window
Once focused in the Callstack window... Up & Down arrows will move you through the call stack frames
I've then bound
CTRL-C, CTRL-S to "DebuggerContextMenus.CallStackWindow.SwitchToFrame"
and
CTRL-C, CTRL-C to "DebuggerContextMenus.CallStackWindow.SwitchToCode"
both of which will take you back into the code window at the particular frame.
Hope that helps.

Huge thanks to #Oleg Svechkarenko for his answer that gave me a starting point in crafting this solution. Since modern versions of Visual Studio no longer have official macro support, this should drop in for those who use the Visual Commander plugin, but probably can be easily adapted for any other macro extension.
Here is the code for the command, I created one for navigating up the call stack and one for navigating down with the same code except the parameter passed to MoveStackIndex(), then bound keyboard shortcuts to them:
using EnvDTE;
using EnvDTE80;
using System;
public class C : VisualCommanderExt.ICommand
{
enum MoveDirection
{
Up,
Down,
}
private bool IsValidFrame(StackFrame frame)
{
string language = frame.Language;
bool result = (language == "C#" ||
language == "C++" ||
language == "VB" ||
language == "Python");
return result;
}
private void MoveStackIndex(EnvDTE80.DTE2 DTE, MoveDirection direction)
{
StackFrame currentFrame = DTE.Debugger.CurrentStackFrame;
bool foundTarget = false;
bool pastCurrent = false;
StackFrame lastValid = null;
foreach (StackFrame frame in DTE.Debugger.CurrentThread.StackFrames)
{
bool isCurrent = frame == currentFrame;
if (direction == MoveDirection.Down)
{
if (isCurrent)
{
if (lastValid == null)
{
// No valid frames below this one
break;
}
else
{
DTE.Debugger.CurrentStackFrame = lastValid;
foundTarget = true;
break;
}
}
else
{
if (IsValidFrame(frame))
{
lastValid = frame;
}
}
}
if (direction == MoveDirection.Up && pastCurrent)
{
if (IsValidFrame(frame))
{
DTE.Debugger.CurrentStackFrame = frame;
foundTarget = true;
break;
}
}
if (isCurrent)
{
pastCurrent = true;
}
}
if (!foundTarget)
{
DTE.StatusBar.Text = "Failed to find valid stack frame in that direction.";
}
}
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
if (DTE.Debugger.CurrentProgram == null)
{
DTE.StatusBar.Text = "Debug session not active.";
}
else
{
// NOTE: Change param 2 to MoveDirection.Up for the up command
MoveStackIndex(DTE, MoveDirection.Down);
}
}
}

Look in Tools->Options->Environment->Keyboard. Enter "stack" or "frame" and related menus will appear. It seems that there's no next and previous call-stack frame.

Related

Adding a delay in my code, not working. C++

Trying to make simon says game as my semester project, problem is I cant add a delay between the colors when they change,
i.e i want to add a delay so that when one box color changes, then after about 3~4 seconds the next box color changes, but the problem is when I put the Sleep() in my for loop, the system pauses for the amount given as a whole, then displays all the colors changed at the same time not one by one....
Any help, here is the function that i call when the game's start button is clicked. How to fix it ?
void flash()
{
srand(time(NULL));
int x;
for (int i = 5; i > 0;i--)
{
x = rand() % 4;
if (x == 0)
{
button1->BackColor = System::Drawing::Color::Blue;
}
else if (x == 1)
{
button2->BackColor = System::Drawing::Color::Blue;
}
else if (x == 2)
{
button3->BackColor = System::Drawing::Color::Blue;
}
else if (x == 3)
{
button4->BackColor = System::Drawing::Color::Blue;
}
Sleep(500);
}
}
P.s I have tried to put the sleep in the if statements but that doesn't work either, Any help please ?
As your code is single-treaded and you are updating the colors of the buttons in a loop, there is (currently) no chance for the application's standard drawing routines to kick in, until the loop is finished. If you do want a redraw while being in the loop, you have to manually issue it by (e.g.):
button1->Invalidate();
button1->Update();
Please be aware that, if you stay in the loop for too long, windows does recognize that your application is not responding to windows messages and renders it "unresponsive" (window fading to half white). To circumvent this, you can use the Timer class from System::Windows::Forms to implement the delay behaviour.

Is there a tool that computes what happens in a method based on the values of the args passed in?

I'm working on a legacy app that is not just spaghetti, but turns to egg shells when broken (Humpty Dumpty syndrome), where figuring out what is going on as the code meanders around like a drunken sailor in Old Manila is like trying to find a poodle in a smokestack.
As an example, here is a method that I must grok; this is just the first part of it:
private void InitializeBackgroundThread( LoginStatuses loginStatus, string DialogCap )
{
try
{
double pause = 1;
int wait = 250;
ProgressChangedFlag = false;
ProgressChangedIndex = 0;
pc = new PendingCommands( pause, wait );
PendingCommands.ProcessCommands = true;
if (!((loginStatus == LoginStatuses.LoginVendors) || (loginStatus == LoginStatuses.LoginInventory)))
PendingCommands.Processing = false;
PendingCommands.Timeout = false;
Util.StopCancelRequested = false;
if( timeOut != "" )
pc.timeOut = timeOut;
if (!((loginStatus == LoginStatuses.LoginVendors) || (loginStatus == LoginStatuses.LoginInventory)))
{
InitializeBackgroundThread_CCRLoginTerminate (true);
InitializeBackgroundThread_CCRTimerExceeded (true);
InitializeBackgroundThread_CCROnline (true);
}
if (loginStatus == LoginStatuses.LoginVendors)
{
InitializeBackgroundThread_CCRCommandConfirmedGetsites (false);
InitializeBackgroundThread_CCRCommandConfirmed (false);
InitializeBackgroundThread_CCRCommandConfirmedSitesetup (true);
}
else if (loginStatus == LoginStatuses.LoginSitesData)
{
InitializeBackgroundThread_CCRCommandConfirmed (false);
InitializeBackgroundThread_CCRCommandConfirmedSitesetup (false);
InitializeBackgroundThread_CCRCommandConfirmedGetsites (true);
}
else
{
InitializeBackgroundThread_CCRCommandConfirmedSitesetup (false);
InitializeBackgroundThread_CCRCommandConfirmedGetsites (false);
InitializeBackgroundThread_CCRCommandConfirmed (true);
}
InitializeBackgroundThread_CCRProgress (true);
InitializeBackgroundThread_CCRProgressChanged (true);
InitializeBackgroundThread_CCRProgressComm (true);
Now I can "deskcheck" it by going through it with a notepad, asking myself, "Okay, what will happen - which variables will be assigned which values, and which methods will be called - if loginStatus is "AllQuiet"? What if loginStatus is "SNAFU"? Etc. etc. ad nauseum.
Wouldn't it be great if a tool could eat this spaghetti right up and spit out a report such as:
*With a loginStatus of "AllQuiet"
PendingCommands.Processing is set to true.
InitializeBackgroundThread_CCRProgressChanged is called.
...
With a loginStatus of "SNAFU"
(etc.)*
This would be a "killer" debugging/sanity check tool. I know there are code coverage tools, but are there any that are this sophisticated?
This isn't code coverage, which simply tracks what code gets executed if you run a specific test.
What you want is something like a cross between program slicing ("show me everything downstream/upstream from some code point" aka 'a slice' http://en.wikipedia.org/wiki/Program_slicing),
and partial evaluation ("show me what this code looks like if I assume some value is a specific constant" http://en.wikipedia.org/wiki/Partial_evaluation). And you want it to display the result superimposed on top of your actual code (e.g. boldface the selected part) to see your focus.
Yes, that would be wickedly nice tool.
No, I don't know of any. There are program slicers for C and C++ (See http://www.grammatech.com/research/technologies/codesurfer). I don't think they have the partial evaluation part, but I think they do have some other options to minimize the size the slice being inspected.

Visual Studio Shortcutkeys

I was working on a project, and while pressing some shortcut keys, I noticed the status bar of Visual Studio 2010:
Please try some shortcuts yourself to notice the whole behavior of VS, and then...how could I achieve that effect at the same level of performance? Thanks in advance!
P.S. I have the following code block taken from Stack Overlow, that does something like that but not the same performacnce level. My code works for CTRL + K, P.
protected override bool ProcessCmdKey( ref Message msg, Keys keyData )
{
if (prefixSeen)
{
if (keyData == ( Keys.Control | Keys.P))
{
MessageBox.Show( "Got it!" );
keyComb.Text = "Ready";
}
prefixSeen = false;
return true;
}
if (keyData == ( Keys.Control | Keys.K))
{
prefixSeen = true;
keyComb.Text = "CTRL + K was pressed. Waiting for a second chord of keys...";
return true;
}
return base.ProcessCmdKey( ref msg, keyData );
}
But after pressing CTRL + K The label keyComb does not take the value "CTRL + K was pressed. Waiting for a second chord of keys..."
Code taken from: How to get a combination of keys in c#

Cant split left control and right alt in polish language

I setup "polish-programmers" keyboard layout
I try to:
HKL hkl=GetKeyboardLayout(0);
for(unsigned long ch=0x20; ch<=0xff ; ++ch)
{
int v = HIBYTE(VkKeyScanEx(ch,hkl));
if(v==6){
return (GetKeyState(VK_CONTROL) & 0x8000) &&(GetKeyState(VK_RMENU) & 0x8000);
}
}
return false;
I made test with GetKeyboardState - same result: always left control have same flags as right alt(altgr)
May be somebody have workaround?

How to put breakpoint in every function of .cpp file?

Is there a macro that does it? Which DTE objects to use?
(This is not quite what you're asking for, but almost:)
You can put a breakpoint on every member function of a class in Visual Studio by bringing up the New Breakpoint dialog and entering:
CMyClass::*
See http://blogs.msdn.com/b/habibh/archive/2009/09/10/class-breakpoint-how-to-set-a-breakpoint-on-a-c-class-in-the-visual-studio-debugger.aspx for more details.
Here's a quick implementation of 1800 INFORMATION's idea:
Sub TemporaryMacro()
DTE.ActiveDocument.Selection.StartOfDocument()
Dim returnValue As vsIncrementalSearchResult
While True
DTE.ActiveDocument.ActiveWindow.Object.ActivePane.IncrementalSearch.StartForward()
returnValue = DTE.ActiveDocument.ActiveWindow.Object.ActivePane.IncrementalSearch.AppendCharAndSearch(AscW("{"))
DTE.ActiveDocument.ActiveWindow.Object.ActivePane.IncrementalSearch.Exit()
If Not (returnValue = vsIncrementalSearchResult.vsIncrementalSearchResultFound) Then
Return
End If
DTE.ExecuteCommand("Debug.ToggleBreakpoint")
DTE.ExecuteCommand("Edit.GotoBrace")
DTE.ActiveDocument.Selection.CharRight()
End While
End Sub
I don't know what DTE functions to use, but you could very simply record a macro that could pretty much do it:
Go to the top of the file
ctrl - shift - R (start recording)
ctrl - I (incremental search)
{ (search for the first { character).
F9 (set breakpoint)
ctrl - ] (go to matching } character)
ctrl - shift - R (stop recording)
Now just run this over and over (ctrl - shift P repeatedly) until you reach the end of the file.
If you have namespaces, then change 4. to:
( (search for "(" at the start of the function definition)
esc (stop incremental search)
ctrl - I (incremental search again)
{ (start of function body)
This kind of thing can be infinitely modified to suit your codebase
Like Constantin's method... This seems like windbg territory.
Since you have the cpp, (even if you didn't you could script something to get by), it should be no problem to use logger part of the debugging tools for windows... it's a very handy tool, shame so few people use it.
logger debug's C/COM/C++ easily, with rich symbolic info, hooks/profiling/flexible instrumentation;
One way to activate Logger is to start CDB or WinDbg and attach to a user-mode target application as usual. Then, use the !logexts.logi or !logexts.loge extension command.
This will insert code at the current breakpoint that will jump off to a routine that loads and initializes Logexts.dll in the target application process. This is referred to as "injecting Logger into the target application."
Here's how something similar could be achieved in WinDbg:
bm mymodule!CSpam::*
This puts breakpoint in every method of class (or namespace) CSpam in module mymodule.
I'm still looking for anything close to this functionality in Visual Studio.
There is a macro, but I tested it only with c#.
Sub BreakAtEveryFunction()
For Each project In DTE.Solution.Projects
SetBreakpointOnEveryFunction(project)
Next project
End Sub
Sub SetBreakpointOnEveryFunction(ByVal project As Project)
Dim cm = project.CodeModel
' Look for all the namespaces and classes in the
' project.
Dim list As List(Of CodeFunction)
list = New List(Of CodeFunction)
Dim ce As CodeElement
For Each ce In cm.CodeElements
If (TypeOf ce Is CodeNamespace) Or (TypeOf ce Is CodeClass) Then
' Determine whether that namespace or class
' contains other classes.
GetClass(ce, list)
End If
Next
For Each cf As CodeFunction In list
DTE.Debugger.Breakpoints.Add(cf.FullName)
Next
End Sub
Sub GetClass(ByVal ct As CodeElement, ByRef list As List(Of CodeFunction))
' Determine whether there are nested namespaces or classes that
' might contain other classes.
Dim aspace As CodeNamespace
Dim ce As CodeElement
Dim cn As CodeNamespace
Dim cc As CodeClass
Dim elements As CodeElements
If (TypeOf ct Is CodeNamespace) Then
cn = CType(ct, CodeNamespace)
elements = cn.Members
Else
cc = CType(ct, CodeClass)
elements = cc.Members
End If
Try
For Each ce In elements
If (TypeOf ce Is CodeNamespace) Or (TypeOf ce Is CodeClass) Then
GetClass(ce, list)
End If
If (TypeOf ce Is CodeFunction) Then
list.Add(ce)
End If
Next
Catch
End Try
End Sub
Here's one way to do it (I warn you it is hacky):
EnvDTE.TextSelection textSelection = (EnvDTE.TextSelection)dte.ActiveWindow.Selection;
// I'm sure there's a better way to get the line count than this...
var lines = File.ReadAllLines(dte.ActiveDocument.FullName).Length;
var methods = new List<CodeElement>();
var oldLine = textSelection.AnchorPoint.Line;
var oldLineOffset = textSelection.AnchorPoint.LineCharOffset;
EnvDTE.CodeElement codeElement = null;
for (var i = 0; i < lines; i++)
{
try
{
textSelection.MoveToLineAndOffset(i, 1);
// I'm sure there's a better way to get a code element by point than this...
codeElement = textSelection.ActivePoint.CodeElement[vsCMElement.vsCMElementFunction];
if (codeElement != null)
{
if (!methods.Contains(codeElement))
{
methods.Add(codeElement);
}
}
}
catch
{
//MessageBox.Show("Add error handling here.");
}
}
// Restore cursor position
textSelection.MoveToLineAndOffset(oldLine, oldLineOffset);
// This could be in the for-loop above, but it's here instead just for
// clarity of the two separate jobs; find all methods, then add the
// breakpoints
foreach (var method in methods)
{
dte.Debugger.Breakpoints.Add(
Line: method.StartPoint.Line,
File: dte.ActiveDocument.FullName);
}
Put this at the top of the file:
#define WANT_BREAK_IN_EVERY_FUNCTION
#ifdef WANT_BREAK_IN_EVERY_FUNCTION
#define DEBUG_BREAK DebugBreak();
#else
#define DEBUG_BREAK
#endif
then insert DEBUG_BREAK in the beginning of every function, like this:
void function1()
{
DEBUG_BREAK
// the rest of the function
}
void function2()
{
DEBUG_BREAK
// the rest of the function
}
When you no longer want the debug breaks, comment the line
// #define WANT_BREAK_IN_EVERY_FUNCTION
at the top of the file.

Resources