none
PowerShell via Managed C++: PSCmdlet vs ps command vs powershell vs Cmdlet Classes RRS feed

  • Question

  • Hi,

    I am trying to execute PS Command(Via Managed C++ code). I found so many variants for the same.

    Can someone explain me whats the difference between below 4 or more if there any any such:
    PSCmdlet class vs ps command class vs powershell class vs Cmdlet Classes below:

    1. https://msdn.microsoft.com/en-in/library/system.management.automation.powershell(v=vs.85).aspx

    2. https://msdn.microsoft.com/en-us/library/system.management.automation.pscommand_members(v=vs.85).aspx

    3. https://msdn.microsoft.com/en-us/library/ms714395(v=vs.85).aspx

    Its so confusing.

    Thanks !



    • Edited by sdkjain Thursday, April 14, 2016 11:31 AM
    Thursday, April 14, 2016 11:29 AM

Answers

  • Hi sdkjain,

    Let's focus on Pscommand vs Powershell class.

    Powershell class provides methods that are used to create a pipeline of commands and invoke those commands either synchronously or asynchronously within a runspace. we can add scripts or commands to execute. Call the AddScript() and AddCommand()methods to add this content to the execution pipeline.  

      /// <param name="args">This parameter is not used.</param>
        private static void Main(string[] args)
        {
          // Call the PowerShell.Create() method to create an 
          // empty pipeline.
          PowerShell ps = PowerShell.Create();
    
          // Call the PowerShell.AddCommand(string) method to add 
          // the Get-Process cmdlet to the pipeline. Do 
          // not include spaces before or after the cmdlet name 
          // because that will cause the command to fail.
          ps.AddCommand("Get-Process");
    
          Console.WriteLine("Process                 Id");
          Console.WriteLine("----------------------------");
    
          // Call the PowerShell.Invoke() method to run the 
          // commands of the pipeline.
            foreach (PSObject result in ps.Invoke())
          {
            Console.WriteLine(
                    "{0,-24}{1}",
                    result.Members["ProcessName"].Value,
                    result.Members["Id"].Value);
          } // End foreach.
        } // End Main.
     

    Pscommand defines a pipeline that can be run by a PowerShell object.

     static void Main(string[] args)
        {
          // Using the PSCommand object, add the cmdlet 
          // to the command pipeline.
          PSCommand cmd = new PSCommand();
                    cmd.AddCommand("Get-Process");
          
          // Using the PowerShell object, set the command
          // pipeline and invoke the pipeline synchronously.
          PowerShell ps = PowerShell.Create();
          ps.Commands = cmd;
    
          foreach (PSObject result in ps.Invoke())
          {
            Console.WriteLine("{0,-20}{1}",
                    result.Members["ProcessName"].Value,
                    result.Members["Id"].Value);
          } // End foreach.
        } // End Main

    Compare above two sample, they are all show how to synchronously invoke a pipeline that contains a Get-Process cmdlet. 

    Cmdlet VS PSCmdlet Class

    A cmdlet is a lightweight command that is used in the Windows PowerShell environment.

    A cmdlet class can derived from two different classes: Cmdlet and PSCmdlet. The difference is how much you depend on the Windows PowerShell environment. When deriving from Cmdlet, you aren't really depending on PowerShell. You are not impacted by any changes in the PowerShell runtime. In addition, your cmdlet can be invoked directly from any application instead of invoking it through the Windows PowerShell runtime.

    In most cases, deriving from Cmdlet is the best choice, except when you need full integration with the PowerShell runtime, access to session state data, call scripts etc. Then, you'll derive from PSCmdlet.

    For more details, please check this nice article  http://www.codeproject.com/Articles/20867/Build-a-PowerShell-cmdlet

    Best regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Friday, April 15, 2016 3:06 AM
  • It says "pipeline" so I think it's executing a command like this:

    invoke-item C:\Users\Desktop\Download.png | new-item -path C:\Users\Desktop\ -name test.txt -type file -value 'some text'

    and because invoke-item does not output anything here, new-item is not executed.

    Perhaps you need to call PSCommand.AddStatement between the commands. PowerShell 2.0 does not support it though, so I didn't try it.

    Thursday, April 21, 2016 5:34 PM

All replies

  • Hi sdkjain,

    Let's focus on Pscommand vs Powershell class.

    Powershell class provides methods that are used to create a pipeline of commands and invoke those commands either synchronously or asynchronously within a runspace. we can add scripts or commands to execute. Call the AddScript() and AddCommand()methods to add this content to the execution pipeline.  

      /// <param name="args">This parameter is not used.</param>
        private static void Main(string[] args)
        {
          // Call the PowerShell.Create() method to create an 
          // empty pipeline.
          PowerShell ps = PowerShell.Create();
    
          // Call the PowerShell.AddCommand(string) method to add 
          // the Get-Process cmdlet to the pipeline. Do 
          // not include spaces before or after the cmdlet name 
          // because that will cause the command to fail.
          ps.AddCommand("Get-Process");
    
          Console.WriteLine("Process                 Id");
          Console.WriteLine("----------------------------");
    
          // Call the PowerShell.Invoke() method to run the 
          // commands of the pipeline.
            foreach (PSObject result in ps.Invoke())
          {
            Console.WriteLine(
                    "{0,-24}{1}",
                    result.Members["ProcessName"].Value,
                    result.Members["Id"].Value);
          } // End foreach.
        } // End Main.
     

    Pscommand defines a pipeline that can be run by a PowerShell object.

     static void Main(string[] args)
        {
          // Using the PSCommand object, add the cmdlet 
          // to the command pipeline.
          PSCommand cmd = new PSCommand();
                    cmd.AddCommand("Get-Process");
          
          // Using the PowerShell object, set the command
          // pipeline and invoke the pipeline synchronously.
          PowerShell ps = PowerShell.Create();
          ps.Commands = cmd;
    
          foreach (PSObject result in ps.Invoke())
          {
            Console.WriteLine("{0,-20}{1}",
                    result.Members["ProcessName"].Value,
                    result.Members["Id"].Value);
          } // End foreach.
        } // End Main

    Compare above two sample, they are all show how to synchronously invoke a pipeline that contains a Get-Process cmdlet. 

    Cmdlet VS PSCmdlet Class

    A cmdlet is a lightweight command that is used in the Windows PowerShell environment.

    A cmdlet class can derived from two different classes: Cmdlet and PSCmdlet. The difference is how much you depend on the Windows PowerShell environment. When deriving from Cmdlet, you aren't really depending on PowerShell. You are not impacted by any changes in the PowerShell runtime. In addition, your cmdlet can be invoked directly from any application instead of invoking it through the Windows PowerShell runtime.

    In most cases, deriving from Cmdlet is the best choice, except when you need full integration with the PowerShell runtime, access to session state data, call scripts etc. Then, you'll derive from PSCmdlet.

    For more details, please check this nice article  http://www.codeproject.com/Articles/20867/Build-a-PowerShell-cmdlet

    Best regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Friday, April 15, 2016 3:06 AM
  • Thank you very much for your reply, that's very useful !!

    I have one more below question:

    Scenario: PowerShell command execution via Managed C++ code.

    Code Snippet:

       PowerShell^ _ps = PowerShell::Create();
       PSCommand^ psCmd = gcnew PSCommand();
       psCmd->AddCommand("invoke-item");
       psCmd->AddArgument("C:\\Users\\Desktop\\download.png");

       psCmd->AddCommand("new-item");
       psCmd->AddParameter("path", "C:\\Users\\Desktop\\");
       //psCmd->AddArgument();
       psCmd->AddParameter("name","test.txt");
       psCmd->AddParameter("type","file");
       psCmd->AddParameter("value","some text");

       _ps->Commands = psCmd;

    _ps->Invoke();

    Doubt: Here I have added two commands but only one get executed(when it hits _ps->invoke only invoke-item executed).

    I want to run multiple commands and sequentially(or synchronously) i.e one by one. Can you tell how can I do that ??

    Thanks,

    sdkJain.

    Thursday, April 21, 2016 3:48 PM
  • It says "pipeline" so I think it's executing a command like this:

    invoke-item C:\Users\Desktop\Download.png | new-item -path C:\Users\Desktop\ -name test.txt -type file -value 'some text'

    and because invoke-item does not output anything here, new-item is not executed.

    Perhaps you need to call PSCommand.AddStatement between the commands. PowerShell 2.0 does not support it though, so I didn't try it.

    Thursday, April 21, 2016 5:34 PM