IPABS 3 Configuration and Build Management Richard Rush
Mar 26, 2015
IPABS 3 Configuration and Build Management
Richard Rush
2
IPABS 3 Configuration and Build Management
Web.config Management
Installer extension
Build automation
Version Numbering
Future work
3
Web.config Management
Implemented specifically to avoid the woes of multiple web.configs
Use VisualStudio’s built-in Build Configuration features, as well as pre-compile commands
4
Web.config Management
Each target environment gets its own named Build Configuration.
For IPABS, these are:Debug
Test
UAT
Staging
Release
Each Build Configuration gets a Web.config file, named Web.config.[Build Configuration]
5
Web.config Management
We’re using source control, however, which means Web.config might not always be editable, so first:
attrib -R "$(ProjectDir)Web.config"
Then, we use a pre-compile command to copy the appropriate Web.config.[Build Configuration] over Web.config
"$(ProjectDir)utils\CopyIfDifferent.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config“
6
CopyIfDifferent.bat
@echo offecho Comparing two files: %1 with %2
if not exist %1 goto File1NotFoundif not exist %2 goto File2NotFound
fc %1 %2 if %ERRORLEVEL%==0 GOTO NoCopy
echo Files are not the same. Copying %1 over %2copy %1 %2 /y & goto END
:NoCopyecho Files are the same. Did nothinggoto END
:File1NotFoundecho %1 not found.goto END
:File2NotFoundcopy %1 %2 /ygoto END
:ENDecho Done.
7
Pre-build events
8
Installer Extension
Automate tedious, repetitive tasks
Produce a more professional looking product
Enable non-developers to deploy the application
9
Example: Web.config Encryption
Encrypt sections of Web.configAppSettings
ConnectionStrings
Previously done with a batch file
aspnet_regiis -pe "appSettings" -app "/IPABS3"aspnet_regiis -pe "connectionStrings" -app "/IPABS3"
Now done as part of the installation process
10
Extending the Installer
1. Add the custom actions to the installer project
2. Add new dialogs to the installer user interface
3. Provide parameters you need to the custom actions
4. Define the custom Installer class
5. Override the action methods
11
View → Custom Actions
12
User Interface → Add Dialog
13
View → User Interface
14
Encrypt Web.Config Dialog
15
Custom Action Parameters
Follow the format ‘/ParameterName=“ParameterValue”’
16
Custom Action Parameters
The parameters to the custom Commit action are:
/targetvdir="[TARGETVDIR]" /EncryptAppSettingsCheckbox="[ENCRYPTAPPSETTINGSCHECKBOX]" /EncryptConnectionStringsCheckbox="[ENCRYPTCONNECTIONSTRINGSCHECKBOX]"
These values are being pulled from the Installer configuration and Installer UI controls.
17
Custom Installer Actions
Define an Installer classInherit from System.Configuration.Install[RunInstaller(true)]
Implement the custom action behaviorpublic override void Commit(IDictionary savedState) { }
Call the base implementationbase.Commit(savedState);
Access Installer dataEncryptWebConfig(Context.Parameters["TargetVDir"]);
18
Example: Custom Installer Actions
using System.Configuration.Install;
namespace PPC.Ipabs {
/// <summary> /// Custom IPABS Web Application Installer /// </summary> [RunInstaller(true)] public partial class IpabsInstaller : Installer {
/// <summary>/// Handles the Commit action for IPABS 3/// </summary>/// <param name="savedState">State Dictionary</param>public override void Commit(IDictionary savedState) {
base.Commit(savedState);
try { EncryptWebConfig(Context.Parameters["TargetVDir"]); } catch (Exception ex) { // Handle the exception! }
}
}
19
Example: Encrypting Web.config
/// <summary>/// Encrypts the Web.config/// </summary>/// <param name="applicationName">Application to encrypt the Web.config for</param>private void EncryptWebConfig(string applicationName) { bool encryptConnectionStrings; Configuration configuration;
// Get the installer encryptConnectionStrings =
Convert.ToBoolean((int)Context.Parameters["EncryptConnectionStringsCheckbox"]); configuration = WebConfigurationManager.OpenWebConfiguration("/"+ applicationName);
// Protect the ConnectionStrings section if (encryptConnectionStrings && !
configuration.ConnectionStrings.SectionInformation.IsProtected) { configuration.ConnectionStrings.SectionInformation.ProtectSection(String.Empty); }
// Save the configuration try { configuration.Save(); } catch (Exception ex) { //TODO: Handle the exception! }
}
20
Build Automation
Done to avoid tedious, repetitive tasks
Produce a build for each configuration simultaneously
Currently done with a batch file
21
BuildAllConfigurations.bat
Called with the format:
BuildAllConfigurations InstallProjectName BuildConfigurationName[,BuildConfigurationName+]
So:
BuildAllConfigurations IPABS Debug,Test,UAT,Release
22
BuildAllConfigurations.bat Pseudocode
1. Load the VisualStudio 2005 environment variables
2. Determine the timestamp
3. Clean the solution
4. Build each specified configuration
:PERFORM_BUILDIF (%1)==() GOTO DONE_BUILDINGECHO Building %1...RMDIR /S /Q %1DEVENV %ProjectName%.vdproj /build %1COPY /Y "%1\%ProjectName%.msi" "Builds\%date% %ProjectName%\%1 %date%
%ProjectName%.msi"ECHO Done building %1...SHIFT
GOTO PERFORM_BUILD:DONE_BUILDING
23
BuildAllConfigurations.bat Results
24
Version Numbering
Version numbers are attributes of an assembly
Can be accessed at runtime through reflection
Can be significant when referencing external libraries
Useful for tracking features (versioning? crazy talk!)
25
Version Numbering
Microsoft’s Recommended format:[Major Version].[Minor Version].[Build Number (yyMMdd)].[Revision]
Software Solutions Development’s common library format:[Major Version].[Minor Version].[Build Number (yyMM)].[Revision]
Why the difference?Revision is handled as a short (int16) internally
(int)070101 > 65,535
With the yyMMdd format, anything from 2007 onward is too large
26
Version Numbering
Are set in AssemblyInfo.cs (or AssemblyInfo.vb)Two attributes:
AssemblyVersionCan be automatically incremented
<Assembly: AssemblyVersion("1.0.0.*")>
Displayed in the Properties Screen of the .dll
AssemblyFileVersionCannot be automatically incremented
<Assembly: AssemblyFileVersion("1.0.0802.3")>Displayed in Windows Explorer
27
Version Numbering
We want to use AssemblyFileVersionWe want it automated
Custom MSBuild task: AssemblyInfoTaskDeveloped by the MSBuild team
Source available from GotDotNet
Modified installer assembly with SSD’s version number format
VisualStudio build process does not provide the Build Configuration to its implementation of MSBuild
This will… complicate things
28
Using PPC AssemblyInfoTask
1. Run “PPC AssemblyInfoTask.msi”Select “Install to User’s Application Data folder”
2. Update the project definition file (.csproj or .vbproj) Add a call to the AssemblyInfoTask build task
3. Check out AssemblyInfo.cs (or AssemblyInfo.vb)AssemblyInfoTask will be updating this file
4. Build the library using MSBuild, not VisualStudioSet up the MSBuild external tool
Build using this when building to Release
29
PPC AssemblyInfoTask Installer
30
Update .csproj or .vbproj
<Project>
<!-– Lots of stuff omitted here -->
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- Or, as appropriate: <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> -->
<!-- Here’s where we make the call to the custom build action --> <Import Project="$(APPDATA)\Microsoft\MSBuild\AssemblyInfoTask\
Microsoft.VersionNumber.Targets" Condition=" '$(Configuration)' == 'Release' " />
</Project>
31
External Tools Dialog
Command:Path to MSBuild.exe
Arguments:$(ProjectDir)$(ProjectFileName)/m /p:Configuration=Release
Initial Directory$(ProjectDir)
Use Output window
Prompt for arguments
32
Future Work
Automate source control accessVisual SourceSafe
Team Foundation
Is this as bad an idea as I think it is?
MSBuild automation?Why use DEVENV in the build script when we could use MSBuild?
Custom MSBuild tasks won’t work with DEVENV
.Net Console Application?Why use a .bat file when we could use managed code?
Third Party ToolsWho likes reinventing the wheel?