Projects
Projects are the second type of container used in Visual Studio .NET. Projects are used to maintain the source files associated with individual assemblies, Web sites and services, and applications. As with solutions, Solution Explorer is the primary tool for managing projects in Visual Studio .NET.
Project Items
Projects in Visual Studio .NET consist primarily of file items. These items can be links to files or source files in the same folder as the project file. Whether an item is a link or an actual file depends on the type of project you're working with. The files associated with Visual C++ projects are links displayed in Solution Explorer. It just so happens that these files are usually in the same folder as the projects. Deleting a link to a file in a Visual C++ project doesn't necessarily delete the file that's opened by the link. It's a rather fine distinction, but if you've ever moved a Visual C++ project and found yourself missing a project file, it might be that the file existed outside the project folder. Windows Forms projects can consist of a mix of links and actual file items. Web Forms projects generally contain the actual files in the folder structure that hosts the project file. Table 2-1 shows the possible relationships between project type and file items in Visual Studio .NET 2003.
Project Type | Associated Items |
---|---|
Visual C++ | Links to items |
Visual Basic .NET (Web) | Items in the project folder |
Visual C# .NET (Web) | Items in the project folder |
Visual Basic .NET | Links and actual items |
Visual C# .NET | Links and actual items |
Visual J# | Links and actual items |
Figure 2-5. Links and files in a Visual C# solution

In addition to the items, a project stores the configuration metadata associated with the project. Information stored includes configuration data that you specify in the IDE as well as build and debugging data. The nature of this data differs from project type to project type. All .NET languages compile to Microsoft intermediate language (MSIL), but the compilers themselves are written by different teams, so the available options differ from language to language.
Project Properties
You set the options for a project in the Property Pages dialog box. (In Solution Explorer, right-click on a project and choose Properties from the shortcut menu.) The Property Pages dialog box looks a lot like the Solution Property Pages dialog box we discussed earlier. However, the project Property Pages dialog box has a lot more options that you can configure in a project. Most of these options are settings that you would otherwise have to specify at the command line when compiling a project; these settings match particular command-line options.Between the four major languages that ship with Visual Studio .NET and the different types of projects that you can create, we're talking about a lot of compiler options. This is where project configuration in Visual Studio .NET gets fun. By creating custom project configurations, you can try out a lot of different types of builds and save those configurations for future use and reference.
Saving a Custom Configuration
You can access the Configuration Manager dialog box by clicking the Configuration Manager button in the Property Pages dialog box, or you can enter Build.ConfigurationManager in the Command Window. To create a new project configuration, click the drop-down button adjacent to the desired project in the Configuration column of the Project Contexts grid and then click New. You'll see the New Project Configuration dialog box (shown in Figure 2-6).
Figure 2-6. The New Project Configuration dialog box

Give your new configuration a name, and set the base settings for the configuration by selecting an existing configuration from the Copy Settings From drop-down list. As with the New Solution Configuration dialog box, you can create a new solution configuration automatically to match your new project configuration by selecting the Also Create New Solution Configuration(s) check box. At this point, you should be ready to play with some settings in your project. Just create a new test configuration that you can play with and leave all the default settings in the two default configurations.Let's look at the different types of projects and some of the settings you can configure in each.
Managed Application Projects
Managed applications, such as Visual Basic .NET, Visual C#, and Visual J#, all use somewhat similar layouts in the Property Pages dialog box. Different folders are available depending on whether you're creating a Windows Forms application or a Web Forms application.
Common Properties
Figure 2-7 shows the General page for a Visual Basic .NET Windows Forms application that's located in the Common Properties folder. This page is different from the General page in the Configuration Properties folder. Notice that the Configuration combo box, Platform combo box, and Configuration Manager button are all unavailable when items from the Common Properties folder are open. You can't save these settings separately when you save a new build type. The settings in this folder set properties such as Assembly Name, Output Type, and Namespace. Other Common Properties settings include Page Layout, which lets you specify either a Flow or Grid type layout for your Web Forms and Windows Forms applications; Target Schema, which lets you specify the level and type of Web browser that your application will be compatible with; and the Scripting Language for your application.
Figure 2-7. The General page in the General folder for a Visual Basic .NET Windows Forms application

Contrast this dialog box style with that shown in Figure 2-8, which shows the General page for a Visual C# Web Forms application. The Visual Basic .NET page uses controls to configure the same types of settings that are set in Visual C# using a grid.
Figure 2-8. The General page for a Visual C# Windows Forms application

These two types of property page styles are consistent for each language. Even though these page types are visually different, they provide access to the same kinds of settings.
Configuration Properties
The Configuration Properties folder for a project is the place where you can play with settings and save them out in separate build types. You can easily create and save new build types for almost any kind of Visual Studio .NET project and compile them from inside the IDE or from the command line, as we'll show you in Chapter 15.In this section, we'll point out a few of the important Configuration Properties settings in the Property Pages dialog box for Visual C# projects. You can get to most of these settings in a Visual Basic .NET Property Pages dialog box as well, but we're using Visual C# because the grid style for these pages makes them a little more concise.Figure 2-9 shows the Build page from the Configuration Properties folder for a Visual C# project. You can save any of these settings to a custom build type. One of the most useful settings for configuring for a custom build type is the Output Path. The default output path for a Visual C# Debug build is \bin\Debug\. The release build is \bin\Release\ by default. When you create a custom build type, you get one of these two paths, depending on which type of build you get your initial settings from. If you're creating a custom build, it might make sense to copy the output of that build to a new folder so you can compare the output assemblies. For cases like this, you can create a new build path to match your build name. For example, if you have a build named DebugOverflow (to indicate that you've enabled overflow checks for this build type), you can change the output to \bin\DebugOverflow.
Figure 2-9. The Build page for a Visual C# Windows Forms application

The Debugging page, shown in Figure 2-10, can be especially useful when you're building class library, Web Forms, and XML Web services projects. You can play with a lot of settings on this page, but one of the most useful to our discussion is the Start URL option. Using different build types, you can specify particular URLs that you want to test your XML Web service against. You can use the Start Application option in the same way to test your libraries. It lets you easily debug your service or library against a number of test applications.
Figure 2-10. The Debugging page for a Web Forms application

Command-Line SettingsOne setting I often use custom builds for is Command Line Arguments. By creating a custom build type and setting a command-line argument for that build type, I can save a lot of time that I'd normally spend fiddling with scripts and the command shell. This setting came in handy when I was tech-editing a security book and needed to test a number of different strings in buffer overrun scenarios. By creating three or four different build configurations, I was able to quickly debug and test applications using different command-line arguments. Most important, I was able to create these build types, move on to something else for a while, and come right back to the security project and get straight into it because I had already saved all my test scenarios as custom builds. |
Figure 2-11. The Advanced page for a Web Forms application

Visual C++ Projects
The Property Pages dialog box for Visual C++ projects has a huge number of settings because of the large number of compile and link options available. The custom build options that we've talked about in this chapter apply to Visual C++ as well. In fact, because of the many properties available, you should find custom settings for unmanaged projects very useful, especially in testing and teaching scenarios.Figure 2-12 shows the Property Pages dialog box for a Visual C++ Win32 project. You should notice right away that there's only one root folder in the folder list on the left. Everything in that folder can be customized and saved in a unique project configuration.
Figure 2-12. A custom configuration in Visual C++

The Property Pages dialog box for a Visual C++ project has a number of subfolders under the Configuration Properties folder. Table 2-2 contains a list of these folders and the general property types that you can set from each.
Subfolder | Properties |
---|---|
C/C++ | Compiler options, preprocessor definitions, paths to some output files, and command-line compile options |
Linker | Link options, debug options, and command-line link options |
Resources | Resource filename and path, culture, and resource compiler command line |
MIDL | Microsoft Interface Definition Language (MIDL) compiler options, output paths, and compiler command line |
Browse Information | Options relating to BSCMAKE (browser files) |
Build Events | Commands that you can run during the build process |
Custom Build Step | Properties for configuring an additional task you specify when building a file or a project. For example, you might pass an input file to a tool that returns an output file. |
Web References | Properties that determine how an XML Web service proxy class will be created when you reference an XML Web service in your project |
Web Deployment | Specifies how a Web deployment tool will install your application |
Figure 2-13. Build events let you run applications during your build process.

Lab: Adding a Build EventThis is sort of a homework scenario, but I still find this kind of build trick useful when I'm playing around with code. Let's say you're working on some problems in C and you want to open the folder in which you've built your new file. You could add a new tool to the Tools menu in Visual Studio .NET that would let you open Windows Explorer to the current project's build folder. (You should add such a tool because it's an easy way to get a folder where you want it.) But let's be really lazy and create a post-build event that launches Explorer.exe to the folder where our build is being placed:Create a custom build called PostExplorer.Add the following Command Line to the Post-Build Event: Rebuild your project. You'll see the build process take place normally. After the build is finished, you should see Windows Explorer open to your target folder. You can now double-click the executable to run it, examine the files created in the build, and read the BuildLog file. |
Macro | Description |
---|---|
$(ConfigurationName) | Current project configuration |
$(DevEnvDir) | Visual Studio .NET installation folder |
$(FrameworkDir) | .NET Framework installation folder |
$(FrameworkSDKDir) | .NET Framework SDK installation folder |
$(FrameworkVersion) | .NET Framework version number |
$(Inherit) | Specifies the order of the inherited properties at the command line created by Visual Studio .NET |
$(InputDir) | Input file folder is equivalent to the project file folder |
$(InputExt) | Extension of the input file |
$(InputFileName) | Name of the input file (name + extension) |
$(InputName) | Input filename |
$(InputPath) | Input file path |
$(IntDir) | Intermediate file path |
$(NoInherit) | Forces properties to not be inherited |
$(OutDir) | Output folder |
$(PlatformName) | Name of the project platform, usually Win32 or .NET |
$(ProjectDir) | Folder containing the project files |
$(ProjectExt) | Extension of the project (.vcproj) |
$(ProjectFileName) | Full name of the project (CPPWin32.vcproj) |
$(ProjectName) | Name of the project (CPPWin32) |
$(ProjectPath) | Full path to the project file |
$(RemoteMachine) | Remote machine (when debugging remotely) |
$(SolutionDir) | Folder containing the solution file |
$(SolutionExt) | Extension of the solution file (.sln) |
$(SolutionFileName) | Full name of the solution (Chapter02.sln) |
$(SolutionName) | Name of the solution (Chapter02) |
$(SolutionPath) | Full path to the solution file |
$(TargetDir) | Output folder for the project |
$(TargetExt) | Extension of the output target (.exe) |
$(TargetFileName) | Target filename (CPPWin32.exe) |
$(TargetName) | Name of the target (CPPWin32) |
$(TargetPath) | Full path to the target |
$(VCInstallDir) | Visual C++ .NET installation folder |
$(VSInstallDir) | Visual Studio .NET installation folder |
Project Source Files
Project source files have different extensions, based on the language specific to the project. The extensions and the project types that they hold are listed in Table 2-4. Adding languages developed by Visual Studio Integration Program (VSIP) vendors adds new project types.
Project Type | Extension |
---|---|
Visual Basic .NET | .vbproj |
Visual C# | .csproj |
Visual C++ | .vcproj |
Visual J# | .vjproj |
Deployment | .vdproj |
Listing 2-2 An example project file
CSWinApp.csproj
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.10.2215"
SchemaVersion = "2.0"
ProjectGuid = "{9DC32270-2155-414F-9BE5-C593ADE47FFD}"
>
<Build>
<Settings
ApplicationIcon = "App.ico"
AssemblyKeyContainerName = "
AssemblyName = "CSWinApp"
AssemblyOriginatorKeyFile = "
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "WinExe"
PreBuildEvent = "
PostBuildEvent = "
RootNamespace = "CSWinApp"
RunPostBuildEvent = "OnBuildSuccess"
StartupObject = "
>
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = "
DefineConstants = "DEBUG;TRACE"
DocumentationFile = "
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
NoStdLib = "false"
NoWarn = "
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Release"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = "
DefineConstants = "TRACE"
DocumentationFile = "
DebugSymbols = "false"
FileAlignment = "4096"
IncrementalBuild = "false"
NoStdLib = "false"
NoWarn = "
Optimize = "true"
OutputPath = "bin\Release\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Debug1"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "true"
ConfigurationOverrideFile = "
DefineConstants = "DEBUG;TRACE"
DocumentationFile = "
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
NoStdLib = "false"
NoWarn = "
Optimize = "false"
OutputPath = "bin\Debug\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "true"
WarningLevel = "3"
/>
</Settings>
<References>
<Reference
Name = "System"
AssemblyName = "System"
HintPath =
"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
/>
<Reference
Name = "System.Data"
AssemblyName = "System.Data"
HintPath =
"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
/>
<Reference
Name = "System.Drawing"
AssemblyName = "System.Drawing"
HintPath =
"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll"
/>
<Reference
Name = "System.Windows.Forms"
AssemblyName = "System.Windows.Forms"
HintPath =
"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Windows.Forms.dll"
/>
<Reference
Name = "System.XML"
AssemblyName = "System.Xml"
HintPath =
"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
/>
</References>
</Build>
<Files>
<Include>
<File
RelPath = "App.ico"
BuildAction = "Content"
/>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Form1.cs"
SubType = "Form"
BuildAction = "Compile"
/>
<File
RelPath = "Form1.resx"
DependentUpon = "Form1.cs"
BuildAction = "EmbeddedResource"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>
Visual Basic .NET, Visual C#, and Visual J# projects also contain user option files. These files take the form ProjectName.ProjectExt.user.A Visual Basic .NET user options file has the extension .vbroj.user. These project user files are in XML and contain information specific to the custom builds that you've created. The Visual C# project user file in Listing 2-3 is matched to the .csproj file from Listing 2-2. Notice that there's an extra configuration named Debug1. This is a custom configuration that was added to the project during development. Unlike the binary .suo file, the .user files are intrinsic to the custom build and should usually be kept with a project.
Listing 2-3 An example project user options file
CSWinApp.csproj.user
<VisualStudioProject>
<CSHARP LastOpenVersion = "7.10.2215" >
<Build>
<Settings ReferencePath = " >
<Config
Name = "Debug"
EnableASPDebugging = "false"
EnableASPXDebugging = "false"
EnableUnmanagedDebugging = "false"
EnableSQLServerDebugging = "false"
RemoteDebugEnabled = "false"
RemoteDebugMachine = "
StartAction = "Project"
StartArguments = "
StartPage = "
StartProgram = "
StartURL = "
StartWorkingDirectory = "
StartWithIE = "true"
/>
<Config
Name = "Release"
EnableASPDebugging = "false"
EnableASPXDebugging = "false"
EnableUnmanagedDebugging = "false"
EnableSQLServerDebugging = "false"
RemoteDebugEnabled = "false"
RemoteDebugMachine = "
StartAction = "Project"
StartArguments = "
StartPage = "
StartProgram = "
StartURL = "
StartWorkingDirectory = "
StartWithIE = "false"
/>
<Config
Name = "Debug1"
EnableASPDebugging = "false"
EnableASPXDebugging = "false"
EnableUnmanagedDebugging = "false"
EnableSQLServerDebugging = "false"
RemoteDebugEnabled = "false"
RemoteDebugMachine = "
StartAction = "Project"
StartArguments = "
StartPage = "
StartProgram = "
StartURL = "
StartWorkingDirectory = "
StartWithIE = "true"
/>
</Settings>
</Build>
<OtherProjectSettings
CopyProjectDestinationFolder = "
CopyProjectUncPath = "
CopyProjectOption = "0"
ProjectView = "ProjectFiles"
ProjectTrust = "0"
/>
</CSHARP>
</VisualStudioProject>
Project Dependencies
If you're building complex solutions that contain a number of assemblies with interproject dependencies, you can take advantage of Solution Explorer to help you manage these dependencies. Solution Explorer makes it really easy to add file, project, and Web references to your projects. For solutions with dependencies between projects, you'll want to use project references.To add a project reference, open the Add Reference dialog box by selecting a project in Solution Explorer and entering Project.AddReference in the Command Window. On the Projects tab, you'll see a list of the projects in your solution, as shown in Figure 2-14.
Figure 2-14. Adding a project reference to a project in a solution

After you add a project reference, the functionality available from the referenced project becomes available to the project adding the reference. At this point, build order becomes important because the referenced assembly must be built before the project that references it. To help you manage dependencies such as this, Visual Studio .NET provides a Project Dependencies dialog box (Projects.ProjectDependencies), as shown in Figure 2-15. This dialog box lets you specify a dependency, and it then changes the build order of affected projects in a solution accordingly. The dialog box was updated automatically with the dependency information when we added the project dependency. (If we had added the output of this project as a standard dependency, Visual Studio .NET wouldn't have changed this option for us.) Once the dependency was specified, the XML Web service we referenced was added to the top of the build list on the Build Order page.
Figure 2-15. Configuring build dependencies for a project
