Entries in vs2005 (4)

Thursday
Jun152006

VS 2005 Project Subtypes

I’ve had the opportunity lately to work on a project that needed to generate some code for a project based on a given file within the project and then include/add those files to the project for inclusion during build. We spent a good bit of time looking at the various options such as custom MSBuild tasks, add-ins, VSPackages, etc. and finally settled on a Visual Studio Package that implemented a project subtype, a custom project property page, and a custom tool (single-file generator).

The documentation in the VS 2005 SDK continues to improve as does the general toolset. For those of you who aren’t aware, the SDK team has moved to a very aggressive release schedule posting new builds every few months in the CTP/RTM model. Of particular note has been the improvements to the managed package framework - MPF (no, not Microsoft provisioning framework). These improvements have made it possible for non-C++ aficionados such as myself to write some interesting tools fully integrated into the platform.

I used the ProjectSubType sample (installed by default to C:\Program Files\Visual Studio 2005 SDK\2006.04\VisualStudioIntegration\Archive\CS_Samples\ProjectSubtype\ProjectSubtype) provided in the SDK as my guide for much of the features I needed to implement. I encountered a few “gotchas” along the way (thanks to those who lent support) and I am going to document them here for my own sake (easy to find in the future) as well as maybe helping others who find themselves hitting the same issues. In this post I’ll cover a few of the items I hit and I’ll cover some others in subsequent posts.

Creating a project sub-type seemed incredibly easy… simply modify/include the files I wanted in a /templates/projects directory (this really can be anywhere so long as the path is properly registered for your package in the registry) and I was ready to go. The SDK documentation is really pretty clear on this and you will find yourself with a custom project (in my case a flavor of a C# class library) in no time at all.

The first place where things got a little hairy was the custom properties page. I actually took the samples from the ProjectSubType project and had a custom page in no time, however it had one major drawback as it related to my project – the properties it saved were configuration specific (i.e. debug/release) rather than being configuration ambivalent as I wanted. I spent some time fighting through things and finally ended up doing the following…

  1. On my project sub-type (project.cs) I implemented the IPersistXMLFragment interface nearly identically from the SDK sample documents. The only thing I did differently is that I did not pass the request on to other project sub-types (I don’t intend for anyone to sub-type my project).
  2. I created an interface (say IMyCustomProperties) that defined accessors for the properties I wanted to expose and then implemented the interface on my flavored project (project.cs).
  3. The default sample shows (in the implementation of IVsHierarchy) the GetProperty method removing one property page and then adding another. What I learned, is that the case branch in which they remove a property page (__VSHPROPID2.VSHPROPID_PropertyPagesCLSIDList) is actually where you want to add your page if you want it to appear and be configuration independent. As in the following…
protected override int GetProperty(uint itemId, int propId, out object property)
{
switch (propId)
{
case (int)__VSHPROPID2.VSHPROPID_PropertyPagesCLSIDList:
{
// Get the list from the base class
ErrorHandler.ThrowOnFailure(base.GetProperty(itemId, propId,
out property));

// Add our WES Property Page
Debug.Assert(typeof(IPropertyPage).IsAssignableFrom(
typeof(MyPropertyPage)),
"Property page should implement IPropertyPage");

property += ';' + typeof(MyPropertyPage).GUID.ToString("B");
//property = propertyPagesList;
return VSConstants.S_OK;
}
}

return base.GetProperty(itemId, propId, out property);
}



Where MyPropertyPage is a local class that inherits from PropertyPageBase.PropertyPage (provided as shared-source in the SDK).



The item I struggled with for quite some time was the implementation of MyPropertyStore – a class for interacting with the data store and implementing PropertyPageBase.IPropertyStore. The sample project implements this file, however it is once again interacting with configuration-specific data and the way in which it retrieves the main “data object” (casting the data object in the Initialize() method as IVsCfg). NOTE: The Initialize() method is called by the SetDataObjects() method that is implemented in the PropertyPageBase.PropertyPage class. I knew that what I really wanted was to get the IMyCustomProperties interface from my project object so I could access my custom properties. I tried a QueryInterface on the data variable using all sorts of classes and interfaces and was patently unsuccessful until someone pointed me in the correct path… the proper procedure when using project-based properties is to cast the object as an IVsBrowseObject first, and then you can call GetProjectItem to retrieve the IVsHierarchy object, from which you can finally obtain the custom interface you wanted…



 



void PropertyPageBase.IPropertyStore.Initialize(object[] dataObject)
{
// If we are editing multiple configuration at once, we may get multiple objects
foreach (object data in dataObject)
{
if (data is IVsBrowseObject)
{
// get the Browse object…
IVsBrowseObject browse = data as IVsBrowseObject;

// Get the project item…
IVsHierarchy project;
uint count;
browse.GetProjectItem(out project, out count);

// now get/store the IMyCustomProperties object
this.myCustomProperties = (IMyCustomProperties)project;
}
else
{
Debug.WriteLine("Not IVsBrowseObject");
}
}
}



This was the trick that allowed me to finish my implementation of the custom properties page, and to have data read from the .csproj file, displayed in a custom properties tab, edited by the user, and then persisted to the .csproj file.



I’ll eventually post a full sample, but in a follow-up post I’ll illustrate how I was able to read these properties in my custom single file generator.



 



This posting is provided "AS IS" with no warranties, and confers no rights

Tuesday
Jul192005

Writing MPF Schemas is easier now using VS 2005

I know many people do not take the time to include schemas in their MPF named procedures, but I am a big fan.  Here at eQuest, we use these in-line schemas for all sorts of things ranging from auto-generating CHM files to auto-generating strongly-typed C# and XML Web Service wrappers. The problem is, these are a *pain* to write.  I hate writing them, and even worse, they are hard to get accurate.  It is very easy to miss a step, or mis-state a requirement, etc.  It is very easy to duplicate a node, or forget to include a node, etc.

Yesterday I was faced with the need to write a schema for a named procedure I had just written for a client.  Because of some rather unique lab environment issues, I elected to write them directly on my machine, where, I just happened to have VS.NET 2005 Beta 2 installed.

What I found was that VS.NET 2005 includes two features that make the editing of XML and the associated schemas much easier. The first is intellisense.  This is not a surprise, and I had heard that VS 2005 included better support for a wider range of XML namespaces, but I suppose I didn’t really think about it until it “just started working”.  The following is an example of in-line schema intellisense…

schema02

The second feature, and probably cooler feature (from my perspective) is the ability for VS to validate the schema nodes I’m creating relative to the schema nodes I’ve already created.  For example, if I add an <element /> node for a type for which I have not yet defined an <ElementType/>, I will get the appropriate squiggly lines indicating a problem.  The same is true for <attribute/> and <AttributeType/> tags. Also, if I have duplicate <element/> nodes it will complain.  Where this helps me, is that it is often easier (for me, in my limited view of this) to begin by creating the <ElementType /> node for type=executeData and then populating all of the appropriate <element/> nodes.  Then, I can use the validation features of VS to let me know when I have finished implementing the required <ElementType/> nodes.  The following is a screen shot of this validation:

schema01

These are great new features and I’m excited to see how this will speed my development moving forward

(note: yes, I’m aware that XMLSpy does this now, but I’ve simply not been able to get myself into the habit of having two “heavier” apps running to support my coding… I end up using VS for all of it… and I’m also aware that XMLSpy has an add-in for VS… but it changes the XML fonts and styles and that bugs me… oh well…)

Thursday
Apr212005

VisualStudio.Net.2005.Beta2(firstExperience) == Really.Good;

Wow… early this morning was the first time that I was really able to spend some time with the new Visual Studio 2005 beta… and let me join the majority of the blogsphere in saying that I’m quite impressed.  My task today was a simple one… that of converting a primarily content-focused website that I had build using Dreamweaver MX to ASP.NET 2.0.  The following are some general impressions…

1. Vault and the beta work great together…. We are actually running an older version of Vault (2.06) yet it still connected up and worked like a champ… in fact, I was amazed at how fast the source control operations (checkin/out) were compared to RTM version of VS 2003 and the same Vault environment… a very nice start…

2. Project-less websites are great … no more adding files to the solution/project… VS simply “knew” about all of the files in the directories I was working on… it is very nice.

3. Master pages “just work”… As someone who has used the templating feature in Dreamweaver, and has also built an ASP.NET master-pages “engine” (capitalizing heavily on the work of Rob Howard and team, supplemented by Paul Wilson) I wasn’t “amazed” by the master pages feature… I just wanted it to work better/faster than my current tools and hopefully have a better implementation.  I was not disappointed… the Master Pages support was easy, and quick to utilize…. now if only they could get nested master pages to work in the designer…

4. XHTML compliance… finally… Some people probably don’t care so much about standards compliance, but I’ve been working pretty hard lately on some of these sites to make them XHTML compliant… this site in particular had been compliant until I added some ASP.NET controls (text boxes, buttons, validators, etc.).  I moved things over this morning, fired up the page, ran the W3C validator (thanks to the Checky extension for FireFox) and it validated (XHTML Strict) on the first run… very impressive

5. System.Web.Mail is deprecated… most of you all probably knew this already… and yes, I probably have had my head in the sand, but I was surprised when the compiler griped at me this morning about my form that sends mail based on user input… I took some time and without too much work was able to get the form processing code using the System.Net.Mail namespace which seems to be the new “right” way to do it… works like a champ.

I’m very excited… don’t have time to talk about the built-in webserver, or direct FTP support… which is great….  I’ll post more later.

Wednesday
Jun302004

MPS and VS 2005

As a member of the development community, it seems almost requisite to comment on the newly-released Visual Studio 2005 beta 1 products.  I learned of the release while on client site participating in a discovery project for a MPS rollout.  One of the things the client was concerned about was the ability to "drive" the provisioning system from their current *nix-based SOP system.  We had been talking about the web services interface as the most probably interface candidate.  During the meeting I was able to download and install the Visual Web Developer 2005 beta 1, and within a matter of minutes build a web service example on the fly and demonstrate to the customer how his existing systems could call the methods and interact with MPS (I happened to be running a copy of the MPF engine on my laptop making the demonstration complete).  Needless to say, it was easy to keep their attention after such an easy and quick example.

Because this client is looking at providing Windows Hosting solutions, they were very interested in ASP.NET and its capabilities.  I was able to easily build a little web site, add a pagable, sortable, editable data grid in what seemed like less than a minute.  I was thrilled to hear the client's reaction... "Let's see my Linux guys do it that easily and quickly!"

You know... this .NET thing... it may just catch on...