0

I try to programmatic add the reference of dll into csproj file at time of installation service through the MSI Installer.

<Reference Include="TestProject">
    <HintPath>..\..\TestProject.dll</HintPath>
</Reference>

I put below line of source code of add node into
protected override void OnAfterInstall(IDictionary savedState) of ProjectInstaller.cs

var refnode = xml.CreateElement("Reference");
var attribute = xml.CreateAttribute("Include", null);
attribute.Value = "TestProject";
refnode.Attributes.Append(attribute);
var hintPath = xml.CreateNode(XmlNodeType.Element, "HintPath", null);
hintPath.InnerText = "..\..\TestProject.dll";
refnode.AppendChild(hintPath);
xml.AppendChild(refnode);
xml.Save(file);

Output of code

<Reference Include="TestProject" xmlns="">
    <HintPath>..\..\TestProject.dll</HintPath>
</Reference>

But the source code add xmlns="" more attribute into Reference element. what is wrong in this code how I will remove xmlns="" attribute because csproj file not take custom attribute.

Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
Saroop Trivedi
  • 2,245
  • 6
  • 31
  • 49
  • As far as I understand, you're trying to modify the file you've just installed from within the installer? Can this logic be moved to the build time? If it does, it's preferable in terms of complexity and future maintenance. – Yan Sklyarenko Jun 06 '12 at 13:58
  • @YanSklyarenko: Not possible because if i change the csproj at time of build then my TFSBuild and MSBuild goes failed. – Saroop Trivedi Jun 06 '12 at 14:11
  • Ok, if you deliver that csproj to the end user, and then transform it the way you are going to, are you sure it will compile afterwards? I see you've already accepted the answer, but I suspect the way you chose is conceptually wrong, and I'd like to help you. It would be great if you share the high-level use case which requires this behavior during install time. – Yan Sklyarenko Jun 06 '12 at 15:25
  • @YanSklyarenko: I provide the one example source code to client in installer. In project I have 4 project references. I add the source files of project into MSI Installer. Now problem is 4 project reference i need to convert that reference to dlls reference because project are not available.Current reference of project and dll from TFS reference I need to change reference of all dlls from Application folder where I installed the application. application Path : C:\Programfiles\TestProject. Source code : C:\Programfiles\TestProject\Examples\TestProject. Please guide me. Waiting for your reply. – Saroop Trivedi Jun 07 '12 at 06:21
  • I still not sure I understand your intention, but it sounds like your project files layout during the build time is not the same as the one at the client. This can be solved like this: change your build time files layout to reflect the one at the client, but don't include those files you don't need into the MSI installer. Thus, you won't have to patch *.proj files at install time - those will already contain correct relative references. – Yan Sklyarenko Jun 07 '12 at 08:31
  • @YanSklyarenko: As per the client requirement. I need to pass the sourcefiles of project into MSI Installer without affecting the TFS build and MSBuild of project. So I copy the source file through the Output option in MSI Installer and then change the reference of all project to dll references.What is wrong in that? – Saroop Trivedi Jun 07 '12 at 09:17
  • I've shaped my thoughts into an answer to this thread. – Yan Sklyarenko Jun 07 '12 at 12:15
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/12254/discussion-between-sarooptrivedi-and-yan-sklyarenko) – Saroop Trivedi Jun 07 '12 at 13:05

3 Answers3

2

The default namespace for C# project files is xmlns="http://schemas.microsoft.com/developer/msbuild/2003". You didn't specify any namespace so the namespace had to be cleared to be able to add the children you wanted. Set the right namespaces and you probably won't have a problem.

var ns = "http://schemas.microsoft.com/developer/msbuild/2003";
var refnode = xml.CreateElement("Reference", ns);
var attribute = xml.CreateAttribute("Include", ns);
attribute.Value = "TestProject";
refnode.Attributes.Append(attribute);
var hintPath = xml.CreateNode(XmlNodeType.Element, "HintPath", ns);
hintPath.InnerText = "..\..\TestProject.dll";
refnode.AppendChild(hintPath);
xml.AppendChild(refnode);
xml.Save(file);
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
1

Although this is not the answer to the original question, I'd like to share what I consider better practices, since I see the design issue behind the question.

When delivering software, one should prefer build-time complexity over install-time complexity.

The first one is fully under developer's control, and the mistake on that phase is not that critical and can be tested. The problem will most likely be caught before it makes damage to the end users.

The latter one is more has much higher effect on the target system. You never know the exact environment you install onto. You can't rely on anything literally. And the mistake on that phase costs much more and is spread in a blink of an eye as people download your software.

So, to repeat myself, prefer build-time complexity over install-time complexity. The installation program should never fix the design issues of the application itself. Leave only those things to the installation time which you can't guess during build.

In your particular case, I suppose you can modify the projects layout during the build in order not to patch project files with DLL references. Teach your build system to include only necessary stuff into the MSI package.

Hope this helps.

Yan Sklyarenko
  • 31,557
  • 24
  • 104
  • 139
  • Your suggestion is very useful for me. But client want some default source code with installer so that end use understand how to develop the application. they are not even allow me to deploy custom Dlls on GAC so that end user take the reference from GAC. – Saroop Trivedi Jun 07 '12 at 13:04
0

In your var attribute = xml.CreateAttribute("Include", null); line, you create the attribute with no namespace URI attached. However, in MSBuild files, the default namespace (no namespace prefix) is usually set to xmlns="http://schemas.microsoft.com/developer/msbuild/2003". As you explicitely indicate with your null value that the Include attribute is not associated with that namespace, the Xml writer overrides the default namespace for the respective document fragment.

Try creating your attribute like this:

var attribute = xml.CreateAttribute("Include", "http://schemas.microsoft.com/developer/msbuild/2003");

The same applies to creating the HintPath element a few lines below.

O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114