【问题标题】:Powershell script to change value in csproj file用于更改 csproj 文件中的值的 Powershell 脚本
【发布时间】:2021-03-28 05:07:59
【问题描述】:

我想在下面的 test.csproj 文件中更改 ProductVersion 标记的值。我只需要将 ProductVersion: 8A-0V-W3 第一次出现的值更改为 A0-B0-C0

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
    <ProductVersion>8A-0V-W3</ProductVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
    <DebugSymbols>true</DebugSymbols>
    <ProductVersion>PK-0X-SD</ProductVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
    <DebugType>none</DebugType>
    <ProductVersion>SD-AA-SW</ProductVersion>
  </PropertyGroup>

我想出了下面的命令,但它会删除所有出现的标签。有没有办法只删除第一次出现,然后将更新的标签插入同一位置

get-content ./test.csproj | select-string -pattern 'ProductVersion' -notmatch | Out-File ./test1.csproj

【问题讨论】:

    标签: powershell scripting


    【解决方案1】:

    使用Select-Xml cmdlet:

    $firstVersion = (
      Select-Xml //ns:ProductVersion test.csproj -Namespace @{ ns='http://schemas.microsoft.com/developer/msbuild/2003' }
    )[0].Node
    
    $firstVersion.InnerText = 'A0-B0-C0'
    
    $firstVersion.OwnerDocument.Save((Join-Path $PWD.ProviderPath test1.csproj))
    

    【讨论】:

    • 有没有一种方法可以应用相同的命令来修改以下文件中的一个字符串标签,例如将 com.ab c.com 的值更改为 com.def.com,而不使用数组与前面的命令一样,指定出现次数 - 因为文件可能会更新 MinimumOSVersion12.0CFBundleDisplayNamemycompanyyCFBundleIdentifier com.abc.comCFBundleVersion1.0.1CFBundleShortVersionString1.0
    • @ninja666,你会想要像Select-String '//string[.="com.abc.com"]' some.xml 这样的东西。如果您需要进一步的帮助,请提出新问题;完成后,请随时在此处通知我。
    【解决方案2】:
    $oldValue = "8A-0V-W3";
    $newValue = "A0-B0-C0";
    $projFile = "./test.csproj";
    
    $config = (Get-Content $projFile) -as [Xml];
    $ns = New-Object System.Xml.XmlNamespaceManager($config.NameTable);
    $ns.AddNamespace("cs", $config.DocumentElement.NamespaceURI);
    
    $config.DocumentElement.SelectNodes("//cs:ProductVersion", $ns) | % {
        $node = $_;
        if ($node.InnerText -ieq $oldValue) {
            $node.InnerText = $newValue;
        }
    }
    
    $config.Save($projFile);
    

    【讨论】:

    • 两个旁白:.NET 的工作目录通常与 PowerShell 的不同,因此您应该始终将 完整 路径传递给 .NET 方法调用。假设它已经存在,使用Convert-Path 将相对路径转换为完整路径。有关详细信息,请参阅this answer
    • Get-Content 通常不是用于 XML 文件的正确命令,因为它将(在没有 BOM 的情况下)假定 默认编码 i> 而不是尊重给定文件声明中潜在的特定编码(例如,&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;)。安全的方法是使用$xmlDoc = [xml]::new(),然后使用$xmlDoc.Load('/full/path/to/some.xml') - 需要使用完整 路径。如果您碰巧知道Get-Content 在特定情况下 可以安全使用,您可以使用$xmlDoc = [xml] (Get-Content -Raw some.xml) - 请注意-Raw 以提高性能。
    猜你喜欢
    • 1970-01-01
    • 2013-10-02
    • 2015-06-08
    • 2013-05-01
    • 2010-09-23
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    相关资源
    最近更新 更多