I have seen this question posed a lot so I decided that I would post a quick code sample here and the complete sample on my samples site.

In my sample I created a managed client and a native client which both call into a managed DLL that runs the Get-ExchangeServer cmdlet using Remote Powershell.  Here is the method that actually does the work if you don't want to download the entire sample:

        private const string SHELL_URI = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";
        public void GetExchangeServers(string serverName, string userName, string password, out string[] servers)
        {

            System.Uri serverUri = new Uri(String.Format("http://{0}/powershell?serializationLevel=Full", serverName));
            string[] retVal = null;
            System.Security.SecureString securePassword = new System.Security.SecureString();
           
            foreach (char c in password.ToCharArray())
            {
                securePassword.AppendChar(c);
            }

            System.Management.Automation.PSCredential creds = new System.Management.Automation.PSCredential(userName, securePassword);
           
            RunspaceConfiguration rc = RunspaceConfiguration.Create();
            WSManConnectionInfo wsManInfo = new WSManConnectionInfo(serverUri, SHELL_URI, creds);

            using (Runspace rs = RunspaceFactory.CreateRunspace(wsManInfo))
            {
                rs.Open();
                PowerShell psh = PowerShell.Create();
                psh.Runspace = rs;
                psh.AddCommand("Get-ExchangeServer");

                Collection<PSObject> results = psh.Invoke();

                if (psh.Streams.Error.Count > 0)
                {
                    foreach (ErrorRecord err in psh.Streams.Error)
                    {
                        // handle the error some how
                    }
                    rs.Close();
                    servers = null;
                    return;
                }
                retVal = new string[1];

                foreach (PSObject result in results)
                {
                    if (null == retVal[0] || retVal[0].Length == 0)
                    {
                        retVal[0] = result.Members["Name"].Value as string;
                    }
                    else
                    {
                        string[] newVal = new string[retVal.Length + 1];
                        retVal.CopyTo(newVal, 0);
                        newVal[retVal.Length] = result.Members["Name"].Value as string;
                        retVal = newVal;
                    }
                }
                rs.Close();
            }
            rc = null;
            servers = retVal;
        }