views:

804

answers:

5

I have a question I don't know if it can be solved. I have one C# project on Visual Studio 2005 and I want to create different DLL names depending on a preprocessor constant. What I have in this moment is the preprocessor constant, two snk files and two assembly's guid. I also create two configurations (Debug and Debug Preprocessor) and they compile perfectly using the snk and guid appropiate.

#if PREPROCESSOR_CONSTANT
[assembly: AssemblyTitle("MyLibraryConstant")]
[assembly: AssemblyProduct("MyLibraryConstant")]
#else
[assembly: AssemblyTitle("MyLibrary")]
[assembly: AssemblyProduct("MyLibrary")]
#endif

Now, I have to put the two assemblies into the GAC. The first assembly is added without problems but the second isn't.

What can I do to create two or more different assemblies from one Visual Studio project?

It's possible that I forgot to include a new line on "AssemblyInfo.cs" to change the DLL name depending on the preprocessor constant?

A: 

I thinks there is no such way. Output assembly name is strictly fixed into Project settings: one assembly per one projects.

Also AssemblyAttributes you given only indicates visible assembly properties (for example in Windows Explorer), not it's file name.

abatishchev
A: 

One project, one assembly.

I suggest you create two projects with the same code files in them, each configured for a different assembly output, rather than go through a post-build process.

Randolpho
+3  A: 

Visual Studio does not allow per-configuration output filenames. However, you could rename the output file as part of your build script. You could do this in your MSBuild script for the particular project in question.

For example, put this at the end of your .csproj file:

<Target Name="AfterBuild">
    <Copy SourceFiles="$(OutputPath)\YourAssembly.dll" DestinationFiles="$(OutputPath)\YourAssemblyRenamed.dll"/>
    <Delete Files="$(OutputPath)\YourAssembly.dll"/>
</Target>

HTH, Kent

Kent Boogaart
Hi Kent, I think this is the solution for my problem but MSBuild doesn't have a command like <AssemblyName />. I wrote to Jay Shrestha from Microsoft and told me that in Visual Studio it's impossible do what I want. Instead of this, I'd have to use "msbuild.exe" to build the project.
jaloplo
Visual Studio executes a specific MSBuild target after each build. Simply edit that target and use the appropriate MSBuild task to rename the file.
Kent Boogaart
Updated my post to show you how.
Kent Boogaart
This configuration is for Visual Studio 2008???
jaloplo
This part of the configuration is the same for VS 2005 and VS 2008. This is part of the .csproj file.
configurator
Hi, can you send me a web page that explains the msbuild commands for visual studio? Thanks in advance!!
jaloplo
You can start at http://msdn.microsoft.com/en-us/library/7z253716.aspx. Note that you also write your own tasks or download libraries of tasks, such as this one: http://msbuildtasks.tigris.org/
Kent Boogaart
+4  A: 

Here is a sample Post-Build event:

if "$(ConfigurationName)" == "Debug" goto Debug
if "$(ConfigurationName)" == "Release" goto Release

goto End

:Debug
del "$(TargetDir)DebugOutput.dll"
rename "$(TargetPath)" "DebugOutput.dll"

:Release
del "$(TargetDir)ReleaseOutput.dll"
rename "$(TargetPath)" "ReleaseOutput.dll"

:End

Change DebugOutput.dll and ReleaseOutput.dll to the proper filenames. you can change "Debug" and "Release" to support other configurations, and add sections to support more configurations.


That script will create two dlls with different file names; to create two different AssemblyNames, you have two options.

The assembly name is built as follows:

Name <,Culture = CultureInfo> <,Version = Major.Minor.Build.Revision> <, StrongName> <,PublicKeyToken> '\0'

So you have to either change the culture info, the version or the strong name.

The two simplest options are:

  1. Change the assembly version:

    #if SOME_COMPILER_SYMBOL
    [assembly: AssemblyVersion("1.0.0.0")]
    #else
    [assembly: AssemblyVersion("1.0.0.1")]
    #endif
    
  2. Change the keyfile - create two keyfiles with the sn tool, and in AssemblyInfo.cs:

    #if SOME_COMPILER_SYMBOL
    [assembly: AssemblyKeyFile("FirstKey.snk")]
    #else
    [assembly: AssemblyKeyFile("SecondKey.snk")]
    #endif
    

Both these options will result in two different assemblies as far as the GAC knows - since it compares the full assembly name, and not the 'simple' name.

configurator
your deleting it and then renaming it? You shouldn't have to delete it, just rename it. or am I missing something? :-)
Muad'Dib
Could be that an older version still remains there.
Dave Van den Eynde
Yes, the rename operation does not overwrite. You could use `move /y "$(TargetPath)" "$(TargetDir)ReleaseOutput.dll"` instead of the del-rename lines - the move operation can overwrite.
configurator
This script is very good but it doesn't what I want. I tried to move to GAC both dll (the one and the renamed) and it didn't work. This is a good solution to rename dll's but not is the best.
jaloplo
@jaloplo: See the edit for ways to make the GAC see two different files.
configurator
What you wrote I checked yet and It doesn't work. I didn't change the Version because it isn't a clean solution, so this is not what I need. Jay Shrestha from Microsoft told me that is impossible to build two different assemblies from one project, and the best solution is MSBuild implementation.
jaloplo
The second options I suggested works. I checked it on my machine.You need to have the compiler symbol defined in the configuration which should produce the different key. i.e. in this example, I'd have one configuration set the SOME_COMPILER_SYMBOL flag, and the other wouldn't set it.
configurator
Note: The two key files should be created by running "sn -k FirstKey.snk" and then "sn -k SecondKey.snk"
configurator
You have reason. I can generate two different dll's using different snk's files. This is the first thing I want to do. Thanks!!! For the other thing, I think that is impossible to do as Microsoft guy tell me. But, combining this solution with the answer below.
jaloplo
I checked it and you're responses are enough to do what I want. Till I don't like it at all but it works. Thanks!!!
jaloplo
I'm happy to help. I understand why you don't like it - I don't either - but I guess .Net is not 'meant' for multiple assemblies from one project, which is why we needed such a hack.
configurator
+1  A: 

I havn't tried this myself so take it as a friendly suggestion. Try manually editing your .csproj adding or uncommenting the BeforeBuild target with a snipped inspired from the following:

<Target Name="BeforeBuild">
    <AssemblyName Condition="'$(Configuration)' == 'Release'">MyReleaseName</AssemblyName>
    <AssemblyName Condition="'$(Configuration)' == 'Debug'">MyDebugName</AssemblyName>
</Target>
Cristian Libardo