【问题标题】:Remove xmlns="" attribute when adding Reference element into csproj将引用元素添加到 csproj 时删除 xmlns="" 属性
【发布时间】:2012-06-06 13:44:04
【问题描述】:

我尝试在安装服务时通过 MSI 安装程序以编程方式将 dll 的引用添加到 csproj 文件中。

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

我将添加节点的源代码下面一行放入ProjectInstaller.cs的
protected override void OnAfterInstall(IDictionary savedState)

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);

代码输出

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

但是源代码将xmlns=""更多属性添加到R​​eference元素中。这段代码有什么问题,我将如何删除 xmlns="" 属性,因为 csproj 文件不采用自定义属性。

【问题讨论】:

  • 据我了解,您正在尝试从安装程序中修改刚刚安装的文件?这个逻辑可以移到构建时间吗?如果是这样,就复杂性和未来的维护而言,它是可取的。
  • @YanSklyarenko:不可能,因为如果我在构建时更改 csproj,那么我的 TFSBuild 和 MSBuild 会失败。
  • 好的,如果您将该 csproj 交付给最终用户,然后按照您的方式对其进行转换,您确定它会在之后编译吗?我看到您已经接受了答案,但我怀疑您选择的方式在概念上是错误的,我想帮助您。如果您分享在安装期间需要此行为的高级用例,那就太好了。
  • @YanSklyarenko:我在安装程序中向客户端提供了一个示例源代码。在项目中,我有 4 个项目参考。我将项目的源文件添加到 MSI Installer 中。现在的问题是 4 项目引用我需要将该引用转换为 dll 引用,因为项目不可用。来自 TFS 引用的项目和 dll 的当前引用我需要更改安装应用程序的应用程序文件夹中所有 dll 的引用。应用程序路径:C:\Programfiles\TestProject。源代码:C:\Programfiles\TestProject\Examples\TestProject。请指导我。等待您的回复。
  • 我仍然不确定我是否理解您的意图,但听起来您在构建期间的项目文件布局与客户端的布局不同。这可以这样解决:更改构建时文件布局以反映客户端的布局,但不要将那些不需要的文件包含到 MSI 安装程序中。因此,您不必在安装时修补 *.proj 文件 - 这些文件已经包含正确的相对引用。

标签: c# xml windows-installer xmldocument csproj


【解决方案1】:

C# 项目文件的默认命名空间是xmlns="http://schemas.microsoft.com/developer/msbuild/2003"。您没有指定任何名称空间,因此必须清除名称空间才能添加您想要的子项。设置正确的命名空间,你可能不会有问题。

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);

【讨论】:

    【解决方案2】:

    虽然这不是原始问题的答案,但我想分享我认为更好的做法,因为我看到了问题背后的设计问题。

    在交付软件时,应该更喜欢构建时复杂性而不是安装时复杂性。

    第一个完全在开发人员的控制之下,那个阶段的错误不是那么严重,可以测试。该问题很可能会在对最终用户造成损害之前被发现。

    后者对目标系统的影响更大。您永远不知道您安装到的确切环境。你不能从字面上依赖任何东西。而那个阶段的错误代价更高,并且随着人们下载您的软件,眨眼间就会传播开来。

    因此,重复我自己,更喜欢构建时复杂性而不是安装时复杂性。安装程序不应该修复应用程序本身的设计问题。仅将那些您在构建期间无法猜测的内容留给安装时间。

    在您的特定情况下,我想您可以在构建期间修改项目布局,以免使用 DLL 引用修补项目文件。教你的构建系统只在 MSI 包中包含必要的东西。

    希望这会有所帮助。

    【讨论】:

    • 你的建议对我很有用。但是客户需要一些带有安装程序的默认源代码,以便最终用户了解如何开发应用程序。他们甚至不允许我在 GAC 上部署自定义 Dll,以便最终用户从 GAC 获取参考。
    【解决方案3】:

    在您的var attribute = xml.CreateAttribute("Include", null); 行中,您创建没有附加命名空间URI 的属性。但是,在 MSBuild 文件中,默认命名空间(无命名空间前缀)通常设置为 xmlns="http://schemas.microsoft.com/developer/msbuild/2003"。当您使用 null 值明确指出 Include 属性与该命名空间无关时,Xml 编写器会覆盖相应文档片段的默认命名空间。

    尝试像这样创建你的属性:

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

    这同样适用于在下面几行创建HintPath 元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多