Click here to Skip to main content
11,648,094 members (58,684 online)
Click here to Skip to main content

Visual Studio Project Manipulations

, 15 Jun 2012 CPOL 28.3K 627 23
Rate this:
Please Sign up or sign in to vote.
This project provides mass manipulation of Visual Studio projects.

Introduction

Visual Studio projects contain all the necessary information to build a .NET assembly. A project may contain source code, resources, user settings, configuration files. The structure of a Visual Studio project is stored in an XML file that adheres to the MSBuild XML schema. The schema is defined in http://msdn.microsoft.com/en-us/library/5dy88c2e.aspx. IT systems often consist of hundreds of Visual Studio projects. There is sometimes a need to make the same modifications across all these projects. With this solution, projects may be checked-out and checked-in through Team Foundation, the OutputPath, and the strong key file may be set using absolute or relative paths, the AssemblyFileVersion may be set, a search and replace may be performed across all project files, and a hierarchical view of the projects may be displayed based on their references. Through this solution several .NET functionalities are demonstrated such as parallel processing with the Parallel.For statement, calling Team Foundation through the Workspace class, reading and writing XML files with XmlDocument, making Regular Expression replacements with the Regex class, displaying a grid with the DataGridView (Windows Forms) class and with the DataGrid (WPF) class, displaying data in XmlDocument with a TreeView (Windows Forms and WPF) control and signing a project with a strong key.

Background

Visual Studio project files have the extension vbproj for Visual Basic projects, and csproj for C# projects. These files have two entries for each of the debug and release configuration for the OutputPath:

<Project ToolsVersion="4.0" DefaultTargets="Build" 
        xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <OutputPath>bin\Debug\</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <OutputPath>bin\Debug\</OutputPath>
  </PropertyGroup>
</Project>

In an IT system with hundreds of project files, there is a need to set the output path to the same folder in all projects. This output path may be absolute (for example, C:\ITSystem1\Runtime) or relative (for example, ..\..\Runtime).

Project files contain references to other assemblies:

<Project ToolsVersion="4.0" DefaultTargets="Build" 
              xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Reference Include="Assembly1">
      <Name>Assembly1</Name>
      <HintPath>C:\ITSystem1\Runtime\Assembly1.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="Assembly2">
      <Name>Assembly2</Name>
      <HintPath>C:\ITSystem1\Runtime\Assembly2.dll</HintPath>
      <Private>False</Private>
    </Reference>
  </ItemGroup>
</Project>

The paths in the element "HintPath" may also be absolute, or relative. Assemblies that are entered into the Global Assembly Cache (GAC) must be strong signed. In older projects, the key file was defined in the AssemblyInfo.vb and AssemblyInfo.cs, respectively:

Visual Basic: <Assembly: AssemblyKeyFile("C:\ITSystem1\Runtime\Key1.snk")>
C#: [assembly: AssemblyKeyFile("C:\ITSystem1\Runtime\Key1.snk")]

The path had to be an absolute path. In Visual Studio 2010, there is a possibility to define a relative path to the key file. The key file is no longer referenced in the AssemblyInfo but in the project file. In Visual Studio, you may right-click on the project, choose the menu item Add/Existing Item, select the strong key file and on the Add button, choose Add As Link. This will add in the project a link to the strong key file. In project properties under tag Signing, you may add the strong key file as the following figure shows:

Project properties Signing tab

The following entries are created in the project file:

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
  <PropertyGroup>
    <AssemblyOriginatorKeyFile>..\Runtime\Key1.snk</AssemblyOriginatorKeyFile>
    <SignAssembly>true</SignAssembly>
  </PropertyGroup>
  <ItemGroup>
    <None Include="..\Runtime\Key1.snk">
      <Link>FTS.snk</Link>
    </None>
  </ItemGroup>
</Project>

Generally, relative paths should be used, so that the entire IT system may be relocated to another folder, and because different branches may exist for development, integration test, UAT test, and production.

AssemblyInfo files have an entry for the file version:

Visual Basic: <Assembly: AssemblyFileVersion("6.0.0.0")>
C#: [Assembly: AssemblyFileVersion("6.0.0.0")]

It is often desired to change this version number to the same value across all projects.

The Solution

There are three Visual Basic projects included in the zip file:

  1. Tests.BL.ProjManip: Contains the logic for several project manipulations. Is signed with a strong key.
  2. Tests.UI.ProjManipWNF: User interface in Windows Forms, references Tests.BL.ProjManip.
  3. Tests.UI.ProjManipWPF: User interface in WPF, references Tests.BL.ProjManip.
All projects are provided with OutputPath, references, and key-file-path as relative paths. With this solution, these paths can be changed to absolute paths, and then the may be changed back to relative paths. You may unzip the source into any folder, for example, D:\ProjManip.

  1. Open ProjManip.sln with Visual Studio 2010, build the solution and close it.
  2. Depending on which client you want to run, double-click the corresponding exe file:
    • Windows Forms: Runtime\Tests.UI.ProjManipWNF.exe
    • WPF: Runtime\Tests.UI.ProjManipWPF.exe
    The following form appears:
    • Windows Forms:

      Main form of Tests.UI.ProjManipWNF project

    • WPF:

      Main form of Tests.UI.ProjManipWPF project

  3. In the combobox "Source folder", set the folder under which all the projects are situated, for example, D:\ProjManip. The combobox provides the last 10 entries. If you use the button to choose the folder, all files under that folder with the extension defined in "File filter", for example, *.vbproj are loaded and displayed on the grid. If you just type in the combobox, choose the menu File/Reload to load the files to the grid. In the "File filter" you may also define *.csproj for C# projects or any files adhering to the MSBuild standard. The WPF version does not have a button to choose the folder, because strange as it is, there is no FolderBrowserDialog in WPF.
  4. Actions operate on the selected items in the grid. In the textbox "Threads" the number of parallel threads may be defined. Each action spawns the number of defined threads, and each thread processes a portion of the selected items. You may choose one of the following actions:
  5. If you use source control of Team Foundation Server
    1. If you want to manipulate project files, choose the menu Tools/Projects/Check out. This will check out all selected projects.
    2. If you want to manipulate AssemblyInfo files, choose the menu Tools/AssemblyInfo/Check out. This will check out all AssemblyInfo files of the selected projects.
  6. If you want to set the AssemblyFileVersion value in the AssemblyInfo files, choose the menu Tools/AssemblyInfo/Set file version. A prompt appears, displaying the AssemblyFileVersion of the first selected AssemblyInfo, which may be changed.

    AssemblyFileVersion input

    Upon accepting the value, the AssemblyFileVersion value is set in all AssemblyInfo files of the selected projects. For example:

    <Assembly: AssemblyFileVersion("1.0.0.1")>
  7. If you want to set the OutputPath in the project files, set the output path in the text box "Output folder", for example, D:\ProjManip\Runtime, and then choose the menu item Tools/Projects/Set output path.
    • If the checkbox "Use relative paths" is not checked, the OutputPath is set as is in the selected projects. For example, in Tests.ClassLibrary1.vbproj and Tests.WindowsApplication1.vbproj, the OutputPath and the references are set as absolute paths. The output for Tests.ClassLibrary1.vbproj:
      <OutputPath>D:\ProjManip\Runtime\</OutputPath>
          <Reference Include="Tests.ClassLibrary1">
            <HintPath>D:\ProjManip\Runtime\Tests.ClassLibrary1.dll\</HintPath>
          </Reference>
    • If the checkbox "Use relative paths" is checked, the OutputPath and all references to other assemblies are changed to relative paths. Note that for the relative paths to become correct, the existing paths must be absolute. The output for Tests.ClassLibrary1.vbproj:
      <OutputPath>..\Runtime\</OutputPath>
          <Reference Include="Tests.ClassLibrary1">
            <HintPath>..\Runtime\Tests.ClassLibrary1.dll\</HintPath>
          </Reference>
  8. If you want to search and replace with Regular Expressions in all projects, choose the menu item Tools/Projects/Search and Replace. This will open a form with two text boxes for the search pattern and the replace string.
    • Windows Forms:

      Search and replace form

    • WPF:

      Search and replace form

    The search and replace values may contain Regular Expressions as defined in Regex.Replace. Upon pressing the button OK, the search and replace is performed across all selected projects. In the example above, the OutputPath will be changed from:

    <OutputPath>..\Runtime\</OutputPath>

    to:

    <OutputPath>..\..\Runtime\</OutputPath>
  9. If you want to set the strong key file in the project files, choose the menu item Tools/Add strong key to projects. This will search for a *.snk file in the folder defined by the textbox "Output folder". This file is then added as a link to the project, and the project is set to be signed by this key file. The key file entry in AssemblyInfo is deleted. Tests.ClassLibrarary1.vbproj will be as follows:
    • Use relative paths checked:
      <PropertyGroup>
          <AssemblyOriginatorKeyFile>..\Runtime\Tests.snk</AssemblyOriginatorKeyFile>
          <SignAssembly>true</SignAssembly>
      </PropertyGroup>
      <ItemGroup>
          <None Include="..\Runtime\Tests.snk">
            <Link>Tests.snk</Link>
          </None>
      </ItemGroup>
    • Use relative paths not checked:
      <PropertyGroup>
          <AssemblyOriginatorKeyFile>D:\ProjManip\Runtime\Tests.snk</AssemblyOriginatorKeyFile>
          <SignAssembly>true</SignAssembly>
      </PropertyGroup>
      <ItemGroup>
          <None Include="D:\ProjManip\Runtime\Tests.snk">
            <Link>Tests.snk</Link>
          </None>
      </ItemGroup>

    The AssemblyInfo file will have no entry for the strong key file.

  10. If you want to set the strong key file in the AssemblyInfo files, choose the menu item Tools/Add strong key to AssemblyInfo. This will search for a *.snk file in the folder defined by the textbox "Output folder". A line for the key file is added to the AssemblyInfo, and the information about the key file is deleted from the project file. The Tests.BL.ProjManip\My Project\AssemblyInfo.vb file will have the following entry:
    <Assembly: AssemblyKeyFile("D:\ProjManip\Runtime\Tests.snk")>

    Tests.BL.ProjManip.vbproj will have no information about the strong key file. The projects Tests.UI.ProjManipWNF and Tests.UI.ProjManipWPF will not be changed, because no entry about a strong key file exists either in the project or in the AssemblyInfo.

  11. When you have finished, you may check-in the projects and AssemblyInfos through Tools/Projects/Check and Tools/AssemblyInfo/Check in, respectively.
  12. If you want to cancel your changes, choose Tools/Projects/Undo check out and Tools/AssemblyInfo/Undo check out, respectively.
  13. You may double click on a grid row to open a project. The development environment defined in the textbox "DevEnv" is used.
  14. To load the references of the projects to memory, choose Tools/Load references. This will read the references of the selected projects and put them into an XmlDocument.
  15. To view the references of the projects in a hierarchical order, right-click on the grid and choose "References". To change back to grid view, right-click on the tree and choose "List view". The hierarchical view looks like in the following figure:
    • Windows Forms:

      References hiererachical view

    • WPF:

      References hiererachical view

  16. To view the projects that reference the selected projects in a hierarchical order, right-click on the grid and choose "Referenced by". To change back to grid view, right-click on the tree and choose "List view". The hierarchical view looks like in the following figure:
    • Windows Forms:

      Referenced by hiererachical view

    • WPF:

      Referenced by hiererachical view

Developing

This section describes how the projects were developed, which elements were constructed visually with the designer of Visual Studio and which elements were coded. The following steps were followed through:
  1. The class library Tests.BL.ProjManip was coded, which contains the logic of the functionality. The output path was set to ..\Runtime and the project was compiled.
  2. Two new UI projects were added:
    1. Tests.UI.ProjManipWNF: Windows Forms Application. Form1.vb was renamed to FormMain.vb.
    2. Tests.UI.ProjManipWPF: WPF Application. MainWindow.xaml was renamed to FormMain.xaml.
    In both projects a reference to ..\Runtime\Tests.BL.ProjManip.dll was added. The output path was set to ..\Runtime and the projects were compiled.
  3. In both projects, a new data source was added:

    Creating a data source

    1. Menu Data/Add New Data Source...
    2. The form Data Source Configuation Wizard is displayed.
    3. The cylinder Object is chosen.
    4. A tree-view showing projects with their data types is displayed.
    5. The dataset ItemsData of project Tests.BL.ProjManip is selected.
    6. Upon clicking finish, the data source is added to the project and may be viewed through menu Data/Show Data Sources.
  4. Creation of grid:
    1. Windows Forms:

      Creation of grid

      In the data sources window, the Items DataTable is shown in a combobox. The item DataGridView is selected and dragged onto form FormMain. A DataSet, BindingSource, DataGridView and a BindingNavigator are created. The BindingNavigator control is not necessary and is deleted. In the designer the following elements are renamed:
      1. ItemsData -> ItemsData1
      2. ItemsBindingSource -> ItemsData1BindingSource
    2. WPF:

      Creation of grid

      In the data sources window, the Items DataTable is shown in a combobox. The item DataGrid is selected and dragged onto form FormMain. A DataGrid control is created and binding code is added to XAML. In XAML code the following elements are renamed:
      1. ItemsData -> ItemsData1
      2. ItemsViewSource -> ItemsViewSource1
  5. Creation of combobox:
    1. Windows Forms:

      Creation of combobox

      In the form designer, the dataset ItemsData1 is copied and pasted which creates the dataset ItemsData2. In the data sources window, the Items DataTable is shown in a combobox. The item Customize... is selected and in the provided Options form the checkbox ComboBox is ticked. The Items DataTable is dragged onto the form. Because there are two datasets, the dialog choose "Data Source Instance" is displayed. The dataset ItemsData2 is selected, and a BindingSource and a ComboBox are created. In the designer the following elements are renamed:
      1. ItemsBindingSource -> ItemsData2BindingSource
      2. ItemsComboBox -> ComboBoxItemType
    2. WPF:

      Creation of combobox

      In the data sources window, the Items DataTable is shown in a combobox. The item ComboBox is selected and dragged onto form FormMain. A ComboBox control is created and binding code is added to XAML. In XAML the following modifications are done:
      1. Under the element <Window.Resources/> the following is added:
        <my:ItemsData x:Key="ItemsData2" /> <CollectionViewSource x:Key="ItemsViewSource2" Source="{Binding Path=Items, Source={StaticResource ItemsData2}}" />
      2. The ComboBox element is changed to:
        <ComboBox ItemsSource="{Binding Source={StaticResource ItemsViewSource2}}" SelectedValuePath="Items_Id" DisplayMemberPath="Name"/>
  6. Layout:
    1. Windows Forms: The rest of the controls are added from the toolbox. They are arranged with absolute coordinates on the form. For correct behaviour when the form is resized, the Anchor property of the controls is set.
    2. WPF: To the laytout Grid are added 6 columns and 7 rows. The rest of the controls are added to the layout Grid, by specifying the row, column, row span and column span.

History

Revisions:
  1. Path changes absolute and relative, check-out, check-in, strong key, assembly file version, search and replace.
  2. Added References hiererachical view.
  3. Corrected donwload size.
  4. Added history
  5. Added Referenced by hiererachical view.
  6. Added WPF version.
  7. Added section Developing.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Alexandros Pappas
Software Developer (Senior)
Greece Greece
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionSetting OutputPath Pin
Anthony Nicholls23-Apr-15 8:39
memberAnthony Nicholls23-Apr-15 8:39 
QuestionGetAssemblyInfo hard coded to .vb files Pin
Richard Collette2-May-13 9:04
memberRichard Collette2-May-13 9:04 
GeneralMy vote of 4 Pin
John Kasra23-Jun-12 3:42
memberJohn Kasra23-Jun-12 3:42 
GeneralSome of the images are missing Pin
Ammar_Ahmad14-Jun-12 11:50
memberAmmar_Ahmad14-Jun-12 11:50 
GeneralRe: Some of the images are missing Pin
Alexandros Pappas14-Jun-12 21:31
memberAlexandros Pappas14-Jun-12 21:31 
GeneralNice Pin
Espen Harlinn14-Jun-12 5:39
mvpEspen Harlinn14-Jun-12 5:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150804.4 | Last Updated 15 Jun 2012
Article Copyright 2012 by Alexandros Pappas
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid