Managing Multiple Configuration File Environments with Pre-Build Events

桃扇骨 2022-07-13 11:11 146阅读 0赞

ScottGu mentioned an idea to me last week that he’d had for managing configuration files like web.config depending on what the current build config is. Bil Simser mentioned one part of this in January and Rob Chartier offered batch file help on a mailing list in June. Since ScottGu is busy Managing Generally (he IS the General Manager) so I said I’d prove the concept for him.

Here’s the general idea. It’s not too hard. I’ll use an ASP.NET Web Site and web.config as an example, but this will work with most any kind of project, exe’s or .dll’s.

1. From Visual Studio, go File | New Project, and select ASP.NET Web Application.
Note: Do NOT “New Web Site” as we want a .csproj and we’re going to use a Pre-Build Event, not supported by Web Sites. I’ve named mine FooFoo.

New Project (2)

2. Right click in the Toolbars and ensure that the “Standard” toolbar is showing. You’ll know if you see a dropdown that says “Debug” next to one that says “Any CPU.”

Click the dropdown and select “Configuration Manager.”

image

You’ll probably have Debug and Release configurations, but you can also make custom ones and base them on existing configuration. In this dialog I’ve made a new “Deploy” and I’ll base it on the “Release” configuration.

WindowClipping (8)

Make sure to create a Solution Configuration AND a Project Configuration, as they are different. Here I’ve made one called Deploy for the Project also. If you get an error message, be aware of the “Create new project configurations” checkbox. You might get a warning if you are making a new configuration and the dialog tries to make another configuration with the same name; uncheck the checkbox if that happens.

deploy

Of course, you can have as many Configurations as you’d like.

3. Add some custom configuration stuff in web.config, like connectionStrings:

  1. <connectionStrings>
  2. <add name="Foo"
  3. connectionString="Data Source=localhost;Initial Catalog=DatabaseName; User Id=sa;Password=debug;"
  4. providerName="System.Data.SqlClient" />
  5. </connectionStrings>

See now I’ve made the password in my nonsense connectionString = “debug”? Now, create three new web.config’s by CTRL-dragging the web.config on top of the project. Name them web.config.debug, web.config.deploy, and web.config.release. Make the password equal to “deploy” and “release” respectively.

WindowClipping (6)

4. Ok, now we’ve got different configuration and different configuration files. Let’s create a batch file called “copyifnewer.bat” and here’s the contents:

  1. @echo off
  2. echo Comparing two files: %1 with %2
  3. if not exist %1 goto File1NotFound
  4. if not exist %2 goto File2NotFound
  5. fc %1 %2
  6. if %ERRORLEVEL%==0 GOTO NoCopy
  7. echo Files are not the same. Copying %1 over %2
  8. copy %1 %2 /y & goto END
  9. :NoCopy
  10. echo Files are the same. Did nothing
  11. goto END
  12. :File1NotFound
  13. echo %1 not found.
  14. goto END
  15. :File2NotFound
  16. copy %1 %2 /y
  17. goto END
  18. :END
  19. echo Done.

Basically this batch file will copy a file over another if the files don’t match. It’s not strictly “copyifnewer” (like, not at all) but it does the job.

Why bother with a batch file to check for changes and not just copy over the file every time? Well, each time you copy over a web.config it restarts all the designers and running AppDomains that are watching that file. No need to copy over a file if it hasn’t changed…everything will churn less.

Put this copyifnewer.bat file in the root of your project.

WindowClipping (10)

Why not use PowerShell? One word - speed. Batch files are fast. Full stop. This is a build, so it needs to be fast.

5. Create a Pre-build Event. Right-click on your Project and select Properties. Click Build Events and in the “Pre-build event command line” and enter this value:

  1. "$(ProjectDir)copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config"

Notice the magic dust, the $(ConfigurationName) project variable, that contains “Debug” or “Release” or “Deploy.”

WindowClipping (9)

6. Build. Now if you build, you’ll see in the Build Output the batch file being run and the files being copied. Because it’s a Pre-Build Event it’ll be seen in both the Build Output in Visual Studio .NET.

When you build within Visual Studio the currently selected item in the drop-down list is the current configuration.

image

The configuration value can also be passed in on the command line when building with MSBUILD.

  1. msbuild FooFoo.sln /p:Configuration=Deploy

Administrator Visual Studio 2008 Beta 2 Command Prompt

And there you go. The connection string in the web.config now contains deployment-specific configuration data.

  1. <connectionStrings configSource="separateConnStrings.config"/>

Bad things are that you’ve got to keep web.config’s in sync if there’s lots of settings, but you could totally break it apart via “include files.”

发表评论

表情:
评论列表 (有 0 条评论,146人围观)

还没有评论,来说两句吧...

相关阅读