Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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);
        }
    }
share|improve this question
    
In your script, you dot source 'Runspace.ps1' and then call your function Get-MyCommand, without arguments you don't fortget $args ? –  JPBlanc Sep 16 '11 at 3:58
    
The argument is passed in when I'm constructing the Runspace and Powershell object. posh.AddArgument(allProjects); –  drohm Sep 16 '11 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 –  JPBlanc Sep 16 '11 at 5:51
    
@Kiquenet I'll try to dig it up this afternoon for you. –  drohm Jun 11 '12 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. –  drohm Jun 12 '12 at 18:49

1 Answer 1

up vote 1 down vote accepted

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.

share|improve this answer
    
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". –  drohm Sep 16 '11 at 13:35
    
Also, the powershell function parameter is defined like this [Parameter(ValueFromPipeline = $true)] [Company.Project.Entities.Project[]] $Projects –  drohm Sep 16 '11 at 13:41
    
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. –  JPBlanc Sep 16 '11 at 14:26
    
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. –  drohm Sep 16 '11 at 14:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.