1

There are several examples in the common parameters, like ErrorVariable, InformationVariable;

get-item foad: -ev foo
$foo

"get-item" will create and set the value for $foo to an instance of ErrorRecord. How can I create my own parameters that do something similar?

Basically, I'm creating a cmdlet that uses WriteObject() to write data to the pipeline, but then I also have some additional information that I want to allow users to access - essentially out of band data - that isn't part of the pipeline.

An example of an out parameter in C#:

public class ExampleCode
{
    public int GetMyStuff(int param1, out string someVar)
    {
        someVar = "My out-of-band result";
        return param1 + 1;
    }

    public static void RunMe()
    {
        ExampleCode ex = new ExampleCode();
        string value;
        int result = ex.GetMyStuff(41, out value);

        Console.WriteLine($"result is {result}, OOB Data is {value}");
    }
}

I'm looking for how to convert "GetMyStuff()" into a powershell cmdlet.

[Cmdlet(VerbsCommon.Get, "MyStuff")]
public class ExampleCmdLet : PSCmdlet
{
    [Parameter(Mandatory = false)] int param1;
    [Parameter(Mandatory = false)] string someVar; // How to make this [out] ?
    protected override void ProcessRecord()            
    {
        someVar = "My out-of-band result";
        WriteObject(param1 + 1);
    }
}

1 Answer 1

2

You're looking to set a PowerShell variable, not a .NET variable.

Accessing PowerShell variables requires accessing them via the caller's session state.

In System.Management.Automation.PSCmdlet-derived cmdlets you can set variables via this.SessionState.PSVariable.Set(<varName>, <value>):

# Compile a Get-MyStuff cmdlet and import it into the current session.
Add-Type -TypeDefinition @'
using System.Management.Automation;

[Cmdlet(VerbsCommon.Get, "MyStuff")]
public class ExampleCmdLet : PSCmdlet
{
    [Parameter()] public int Param1 { get; set; }
    [Parameter()] public string SomeVar { get; set; }

    protected override void ProcessRecord()
    {

        // Assign to the $SomeVar variable in the caller's context.
        this.SessionState.PSVariable.Set(SomeVar, 42);

        WriteObject(Param1 + 1);
    }

}
'@ -PassThru | % Assembly | Import-Module                                                                           #'

# Call Get-MyStuff and pass the *name* of the 
# variable to assign to, "targetVariable", which sets
# $targetVariable:
Get-MyStuff -Param1 666 -SomeVar targetVariable
# Output the value of $targetVariable
$targetVariable

The above yields:

667  # Output from the cmdlet, via WriteObject()
42   # Value of $targetVariable, set by Get-MyStuff
Sign up to request clarification or add additional context in comments.

1 Comment

To expand on this answer - accepting a string variable name is the canonical way to do this in PowerShell - e.g. Tee-Object -Variable MyVar creates $MyVar, or the automatic ErrorVariable parameter on all cmdlets. If you're nice, you'll support the + prefix to append to an existing ArrayList. An alternate way to do it is to accept a parameter of type [ref], but that's not very powershelly.

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.