I consuming my service stack using EXE project (startup task for azure application) in that I have copied following service stack's DLL & some Azure's DLLs in to EXE project.
When I build this EXE project then Azure DLLs will be bundled with my EXE but service stack's DLL will not be bundled with EXE, because to run my EXE on any machine I need to copy all service stack's DLL manually.
I have used this service stack's dll to use
JsonServiceClient client = new JsonServiceClient(servicepath);
What should I have to do to bundled all these DLLs in to my EXE?
You have several options:
use ILMerge (free)
For howto see here and here
OR
use some tool like SmartAssembly (commercial)
it can embed and merge among other things (no need to change your source code)
OR
code that yourself in less than 10 lines (free but minimal source code change)
mark all needed dependencies as "embedded resource" - this way they are included in the EXE file... you need to setup an AssemblyResolve handler which at runtime reads from Resources and returns the needed DLLs to the .NET runtime...
A great tool to include referenced assemblies as embedded resources is Costura (a Fody add-in). The author Simon Kropp describes it as follows:
[...] a combination of two methods:
Jeffrey Richter's suggestion of using embedded resources as a method of merging
assemblies
Einar Egilsson's suggestion using cecil to create module initializers
The result is a super simple solution which merely requires to fetch Costura.Fody from NuGet.
Features:
Including debug symbols
Compression of embedded assemblies
Including/excluding specific assemblies
Others (see Readme)
The tool you are looking for is called ILMerge .
It is a command line tool and can be used like this:
ilmerge /target:winexe /out:MyApp.exe
MyExe.exe ServiceStack.dll ServiceStack.Interfaces.dll ServiceStack.ServiceInterface.dll ServiceStack.Text.dll
There is also an article that describes how to include ILMerge into your VS project setup here
Try ILMerge-GUI, the .NET merger.
It's a GUI based Ilmerge which avoids all command line work.
If you have WPF dependencies your options may be more limited..... ILMerge doesn't appear to deal with these. Costura.Fody (as mentioned by Codefox above) worked perfectly for us however and took about 5 minutes to get going... a very good experience.
Install with Nuget (selecting the correct default project in the Package Manager Console).
It merges the all DLLs marked "Copy Local" = true and produces a merged .EXE (alongside the standard output, most of which is now not necessary) which is also compressed. This can then be used standalone.
The license is MIT as so you can modify/distribute as required.
https://github.com/Fody/Costura/
.net core 3 introduces two new options in the project configuration, called single file publish and trimming.
You can find more details on docs here, project configuration copied here for reference.
Project Configuration:
<PropertyGroup>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
Using CLI:
dotnet publish -r win10-x64 -p:PublishSingleFile=true
dotnet publish -r <rid> -c Release
It is fully supported to combine the two options together to get a trimmed single assembly for your application.
Checkout the ServiceStack.Gap project which shows several examples of howto ILMerge ServiceStack into a single cross-platform .exe.
ServiceStack also includes a number of other features that's particularly well suited for these creating embedded apps where it:
Allows your services to be self-hosted using .NET's HTTP Listener
Supports pre-compiled Razor Views
Supports Embedded Resources
Supports an embedded database in Sqlite and OrmLite
Can be ILMerged into a single .exe
Related
I have a windows forms application that is deployed to two different locations.
Intranet - ClickOnce
Internet - Installed on a citrix farm through Windows installer
I display ClickOnce version number for click-once deployed versionApplicationDeployment.IsNetworkDeployed.
if (ApplicationDeployment.IsNetworkDeployed)
return ApplicationDeployment.CurrentDeployment.CurrentVersion;
But for the non-click application, I am not sure how to retrieve clickonce version unless I hardcode the version number in assembly info.
Is there an automatic way of retrieve ClickOnce version number for non-clickonce deployed version?
Add an assembly reference to System.Deployment to your project.
Import the namespace in your class file:
VB.NET:
Imports System.Deployment.Application
C#:
using System.Deployment.Application;
Retrieve the ClickOnce version from the CurrentVersion property.
You can obtain the current version from the ApplicationDeployment.CurrentDeployment.CurrentVersion property. This returns a System.Version object.
Note (from MSDN):
CurrentVersion will differ from UpdatedVersion if a new update has
been installed but you have not yet called Restart. If the deployment
manifest is configured to perform automatic updates, you can compare
these two values to determine if you should restart the application.
NOTE: The CurrentDeployment static property is only valid when the application has been deployed with ClickOnce. Therefore before you access this property, you should check the ApplicationDeployment.IsNetworkDeployed property first. It will always return a false in the debug environment.
VB.NET:
Dim myVersion as Version
If ApplicationDeployment.IsNetworkDeployed Then
myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion
End If
C#:
Version myVersion;
if (ApplicationDeployment.IsNetworkDeployed)
myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
Use the Version object:
From here on you can use the version information in a label, say on an "About" form, in this way:
VB.NET:
versionLabel.Text = String.Concat("ClickOnce published Version: v", myVersion)
C#:
versionLabel.Text = string.Concat("ClickOnce published Version: v", myVersion);
(Version objects are formatted as a four-part number (major.minor.build.revision).)
No I do not believe that there is a way. I believe the ClickOnce information comes from the manifest which will only be available in a ClickOnce deployment. I think that hard coding the version number is your best option.
I would simply make the assembly version of the main assembly the same as the CLickOnce version every time you put out a new version. Then when it runs as a non-clickonce application, just use Reflection to pick up the assembly version.
Try thread verification:
if (ApplicationDeployment.IsNetworkDeployed)
{
if (ApplicationDeployment.CurrentDeployment.CurrentVersion != ApplicationDeployment.CurrentDeployment.UpdatedVersion)
{
Application.ExitThread();
Application.Restart();
}
}
not that it matters three years later, but I ended up just parsing the manifest file with xml reader.
To expand on RobinDotNet's solution:
Protip: You can automatically run a program or script to do this for you from inside the .csproj file MSBuild configuration every time you build. I did this for one Web application that I am currently maintaining, executing a Cygwin bash shell script to do some version control h4x to calculate a version number from Git history, then pre-process the assembly information source file compiled into the build output.
A similar thing could be done to parse the ClickOnce version number out of the project file i.e., Project.PropertyGroup.ApplicationRevision and Project.PropertyGroup.ApplicationVersion (albeit I don't know what the version string means, but you can just guess until it breaks and fix it then) and insert that version information into the assembly information.
I don't know when the ClickOnce version is bumped, but probably after the build process so you may need to tinker with this solution to get the new number compiled in. I guess there's always /*h4x*/ +1.
I used Cygwin because *nix scripting is so much better than Windows and interpreted code saves you the trouble of building your pre-build program before building, but you could write the program using whatever technology you wanted (including C#/.NET). The command line for the pre-processor goes inside the PreBuildEvent:
<PropertyGroup>
<PreBuildEvent>
$(CYGWIN_ROOT)bin\bash.exe --login -c refresh-version
</PreBuildEvent>
</PropertyGroup>
As you'd imagine, this happens before the build stage so you can effectively pre-process your source code just before compiling it. I didn't want to be automatically editing the Properties\AssemblyInfo.cs file so to play it safe what I did was create a Properties\VersionInfo.base.cs file that contained a text template of a class with version information and was marked as BuildAction=None in the project settings so that it wasn't compiled with the project:
using System.Reflection;
using EngiCan.Common.Properties;
[assembly: AssemblyVersion("0.$REVNUM_DIV(100)$.$REVNUM_MOD(100)$.$DIRTY$")]
[assembly: AssemblyRevisionIdentifier("$REVID$")]
(A very dirty, poor-man's placeholder syntax resembling Windows' environment variables with some additional h4x thrown in was used for simplicity's/complexity's sake)
AssemblyRevisionIdentifierAttribute was a custom attribute that I created to hold the Git SHA1 since it is much more meaningful to developers than a.b.c.d.
My refresh-version program would then copy that file to Properties\VersionInfo.cs, and then do the substitution of the version information that it already calculated/parsed (I used sed(1) for the substitution, which was another benefit to using Cygwin). Properties\VersionInfo.cs was compiled into the program. That file can start out empty and you should ignore it by your version control system because it is automatically changing and the information to generate it is already stored elsewhere.
Hard code, or... Keep track on your versions (File, Assembly, Deploy) in a database. Make a call to the database with your Assembly and get the Deploy version.
This assumes that you are incrementing your versions in a logical way such that each version type has a relationship. It's a lot of work for such a minor problem. I'd personally go with Jared's solution; although I hate hard coding anything.
Using a build component, you could read the click-once version from the project file and write it automatically to the assembly info so both of them are in sync.
Solution for .NET (Core) 7 and higher
On .net Core, you can read the version number from the environment variable ClickOnce_CurrentVersion.
string versionString = Environment.GetEnvironmentVariable("ClickOnce_CurrentVersion") ?? "0.0.0.0";
Version version= Version.Parse(versionString);
MessageBox.Show(version.ToString());
See documentation
I have put a library that my team uses into a nuget package that is deployed from TeamCity into a network folder. I cannot debug into this code though! SymbolSource is one solution I have read about but I would much rather find some way to have access to the .pdb/source files directly from TeamCity. Does anyone know how to do this?
Edit. When I check 'Include Symbols and Source' in the Nuget Pack build step, TeamCity creates a .Symbol.nupkg in addition to the .nupkg file in the network folder. The .Symbol.nupkg contains the src and the .pdb file.
Edit. I unchecked 'Include Symbols and Source' on TeamCity and added the following to my nuspec file:
<files>
<file src="..\MyLibrary\bin\release\MyLibrary.dll" target="lib\net40" />
<file src="..\MyLibrary\bin\release\MyLibrary.pdb" target="lib\net40" />
<file src="..\MyLibrary\*.cs" target="src" />
<file src="..\MyLibrary\**\*.cs" target="src" />
</files>
This added the dll, the pdb, and the source files for my library in the nuget package and didn't generate a .Symbols file which I think is only needed for symbol servers.
Traditional method
Put the pdb in the NuGet package alongside the dll.
Add the source code to the Debug Source Files for the solution that references the package.
This means you'll be able to step through code and view exceptions, but you might have to find a file on disk and open it before you can set a breakpoint. Obviously you need to be careful that the source is at the right revision.
More detail on step
If you're currently packaging without a Nuspec, you'll need to create a Nuspec, then add the pdb to the list of files in the lib folder "NuGet spec" may be a useful command for generating the initial spec as defined in NuGet docs. Then ensure the Team City Nuget Pack step is referencing your new nuspec.
More detail on step 2
When you have a solution open, right click on Solution, select Properties...Common Properties...Debug Source Files, and add the root source directory for the relevant binary reference. Or see MSDN.
Note, you can't open the solution properties while debugging.
Still not hitting breakpoints?
Try disabling this from Tools->Options:
Modern way for public or private repos
To ensure the exact version of the source is available, embed it at build time.
From Visual Studio 2017 15.5+ you can add the EmbedAllSources property:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<EmbedAllSources>true</EmbedAllSources>
Modern way for public repos
To keep your nuget and library size small, you can use the sourcelink package.
It generates a pdb that directs the debugger to the correct version of the file from your VCS provider (e.g. GitHub, BitBucket).
The latest version of dotPeek (free!) can act as a symbol server and generate pdb files on the fly. This has allowed me to debug into the dlls that are served via teamcity.
Download it here:
http://blog.jetbrains.com/dotnet/2014/04/09/introducing-dotpeek-1-2-early-access-program/
Instructions on how to set it up here.
https://web.archive.org/web/20160220163146/http://confluence.jetbrains.com/display/NETCOM/dotPeek+Symbol+Server+and+PDB+Generation
You could of course set-up & configure your own symbol server, but it's probably easiest to...
download and install Inedo's ProGet
enable symbol serving on the target feed
publish packages from TeamCity to the ProGet feed
use ProGet as your primary feed source (as it can aggregate multiple feeds including nuget.org)
All of this can be done with the free edition of ProGet.
disclaimer -- my day job is at Inedo
In your .nuspec (directly under <package>):
<files>
<file src="bin\$configuration$\$id$.pdb" target="lib\net451\" />
</files>
(change net451 to the platform you're compiling for)
If you have the source code for the package, then the foolproof (but possibly laborious) method is:
Add the source code for the package to your solution (right click Solution -> Add Existing Project)
Go through all of your projects in the solution and remove the NuGet reference to the library (i.e. open the References folder under each project and delete the reference to the package.) Then, add a reference to the NuGet package project in your solution. (i.e. Right click References, add Reference, choose Projects and tick the box for the project)
I had to do it this way when I the method I wanted to debug inside the NuGet package was called by the framework and not by my code, thus I couldn't step into it. (In my case, the method was an ASP.NET DelegatingHandler).
Once you're done you'll want to undo all your changes via source control so that the NuGet package is referenced correctly.
I've found a super simple way to do this, which I have blogged about here:
https://mattfrear.com/2017/11/29/speed-up-development-in-a-nuget-package-centric-solution/
This only works if you're using the new .NET Core style .csproj with <PackageReference> (on either .NET Core or .NET Framework).
This again assumes you have access to the source code of the NuGet package.
Build and compile the NuGet package on your local machine
Copy the .dll you've just compiled into your local NuGet packages feed folder (On my machine, this is C:\Users\matt\.nuget\packages\), overwriting the existing NuGet package .dll.
That's it! You should be able to step into the package while debugging. No messing around with .pdbs or source servers. This has greatly sped up my development cycle.
Since this question was originally posted, Jetbrains have written an entire blog post on how to accomplish this. The steps can be summarised as:
Install Debugging Tools for Windows on the agents.
Install & Enable the Symbol Server plugin.
Add Symbol Files Indexer build feature to your build configurations.
Ensure PDB files are output as an artefact.
Configure Visual Studio to use TeamCity as source server.
If you are using Nuget Package build steps, you can check 'Include Symbols and Source' to output a .symbol.nupkg which contains the PDBs. Depending on whether the Symbol Files Indexer is smart enough to look inside this file or not, you may need to change the file extension for things to work.
The full details are given here:
https://blog.jetbrains.com/teamcity/2015/02/setting-up-teamcity-as-symbol-and-source-server/
This is what I have found to work, but all the steps are probably not required...
Note: this doesn't allow you to debug both, only either the nuget
package or the solution in which it is installed.
Run Visual Studio as Administrator
Open and Start the host application (the one in which you installed the Nuget package) without debugging (Ctrl + F5)
In the Nuget package solution, ensure that Tools > Options > Debugging > General > "Require source files to exactly match the original version" is NOT checked.
Ensure that "Enable just my code" is NOT checked
Add a new folder in Tools > Options > Debugging > Symbols pointing to the source directory of the Nuget package. (You literally enter the folder path , see image below)
Click Debug > Attach to Process...
Find iisexpress (there may be multiple, it won't do any harm attaching to all)
If your code is in a public Git repository, or, at least in your network, is accessible without authentication, then GitLink would be an option:
https://github.com/GitTools/GitLink
GitLink makes symbol servers obsolete by changing the PDB to point to the Git server. But, as said before, this makes it necessary for the Git repository to be public - until now there's no "proper" way to authenticate when accessing a private repository.
Microsoft has now integrated the SourceLink NuGet package at https://github.com/dotnet/sourcelink/ which allows source code to be downloaded on demand while debugging if the publisher of the NuGet package sets it up.
I'd like to have a web project in a solution that is set to "not build" in the solution configuration, however I would still like the project's references (and their dependencies) to be copied into that project's bin folder. There are class library projects in the sln that are actually built, and the web project references those.
Our current "build" just calls devenv, which does exactly this. For obvious reasons, I'd rather use MSBuild.
I am not looking for methods to do manual file copying (either individually or *.dll). There are many ways to do this. I am looking specifically for a way to replicate the behaviour that devenv.exe gives us - automatically copy references (and their dependencies) based on what is in the project section in the solution file (below).
These references come from the solution in this section:
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}")="TheWebProjectName",
"Web\Project\Folder",
"{1CBD1906-0C2E-4C92-A81D-63C2AD816EA1}"
ProjectSection(WebsiteProperties) = preProject
TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
ProjectReferences = "{B125568E-E80C-4080-B8D3-5602B604734C}|Some.Reference.dll;
{117E8B0A-F0D6-47D0-BB51-71099969566D}|Some.OtherRef.dll;"
...
EndProjectSection
EndProject
MSBuild uses target files to determine it's build steps. Take a look at the relevant target files and determine how MSBuild copies those files, create your own target file and modify your build configuration to use the new target.
Relevant target files:
Location: C:\Windows\Microsoft.NET\Framework\v$(version)
Microsoft.CSharp.targets
Microsoft.Common.targets
Relevant documentation:
MSBuild
Specifying Targets
You can do build operations such as this using MSBuild Tasks: http://msdn.microsoft.com/en-us/library/ms171466(v=vs.80).aspx
In your specific case you'll probably be interested in the built in Copy Task: http://msdn.microsoft.com/en-us/library/3e54c37h(v=vs.80).aspx
Try using powershell instead of msbuild!! Ria services also relies strongly on powershell commandlets.
Cheers..
Call devenv.exe using an Exec task - we do it all the time for BizTalk solutions because old versions of MSBuild do not support the BizTalk project files...
I've a same project that need to be compiled with .NET and Compact .NET Framework.
It is possible to create a C#
compiler that will compile my
project with both framework ?
Some feature aren't present in
CF.NET Framework so I created it by
myself (creating classes having
exactly the same name & options that
in .NET Framework. If I decore this
classes with an attribute like
[CF35] it's possible to parse the
project and :
Use this class when compile the
project using CF.NET
Ignore this class when compile the project using
.NET
?
Thanks for all constructive answers.
[EDIT]
I know the solution that consists to create two projects referencing the same files.
Problem is, you should every time compile both manually.
Moreover, when you add a file to one, you need to open the second and reference it too, that it's just borring to do and according that we are many people to work on the same project, I would like to do this part automatically.
Seems to be possible?
[EDIT 2]
All works fine except ... resources files !
So, to resume, I've three project :
the development project (CF.NET)
the release project (CF.NET 3.5), including all files via ""
the release project (NET 3.5), including all files via ""
As said, all works fine, but now my problem is using Resources files.
What's the method to apply to use it?
When I use the development project, Resource file is correctly retrieved
When I use the two other projects, ResourceManager throws MissingManifestResourceException
Any idea?
You'll need to create different build configurations for each and define a custom flag like USE_CF. Then wrap your custom classes with #if USE_CF and #endif so they get ignored when compiling without that flag
The basic idea would be to decorate your code with #if compiler directives for each framework version?
#if CFNET
// .net CF code
#else
// .net code
#endif
From here one you have two options:
A) 1 project file with custom build configurations
If you would like to have everything in 1 csproj file you'll need to modify it manually. Since this is a msbuild file this is more of a msbuild problem. I figure you would need to do the following things:
Use 2 platform names say "NET" and "CF" (instead of the default Any CPU or x86)
Define CF constant (From now on Edit csproj):
<PropertyGroup Condition="'$(Platform)' == 'CF'">
<DefineConstants>CF</DefineConstants>
</PropertyGroup>
Import correct build targets depending on selected platform:
<Import Condition="'$(Platform)' == 'NET'" Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Condition="'$(Platform)' == 'CF'" Project="$(MSBuildToolsPath)\<CFtargets>.targets" />
I don't know the targets file name of CF since I don't have it installed. It sould be somewhere in C:\Windows\Microsoft.NET\**.targets
B) 2 project files each containing the appropriate build configuration
As I initially pointed out, and also some commenter pointed out, the best solution is to have 2 project files, that you keep in sync. You can have the same source files in both project files.
So an idea would be (instead of copying the file list manually each time) to
think about using T4 templates, to keep the source files in sync (and have 2 solutions, so you wouldn't be prompted to reload the whole solution each time) or to
modify the two csproj files and use a wildcard compile tag like this:
<Compile Include="**/*.cs"/>
There's only one C# compiler, it emits the exact same IL for whatever platform. What's different are the reference assemblies, you have to use the CF versions for the project that targets CF, the desktop versions for the project that targets .NET. Which requires two projects. They can reference the same source code files. Adding CF-only source code files is now of course no longer a problem.
Keeping projects in sync is a feature available in VS2010. Intended for Silverlight, pointless for a CF project of course since it no longer supports it.
a better way is to create your normal project class library (.NET) and add all of your code. Then create your second class library project (.NET CF) but reference the code files from the first project (not copy, but reference). Then you end up with 2 DLL's and you don't have to deal with nasty ugly compiler directives. You get the result you want with no extra work to maintain both projects. Obvisouly you would need to be careful with what you put in the code since .NET CF is limited compared to .NET. I don't know how to add file references (shortcuts) using visual studio but I open the proj file in notepad and use relative paths to the files to include. I've used this method for .NET/.NET CF and also .NET/Silverlight
Also, have a look at Portable Library Tool CTP http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981/?localeName=ko-kr
When using Visual Stdio 2008, you can make a C++ project build with an internal tool rather than having the IDE invoke MSVC directly. This improves the consistency of builds across platforms if a cross-platform build system is used.
However, I cannot figure out how to do the same as a C# project. It would be possible to simply register it as a native project with C# sources, however, you lose some of the advantages gained through having a C# project. More importantly, it will mean that allowing a project to build both directly and with an external tool (which is sadly necessary) will require two separate projects, rather than merely creating an alternate build configuration to invoke the external tool.
Does anyone know if it's possible to prevent Visual Studio from invoking csc by itself and instead call an external tool?
EDIT: Apparently there has some misunderstanding. The goal here is not to compile anything outside of Visual Studio. Instead, it's to allow Visual Studio to serve as the IDE but not the build system. There is already a (Scons-based) build system capable of compiling the C# and C++ sources, and Visual Studio has been configured to invoke Scons for compilation of C++ projects. I'm trying to configure it so that when you hit the 'Build' button, it will invoke Scons for the C# projects as well as the C++ ones.
Edit: Your question is still answered using MSBuild(if you are simply looking to compile outside the IDE). The IDE(Visual Studios) is simply a "fancy" way of constructing the build files that are built by MSBuild. Visual Studios isn't building the files, it simply is invoking MSBuild which ships with the .NET Framework 2.0 and up which compiles your code based on the project file that you create. If Scons can read and process an MSBuild file then I'm sure you can invoke it to build your project. But considering the fact that C# is a Microsoft language, I think you will be hard-pressed to find a value-add in not using MSBuild since I'd assume both the language and build tool are very tuned to work together. - End Edit
You can use MSBuild to compile your C# project. If you open your .csproj file in a text editor you will see that it is a MSBuild file. If you want to write some C# outside of the IDE you can construct a build file using the .csproj file as a starting point and invoke MSBuild to compile your apps. The IDE is just a way of abstracting the editing of the MSBuild file away for you.
If you are really industrious you can create a set of custom tasks to do things in your custom build process like move files around and versioning. MSBuild Community Tasks are a great example of using custom code to do task for you during MSBuild.
Given all the other answers, what MSBuild does when either VS or MSBuild perform a build can be found in the Targets files that ship with .Net. These can be be found in the FrameWork directory on your system. In my case:
C:\Windows\Microsoft.NET\Framework64\v3.5
Contains Microsoft.Common.targets among others. This file contains the following snippit:
<!--
============================================================
Build
The main build entry point.
============================================================
-->
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(BuildDependsOn)"
Outputs="$(TargetPath)"/>
This means that redifining this Target you can make MSBuild an VS do anything you want. The top of the mentioned file contains an important messagge:
Microsoft.Common.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
This file defines the steps in the standard build process for .NET projects. It
contains all the steps that are common among the different .NET languages, such as
Visual Basic, C#, and Visual J#.
My suggestion would be to read all you can about MSBuild and it's build file syntax and try redifining the Build target in your project(s). My impression is that after reading up on MSBuild you'll probably find an easier way to meet your requierements. You can find an example of redifining a Target like this in one of the answers of this so question .
Edit:
How to redefine a target?
Redefining is essentially defining the same target 'after' it has been defined. So for instance in your .*proj file(s) define a Build Task after the <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> line that imports all targets needed to in this case build a C# project. An example could be
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="BeforeBuild"
Outputs="$(TargetPath)">
<Exec Command="nmake" />
</Target>
I found a question in the same direction here, where it is suggested to edit the registry. I am pretty sure there is no other way to change the compiler used by Visual Studio because there is no trace of csc.exe in any solution, config, csproj file or whatsoever, nor in the Visual Studio 9.0 folder / subfolders within the Program Files dir.
Registry locations can be found in:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\74ACAA9F1F0087E4882A06A5E18D7D32
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\9055DA7481CC1024CB23A6109FD8FC9B
but those keys may differ dependng on your installation. Conclusion: changing the compiler used by VS seems next to impossible.
Addition: The following MSDN article deals with the same question for an custom C++ compiler, and Ed Dore's answer seems to confirm my theory that there's no way to choose an custom compiler for use within VS.
Under 'Tools' > 'External Tools' you should be able to define an outside tool to do activities for you. The Command should be the path to the executible for your external tool.
Hope this helps some.
You don't have to maintain different project files to build using an external tool. MSBuild is designed to build using the same project files that Visual Studio uses.
Here's an article that describes it.
Customize Your Builds in Visual Studio Using the Standalone MSBuild Tool
It's for VS2005, but should apply to VS2008 as well.
Looking through the answers, it seems clear to me that integrating scons into Visual Studio in a way that is compatible with the debugger and so on is not going to happen...
An option you might to consider, and I understand you don't want to change build systems, but bear with me, is to use a meta-build system, ie 'cmake'. http://www.cmake.org/
Cmake doeesn't actually build the project. What it does is to create build files for you, that you can use to build the project, and on Windows, the build files it creates for you are: Visual Studio project files. You can simply load those directly into your IDE, and compile, and use normally!
CMake is I feel very easy to use, and provides a high level of transparence and maintainability.
The exact same CMakeLists.txt files on linux will causes linux makefiles to be generated.
On mingw, they can generate mingw makefiles.
There are numerous generators available within cmake. The list is here:
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#section_Generators
http://springrts.com is a huge opensource rts game that used to use scons as its cross-platform build system and now uses cmake.
I understand that you don't really want to have to change build systems, so it is a medium to long term solution.
Cmake is in any case one more option, to add to those of using a custom build tool, or using msbuild, or running the scons build from the commandline by hand.
Edit your project file and update the CscToolPath keys to point to the directory containing your tool and add CscToolExe keys that holds the name of the directory:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|.NET 3.5' ">
.
.
.
<CscToolPath>path\to\custom\tool\directory</CscToolPath>
<CscToolExe>exe name</CscToolExe>
.
.
.
</PropertyGroup>
I have not tested this, and the CscToolExe key may cause problems, in which case I would simply rename the external tool executable to "csc.exe".
You can build your solution from the command line like this:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>msbuild.exe "C:\path\Your Solution.sln"