anoopb
anoopb

Reputation: 543

Trying to invoke PSCmdlet class from within C#

At first, I tried to simply declare a new instance of cmdlet but got an error that indicated I couldn't invoke powershell cmdlets of type pscmdlet from within a cmdlet.

in order to do this, i have to instantiate Powershell engine.

PowerShell ps = PowerShell.Create();
ps.AddCommand("Get-Info");

In my case, if i use Get-Process, that works just fine but Get-Info, which is another PSCmdlet in the same project doesn't seem to work.

Get-Name : The term 'Get-Info' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

I can invoke get-info manually from the powershell window but not from within my code.

Does this have to do with a modulepath maybe? or because my module isn't loaded in this newly instantiated engine?

if so, how do i get the new engine to load the module as well?

Here's how get-info is defined

namespace APICLI
{
[Cmdlet(VerbsCommon.Get, "Info")]
public class GetInfo : PSCmdlet

the cmdlet that is calling powershell.create() is get-name

namespace APICLI
{
[Cmdlet(VerbsCommon.Get, "Name")]
public class GetName : PSCmdlet

The Idea is that get-info gets everything that pertains to a certain object but you can use get-name to get specific information.

I was hoping to use this to create smaller more constrained cmdlets that would simply call get-info.

but I think it's related to the path since my project isn't imported into the newly created powershell engine instantiated within get-name.

thanks!

Upvotes: 0

Views: 1843

Answers (2)

carrvo
carrvo

Reputation: 638

You are right about it not being imported. While you could use Import-Module, a much more strongly-typed approach would be

PowerShell ps = PowerShell.Create();
ps.AddCommand(new CmdletInfo("Get-Info", typeof(GetInfo)));

While there are merits to calling PowerShell from C#, if you are tempted to do so likely you should re-think your approach because you are likely following an anti-pattern. In your case, Get-Name sounds like it is trying to return part of the information Get-Info is; in which case, you would be better off only having the one cmdlet and using Select-Object like so

Get-Info | Select-Object -Property Property1,Property2,Property3,etc

Upvotes: 0

anoopb
anoopb

Reputation: 543

I believe I've found the answer at

Hosted PowerShell cannot see Cmdlets in the same Assembly

You can add the following after Powershell.Create(); to include your current assembly.

        PowerShell ps = PowerShell.Create();
        ps.AddCommand("Import-Module").AddParameter("Assembly", System.Reflection.Assembly.GetExecutingAssembly());
        ps.Invoke();
        ps.Commands.Clear();

Thanks again for assisting.

Upvotes: 1

Related Questions