LuckyLikey
LuckyLikey

Reputation: 3840

MSBuild inline Task does not work (not caused by program logic)

I have created an inline Task which will return the latest two version-strings of a list of version-strings.

Task:

<UsingTask TaskName="GetLatestVersions" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
        <AllVersions ParameterType="System.String" Required="true" />
        <CurrentVersion ParameterType="System.String" Output="true" />
        <LastVersion ParameterType="System.String" Output="true" />
    </ParameterGroup>
    <Task>
        <Using Namespace="System" />
        <Code Type="Fragment" Language="cs">
            <![CDATA[
        var currentVersion = "0.0.0.0";
        var lastVersion = "0.0.0.0";

        var compareWithCurrent = new Func<string, string, bool>((toCompare, with) =>
        {
            var convertToIntArray = new Func<string, int[]>(version =>
            {
                int mayor, minor, build, revision;
                var parts = version.Split('.');

                if (int.TryParse(parts[0], out mayor) &&
                    int.TryParse(parts[1], out minor) &&
                    int.TryParse(parts[2], out build) &&
                    int.TryParse(parts[3], out revision))
                {
                    return new[] {mayor, minor, build, revision};
                }
                return new[] {0, 0, 0, 0};

            });
            var current = convertToIntArray(with);
            var toCompareArr = convertToIntArray(toCompare);

            return toCompareArr[0] > current[0] ||
                    toCompareArr[0] == current[0] && toCompareArr[1] > current[1] ||
                    toCompareArr[0] == current[0] && toCompareArr[1] == current[1] && toCompareArr[2] > current[2] ||
                    toCompareArr[0] == current[0] && toCompareArr[1] == current[1] && toCompareArr[2] == current[2] && toCompareArr[3] > current[3];

        });

        foreach (var version in AllVersions.Replace("\\", "").Split(';'))
        {
            if (compareWithCurrent(version, currentVersion))
            {
                lastVersion = currentVersion;
                currentVersion = version;
            }
        }

        CurrentVersion = currentVersion;
        LastVersion = lastVersion;
    ]]>
        </Code>
    </Task>
</UsingTask>

Call:

    <GetLatestVersions AllVersions="@Versions">
        <Output PropertyName="CurrentVersionProperty" TaskParameter="CurrentVersion" />
        <Output PropertyName="LastVersionProperty" TaskParameter="LastVersion" />
    </GetLatestVersions>

@Versions contains a string like this (dumped via Message):

\3.7.1.3846;\3.7.2.3884;\3.7.3.3962;\3.7.4.4112;\3.8.0.4274;\3.9.0.4362;\3.9.0.4386

The variables CurrentVersionProperty and LastVersionProperty are both 0.0.0.0

What I tried

Normally you would say "The code inside the Task must be false" - thats what I expected.

I have created and debugged the following source code (Console Program) and the Codelogics seem to work well.

class Program
{
    static void Main(string[] args)
    {
        var versions =
             @" \1.8.19.0;\1.9.23.0;\2.1.3.0;\2.10.0.2304;\2.10.0.2326;\2.10.0.2367;\2.11.0.2422;\2.12.0.2543;\2.14.0.2716;\2.15.0.2779;\2.16.0.2881;\2.16.0.2888;\2.17.0.2977;\2.18.0.3093;\2.2.19.0;\2.2.27.0;\2.2.29.0;\2.3.7.0;\2.3.8.568;\2.4.0.941;\2.5.0.1448;\2.6.0.1642;\2.8.0.2008;\2.8.0.2045;\2.9.0.2176;\2.9.0.2222;\3.0.0.3174;\3.0.0.3174-Prof;\3.0.0.3229;\3.1.0.3255;\3.10.0.4470;\3.10.0.4480;\3.10.1.4538;\3.11.0.4656;\3.12.0.4769;\3.12.1.4872;\3.13.0.4985;\3.13.0.5009;\3.13.0.5019;\3.13.1.5094;\3.13.1.5171;\3.14.0.5217;\3.2.0.3342;\3.2.0.3370;\3.3.0.3408;\3.4.0.3546;\3.5.0.3602;\3.6.0.3664;\3.7.0.3794;\3.7.1.3846;\3.7.2.3884;\3.7.3.3962;\3.7.4.4112;\3.8.0.4274;\3.9.0.4362;\3.9.0.4386";

        string current, last;
        GetLatestVersions(out current, out last, versions);

    }

    public static void GetLatestVersions(out string CurrentVersion, out string LastVersion, string AllVersions)
    {
        //EXACTLY the same code as in Task - omitted to save space
    }
}

I have also tried changing Variablenames.

My Guesses:

The problem has to be somwhere inside MSBuild. Maybe there's a Problem with the Outparameters or what ever. I'd appreciate any help! Thank you.

Upvotes: 1

Views: 176

Answers (1)

stijn
stijn

Reputation: 35901

Seems like a simple typo:

<GetLatestVersions AllVersions="@Versions">

should of course be a proper ItemGroup expansion so

<GetLatestVersions AllVersions="@(Versions)">

Instead of reinventing the wheel I'd also suggest you use the Version class since that already provides parsing/less than/greater than/... so your compareWithCurrent can be rewritten as

var compareWithCurrent = new Func<string, string, bool>( ( toCompare, with ) =>
{
  return new Version( toCompare ) > new Version( with );
} );

Btw if I input 1.5.0.0;1.2.0.0;1.3.0.0 into your code it tells me currentVersion is 1.5.0.0 and lastVersion is 0.0.0.0. Not exactly what I'd expect - then again, I'm not sure what the code is supposed to do exactly.

Upvotes: 2

Related Questions