title: Invoke a PSCmdlet from within a cmdlet
body: <p>I have a PS-Module completely written in C#. It contains about 20 Cmdlets that are already in production. Some of these "share code". Take this example:</p>
  
  <p>I have a Cmdlet called <code>InvokeCommitCommand</code> that produces a "changeset". This Cmdlet also publishes metadata of this changeset. I would now like to create a new Cmdlet called <code>PublishCommitCommand</code> that can be called independantly to execute the "publishing" of an already existing changeset. I would therefore like to refactor <code>InvokeCommitCommand</code> to make use of the new Cmdlet <code>PublishCommitCommand</code> and avoid code duplication.</p>
  
  <p>More generally speaking ... I am trying to invoke a cmdlet <code>CommandB</code> from cmdlet <code>CommandA</code>. They are defined as follows</p>
  
  <pre><code>public CommandA : PSCmdlet
  {
    ...
  }
  
  public CommandB : PSCmdlet
  {
    ...
  }
  </code></pre>
  
  <p>I have a few options here. But none of them work.</p>
  
  <p><strong>1. Option</strong></p>
  
  <p>Invoke <code>CommandB</code> by creating an instance of it. That would've been my first guess. Like so:</p>
  
  <pre><code>var cmd = new CommandB();
  cmd.Invoke();
  </code></pre>
  
  <p>Unfortunately that does not work. I get the exception:</p>
  
  <p><em>Cmdlets derived from PSCmdlet cannot be invoked directly ...</em></p>
  
  <p>So ... next option.</p>
  
  <p><strong>2. Option</strong></p>
  
  <p>Create an instance of PowerShell and run the command. Like so:</p>
  
  <pre><code>var ps = PowerShell.Create();
  ps.AddCommand("CommandB");
  ps.Invoke();
  </code></pre>
  
  <p>Unfortunately that doesn't work either. This causes a new PowerShell instance to be created and therefore I loose all stream redirections I may have attached to the current PowerShell instance I am running in.</p>
  
  <p>I know I can reuse the runspace. But using the same runspace does <strong>NOT</strong> save me from losing my redirections. If <code>CommandB</code> would call <code>Write-Verbose "Huzzah!"</code>, I would not see that 'Huzzah!' anywhere.</p>
  
  <p>In short: I <strong>need</strong> to run the <code>CommandB</code> in the same PS instance as <code>CommandA</code></p>
  
  <p><strong>3. Option</strong></p>
  
  <p>Use a ScriptBlock. Like so:</p>
  
  <pre><code>var sb = ScriptBlock.Create("CommandB");
  sb.Invoke();
  </code></pre>
  
  <p>That's pretty nice. But the problem here is, that I have no means to pass any complex class arguments to the script block. If <code>CommandB</code> has a parameter of type ... let's say <code>PSCredential</code>, I have no easy way to pass that parameter to the script. If I had a <code>PowerShell</code> object, I could easily do</p>
  
  <pre><code>PowerShell ps
  ps.AddCommand("CommandB");
  ps.AddArgument("Credential", someCredentialObject);
  ps.AddArgument("TargetUri", new Uri("www.google.de"));
  </code></pre>
  
  <p>But I can not that with a <code>ScriptBlock</code>. True, I could use <code>InvokeWithContext</code> which allows me to pass variables to the scriptblock, but I would need to "wrap" each complex argument in a variable first... rather cumbersome.</p>
  
  <p><strong>Conclusion</strong></p>
  
  <p>Any ideas? The best thing would be if I somehow could - from inside <code>CommandA</code> get access to the current instance of <code>PowerShell</code> I am running in. I could then leverage option 2 without the issue of creating a new instance. But I do not know if that is even possible...</p>