Jesper Niedermann's .NET Blog
about .NET and related technologies RSS 2.0
# Sunday, 24 July 2011

When we were to publish a free version of our new Windows Phone Game Photo Challenge I wanted to maintain both the free and paid version in the same Repository. I wanted the solution file and project file for the new free app to use the same source files as the paid app. This gave some headaches because there needs to be a physical WMAppManifest.xml file for each App. I googled various approaches but I finally made up an entirely different approach which I thought fitted our project best. Here is the steps I took:

  • Copied the solution file PhotoChallenge.sln to PhotoChallengeFree.sln – placed in the same folder
  • Copied the project file PhotoChallenge.csproj to PhotoChallengeFree.csproj – placed in the same folder
  • Changed PhotoChallengeFree.sln via notepad to refer to PhotoChallengeFree.csproj
  • Copied AssemblyInfo.cs to two new folders. One for the paid app and one for the free app.
  • Deleted AssemblyInfo.cs from both PhotoChallenge.csproj and PhotoChallengeFree.csproj
  • From PhotoChallenge.csproj I linked to the new Paid version of AssemblyInfo.cs – using Add –> Existing File, but choosing Add As Link instead of Add.
  • The same in PhotoChallengeFree.csproj. But this time linking to the Free version of AssemblyInfo.cs
  • Changed the following properties in the free version of AssemblyInfo.cs: AssemblyTitle, AssemblyProduct and Guid.

I actually wanted to manipulate WMAppManifest.xml in the same way as I did AssemblyInfo.cs. But this turned out to be impossible. The WMAppManifest.xml file has to be physical – not a link. Instead I did this:

  • Made a project folder in PhotoChallenge.csproj called PropertiesPaid
  • Made a project folder in PhotoChallengeFree.csproj called PropertiesFree
  • Copied WMAppManifest.xml to the new folders and added the relevant one to each project.
  • Deleted WMAppManifest.xml from the properties folder.
  • Opened the project files in Notepad (actually I chose “Unload Project” in Visual Studio and then “Edit PhotoChallenge.csproj”). And changed this:
<XnaWindowsPhoneManifestTemplate>Properties\WMAppManifest.xml</XnaWindowsPhoneManifestTemplate>

To this:

<XnaWindowsPhoneManifestTemplate>PropertiesPaid\WMAppManifest.xml</XnaWindowsPhoneManifestTemplate>

Then I reloaded the project in Visual Studio, and did the same for the free project. But now refering to the PropertiesFree folder.

In the free version of WMAppManifest.xml I changed the Title and TokenId to match the AssemblyTitle and AssemblyProduct of AssemblyInfo.cs. Furthermore I changed the ProductId to match the Guid of the AssemblyInfo.cs.

The actual differences between the free and paid version in the source file I maintain using a new compilation symbol I made called “FREE” so I can make statements like this:

#if FREE
//Some code
#endif

Altogether my approach seems to work extremely well to minimize maintainance of the two versions of the same app.

One small problem: For some reason which I have not bothered to find out I cannot use the Compilation symbol Free in the PhotoChallenge.csproj project itself, but I have some other referenced projects where it is no problem. So I just have a class in the referenced project which I can use where ever I have to check if the current version is paid or free:

public static class Edition
{
public static bool IsFree
{
get
{
#if FREE
return true;
#else
return false;
#endif
}
}
}
Sunday, 24 July 2011 19:46:58 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
Visual Studio | Windows Phone 7
# Tuesday, 31 August 2010

The new Guidance Automation Framework GAX 2010 and GAT 2010 which is installed through the Extension Manager in Visual Studio 2010, provides a nicer usability experience compared to the Visual Studio 2008 predecessor. It is installed using the new vsix installer. A vsix install is much nicer than the old msi install since it integrates into Visual Studio. You can uninstall using the Extension Manager and if a new version comes out it should appear on the Updates tab of the extension manager.

Another nice thing is that a generated factory template solution now only consists of one project which itself results in a vsix file. So the installer of your own generated factories will also be vsix files. Nice…

But nicest of all is the fact that it is automatically integrated with the Visual Studio 2010 Experimental Instance (formerly known as Experimental Hive). Before you had to manually edit your recipes to get them to register in the Experimental Hive. But know you just press Ctrl+F5 and the Experimental Instance is automatically launched with your factory installed. It is now almost easy to debug your recipes. :)

But apparently there are few weird bugs in GAX/GAT 2010. One I run into all the time is this error:

Unable to read the project file 'Something.csproj'.

C:\Something\Something\Something.csproj(354,3): The imported project "C:\Microsoft.Practices.RecipeFramework.Build.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.

Which happens when I try to open a Guidance Automation solution.

For some reason the declaration of the variable RecipeFramework in the project file is not provided. This I deal with by editing the Project file by hand and adding a declaration to the end of the first PropertyGroup like this:

 

  <RecipeFrameworkPath>$(DevEnvDir)Extensions\Microsoft patterns and practices\GAX 2010\2.0.20406.0</RecipeFrameworkPath>

After applying this fix I can open the solution.

I have read somewhere that it is important to adhere to the following install order:

    1. Visual Studio 2010 Ultimate or Professional (obviously)
    2. The Visual Studio 2010 SDK
    3. GAX 2010
    4. GAT 2010

And this might be what I have screwed up on the particular machine where I get the error.

Anyway the above mentioned fix works. And overall I am very satisfied with the new improvements in GAX/GAT.

Tuesday, 31 August 2010 17:31:11 (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
.NET | GAX | Tips & Tricks | Visual Studio
# Sunday, 13 June 2010

Imagine that you want to make an extension for Visual Studio 2010 that creates new custom right click menus for the Solution Explorer. Imagine that you could do it by just implementing a good old .NET interface like this:

public class MenuManager : IMenuManager
{
public IEnumerable<IMenuItem> GetMenus(ContextLevels menuForLevel)
{
var menuItems = new List<IMenuItem>();
var menuItem1 = new MenuItem("My Menu1");
menuItems.Add(menuItem1);
var menuItem2 = new MenuItem("My Menu2");
menuItems.Add(menuItem2);
return menuItems;
}

public string MainMenu()
{
return "My Main Menu";
}
}

 

Well it turns out you can. In MME I have helped you do exactly that. No more using the convoluted add-in model of Visual Studio to accomplish this goal. And it is also much simpler than using GAX/GAT (that can do so much more to be fair).

You can easily install MME, either by downloading directly from Codeplex or by installing directly from the Extension Manager in Visual Studio 2010 (you can find it under the Tools menu).

MME does not work for the Express editions of VS.

I also recommend installing the MME MenuManager template which you can also find in the Extension Manager.

At codeplex you can read more about implementing and deploying MME’s and also get further insight on the architecture.

Sunday, 13 June 2010 18:20:02 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
Tools | Visual Studio
# Wednesday, 15 July 2009

Just released version 1.2 of SolZip my convenient tool for Zipping Visual Studio 2008 solutions

The major is a single install for SolZipMME, so you won't have to install ManagedMenuExtensions beforehand.

The release notes are here:

  1. Bug Fix: when multiple projects where referering to the same file it was added to the archive multiple times.
  2. SolZipMME uses SaveFileDialog instead of FolderBrowserDialog for Zip files.
  3. A single file installer for SolZipMME.
  4. Clipboard functionality now works on Vista / Windows Server 2008.
  5. SolZipGuidance changed. The menu will no longer appear on projects that are not C# projects. SolZipMME not changed.
  6. Support for $(SolutionDir) and $(ProjectDir) placeholders added
  7. Now works on Windows Vista even if UAC is not turned off

Enjoy...

Wednesday, 15 July 2009 16:05:27 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
Tools | Visual Studio
# Monday, 29 June 2009

I just released version 1.1 of SolZip which can be downloaded from the download page at the SolZip site.

The new action packed version contains one major improvement, one bug fix, and a few name changes:

  1. Now Source Control bindings for TFS and SCC can be removed from sln and csproj files. The default for all 3 UI's is that the bindings are removed, but you can optionally choose not to remove them. Feel free to contact me if you need bindings from other source control vendors removed.
  2. A bug fixed that made WinZip clients give a warning when unzipping certain archives made by SolZip. The warning was given when there was .. (2 dots) in a path in one of the zipped files.
  3. The Name SunZip.exe for the commandline tool was changed to SolZip.exe. Because SunZip sounded too much like UnZip.
  4. The Name SolutionZipper changed to SolZip everywhere. Except for SolutionZipper.dll which has been changed to SolZipBasis.dll

In the next version I will try to include ManagedMenuExtensions in the install so you won't have to run more than one setup to install SolZipMME.

Enjoy the new version :O)

Monday, 29 June 2009 20:44:48 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
Tools | Visual Studio
# Monday, 15 June 2009

I just released a new codeplex project SolutionZipper which makes it a breeze to zip compress your visual studio solutions and projects. "What's wrong with WinZip you might Ask". Well WinZip has no knowledge of Visual Studio Solutions, which means it will compress everything in the folder, including bin / obj folders and other random debris.

I accomplish the compression by using the following algorithm:

1. Iterate over all items and projects in the sln file and zip each of these.
2. Zip the sln file itself.
3. Iterate over all items in the csproj files and zip each of these. The iteration is done using Linq to Xml of course.
4. Zip the csproj file itself.

As you might have guessed SolutionZipper only works for C# projects, and is only tested with VS2008.

I offer three UI's for SolutionZipper

SunZip - A commandline tool.

 

SolZipMME - Providing Right click menus for Visual Studio 2008 using Managed Menu Extensions .

 

SolZipGuidance - Providing Right click menus for Visual Studio 2008 using Guidance Automation (GAX).

 

For the actual zipping I use the excellent open source framework SharpZipLib.

Monday, 15 June 2009 22:46:31 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
Tools | Visual Studio
# Sunday, 14 June 2009

I was using my codeplex project ManagedMenuExtensions recently when I realized that it threw an Exception, when clicking on a menu attached to a C# project under a solution folder. The reason was that the object which normally contained an EnvDTE.Project when a project was clicked contained null, when this project was contained in a solution folder.

I normally use this code to get at the selected project (m_VSStudio is the DTE object of the current solution):

private UIHierarchyItem SelectedItem
{
get
{
UIHierarchy uiHierarchy = m_VSStudio.ToolWindows.SolutionExplorer;
if(uiHierarchy == null)
return null;

object[] items = uiHierarchy.SelectedItems as object[];
if(items == null || items.Length == 0)
return null;

return items[0] as UIHierarchyItem;
}
}

The SelectedItem.Object of type object now contains a EnvDTE.Solution object if the solution is selected in the solution explorer, and guess what :O) it contains an EnvDTE.Project if a project is selected. It is this SelectedItem.Object that contains null, if the project is contained in a solution folder.

I googled this problem and found others who had the same problem, but none with a solution, so I had to come up with my own. I don't know if this behaviour is by design from Microsoft, or if it is a bug.

My Solution

Normally I would test if a project is selected with this code:

var project = SelectedItem.Object as Project;
if (project != null)
{
//Do something with the project
}

Now I use this code instead:

Project project = GetProject(SelectedItem.Object);
if (project != null)
{
//Do something with the project
}

Where I implemented GetProject(...) as:

private Project GetProject(object selectedItemObject)
{
var project = selectedItemObject as Project;
if (project != null)
return project;

var item = selectedItemObject as ProjectItem;
if (item == null)
return null;

return item.SubProject;
}

Not exactly beautiful, but that is to be expected when playing with Visual Studios AddIn model, and the kind of thing I try to hide in ManagedMenuExtensions. I haven't had a chance to look at Visual Studio 2010 yet, one could hope that they have done a better job of hiding the ugly underlying COM stuff.

 

Anyway, I hope this helps the next person who tries to search for a workaround for this rather weird behaviour.

Sunday, 14 June 2009 18:33:04 (GMT Daylight Time, UTC+01:00)  #    Comments [3] -
.NET | Tips & Tricks | Visual Studio
Archive
<2017 October>
SunMonTueWedThuFriSat
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234
About the author/Disclaimer
I am a software architect with focus on Microsoft Technologies. I have been working with these in different large companies since 1995. I am currently employed at UVdata A/S.
Here is my View Jesper Niedermann's profile on LinkedIn

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

Privacy policy
The privacy policy of this site.

© Copyright 2017
Jesper Niedermann
Sign In
Statistics
Total Posts: 28
This Year: 0
This Month: 0
This Week: 0
Comments: 32
All Content © 2017, Jesper Niedermann
DasBlog theme 'Niedermann' created by Jesper Niedermann, based on 'Business' created by Christoph De Baene (delarou)