question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Pass parameter by reference to a cmdlet written in C#

See original GitHub issue

I am trying to write a simple PowerShell cmdlet in C# that accepts an instance of ArrayList and adds an item to it. The issue I’ve encountered is that cmdlet receives a copy of the collection so modifying it inside the cmdlet does not work. I assume that this is an intended behavior, but cannot find any proof for that in the documentation. I looked specifically here: https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/cmdlet-overview?view=powershell-7.1, but also read other sections. Below is a program to reproduce the issue. Can anyone point to the documentation or explain why cmdlet parameter binding works this way please?

Steps to reproduce

using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace CustomPowerShellCmdlet
{
    class Program
    {
        static void Main(string[] args)
        {
            string powerShellScript = @"
Write-Output ('PowerShell Version is ' + $PSVersionTable.PSVersion)

$A  = New-Object System.Collections.ArrayList
$A.Add('3') | Out-Null
Write-Output  ('Count is ' + $A.Count)

$B  = New-Object System.Collections.ArrayList
Add-CollectionItem -Collection $B -Item '1'
Add-CollectionItem -Collection $B -Item '2'
foreach ($Item in $B) {
    Write-Output $Item
}
Write-Output  ('Count is ' + $B.Count)
";

            var output = RunPowerShellScript(powerShellScript);

            foreach (PSObject psObject in output)
            {
                Console.WriteLine(psObject.BaseObject.ToString());
            }
        }

        private static Collection<PSObject> RunPowerShellScript(string powerShellScript)
        {
            InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
            initialSessionState.Commands.Add(new SessionStateCmdletEntry("Add-CollectionItem", typeof(AddCollectionItemCmdlet), null));

            using (var runspace = RunspaceFactory.CreateRunspace(initialSessionState))
            {
                runspace.Open();

                using (var ps = PowerShell.Create())
                {
                    ps.Runspace = runspace;

                    ps.AddScript(powerShellScript);


                    return ps.Invoke();
                }
            }
        }

        [Cmdlet(VerbsCommon.Add, "CollectionItem")]
        public class AddCollectionItemCmdlet : Cmdlet
        {
            [Parameter(Mandatory = true)]
            [AllowEmptyCollection]
            public ArrayList Collection { get; set; }

            [Parameter(Mandatory = true)]
            public object Item { get; set; }

            protected override void BeginProcessing()
            {
                Collection.Add(Item);
            }
        }
    }
}

Expected behavior

Actual behavior


Environment data

PSVersion 7.1.0 PSEdition Core GitCommitId 7.1.0 OS Microsoft Windows 10.0.19041 Platform Win32NT PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 WSManStackVersion 3.0


Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
AlexKichkailocommented, Dec 11, 2020

Thank you very much, @mklement0 ! I am closing this issue then.

1reaction
AlexKichkailocommented, Dec 11, 2020

@mklement0 thanks. This blows my mind actually. What is interesting is that if you change $al = [System.Collections.ArrayList] @() to New-Object System.Collections.ArrayList then it will output nothing. Is this a bug in PowerShell?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Passing by reference in C - pointers
Passing by reference literally just means passing the memory address of where a variable is stored rather than the variable's value itself. That ......
Read more >
Pass by reference
Passing by by reference refers to a method of passing the address of an argument in the calling function to a corresponding parameter...
Read more >
Pass by reference (C++ only)
Pass -by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function....
Read more >
How to pass the parameters in the PowerShell function
Here, we are passing the $name in the WriteName function and $str variable in the function catches the parameter so, inside the function,...
Read more >
about Functions Advanced Parameters - PowerShell
Dynamic parameters are parameters of a cmdlet, function, or script that are available only under certain conditions. For example, several ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found