RunAsync() fails with arguments passed

The following script failed to execute, because ScriptRun.RunAsync() throws an exception, even though the program code is valid → System.Reflection.TargetParameterCountException: ‘Parameter count mismatch.’.

The project is very simple, a console app with basic scripting - but using async Tasks.

Project:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <RootNamespace>Bug_in_Alternet</RootNamespace>
    <ImplicitUsings>disable</ImplicitUsings>
    <Nullable>disable</Nullable>
    <Platforms>x64</Platforms>
  </PropertyGroup>

	<ItemGroup>
		<PackageReference Include="Alternet.Studio.Scripter" Version="10.0.5" />
	</ItemGroup>

</Project>

Program.cs:

using Alternet.Scripter;
using System;
using System.Threading.Tasks;

class Program
{
    const string AsyncScript = """
            using System;
            using System.Threading.Tasks;

            class AsyncScriptProgram 
            {
                static async Task Main(string[] args)
                {
                    Console.WriteLine($"\t{args.Length} Args:");
                    for (int i = 0; i < args.Length; i++)
                        Console.WriteLine($"\tArg[{i}]: {args[i]}");

                    Console.WriteLine($"\tWait a bit");
                    await Task.Delay(100);
                }
            }
        """;

    public static async Task Main(string[] args)
    {
        Console.WriteLine("Create Script Runtime");

        ScriptRun scriptRun = new ScriptRun()
        {
            AssemblyKind = ScriptAssemblyKind.ConsoleApplication,
            ScriptMode = ScriptMode.Debug,
            ScriptLanguage = ScriptLanguage.CSharp,
            Platform = ScriptPlatform.X64,
        };
        scriptRun.ScriptSource.FromScriptCode(AsyncScript);
        scriptRun.ScriptSource.WithSystemReferences(ScriptTechnologyEnvironment.System, WithSystemReferencesFlags.None);

        Console.WriteLine("Compile Script");
        if (!scriptRun.Compile())
        {
            Console.Error.WriteLine("Failed to compile Script!");
            foreach (ScriptCompilationDiagnostic compileError in scriptRun.ScriptHost.CompilerErrors)
                Console.Error.WriteLine(compileError.ToString());
        }
        else
            Console.WriteLine("Successfully compiled Script");

        string[] scriptArgs = ["Hallo", "Welt", "der", "Programmierer"];

        Console.WriteLine("Run Script");
        await scriptRun.RunAsync(scriptArgs);
        Console.WriteLine("Completed Script");

        Console.WriteLine("Done, press key to exit");
        Console.ReadKey();
    }
}

Thank you for the bug report. I was able to reproduce the issue with your sample project. We are currently investigating the cause and working on a fix. I will post an update here—hopefully by tomorrow—once we have a solution or further information.

There were a bug in ScriptMethod.InvokeMainMethod. With the fix it works fine on your sample project. We will test it in other scenarios and hope to include with the next build which is planned very soon.

1 Like

Awesome! Thanks for the fast response.

This was fixed in 10.0.6 build which was just released.

The actual bug with async Main(string args) is now fixed in 10.0.6, but there is another bug which is directly related - which maybe got broken in that fix.

The following script does not run, because the arguments string array are always 1 and contains a single element, that is an string array with the actual arguments.

class ScriptProgram 
{
    public static int Main(string[] args)
    {
        Console.WriteLine($"\t{args.Length} Args:");
        for (int i = 0; i < args.Length; i++)
            Console.WriteLine($"\tArg[{i}]: {args[i]}");

        if (args.Length == 0) {
            Console.Error.WriteLine($"\tNo file arguments passed");
            return -1;
        }

        for (int i = 0; i < args.Length; i++) {
            string filePath = args[i];
            Console.WriteLine($"\tOpen file: {filePath}");
            // ...
        }

        return 0;
    }
}

That script is run like this (no async!):

string[] scriptArgs = ["FileA", "FileB", "FileC"]; // Is just an example

Console.WriteLine($"Run Script with args '{string.Join("|", scriptArgs)}'");
try
{
    object returnValue = scriptRun.Run(scriptArgs);
    Console.WriteLine($"Completed Script with return value: {returnValue}");
}
catch (Exception e)
{
    Console.Error.WriteLine($"Failed to Run Script:\n{e.ToString()}");
}

The console output of the script shows clearly what is going wrong:

        1 Args:
        Arg[0]: System.String[]
        Open file: System.String[]