2

We want to store and manage PowerShell scripts in a database an execute them via C#. How can we discover the parameters of such a script before executing it? so we can set them to known values or prompt a user for values.

Some clarification:

We create a management system MS.

  1. An admin stores a PowerShell script in the MS database.
  2. Later a different admin selects this script from a list offered by the MS.
  3. MS discovers the parameters of the script.
  4. MS prompts the admin for values.
  5. MS executes the script with the parameters supplied.

        string testScript = @"
            {
                param(
                    [ValidateNotNullOrEmpty()]
                    [string]$Name
                )
                get-process $name
            ";
    
    Dictionary<string,object> DiscoverParameters()
    {
        using (PowerShell psi = PowerShell.Create())
        {
            psi.AddScript(testScript);
            var pars = new Dictionary<string,object>();
            //How do we get at the parameters
            return pars;
        }
    }
    
    void ExecuteScript(Dictionary<string,object> pars)
    {
        using (PowerShell psi = PowerShell.Create())
        {
            psi.AddScript(testScript);
            pars.ToList().ForEach(p => psi.AddParameter(p.Key, p.Value));
            Collection<PSObject> PSOutput = psi.Invoke();
            //...
        }
    }
    

2 Answers 2

3

You can use the PS parser, and access the parameter information via AST:

$scriptfile = '<full path to script file>'
$AST = [System.Management.Automation.Language.Parser]::ParseFile( $scriptfile,[ref]$null,[ref]$null)

$AST.ParamBlock.Parameters | ft
Sign up to request clarification or add additional context in comments.

Comments

2

mjolinor is correct that using the PowerShell parser is probably the best way to get the parameters. That example is in PowerShell, below is an example in C#. I'm not quite sure what you are looking for with the parameters being Dictionary<string, object>. Here we just stick the names into the list although there is other info you could pull out like the static type.

using System.Management.Automation;
using System.Management.Automation.Language;

static void Main(string[] args)
{
    const string testScript = @"
    param(
        [ValidateNotNullOrEmpty()]
        [string]$Name
    )
    get-process $name
";
    foreach(var parameter in GetScriptParameters(testScript))
    {
        Console.WriteLine(parameter);
    }
}

private static List<string> GetScriptParameters(string script)
{
    Token[] tokens;
    ParseError[] errors;
    var ast = Parser.ParseInput(script, out tokens, out errors);
    if (errors.Length != 0)
    {
        Console.WriteLine("Errors: {0}", errors.Length);
        foreach (var error in errors)
        {
            Console.WriteLine(error);
        }
        return null;
    }

    return ast.ParamBlock.Parameters.Select(p => p.Name.ToString()).ToList();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.