GAC an assembly without embedding it within the MSI - installation

I want to GAC an assembly already present on target machines, I know where this assembly is on every machine (you can assume, that path is static for all target machines and wont change and that I am the owner of this assembly) I do not want to include the assembly to be GAC'd in the MSI since it can change with each solution deployment and we dont want our setup to be modified each time. I tried using the <File> tag with Assembly =".net"
<File
Id="Assembly.dll"
Name="Assembly.dll"
Assembly=".net"
Source="Assembly.dll"
KeyPath="yes" >
</File>
but using File embeds my assembly in the MSI. Any ideas on how to just tell the MSI to just look for the assembly in a particular location and not include it?

That's not supported by the Windows Installer. It isn't immediately clear why you would want to take someone else's file and put into the GAC (if it was your file, why not put it in the GAC to begin with?). :)

Seems like an odd request, but the way to do this would be to write a script / batch file to GAC the file. Test this out by itself without the MSI. Once working, include the script in the MSI, and then execute the script as a custom action to execute on install. You would also want to remove it from the GAC on uninstall.
If you are using a Visual Studio setup project, right click on the project, and choose View->Custom Actions. From there it will let you add the actions for the appropriate events (install, uninstall, etc).

Related

vsdraCOM causes the codebase path to point to build path

We have a couple of dlls we like to install using an msi.
In our test environment, we are using regasm -codebase to register the dlls.
As I understand from googling, this is accompliched in an msi project by setting the register property to vsdraCOM.
The problem is that when we run the installer and checks the registry, the codebase path is set to the path the file were in when building the msi.
I'm going to expand on Hans' answer and that link info, and it may be more than a comment can hold.
That reg file will contain the path to the file and the link article recommends using [TARGETDIR], which is basically wrong if the file is not being installed to the application folder. The path to your file should be written as [#file-key] in the reg file that you import. In a VS setup project the file-key will be (just an example) something like _B049230C37DE4B6787C578DCEE30252A. Open your MSI file with Orca, go to the File Table and use the file key in the File column that corresponds to your file name.
That comes from here:
http://msdn.microsoft.com/en-us/library/aa368609%28v=vs.85%29.aspx
the 7th bullet point. It resolves to the file path wherever it is installed to.
The other thing that can be done is to let Visual Studio do its incorrect thing, then go to the Registry table with Orca, find the path and put that [#file key] in it such as [#_B049230C37DE4B6787C578DCEE30252A] and people sometimes do those kinds of updates with a post build script to update the MSI.
None of these are great, but they should work and get you out of using the GAC. VS setup projects really should be using that [#file key] syntax, and it's just a silly bug I assume.
Speaking as someone who's made a full time living writing installs for 18 years, my first suggestion would be to switch to Windows Installer XML. If you insist on using .VDPROJ, I would suggest reading: Redemption of Visual Studio Deployment Projects.
The concept is you use Windows Installer XML to create a merge module and then consume that merge module with .VDPROJ. In Wix, you use Heat to harvest the DLL. It will extract the COM / Regasm metadata and author it as Registry table entries. This provides a nice clean encapsulation using authoring best practices and avoids the need to do any post build hacking of the built MSI database.

What is the best way for multiple solutions/projects to reference a common assembly?

I have several Visual Studio solutions/projects (some VB, some C#) that all reference a common DLL at design time. This DLL does not have to be copied to the output folder as it is only needed while writing code. Every few months this DLL will be updated to a newer version and all of my projects need to reference the updated version.
What is the best way to handle this?
You have to use a Shared Assembly, shared in GAC (Global Assembly Cache).
Say, you have programmed a class, a piece of software, whatever you have, and you want to make it a shared assembly.
First you make it an assembly by creating a new Class Library Project in VS and transporting all of the code to that project. Don’t build/run it yet! Note that we just transport the code but the assembly (the .DLL file) is not actually made yet, because we have not built the project yet.
Before building the assembly, we have to create/share a key by which the assembly is known, in 2 steps:
a) create the key by executing the cmd below in VS cmd:
sn -k "C:[DirectoryToPlaceKey][KeyName].key" b) share it by adding the attribute below to the AsseblyInfo.vb/cs file in the properties folder of your Class Library project:
In VB.Net:
In C#:
[Assembly: AssemblyKeyFile("C:[directory containing the key file][KeyName].key")] (just copy and paste this into the AssemblyInfo.vb/cs file, but write your directory and file name instead).
Now, you MAKE the assembly by building the project. Just build the project (just press F5 once, at least!). By doing so, the .dll file we need (the assembly) is created in the “bin” folder in the same folder of the project.
Now we share it by Copying the .dll file into the GAC (Global Assembly Cache: it’s where all the assemblies are gathered together. The directory is: “C:\windows\Microsoft.Net\assembly\GAC_MSIL” but you don’t need to know that since the tool below does that for you~) by executing the command below in the VS cmd:
gacutil -I "C:[PathToBinDirectoryInVSProject]\myGAC.dll"
YOU'RE DONE! You may now reference and use the shared assembly from all your applications, and whenever you want to update, just update the shared assembly.
Hope that helps!
You can create nuget resources, and use Nuget Server (Lastest version of teamcity support it) - and all updates w'll be handled by nuget.
Other approach is to create common folder and all project point's to dll in this folder (relativly) in this case you need to udate dll in one folder (after rebuild solution dll'll be updated automaticly)
Ofcourse you can allways install dll in GAC (Global Assembly Cache) this is handled by tool called gacutil.exe (in net is lot of example how to handle it).

Setting the deployment setting to relative path Local.Testsettings

I am wondering if there is a way to set the deployment setting under Local.TestSettings in a Visual Studio 2010 Test to a relative path. Right now we have to copy over a couple of DLL's in order to use our tests correctly. We have this path hard set on a machine, but this gets messed up if you accidentally commit that file and then someone updates.
You can use test setting to add one deployment item. And continually use notepad to edit the *.testsettings file. Then, manually add "outputDirectory" attribute to the deployment item.
For example, there is one folder named "Config" in "myProj" which contains your online codes. And you want to copy all configuration files under the folder - "Config" to your test project - "Test.myProj" and make them also be placed under "Config" under "Test.myProj"
So you need to manually change the *.testsettings and add the following item in the file.
<Deployment>
<DeploymentItem filename="myProj\Config\"
outputDirectory="Test.myProj\Config\" />
</Deployment>
P.S. VS2010 did not allow to input value to "outputDirectory". So u have to use notepad or text editor to update it.
What is the source for these DLL's? How are they being used, as reference DLL's? If they are third party DLL's the tactic we usually do is place them into a "Reference DLL's" folder and add them as deployment items. When VS goes to execute the test it will copy them to the OUT folder along with the test DLL. Now that they're both in the same folder your tests should have no problem finding the needed reference DLL's.
If these DLL's are of your own creation (or your group/organization) I would add the project to the solution then add the reference as a Project reference. VS will automatically detect the dependency and compile the additional projects and copy the built reference DLL's to the out folder.

Visual Studio create release file with all files embeded

I would lik to make 1 exe-file (win32) with all obj, idp, pdb... files embeded to make it easier to copy the program and use it on other computers, can anyone help me?
You don't need obj, idp, pdb... files to run on another computer.
Start by selecting the Release configuration and see what ends up in the output folder. Most likely it's just 1 file.
You can embed Text, Xml and in principal even DLL files but it is not always worth it.
If you want to simply run the generated program on another computer, just copy the .exe and any associated dll files. The pdb file is a debug information database that is not actually needed to run the program - only to load it in the debugger with specific information. The other files are intermediate files created during the build process.
If you don't want to have to install the Visual C++ Runtime on the target machine, or rely on it being there, you will want to go into the Project Settings -> C/C++ Settings -> Code Generation and select that you want the "Multithreaded" library instead of the "Multithreaded DLL" library (or equivalent). This will embed the C++ runtime into your program.
Of course if you're trying to copy the project over to perhaps do more debugging or development on another computer, just pack it all into a zip file.

How to associate external files with an assembly

Let's say you have a class library project that has any number of supplemental files that also need to be included with the compiled assembly (e.g. simple text files or even a legacy unmanaged DLL that's wrapped by the assembly as an interop layer). While embedding the supplemental files into the assembly itself is relatively straightforward, we have situations where this is not possible or just undesirable. We need to have them as "sidecar" files (i.e. files alongside the assembly, potentially in subdirectories relative to the assembly)
Adding those files to the project with an appropriate value for "Copy to Output Directory" specified appears to be sufficient for projects that are completely self-contained within a solution. But if a separate project in another solution adds a reference to the assembly, it does not automatically pickup its sidecar files. Is there a way in the project to somehow mark the resulting assembly such that anything referencing the assembly will also know it needs to include the associated sidecar files? How do you do this?
You can use al.exe, but there also appears to be a C# compiler option. You want to create a multifile assembly using the /linkresource C# compiler option. Instructions are here, but the command is similar to this:
csc /linkresource:N.dll /t:library A.cs
Where N.dll is a native DLL that will go wherever the managed assembly goes (including into the GAC.) There's a very clear description at the link I provided.
Have you tried creating a setup for your solution ? There's an option of including sidecar files targeting to application installation directory.
Another option would be to include the sidecar files in the Assembly resources and un-wrap them to disk when run for the first time.
What if you create a merge module containing the library plus its dependencies? Your installer will then need to reference this module, but you will ensure all of the necessary files will be present.
Unfortunately there doesn't appear to be a lot of built-in support in Visual Studio for this, although I can definitely see the use case.
If you use Subversion for your source control, then you could link in an external reference as an externals definition. This would bring in the source code, and you'd be making a reference to the necessary assembly as a project reference instead of a DLL reference, and then the copy to output directory rules would come into play.
If that's not possible, another solution would be to include commands in the pre/post-build events of your in-solution project to copy the most up-to-date sidecar files from the remote assembly on a build. Of course this comes with the caveat that it doesn't set itself up automatically when you include the DLL in your project; you have to take manual steps to set it up.
I deal with this some time ago. Its a common problem.
You can create some postbuild actions:
http://www.codingday.com/execute-batch-commands-before-or-after-compilation-using-pre-build-or-post-build-events/
Hope this helps... :)
It appears to me that you're using the wrong type of reference. There are two types of references- Reference and ProjectReference. Reference is an explicit reference to a specific assembly. ProjectReference is a reference to another project (say .csproj).
What you're looking for is ProjectReference. VS and the default MSBuild targets are setup to do CopyLocal. If you set CopyToOutputPath true for your "sidecar" files, any ProjectReferences to this project now will also pull in the same files.
I'm not sure if you can to ProjectReferences across solutions in the IDE. I deal a lot with MSBuild where sln files are not relevant and this is how I deal with it.
What we did in our project is that we created as separate build file to do all those stuffs.
In your build file you can have tags to build your main solution, then add tags to copy files you need after build.
NAnt is also your option, but right now I'm happy using Rake as my build/debug automation.
Since this cannot be integrated within Visual Studio, what I'm doing is I create a task (either in MSBuild, NAnt or Rake), that executes vsjitdebugger.exe in the end to attach it to my Visual Studio when debugging.
These are just my styles for now, you can maybe create your own style.

Resources