How can one replace the extension of a file path s

2019-08-28 01:54发布

问题:

I have the following lines in my MSBuild project file:

<PropertyGroup>
    <TestResultsFileName Condition=" '$(TestResultsFileName)' == '' ">
        TestResults.trx
    </TestResultsFileName>
    <TestResultsFilePath>$(OutDir)\$(TestResultsFileName)</TestResultsFilePath>
</PropertyGroup>

I need to create another file, having the same name as TestResultsFilePath only with the .xml extension. So I want to have a property to hold the file path of the other file.

At first, I thought that something like this would work:

<PropertyGroup>
    <NUnitResultsFilePath>
        $(OutDir)\$(TestResultsFileName->'%(Filename).xml')
    </NUnitResultsFilePath>
</PropertyGroup>

And, of course, it did not, because TestResultsFileName is not an item collection. Unfortunately, it cannot be such, because it is a parameter to some task that expects a simple value, not a collection.

So, my question is how can I replace the extension of the TestResultsFileName property value with .xml?

Thanks.

回答1:

Never mind. I have written a custom task to do the job:

    public class ReplaceExtension : Task
    {
        [Required]
        public string FilePath { get; set; }

        public string NewExtension { get; set; }

        [Output]
        public string Result { get; set; }

        public override bool Execute()
        {
            if (string.IsNullOrEmpty(FilePath))
            {
                Log.LogError("FilePath cannot be empty!");
                return false;
            }

            try
            {
                int length = FilePath.Length;
                int startIndex = length;
                int oldExtensionLength = 0;
                while (--startIndex >= 0)
                {
                    char ch = FilePath[startIndex];
                    if (ch == '.')
                    {
                        oldExtensionLength = length - startIndex;
                        break;
                    }
                    if (ch == Path.DirectorySeparatorChar || 
                        ch == Path.AltDirectorySeparatorChar || 
                        ch == Path.VolumeSeparatorChar)
                    {
                        break;
                    }
                }

                bool isNewExtensionEmpty = string.IsNullOrEmpty(NewExtension) ||
                    (NewExtension.Length == 1 && NewExtension[0] == '.');

                if (isNewExtensionEmpty)
                {
                    // The new extension is empty - remove the old extension.
                    if (oldExtensionLength > 0)
                    {
                        Result = FilePath.Remove(startIndex, oldExtensionLength);
                    }
                    else
                    {
                        Result = FilePath;
                    }
                }
                else
                {
                    // Replace the old extension with the new one.
                    StringBuilder sb = new StringBuilder(FilePath.Length - oldExtensionLength +
                        NewExtension.Length + (NewExtension[0] == '.' ? 0 : 1));
                    sb.Append(FilePath, 0, FilePath.Length - oldExtensionLength);
                    if (NewExtension[0] != '.')
                    {
                        sb.Append('.');
                    }
                    sb.Append(NewExtension);
                    Result = sb.ToString();
                }
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex);
            }
            return !Log.HasLoggedErrors;
        }
    }

I am using it like this:

  <Target Name="CreateProperties">
    <ReplaceExtension FilePath="$(TestResultsFilePath)" NewExtension="xml">
      <Output TaskParameter="Result" PropertyName="NUnitResultsFilePath"/>
    </ReplaceExtension>
  </Target>