Scott Hanselman

ASP.NET MVC Beta and RC Upgrades - Confirm your Expectations and Version Numbers in Production Environments

May 22, '12 Comments [18] Posted in ASP.NET | ASP.NET MVC
Sponsored By

I was working on an app locally using a daily build (newer than the currently released one) of ASP.NET MVC and deployed it to a host. I noticed this weird CSS issue. See how the text box on the left running on localhost is small and not styled while the one on the right running on the host is the correct width? You can click on the screenshot if you need to see more.

The Local website's textbox is poorly styled while the same app running the host has a correctly-styled textbox

I dug around a little and using the F12 browser developer tools (as well as good old View Source) I noticed the HTML being created was different! My local app was producing one bit of markup, then when I deployed the same app to my host I would get different markup!

Here's the app's markup running locally:

<input class="text-box single-line" data-val="true" 
data-val-date="The field EventDate must be a date."
data-val-required="The EventDate field is required."
id="EventDate" name="EventDate" type="datetime" value="5/29/2012 1:48:23 AM" />

Here's while running on the host:

<input class="text-box single-line" data-val="true" 
data-val-date="The field EventDate must be a date."
data-val-required="The EventDate field is required."
id="EventDate" name="EventDate" type="text" value="5/29/2012 1:48:23 AM" />

I realize I could have made it more obvious for this but I wanted to make the point that it took a second to notice that my standard ASP.NET MVC Helper call...

<div class="editor-field">
@Html.EditorFor(model => model.EventDate)
@Html.ValidationMessageFor(model => model.EventDate)
</div>

...was returning type="text" on the host but type="datetime" on my local machine and that difference was picked up CSS that targeted specific input tags. Weird. Now, EditorFor() can have its behavior overridden with custom files in ~\Shared\EditorTemplates so if there was a DateTime.cshtml in there that would make sense. There wasn't. I wasn't using the very lovely MvcHtml5Templates NuGet package by Scott Kirkland, so that wasn't it.

My spider-sense was telling me this must be a versioning issue but everything looked right. My only explanation was that somehow what was running on the host was different from what was running on my local machine.

I asked around work and Eilon Lipton suggested I run this snippet to check the version of ASP.NET MVC. He's basically saying "Hey, where did this well known type come from?"

public ActionResult ShowVersion()
{
Type t = null;
try
{
t = Type.GetType("System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35");
}
catch (Exception e)
{
Response.Write("Error finding MVC: " + e.ToString());

}
if (t == null)
{
Response.Write("Can't find MVC");
}
else
{
Response.Write("Found MVC at " + t.Assembly.CodeBase + ", IsInGac = " + t.Assembly.GlobalAssemblyCache + "<br>");
var verAttr = t.Assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyFileVersionAttribute), true)[0] as System.Reflection.AssemblyFileVersionAttribute;
Response.Write("Version = " + verAttr.Version + "<br>");

}
return null;
}

Even better, rather than using this code, I can use the MvcDiagnostics NuGet Package and get THIS useful data from Brad Wilson. Hopefully he will update it for ASP.NET MVC 4 although it worked well.

MvcDiagnostics NuGet Package

This package gives you lots of useful information for debugging weird situations.

ASP.NET MVC Diagnostics Utility gives lots of useful data

Anyway, I put the diagnostic code in a controller and ran it and got this (this version is faked):

Found MVC at file:///C:/mysite/bin/System.Web.Mvc.DLL, IsInGac = False
Version = 4.0.77777.0

Hang on, but my local result was this:

Found MVC at file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Web.Mvc/v4.0_4.0.0.0__31bf3856ad364e35/System.Web.Mvc.dll, IsInGac = True
Version = 4.0.99999.0

My local version was newer and was running from the GAC (Global Assembly Cache) but the hosted version was older and running locally. That means I had older ASP.NET MVC files floating around that my project referenced and deployed to the host.

Aside: The specific change that "got" me here was actually the first external contribution accepted to ASP.NET MVC. It's the one that Miguel de Icaza sent a pull request for while I was on stage at DevConnections. The change is to output HTML5 input types for common default data types, like <input type="datetime"> for System.DateTime when using EditorFor().

It took me a moment to remember that I hadn't added the reference to ASP.NET MVC manually but rather via the NuGet Package Manager. This became crystal clear when I used the built-in NuGet Package Visualizer (from Tools | Library Package Manager) to see the package dependency chain:

The ASP.NET NuGet Packages as viewed in a directed graph in the NuGet Package Visualizer

Basically I needed to either update my out of date NuGet packages or add the assembly references manually without NuGet.

Since I was working on a daily build I did it manually. When you update your ASP.NET MVC 4 Beta applications to a newer build (like ASP.NET MVC 4 Release Candidate (whenever that comes out) or the final Release) you'll want to do update all your packages via NuGet and confirm you're getting the versions and behavior you expect. The NuGet Package Visualizer is a hidden gem indeed.

So, a general reminder to folks (and a specific lesson when upgrading between ASP.NET MVC builds):

  • know your version numbers, what you want, what you're referencing.
  • confirm your version numbers in your debug and production environment.
    • Perhaps a health-check page or a runnable Integration Test to assert your assumptions
  • update your NuGet packages keep your references, and thus your ~\bin up to date
  • know where your assemblies are being loaded from (the GAC or locally)

Hope this helps!


Sponsor: I want to thank my friends at DevExpress for sponsoring this week's feed. Take a moment and check out their stuff! Touch-enabled apps require developers to re-think design & user experiences. DevExpress tools help you take on these new challenges using your existing skills & today’s technologies.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Please Learn to Think about Abstractions

May 17, '12 Comments [80] Posted in Musings
Sponsored By

Jeff Atwood wrote a post called Please Don't Learn to Code and Zed Shaw wrote a post called Please Don't Become Anything, Especially Not A Programmer.

My wife lost her wedding ring down the drain. She freaked out and came running declaring that it was lost. Should we call a plumber?

I am not a plumber and I have no interest in being a plumber. While I advocate that folks try to be handy around the house, I choose to put a limit on how much I know about plumbing.

While my wife has an advanced degree in something I don't understand, she also, is not a plumber. As a user of plumbing she has an understandably narrow view of how it works. She turns on the water, a miracle happens, and water comes out of the tap. That water travels about 8 inches and then disappears into the drain never to be seen again. It's the mystery of plumbing as far as she is concerned.

I, on the other hand, have nearly double the understanding of plumbing, as my advanced knowledge extends to the curvey pipey thing under the sink. I think that's the technical term for it. After the curvey pipey thing the series of tubes goes into the wall, and that's where my knowledge ends.

Everything is a layer of abstraction over something else. I push a button on my Prius and the car starts. No need even for a key in the ignition. A hundred plus years of internal combustion abstracted away to a simple push button.

Jeff said:

Please don't advocate learning to code just for the sake of learning how to code.

Zed says:

Never listen to people who try to make beginners feel like losers.

I think everyone should learn how to think and when to dig deeper and should be able to do it in a welcoming and friendly environment.

Learn how to question how things work. Learn that everything new and simple hides something large and complex. We are all standing on the shoulders of giants like Newton, Tesla, Kettering, Berners-Lee, and on and on.

You can choose to live in a world where things just work, or you can choose to dig a little. You don't need to learn to code, you don't need to be an expert in everything but know that you can learn. You can learn a little or a lot. I don't think the Mayor of New York  needs to know how to code, but it'd be nice if he knew a little about DNS and a little about HTTP.

Judge Alsup in the Oracle v. Google case has been learning Java on the side during the case. Recently when a lawyer tried to imply something was a days work and patentable the Judge, armed with his new understanding that ends an a lower level of abstraction declared (via Groklaw):

Judge: We heard the testimony of Mr. Bloch. I couldn't have told you the first thing about Java before this problem. I have done, and still do, a significant amount of programming in other languages. I've written blocks of code like RangeCheck a hundred times before. I could do it, you could do it. The idea that someone would copy that when they could do it themselves just as fast, it was an accident. There's no way you could say that was speeding them along to the marketplace. You're one of the best lawyers in America, how could you even make that kind of argument?

Oracle: I want to come back to RangeCheck.

Judge: RangeCheck! All it does is make sure the numbers you're inputting are within a range, and gives them some sort of exceptional treatment.

The Judge could have remained in the dark, or relied on an expert to interpret for him, but he dug a step deeper and learned some Java. He knows how to think and he applied to remove a layer of abstraction away from the problem facing his court.

I opened the trap under the sink and retrieved the ring. She was thrilled. "I never knew that was under there." Now she does and now we both know a little about plumbing and abstractions. And that's a good thing.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The Floppy Disk means Save, and 14 other old people Icons that don't make sense anymore

May 9, '12 Comments [145] Posted in Musings
Sponsored By

What happens when all the things we based our icons on don't exist anymore? Do they just become, ahem, iconic glyphs whose origins are shrouded in mystery?

Floppy Disk - Save

Save? Save where? You know, down there. Adding the Arrow to the 3.5" floppy makes me smile. Is it pointing to under my desk? What's a floppy? Why not a USB key? Maybe a cloud icon? That will be easy since there is only One Cloud Icon in the world.

Floppy Disks of Various Sizes, 3.5  disksave

Radio Buttons - Mutually Exclusive Choices

Why are they called Radio Buttons? Because my car radio used to have buttons where only one could be pressed at any time.  I miss my 8-track.

AM Radio from Gina Hogan Edwards' Blog  The Shutdown Windows Dialog

Clipboards

Seriously, short of a doctor's office or the DMV when are we coming in contact with clipboards? And why is the clipboard the icon for Paste? Why not Copy? Or "fill out form?

The Paste Icon with a Clipboard

Bookmarks

We used to use smaller flat dead trees to keep our place in between the dead trees we would read from so that we didn't lose our page. No, books didn't "keep our place when we turned them off."

A bookmark in a book

Address Books and Calendars

We would write down all our addresses and phone numbers in a dead tree and carry it around with us. Sometimes we'd manage our calendar that way also. Everything was bound together with metal spiral loops. Let me check my Filofax.

An address book with a spiral binderA calendar with a spiral binder

Voicemail

I assume that the Voicemail icon is supposed to be evocative of reel to reel tapes but it always look like a container of 110 Film. I suspect my voicemail is no longer stored on spooled magnetic tape. No, you've never seen either of these before, young person. #getoffmylawn

iPhone Voicemail IconReel to Reel Tape110 Camera Film

Manila Folder

I suppose the kids use Pee Chees still these days? I use folders because I use the 43 Folders organizational system but I don't see any reason that we couldn't be storing our files in abstract squares rather than folders in the sky.

Manilla Folders in the CloudsManila Folders are where you put thingsManila Folders

 

Handset Phone Icon

The world's most advanced phones include an icon that looks like a phone handset that you haven't touched in 20 years, unless you've used a pay phone recently. (What's that?)

 

iPhone Phone IconAnd old phone handset plugged into an old cell phone

 

Magnifying Glass and Binoculars

At some time in the past the magnifying glass became the "search everywhere" icon, but for some reason binoculars are for searching within a document. This makes no sense as magnifying glasses are for searching things that are near and binoculars imply breadth of search and distance. These two commands should have had their icons reversed!

The Find icon from Word

A magnifiying glass  A black and white icon of binoculars

Envelopes

Soon the envelope itself will go away and the next generation will wonder what this rectangle means and what it has to do with email. We'll still put other arrows and icons on top of these icons to mean reply, forward, delete, and other things. "Daddy, what's a 'stamp'?"

 

Envelope Various Envelopes with arrows superimposed on them

Wrenches and Gears - Setup/Settings

Want to indicate Settings or Setup to a twenty something? Show them a tool they've never used in their lives.

iPhone Settings is a set of gearsScrewdriver and Wrench crossed

Microphones

If you don't know who Johnny Carson is, how could you know that this is a old-style microphone?

Old timey microphone

The Siri icon is an old time radio microphone

Photography

No one under 30 has seen a Polaroid in years but we keep using them for icons. Instagram sold for $1B with an icon whose subtlety was lost on its target audience. "Shake it like a Polaroid picture."

 

Instagram IconStack of Polaroids

Televisions

Does your TV have "rabbit ears?"

A bunch of TVs with CRTs and

Carbon Copies and Blueprints

I'll "cc" you on that email. Last time I made a carbon copy I was using a mimeograph to do it.

Carbon CopyBlueprints and Carbon Copies

 

What other icons do we use while the original inspiration fades into obscurity?

Note: If one of these icons is yours let me know and I'll link to your site. I found all these and haven't been able to attribute all of them.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The Nerd Parent's Guide: When and how to introduce your kids to Star Wars

May 7, '12 Comments [50] Posted in Daddy
Sponsored By

Tiny Baby Boba FettLet me start by saying I'm not a big Star Wars guy. I enjoyed the films when I was growing up (I think I saw the original  (Ep. 4 ANH) in 1980 along with Empire Strikes Back in 1980) but I haven't thought much about them since. That said, I appreciate the films and I like movies in general. Watching movies with my kids (usually Pixar movies) have brought us a lot of shared joy as a family. However, Star Wars are fun and classics and we wanted to share them with our kids in a way that worked for everyone given their age and our parenting style.

TL;DR Version

  • Show Star Wars to your kids when you think they can discuss and analyze the themes appropriate. That might be 5, it might be 10. They're your kids.
    • Don't forget you can skip parts.
  • Show them the movie in 20 minute segments and make it a serial adventure rather than a movie.
  • Show the films in "Machete Order" which is episodes 4,5,2,3,6. This maintains surprises while ending on a high note.
    • Yes, episode 1 is hacked out and not shown. You can show it at the end of it all along with the Clone Wars cartoons and bill them as supplemental material.
  • Consider Harmy's Despecialized Version fan edit or the Star Wars: Revisited fan edit.
  • Make the films an event with crafts and discussion of mythology rather than just dumping in on their little brains.

You Stayed to Read it All Version

We are extremely conscious of our two boys' "screen time." They don't use the computer or play video games and they can watch TV on "show days." Show Days for us are Tues, Friday and Saturday when they can watch 20-30 minutes of TV. That adds up to about 90 minutes of screen time a week. We'd rather they dance around, dig in the dirt and play, which they do very well.

The boys watch Wild Kratts, Super Hero Squad and a few other kids' shows. They are 4 and a half and 6 and a half. Lately the topic - actually more the mythology - of Star Wars has been coming up.

"Daddy, who is Dark Vader? Is he a bad guy? I heard he has a Light Saver."

As both boys are in school it was inevitable that this topic would come up amongst the other kids. We're not ones to give in to peer pressure but in this case the boys seemed extremely interested in the characters, and as an extension the ideas around space, distance, planets, travel and the meta-topic of good vs. evil.

The wife and I were aiming to wait until they were 6 and 8 to watch Star Wars but since the interest was so high we decided to give it a try in a very structured way. Everyone's kids are different. One 10 year old might not like the aliens in the cantina while other person's 5 year old would be fascinated by how they constructed the masks and not believe they were real aliens. Our kids tend to be "makers," and as such are always constructing and deconstructing. They also understand the idea of actors and general movie making having made small films on an iPod touch so here's how we decided as parents to introduce our two boys to Star Wars.

Disclaimer: Everyone's kids are different. I'm not advocating, preaching or suggesting that you should do any of this. If some of it works for you, great, if not or if you disagree, also great. This system worked for us.

Structure and Time

First, I watched the first 1977 Star Wars to refresh my memory about the themes and general tone. We didn't want to put two hyper little people in front of effectively what is an intense two hour chase scene that they wouldn't understand. We also wanted to see if there were some scenes that we wanted to avoid all together.

My favorite site for getting into extreme detail on a film's content is Kids In Mind. I use this site before the boys and I watch anything. In this case Kids In Mind has this to say about Star Wars.

Smoking skeletons are seen; many people are threatened with laser guns and sometimes are actually shot (resulting in some deaths but no blood). An arm is cut off and some blood is seen. A few scuffles and attacks, and a couple of explosions. A man is strangled and a man is lifted by his throat and then his limp body is tossed across a room.

This is an excellent and short summary of the three scenes that concerned me. The arm cut off in the cantina, the skeleton at Luke's house and Vader force-choking people, as well as general lasers and chaos.

We decided that we'd show them the first movie (ep. 4 ANH) in 20 minute sittings. We literally sat down, watched 20 minutes at a time then stopped it. Star Wars IV: A New Hope is 125 minutes long, so about 5 or 6 sittings. It took us two weeks to watch the movie, which was just about right.

We also skipped over the severed arm in the Cantina as it's the only blood shown in the first movie and kinds of stands out in a gross way. We also implied that Luke's Aunt and Uncle ran away and the smoking husk in front of the house was a droid that was caught in the fire. These two small omissions cut out 90% of the violence that we were uncomfortable with. The rest we deal with by showing the movie in chunks as well as using each segment as an opportunity to talk about interesting topics as a family.

Discussion

The benefits of splitting the movie up into two weeks of six segments are many. The most significant benefit given that the audience is children was time for discussion and "cool down." Little boys LOVE action. My boys were concocting crazy scenarios with good guys, bad guys and explosions long before they even knew what a television was. They are hard-wired for action,  but again, two hours of action is too much for our little people. Twenty minute segments gave the boys one effectively interesting action segment and a bunch of expository dialogue.

Each time something interesting happened or something intense happened we would pause the show and say something like "wow, why did Han do that?" This would often turn into a 10 minute discussion between us - and more often between the two boys - debating the merits of one action versus another. It also allowed the kids to connect to the story more than the action. If we got the sense that they weren't understanding the movie we would just stop it and try again in 6-12 months. No joke. There's no point showing a movie to a kid if they aren't going to understand the themes.

In a fast moving films it can be hard to keep track of what's happening and who is who. Stopping every 10 minutes or so for a discussion or a
feigned confused parent question like "Wait, why is that guy mad at that guy? Who are they?" gives the kids a chance to absorb the content as well as good practice in explaining complex plots to adults.

Watching only 20 minutes at a time also took what would have been an intense two hour explosion and turned it into a fun weekly episodic serial with the excitement of "what will happen next?" propelling the boys through the week. More discussions and analysis continued and continues even now. The boys haven talked about good and bad, when to fight and when not to.

Version

There's lots of versions of Star Wars as George Lucas continues to tinker with it. The Special Editions that came out in 1997 included lots of computer graphics tweaks and changes. He continued to make changes in 2004 when Star Wars was released on DVD and again when it was released on 2011 on Blu-Ray.

There have been a number of "fan edits" of Star Wars but one of the highest quality and certainly the most popular is "Harmy's Despecialized Edition." This edition takes nine different sources and merges them together into an excellent fan preservation. The Despecialized HD version is a 720 AVCHD dual-sided DVD9.

Nerd on: You likely know that a DVD can hold about 5 gigs and shows films at 480p (480 horizontal lines of resolution) and a Blu-Ray can hold 25 gigs (or 50 gigs when dual later) and show films at 1080p. There was another interstitial format that is used on dual layer DVDs that can hold almost 9 gigs. The AVCHD (Advanced Video Coding High Definition) format is similar to Blu-Rays (it's a derivative, effectively) and you'll find it in many Camcorders. It originally supported 720p.

You can get the Star Wars Despecialized Edition HD in an AVCHD format for a Dual Layer DVD9. This is a lovely 720p fan edit that is playable on many Blu-Ray Players.  I own the original DVD boxed set as well. You are required to own a legitimate copy in order to watch a fan edit and you must never pay for a fan edit. There's box art and labels you can download to put together your own copies for the home. There's a number of nice YouTube comparison clips showing your choices so you can decide if you care or not about showing a fan-edit. We watched the Harmy Edit and at least *I* appreciated the effort and attention to details.

Movie Ordering

We all watched the movies in the order they came out which is 4,5,6 then 1,2,3. When you're showing the Star Wars movies to a new person you have the advantage to show them the movies in whatever order you like. The most popular and well respected alternate order is Machete Order from Rod Hilton. He recommends showing the movies in this order:

  • 4 - Star Wars: A New Hope
  • 5 - Empire Strikes Back
  • 2 - Attack of The Clones
  • 3 - Revenge of the Sith
  • 6 - Return of the Jedi

You'll notice there is no film #1. That's for a number of reasons, some passionate but others logical and well-reasoned.

Passion:

"Episode I is a failure on every possible level. The acting, writing, directing, and special effects are all atrocious, and the movie is just plain boring. Luckily, George Lucas has done everyone a favor by making the content of Episode I completely irrelevant to the rest of the series. Seriously, think about it for a minute. Name as many things as you can that happen in Episode I and actually help flesh out the story in any subsequent episode."

Logic:

Every character established in Episode I is either killed or removed before it ends (Darth Maul, Qui-Gon, Chancellor Valorum), unimportant (Nute Gunray, Watto), or established better in a later episode (Mace Windu, Darth Sidious). Does it ever matter that Palpatine had an apprentice before Count Dooku? Nope, Darth Maul is killed by the end of Episode I and never referenced again. You may as well just start with the assumption that Dooku was the only apprentice. Does it ever matter that Obi-Wan was being trained by Qui-Gon? Nope, Obi-Wan is well into training Anakin at the start of Episode II, Qui-Gon is completely irrelevant.

Search your feelings, you know it to be true! Episode I doesn’t matter at all.

He goes on to explain not only that Episode #1 doesn't matter but also that the really exciting surprises like who Luke's father is and others are maintained with this order.

Given that our kids are younger, we will stop the series for a while after Attack of the Clones. Episode 3, Revenge of the Sith is super dark and the most physically violent of the films. I want to wait until I feel the boys are ready to internalize that much intensity. I suspect that will be around 10 years or, perhaps older. After that we'll pick up where we left off. You should decide on your own but it's useful to be aware or reminded how dark episode 3 really is.

Conclusion

We've introduced our little people to the Star Wars mythology in a slow and structured way. There's been more talking and playing in the backyard so far than actual movie watching. There's been discussions of movie making and how to make an alien mask. There's been cardboard light sabers and grappling hooks made of straws. There's been hours of discussion about character motivations, why good guys do good stuff, why bad guys do bad stuff and why Han Solo likes money and whether or not we should "mess with Yoda."

Overall, my wife and I are happy with the results. I hope this post helps you and your kids jump into Star Wars. I'm off now to deal with the burning question in our household this week: "Who took Chewbacca's pants?"

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Introducing Workspace Reloader - A Visual Studio AddIn to save your open files across project reloads

May 2, '12 Comments [27] Posted in Open Source | VS2010
Sponsored By

Works on my machineA while back my buddy Sam Saffron (from Stack Overflow and Mini Profiler) complained to me on Skype that he was finding it very irritating that every time he updated his project outside of Visual Studio he would be prompted to "Reload Project" and would lose all his open files because Visual Studio would close them.

This apparently is becoming kind of an issue at Stack Overflow. Since they use distributed source control and often have a dozen or more folks all coding inside the same project they are integrating all the time. They'll be deep into something, update their project to test it and all their open windows close.

It's a weird Visual Studio behavior that I've never understood. Visual Studio saves all your open files and window positions when you close the IDE and restores them when you open your solution. But when you open a project then right click and "Unload Project" you'll lose all your windows. I've reported it as a bug and it's also been voted up at User Voice, visited as a Question at StackOverflow, and a few folks have tweeted about it (The SO guys with their thumbs on the scale, no doubt) and been bugging some folks but then I got the idea to just fix it myself. It'd be a good chance to write my first Visual Studio Add-In, see if this is even possible, and fix an irritant at the same time.

DOWNLOAD: Workspace Reloader Visual Studio Add-in - "This package will reload the code files you had open when your project file was modified and unloaded then reloaded"

Warranty: To be clear this is the smallest of extensions. It only listens to two events and it's only 12k so you have no reason that I know of to be afraid of it. Plus, it works on my machine so you've got that going for you.

Creating a Visual Studio Extension

Developing Visual Studio Extensions requires some patience. It's gotten a lot better with Visual Studio 2010 but back in the 2003-2005 days it was really hairy. There's a number of different kinds of things you can extend. You can add menus, add tool bars, commands, new templates, new kinds of designers and visualizers, as well as use just the shell to create your own IDE.

I wanted to create an add-in with Zero UI. I had no need for buttons or menus, I just wanted to listen to events and act on them. I downloaded the Visual Studio 2010 SDK after reading this blog on extending Visual Studio 2010. Make sure you get the right version. I have Visual Studio 2010 SP1 so I needed the updated Visual Studio 2010 SP1 SDK.

File | New Project | Visual Studio Package

I made a new Visual Studio Package. This builds into a VSIX (which is just a ZIP file - isn't everything?). A VSIX has a manifest (which his just XML - isn't everything?) that you can edit in a GUI or as a text file.

I want my VSIX package to work on Visual Studio 11 Beta as well as Visual Studio 2010  so I added to the SupportedProducts node like this. VSIXs other than templates aren't supported in Express (I keep pushing, though):

<SupportedProducts>
<VisualStudio Version="10.0">
<Edition>Ultimate</Edition>
<Edition>Premium</Edition>
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="11.0">
<Edition>Ultimate</Edition>
<Edition>Premium</Edition>
<Edition>Pro</Edition>
</VisualStudio>
</SupportedProducts>

I also setup the name, version and description in this file. 

I need to decide when my package is going to get loaded. You can add one or more ProvideAutoLoad attributes to a Package class from the VSConstants class. A number of blogs posts say you need to hard code a GUID like this, but they are mistaken. There are constants available.

[ProvideAutoLoad("{ADFC4E64-0397-11D1-9F4E-00A0C911004F}")]

I can have my package automatically load in situations like these:

  • NoSolution   
  • SolutionExists
  • SolutionHasMultipleProjects   
  • SolutionHasSingleProject
  • SolutionBuilding
  • SolutionExistsAndNotBuildingAndNotDebugging
  • SolutionOrProjectUpgrading
  • FullScreenMode

For my package, I need it loaded whenever a "Solution Exists," so I'll use this Constant (in lieu of a hard coded GUID):

[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)]

Next, I wanted to listen to events from the Solution like the unloading and loading of Projects. I started with the IVsSolutionsEvents interface that includes OnBefore, OnAfter and OnQuery for basically everything. Elisha has a simple listener wrapper as an answer on StackOverflow that I modified.

The SolutionEventsListener uses the very useful Package.GetGlobalService to get hold of the solution.

IVsSolution solution = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution;
if (solution != null)
{
solution.AdviseSolutionEvents(this, out solutionEventsCookie);
}

We then sign up to hear about things that might happen to the Solution using the IVsSolutionEvents interfaces and making them look like friendly events.

public event Action OnAfterOpenProject;
public event Action OnQueryUnloadProject;

int IVsSolutionEvents.OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded)
{
OnAfterOpenProject();
return VSConstants.S_OK;
}

int IVsSolutionEvents.OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel)
{
OnQueryUnloadProject();
return VSConstants.S_OK;
}

I want to hear about things just before Unload happens and then act on them After projects Open. I'll save the Document Windows. There's an interface that manages Documents and Windows for the Shell called, confusingly enough IVsUIShellDocumentWindowMgr

I save the windows just before the unload and reopen them just after the project opens. Unfortunately these are COM interfaces so I had to pass in not an IStream but an OLE.IStream so while the ReopenDocumentWindows is easy below...

listener.OnQueryUnloadProject += () =>
{
comStream = SaveDocumentWindowPositions(winmgr);
};
listener.OnAfterOpenProject += () => {
int hr = winmgr.ReopenDocumentWindows(comStream);
comStream = null;
};

The SaveDocumentWindowPositions is more complex, but basically "make a memory stream, save the documents, and seek back to the beginning of the stream."

private IStream SaveDocumentWindowPositions(IVsUIShellDocumentWindowMgr windowsMgr)
{
if (windowsMgr == null)
{
return null;
}
IStream stream;
NativeMethods.CreateStreamOnHGlobal(IntPtr.Zero, true, out stream);
if (stream == null)
{
return null;
}
int hr = windowsMgr.SaveDocumentWindowPositions(0, stream);
if (hr != VSConstants.S_OK)
{
return null;
}

// Move to the beginning of the stream with all this COM fake number crap
LARGE_INTEGER l = new LARGE_INTEGER();
ULARGE_INTEGER[] ul = new ULARGE_INTEGER[1];
ul[0] = new ULARGE_INTEGER();
l.QuadPart = 0;
//Seek to the beginning of the stream
stream.Seek(l, 0, ul);
return stream;
}

If this does it's job you'll never know it's there. You can test it by installing Workspace Reloader, opening a project and opening a few code files. Now, edit the CSProj as a text file (maybe add a space somewhere) and save it. Visual Studio should prompt you to Reload the Project. Workspace Reloader should keep your files and windows open.

I hope this helps a few people. The source is here.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.