0

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!

anoopb
  • 533
  • 4
  • 6
  • 20
  • Where is get-info defined? can you show it? – DavidG Oct 14 '14 at 00:22
  • Are you creating a new powershell instance within a cmdlet? – Mike Zboray Oct 14 '14 at 00:22
  • @mikez yes, it's within a cmdlet. But the error message i'm getting seems to be around a module path. I wonder if I adjust my PSModulePath, that will fix it. – anoopb Oct 14 '14 at 00:42
  • @davidG, sure it's defined within the namespace of the very same project. Edited the post to show where it's located. – anoopb Oct 14 '14 at 00:43
  • Sorry folks. I think I found the answer at http://stackoverflow.com/questions/7560728/hosted-powershell-cannot-see-cmdlets-in-the-same-assembly – anoopb Oct 14 '14 at 00:54
  • Honestly, I don't think you should be creating another engine instance from within a cmdlet. What you should do is refactor your code so that multiple cmdlets (Get-Info and Get-Name) can share a set of common objects/methods. That said I don't even think that's the best way to do it. Create an `InitialSessionState` that has the module loaded and use that when calling `PowerShell.Create`. – Mike Zboray Oct 14 '14 at 01:05

2 Answers2

1

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.

Community
  • 1
  • 1
anoopb
  • 533
  • 4
  • 6
  • 20
0

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
carrvo
  • 511
  • 5
  • 11