Remote Debugging

Recently we’ve been developing an application that runs on a Win7 PC and has a slimmed down version that runs on Win7 Tablets. In our case we’re using the HP Slate. Our development machines are running Win7 and VS2010. The development machines are on our domain while the HP Slates are not. The project has been going for some months now and we’ve been relying heavily on logging using Enterprise Library to know what errors we’re up against. However, we all know that as the complexity of an application increases so does the likelihood that we may log incorrect, useless, or unrelated data. Enter the need for remote debugging. I thought this would be straightforward and easy but I was very much mistaken.

Getting Ready to Remote Debug
I started on the (MSDN http://msdn.microsoft.com/en-us/library/y7f5zaaa.aspx) in the section (How to: Set Up Remote Debugging http://msdn.microsoft.com/en-us/library/bt727f1t.aspx). Here I learned that firewalls and permissions are the first huge hurdle called out by Microsoft. I must say when it comes to limited time firewalls are out. So instead of fighting my way through setting up firewalls to work correctly I just disabled them for all machines involved for this remote debugging session. Later in this same article it tells how to install the software required for the remote machine in order to debug remotely. There is broken link to the download center for the software required, but the optional location is on the VS2010 installation media in the folder (VS Media)\Remote Debugger. Be sure to install the correct version on the remote machine. Instructions for this are in the article.

Running the Remote Debugging Monitor
STOP! Why? Because you really should figure out which users you’re going to use on both the VS2010 host machine and the remote machine before trying to run the Debugging Monitor.
Selecting the Appropriate User Accounts for Remote Debugging
I tried to remote debug at this point and found there is one more piece of information that I was missing. Going back to the list of articles on the (MSDN http://msdn.microsoft.com/en-us/library/y7f5zaaa.aspx) the next important section is (Remote Debugging Across Domains http://msdn.microsoft.com/en-us/library/9y5b4b4f.aspx). This section lists the restrictions relating to user accounts right away. I will copy the first section here for review:
To connect to msvsmon, you must run Visual Studio under the same user account as msvsmon or under an administrator account. (You can also configure msvsmon to accept connections from other users.)
Visual Studio accepts connections from msvsmon if msvsmon is running as a user who can be authenticated on the Visual Studio computer. (The user must have a local account on the Visual Studio computer.)
With these restrictions, remote debugging works in various scenarios, including the following:

  • Two domains without two-way trust.
  • Two computers on a workgroup.
  • One computer on a workgroup, and the other on a domain.
  • Running the Remote debugging monitor (msvsmon) or Visual Studio as a local account.

Therefore, you must have a local user account on each computer, and both accounts must have the same user name and password. If you want to run msvsmon and Visual Studio under different user accounts, you must have two user accounts on each computer.

You can run Visual Studio under a domain account if the domain account has the same name and password as a local account. You must still have local accounts that have the same user name and password on each computer.

End Quote.

We will cover the last part in detail since that is the scenario I was faced with. In simple terms if your domain is named us and the user account is danny (us\danny) then the VS2010 hosting machine must have a local user account named danny with admin privileges with the same password as the us\danny account. Also, the remote machine, in my case the HP Slate, must have a local user account named danny with the same password as the other two danny accounts and must also be an admin on the machine. After all accounts are created and have been accessed for the first time restart all machines and boot the VS2010 hosting machine into the domain account (us\danny) and the remote machine into the local account with the same name as the domain account (machine name\danny).

This essentially means that three(3) accounts named danny must exist: us\danny, vs2010 machine name\danny, and remote machine name\danny and all of them must be admins on their respective boxes and all must use the same password.

Running the Remote Debugger (For Real)
Again returning to the list of articles on the (MSDN http://msdn.microsoft.com/en-us/library/y7f5zaaa.aspx) the next article is (How to: Run the Remote Debugging Monitor http://msdn.microsoft.com/en-us/library/xf8k2h6a.aspx). You have two choices at this point. Run the monitor as needed or run the monitor as a service. Because we will be constantly debugging using the HP Slate I decided to run the monitor as a service which requires a little extra work. You will need to run Local Security Policy. Then under Local Policies\User Rights Assignment there is a policy named Log on as a service that must be granted for the user that will be running the debugging monitor.
Performing a Remote Debug
I’m still struggling with this a little. I cannot figure out how to have VS2010 compile and launch the application I want to debug on the remote machine. Instead copy the compiled project files from the bin\debug folder of your project to the remote machine (I suggest a location easy to access and replace files in). Run the executable on the remote machine then in VS2010 of the hosting machine open the Attach to Process dialog (ctrl + alt + p). There is a drop down name Qualifier that when opened will detect the machine you’re trying to remote debug. Select the remote machine then attach to the process on the remote machine like you would as if the process were on the VS2010 hosting machine.

Thoughts
It only took a few hours to figure this all out. The part that kept killing me was the fact that even after you create a user account if you don’t log on as that user then it will not be available for use. Remote debugging is definitely cool! It helped us figure out quite a few issues in our remote code very quickly. Now that I know how to set up a remote debugging environment I will be using it more often.

Help improve Visual Studio performance

If you get frustrated by mysterious hangs and long-running operations in Visual Studio 2010 (yes ToolBox, I’m looking at you) there’s often not much you can do about it but sit and wait…

Luckily the VS team wants these problems fixed as much as you do (they write their code in VS too) so to help them identify where people are running into these problems they’ve released a new VS Extension called PerfWatson. It sits in the background and polls VS every few seconds to make sure it’s staying responsive. If VS stops responding, the extension gathers up a report of what you were doing and how long the hang lasted and sends it off to be analyzed and hopefully fixed.

The next version of VS is fast approaching, so the earlier data gets in on things to fix, the better. Go get it now at http://visualstudiogallery.msdn.microsoft.com/fa85b17d-3df2-49b1-bee6-71527ffef441?SRC=Home

Visualizing Changes Across TFS Branches

Moving individual changes between different branches isn’t difficult but can quickly become a headache to keep track of when dealing with many branches and changesets. Fortunately Visual Studio 2010 has some great tools to track the path of changes across a set of TFS branches.

To begin we can look at the branch structure to get an idea of how everything is related. This view can be accessed from Source Control Explorer by clicking on a branch (MAIN here) and selecting Branching and Merging->View Hierarchy. From this we can see that there is a MAIN branch with Dev and Release branches off of it, each with their own sub-branches.

image

Now if I want to see the state of a changeset across branches I can right click it in the History and select Track Changeset. Continue reading

Up and Running with GIT and Visual Studio

This is just a quick guide for those on windows using Visual Studio and wanting to start tinkering with GIT. If you want to know why Git is better than (Insert source control management system here), click this link. Or, if you more in the mood to hear why every other source control system in the world sucks, check out this video from Linus Torvalds who wrote GIT.

First, Git is new as of a few years ago and so the tooling support isn’t phenomenal. That being said, you need to start with by installing msysgit:

Obviously, windows version, download, install, all that good stuff. At this point, you could start using Git as this will install the windows command line tools to do so. However, a command line doesn’t completely cut it for me, and if your reading this, your probably not interested in what I’m writing anyways, so why are you here?

Moving on.

Now that the Git command line tools are installed, You’ll want to install GitExtentions, available here:

This will install tooling support into Visual Studio and also install windows explorer shell extensions and puts a few things into the explorer. Once you run it, you’ll quickly notice that your probably missing a diff tool. You can either install KDiff3 or your own diffing tool. Your preference. If you also don’t have a good text editor (Notepad doesn’t count) I recommend also getting Notepad++ and installing that as well.

Go into settings, and setup your settings to look something like this:

You now have GIT installed. Congratulations!

Now what?

Git 101.

Ok, I’m going to assume you’ve already had some experience with a source control management system of some kind or another (svn, tfs, etc…) before I jump into this. First, everything is local. When you start adding other people or services like GitHub, you realize that your local repository is a branch, and merging involves pulling in changes from other branches, but I digress.

Lets start off with a simple hello world project. Go into visual studio, create a new console project, give it a directory and start it up. Now, to create the repository find this little bar and click on the little folder icon that says ‘browse repository’. (Alternatively, you can simply directly select ‘Create new repository’ from the Git menu in visual studio)

Which will open this:

,

From here, select create new repository, if you allowed Visual Studio to create a directory for your project you’ll want to create the repository one directory down since every file in that directory and any sub directory (besides any listed in the .gitignore file) will be source controlled.

On the next page, I recommend clicking on ‘Edit .gitignore’ and copy the recommended list (this will cause git to ignore any files or directories that match this list).

You now have a repository, well on your way to rocking a Git controlled project. Finally, committing files. So go in make your project spit out hello world to the console, and hit commit. You’ll have the following window:

Select all the files in the Working Directory window, click stage, enter a commit message, hit commit, ok, and done! You’ve now made your first commit.

Now, this is something I didn’t understand right off the bat, when you open up this window everything that is different is listed in the working directory changes window, anything that has changed or is different from the previous version that isn’t in the .gitignore file. Now, to commit something, you ‘stage it’ which takes the current version of whatever file you select and puts it in the staging area (this allows you to make sure your only committing what you want to commit, because there’s many cases where you want to break up your commits into subsets of the entire change list) and commit will only commit those files that are in the staging area. If you go back to the ‘browse repository’ you’ll see something like this (I’ve added several commits):

There’s a lot more I could get into, and I may at some point, but this ought to get you on your way, feel free to leave questions in the comments, tell me where something in this post is wrong or outdated and so on.

Happy Git’ing

Visual Studio Installer Projects and “Previous Versions”

I’ve never really taken the time to learn the exact logic the VS installer projects go through when installing a “newer version” of software.  We just had the question come up here again, so I decided to investigate.  There is a ton of information about this online, Google proves that, so here is just my take on boiling it all down to my “cheat sheet”.

InstallerVersionsProductCode_05165EDA

Setup Project – Properties

Version – you should change this to match the version of the new software you’re building the installer for.  When you change it, you get the prompt that you should change the ProductCode.

  • If answer YES, then the ProductCode is changed (UpgradeCode remains the same – this is how it tracks different versions of the SAME software).  Now you have to worry about the RemovePreviousVersions and the file versions of each assembly you’re installing.
  • If answer NO, then the ProductCode is left the same, and users will get the “you must uninstall the existing version” prompt at install time.

The “cheap” way out here is answering NO.  This forces the user to uninstall any previous version and then they run your newest installer.  You are guaranteed (mostly) that all the new files will be laid down since the previous versions have already been removed.

RemovePreviousVersions – If this is True, the installer will first run the “uninstall function” on any previous versions (different ProductCode) of the same software (same UpgradeCode).

  • Uninstall function is pretty nebulous.  It sounds like it’s going to physically uninstall all the files, but it’s really not.   At least since VS2008, it does a “smart file compare”…
  • First let’s assume you’re installing to a new physical location (maybe a “versioned” directory structure).  In this case, the entire directories for old versions will be removed and the newest version will be copied to its specific directory.  That’s kind of a bummer to have versioned directories though (especially if you have data files laying around in that dir)
  • If you’re installing to the same directory as the previous version, then it get’s a bit more hairy.  When the new installer has files of the same name as the previous versions, it COMPARES FILE VERSIONS of those files to decide whether to overwrite or not.  So … you have to be super detailed about updating AssemblyInfo.cs AssemblyFileInfo atttributes on ALL assemblies in your software.  This can get painful if you’ve got many projects/assemblies involved.  If you’re in this boat, you definitely need some kind of build process to auto-increment the versions of all assemblies.

For now, my cop-out answer is to upgrade the installer project Version and answer NO to the prompt (keeps the same ProductCode).  Shift the pain to the user, right?!  🙂

Up next: I’m working on an automated way to update all the AssemblyFileInfo attributes in a whole tree of projects, using the Community MS Build Task called “FileUpdateTask”.  Stay tuned…

Visual Studio – I got my Ctrl+D back!

I know, first thing you’re asking is “What is Ctrl+D”?  It’s a keyboard command I fell in love with back in VS 2005 days – a “light” version of the FIND dialog. 

FindDialog_414BC236I’m assuming everyone knows about Ctrl+F, which brings up the standard FIND dialog.  But in VS 2010 it’s disappointingly slow to present the dialog.  When I’m cutting code, I want to find something NOW, not in a few milliseconds.  🙂   

In the default C# keyboard mapping, Ctrl+D is called “Edit.GotoFindCombo”.  This command puts the cursor in the “Find ComboBox” in the Standard toolbar.  From here, when you hit RETURN, VS will find the text you typed in the ComboBox.  It has the same history as the Find dialog if you want to arrow down to a recent search term.

FindComboBox_6819D876

In a new VS install, I typically create a new custom toolbar that becomes my “main” toolbar, and it combines my favorite commands from all the various toolbars (edit, find, debug, window management, source control, etc). 

A long long time ago, my Ctrl+D functionality stopped working as well.  Hitting that keystroke would not put the cursor up in the Find ComboBox.  The other day I just happened upon the answer.  I can’t remember why, but for some reason I had the Standard toolbar displayed in addition to my custom main one.  When I hit Ctrl+D, the cursor DID go to the Find ComboBox … IN THE STANDARD TOOLBAR!  So all this time, Ctrl+D has been (sort of) working – just going to MY Find ComboBox in my custom toolbar. 

The fix:  I removed the Find ComboBox from the standard toolbar, so now only one exists, in my toolbar, and the keystroke works. 

I know … simple pleasures…

Of course there are other alternatives to FIND via Ctrl+D or Ctrl+F.  There’s Ctrl+F3 which finds based on the text that’s “under” the cursor (or any currently selected text), and there’s Ctrl+I that does an incremental search as you type.  (Still trying to get used to that one – it’s a little disconcerting when I fat finger a key and have to correct the text, all the while the current selection is jumping all over my code.)

One more cool tidbit about the Find ComboBox:  did you know if you have the cursor up there, type a file name of a file in your solution, and hit Ctrl+Shift+G – VS will open the file?!   This is not that big of a deal any longer with R# which has better file navigation features, but kind of fun/handy to quickly open app.config for example.

(As an aside, I HATE how they changed the toolbar customization in VS 2010 – you can no longer drag-n-drop items from one toolbar to the other or from the dialog of all commands.  Instead you have to monkey around in the customize dialog and find/add them manually.)

VS 2010 Setup Project – the Extra Backslash Killed Me

I have a setup project for a Windows service that we wrote some time ago.  At the start of this current dev cycle, I upgraded the solution from VS 2008 to 2010 and went on my merry way to update code for the service (no changes to the installer).  No big deal – all seemed well, … until I tried running the installer.

During install, we prompt for a username which we use to set ACLs on some files and directories.  We do this by calling NTAccount.Translate like so:

SecurityIdentifier serviceAccountSid = (SecurityIdentifier)new NTAccount(serviceAccount).
Translate(typeof(SecurityIdentifier));

The user is prompted to enter their domain & username (i.e. myDomain\dhanan) and we translate that to a SID to set the file & folder permissions.

This all worked fine with the VS 2008-based installer, but then I spent WAY too much time yesterday debugging why it was failing now (exception: Some or all of the identity references could not be translated”.  TFS source control confirmed that there were no source code changes involved other than the upgrade to VS 2010 (which actually did NOTHING to the setup .vdproj project file).  Mysterious, huh?

I finally discovered that the issue was in the value coming from the installation custom dialog edit box where the user enters their domain and username.  That value that gets added to the dictionary coming into the Installer.OnCommitted() method (via CustomActionData set to “/service_account=[EDITB1]” ).

When debugging into the Installer class and inspecting the value for the service_account, it had TWO backslashes in it (i.e.  @"myDomain\\dhanan”), instead of 1 that I typed in as the user!

The lame thing about this is that it only does this in the VS 2010 setup project, not the VS 2008 one.  The only thing I can find online that’s even loosely related is this:  Troubleshooting Setup and Deployment Projects. (Backslash in textbox causes invalid directory or URL exception).  They don’t mention WHY – I’m wondering if it’s the same issue.

So … I now have a hack at the top of the OnCommitted( ) method:

serviceAccount = serviceAccount.Replace( @"\\", @"\" );

Lame, but it works.  Hey MS – please fix this !!

Update

Thanks Rohit for the comment.  Yep, we ended up fixing it that same way.  (and then removed the string replacement code out of the custom actions).  I guess the lesson learned is *always* put quotes around the variables that are coming from custom dialogs.