title: How to access PowerShell host from C#
body: <p>In a PowerShell profile, one can identify the PowerShell host in order to do appropriate setup for that host's environment. For example:</p>
  
  <pre><code>if ($host.Name -eq 'ConsoleHost')
  {
      Import-Module PSReadline
      # differentiate verbose from warnings!
      $privData = (Get-Host).PrivateData
      $privData.VerboseForegroundColor = "cyan"
  }
  elseif ($host.Name -like '*ISE Host')
  {
      Start-Steroids
      Import-Module PsIseProjectExplorer
  }
  </code></pre>
  
  <p>I would like to be able to do the equivalent identification from a C# context primarily because PowerShell ISE does not support <code>Console.ReadLine</code> so I want to know if it is safe to use it in the current PS host's environment.</p>
  
  <p>I first explored trying to get the output of the <code>Get-Host</code> cmdlet from within C# (per <a href="https://msdn.microsoft.com/en-us/library/ms714876(v=vs.85).aspx" rel="nofollow">Invoking a cmdlet within a cmdlet</a>). After I located the Microsoft.PowerShell.Commands.Utility assembly (under C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0) I could compile this but it yielded null...</p>
  
  <pre><code>var cmd = new Microsoft.PowerShell.Commands.GetHostCommand();
  var myHost = cmd.Invoke();
  </code></pre>
  
  <p>...while this would not compile due to the <code>InternalHost</code> class being (ironically!) internal:</p>
  
  <pre><code>var cmd = new Microsoft.PowerShell.Commands.GetHostCommand();
  var myHost = cmd.Invoke&lt;System.Management.Automation.Internal.Host.InternalHost&gt;();
  </code></pre>
  
  <p>Next, I then modified my cmdlet to inherit from <code>PSCmdlet</code> rather than <code>Cmdlet</code> (to allow access to the <code>SessionState</code>), so I could then access the PS host object like this:</p>
  
  <pre><code>var psVarObject = SessionState.PSVariable.GetValue("Host");
  </code></pre>
  
  <p>Of course, that returns a pure <code>Object</code>, which I then needed to cast to... oh, wait... it's still internal!... so this would not compile:</p>
  
  <pre><code>string psHost = ((System.Management.Automation.Internal.Host.InternalHost)psVarObject).Name;
  </code></pre>
  
  <p>Leaving me no alternative but to use reflection on a foreign assembly (<em>horrors!</em>):</p>
  
  <pre><code>string psHost = (string)psVarObject.GetType().GetProperty("Name").GetValue(psVarObject, null);
  </code></pre>
  
  <p>That works, but is less than ideal, because reflecting upon any 3rd-party assembly is a fragile thing to do.</p>
  
  <p>Any alternative ideas on either (a) identifying the host or, (b) backing up a bit, being able to use the host's own Read-Host cmdlet to get a typed input from a user?</p>