0

I'm having trouble trying to call a Powershell function from C#. Specifically, I'm getting stuck trying to pass a generic list of Project's to a powershell module function. Here is the code:

var script = @". \\server01\Modules\Runspace.ps1; Get-MyCommand";
var allProjects = _pmRepository.GetAllProjects();
using (Runspace runSpace = RunspaceFactory.CreateRunspace())
{
    runSpace.Open();
    PowerShell posh = PowerShell.Create();
    posh.Runspace = runSpace;
    posh.AddScript(script);
    posh.AddArgument(allProjects);

    Collection<PSObject> results = posh.Invoke();
}

The GetAllProjects() method returns a generic list of Project's and Project is a custom class. My module function signature looks like this:

function Get-MyCommand
{
    [CmdletBinding()]
    Param
    (
        [Parameter(ValueFromPipeline = $true)]
        [PSCustomObject[]] $Projects
    )
    Begin
    {}
    Process
    {
        $consumables = New-GenericList "Company.Project.Entities.Project"
        foreach($project in $projects)
        {
            if ($project.State -eq $ProjectStates.Development)
            {
                $consumables.Add($project)
            }
        }
    }
}

I'm getting this error when I try to iterate over the array:

{"Property 'State' cannot be found on this object. Make sure that it exists."}

Is it possible to do what I'm trying to do?

Edit: I used the below code for a while, but ended up consuming the back-end C# code for this web application. The load time to create a powershell session was just too great for our situation. Hope this helps.

    private void LoadConsumableProjects()
    {
        var results = new Collection<PSObject>();
        InitialSessionState iss = InitialSessionState.CreateDefault();
        iss.ImportPSModule(_modules);

        using (Runspace runSpace = RunspaceFactory.CreateRunspace(iss))
        {
            runSpace.Open();
            using (var ps = PowerShell.Create())
            {
                ps.Runspace = runSpace;
                ps.AddScript("Get-LatestConsumableProjects $args[0]");
                ps.AddArgument(Repository.GetAllProjects().ToArray());

                results = ps.Invoke();
                if (ps.Streams.Error.Count > 0)
                {
                    var errors = "Errors";
                }
            }
        }

        _projects = new List<Project>();
        foreach (var psObj in results)
        {
            _projects.Add((Project)psObj.BaseObject);
        }
    }
5
  • In your script, you dot source 'Runspace.ps1' and then call your function Get-MyCommand, without arguments you don't fortget $args ? Commented Sep 16, 2011 at 3:58
  • The argument is passed in when I'm constructing the Runspace and Powershell object. posh.AddArgument(allProjects); Commented Sep 16, 2011 at 4:22
  • Ok, but I was thinking that you have to write something like this var script = @". \\server01\Modules\Runspace.ps1; Get-MyCommand $args"; for the argument be passed tou your function Get-MyCommand Commented Sep 16, 2011 at 5:51
  • @Kiquenet I'll try to dig it up this afternoon for you. Commented Jun 11, 2012 at 19:16
  • 1
    @Kiquenet I updated the original question with the solution I used at the time. I ended up consuming the back end C# code as the time penalty for creating a powershell session was too great for our needs. Hope this helps. Commented Jun 12, 2012 at 18:49

1 Answer 1

1

Ok I put it as an answer because, I think you can test it. As I understand your code your pass an argument to your script :

posh.AddArgument(allProjects);

But inside your script you don't use this argument to pass to your Function. For me you can test :

var script = @". \\server01\Modules\Runspace.ps1; Get-MyCommand $args[0]";

In your script, you dot source 'Runspace.ps1' and then call your function Get-MyCommand without parameters. PowerShell get into the foreach loop with $project equal to null. Just beep if $Projects is null.

Sign up to request clarification or add additional context in comments.

4 Comments

I see what you mean now. I was under the impression that the AddArgument method was passing that argument to the function, not the script I'm asking it to run in the Runspace. I got further but I'm not getting this error: Cannot process argument transformation on parameter 'Projects'. Cannot convert the "Company.Project.Entities.Project[]" value of type "Company.Project.Entities.Project[]" to type "Company.Project.Entities.Project".
Also, the powershell function parameter is defined like this [Parameter(ValueFromPipeline = $true)] [Company.Project.Entities.Project[]] $Projects
It looks like _pmRepository.GetAllProjects() return only one project. Can you just declare $Projects without type and use $Projects.gettype to have a look to the type.
I removed the type constraint on the function parameter and added $paramType = $Projects.GetType() and reran and I'm getting this again: Property 'State' cannot be found on this object. Make sure that it exists.

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.