Exemplo n.º 1
0
        public async Task <HttpResponseMessage> ProcessRequestAsync(HttpRequestMessage request = null)
        {
            DynamicPowershellApiEvents
            .Raise
            .ReceivedRequest(Request.RequestUri.ToString());

            Guid activityId = Guid.NewGuid();

            if (Request.RequestUri.Segments.Length < 4)
            {
                throw new MalformedUriException(string.Format("There is {0} segments but must be at least 4 segments in the URI.", Request.RequestUri.Segments.Length));
            }

            string apiName    = Request.RequestUri.Segments[2].Replace("/", string.Empty);
            string methodName = Request.RequestUri.Segments[3].Replace("/", string.Empty);

            // Check that the verbose messaging is working
            DynamicPowershellApiEvents.Raise.VerboseMessaging(String.Format("The api name is {0} and the method is {1}", apiName, methodName));

            // find the api.
            var api = WebApiConfiguration.Instance.Apis[apiName];

            if (api == null)
            {
                // Check that the verbose messaging is working
                DynamicPowershellApiEvents.Raise.VerboseMessaging(String.Format("Cannot find the requested web API: {0}", apiName));
                throw new WebApiNotFoundException(string.Format("Cannot find the requested web API: {0}", apiName));
            }

            // find the web method.
            WebMethod method = api.WebMethods[methodName];

            if (method == null)
            {
                DynamicPowershellApiEvents.Raise.VerboseMessaging(String.Format("Cannot find the requested web method: {0}", methodName));
                throw new WebMethodNotFoundException(string.Format("Cannot find web method: {0}", methodName));
            }

            // Is this scheduled as a job?
            bool asJob = method.AsJob;

            // Is this a POST method
            IEnumerable <KeyValuePair <string, string> > query2;

            if (Request.Method == HttpMethod.Post)
            {
                string documentContents = await Request.Content.ReadAsStringAsync();

                try
                {
                    // Work out the parameters from JSON
                    var queryStrings = new Dictionary <string, string>();

                    if (documentContents.StartsWith("[")) // it's an array. Let's use a horrible nested loop
                    {
                        JArray tokenArray = JArray.Parse(documentContents);
                        foreach (JObject details in tokenArray)
                        {
                            foreach (var detail in details)
                            {
                                var name  = detail.Key;
                                var value = detail.Value.ToString();
                                queryStrings.Add(name, value);
                            }
                        }
                    }
                    else  // it's an object. Let's just treat it as an object
                    {
                        JObject obj = JObject.Parse(documentContents);

                        foreach (var details in obj)
                        {
                            var name  = details.Key;
                            var value = details.Value.ToString();
                            queryStrings.Add(name, value);
                        }
                    }

                    if (method.Parameters.Any(param => queryStrings.All(q => q.Key != param.Name)))
                    {
                        DynamicPowershellApiEvents.Raise.VerboseMessaging(String.Format("Cannot find all parameters required."));
                        throw new MissingParametersException("Cannot find all parameters required.");
                    }

                    query2 = queryStrings.ToList();
                }
                catch (Exception)
                {
                    DynamicPowershellApiEvents.Raise.VerboseMessaging(String.Format("Cannot find all parameters required."));
                    throw new MissingParametersException("Cannot find all parameters required.");
                }
            }
            else
            {
                // Get our parameters.
                IEnumerable <KeyValuePair <string, string> > query = Request.GetQueryNameValuePairs();
                if (method.Parameters.Any(param => query.All(q => q.Key != param.Name)))
                {
                    DynamicPowershellApiEvents.Raise.VerboseMessaging(String.Format("Cannot find all parameters required."));
                    throw new MissingParametersException("Cannot find all parameters required.");
                }

                query2 = query;
            }

            // We now catch an exception from the runner
            try
            {
                DynamicPowershellApiEvents.Raise.VerboseMessaging(String.Format("Started Executing the runner"));

                if (!asJob)
                {
                    PowershellReturn output =
                        await _powershellRunner.ExecuteAsync(method.PowerShellPath, method.Snapin, method.Module, query2.ToList(), asJob);

                    JToken token = output.ActualPowerShellData.StartsWith("[")
                                                ? (JToken)JArray.Parse(output.ActualPowerShellData)
                                                : JObject.Parse(output.ActualPowerShellData);

                    return(new HttpResponseMessage
                    {
                        Content = new JsonContent(token)
                    });
                }
                else                 // run as job.
                {
                    Guid   jobId         = Guid.NewGuid();
                    string requestedHost = String.Empty;

                    if (Request.Properties.ContainsKey("MS_OwinContext"))
                    {
                        requestedHost = ((OwinContext)Request.Properties["MS_OwinContext"]).Request.RemoteIpAddress;
                    }

                    _jobListProvider.AddRequestedJob(jobId, requestedHost);

                    // Go off and run this job please sir.
                    var task = Task <bool> .Factory.StartNew(
                        () =>
                    {
                        try
                        {
                            Task <PowershellReturn> goTask =
                                _powershellRunner.ExecuteAsync(
                                    method.PowerShellPath,
                                    method.Snapin,
                                    method.Module,
                                    query2.ToList(),
                                    true);

                            goTask.Wait();
                            var output = goTask.Result;

                            JToken token = output.ActualPowerShellData.StartsWith("[")
                                                                ? (JToken)JArray.Parse(output.ActualPowerShellData)
                                                                : JObject.Parse(output.ActualPowerShellData);

                            _jobListProvider.CompleteJob(jobId, output.PowerShellReturnedValidData, String.Empty);

                            string outputPath = Path.Combine(WebApiConfiguration.Instance.Jobs.JobStorePath, jobId + ".json");

                            using (TextWriter writer = File.CreateText(outputPath))
                            {
                                JsonSerializer serializer = new JsonSerializer
                                {
                                    Formatting = Formatting.Indented                                             // Make it readable for Ops sake!
                                };
                                serializer.Serialize(writer, token);
                            }

                            return(true);
                        }
                        catch (PowerShellExecutionException poException)
                        {
                            CrashLogEntry entry = new CrashLogEntry
                            {
                                Exceptions     = poException.Exceptions,
                                LogTime        = poException.LogTime,
                                RequestAddress = requestedHost,
                                RequestMethod  = methodName,
                                RequestUrl     = Request.RequestUri.ToString()
                            };
                            entry.SetActivityId(activityId);
                            string logFile = _crashLogger.SaveLog(entry);

                            DynamicPowershellApiEvents.Raise.InvalidPowerShellOutput(poException.Message + " logged to " + logFile);

                            ErrorResponse response =
                                new ErrorResponse
                            {
                                ActivityId = activityId,
                                LogFile    = logFile,
                                Message    = poException.Message
                            };

                            JToken token = new JObject(response);

                            _jobListProvider.CompleteJob(jobId, false, String.Empty);

                            string outputPath = Path.Combine(WebApiConfiguration.Instance.Jobs.JobStorePath, jobId + ".json");

                            using (TextWriter writer = File.CreateText(outputPath))
                            {
                                JsonSerializer serializer = new JsonSerializer
                                {
                                    Formatting = Formatting.Indented                                             // Make it readable for Ops sake!
                                };
                                serializer.Serialize(writer, token);
                            }
                            return(true);
                        }
                    }
                        );

                    // return the Job ID.
                    return(new HttpResponseMessage
                    {
                        Content = new JsonContent(new JValue(jobId))
                    });
                }
            }
            catch (PowerShellExecutionException poException)
            {
                CrashLogEntry entry = new CrashLogEntry
                {
                    Exceptions     = poException.Exceptions,
                    LogTime        = poException.LogTime,
                    RequestAddress = String.Empty,                     // TODO: Find a way of getting the request host.
                    RequestMethod  = methodName,
                    RequestUrl     = Request.RequestUri.ToString()
                };
                entry.SetActivityId(activityId);
                string logFile = _crashLogger.SaveLog(entry);

                DynamicPowershellApiEvents.Raise.InvalidPowerShellOutput(poException.Message + " logged to " + logFile);

                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.InternalServerError,
                                                                      new ErrorResponse
                {
                    ActivityId = activityId,
                    LogFile    = logFile,
                    Message    = poException.Message
                }
                                                                      );

                return(response);
            }
            catch (Exception ex)
            {
                CrashLogEntry entry = new CrashLogEntry
                {
                    Exceptions = new List <PowerShellException>
                    {
                        new PowerShellException
                        {
                            ErrorMessage = ex.Message,
                            LineNumber   = 0,
                            ScriptName   = "GenericController.cs",
                            StackTrace   = ex.StackTrace
                        }
                    },
                    LogTime        = DateTime.Now,
                    RequestAddress = String.Empty,                     // TODO: Find a way of getting the request host.
                    RequestMethod  = methodName,
                    RequestUrl     = Request.RequestUri.ToString()
                };
                entry.SetActivityId(activityId);
                string logFile = _crashLogger.SaveLog(entry);

                DynamicPowershellApiEvents.Raise.UnhandledException(ex.Message + " logged to " + logFile, ex.StackTrace ?? String.Empty);

                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.InternalServerError,
                                                                      new ErrorResponse
                {
                    ActivityId = activityId,
                    LogFile    = logFile,
                    Message    = ex.Message
                }
                                                                      );

                return(response);
            }
        }
Exemplo n.º 2
0
        /// <summary>	The asynchronous execution method. </summary>
        /// <remarks>	Anthony, 5/27/2015. </remarks>
        /// <exception cref="ArgumentException">		    Thrown when one or more arguments have
        ///                                                 unsupported or illegal values. </exception>
        /// <exception cref="ArgumentNullException">	    Thrown when one or more required arguments
        ///                                                 are null. </exception>
        /// <exception cref="PSSnapInException">		    . </exception>
        /// <exception cref="PowerShellExecutionException">	Thrown when a Power Shell Execution error
        ///                                                 condition occurs. </exception>
        /// <param name="filename">		    The filename. </param>
        /// <param name="snapin">		    The snap in. </param>
        /// <param name="module">		    The module. </param>
        /// <param name="parametersList">	The parameters List. </param>
        /// <param name="asJob">		    Run this command as a job. </param>
        /// <returns>	The <see cref="Task"/>. </returns>
        public Task <PowershellReturn> ExecuteAsync(
            string filename,
            string snapin,
            string module,
            IList <KeyValuePair <string, string> > parametersList,
            bool asJob)
        {
            if (string.IsNullOrWhiteSpace(filename))
            {
                throw new ArgumentException("Argument cannot be null, empty or composed of whitespaces only", "filename");
            }
            if (parametersList == null)
            {
                throw new ArgumentNullException("parametersList", "Argument cannot be null");
            }

            // Raise an event so we know what is going on
            try
            {
                var sb = new StringBuilder();

                foreach (KeyValuePair <string, string> kvp in parametersList)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(";");
                    }

                    sb.Append(string.Format("{0}:{1}", kvp.Key, kvp.Value));
                }

                DynamicPowershellApiEvents
                .Raise
                .ExecutingPowerShellScript(filename, sb.ToString());
            }
            catch (Exception)
            {
                DynamicPowershellApiEvents
                .Raise
                .ExecutingPowerShellScript(filename, "Unknown");
            }

            try
            {
                string strBaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
                string scriptContent    = File.ReadAllText(Path.Combine(strBaseDirectory, Path.Combine("ScriptRepository", filename)));

                RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();

                if (!String.IsNullOrWhiteSpace(snapin))
                {
                    PSSnapInException snapInException;
                    rsConfig.AddPSSnapIn(snapin, out snapInException);
                    if (snapInException != null)
                    {
                        DynamicPowershellApiEvents
                        .Raise
                        .SnapinException(snapInException.Message);
                        throw snapInException;
                    }
                }

                InitialSessionState initialSession = InitialSessionState.Create();
                if (!String.IsNullOrWhiteSpace(module))
                {
                    DynamicPowershellApiEvents
                    .Raise
                    .LoadingModule(module);
                    initialSession.ImportPSModule(new[] { module });
                }

                using (PowerShell powerShellInstance = PowerShell.Create(initialSession))
                {
                    powerShellInstance.RunspacePool = RunspacePoolWrapper.Pool;
                    if (powerShellInstance.Runspace == null)
                    {
                        powerShellInstance.Runspace = RunspaceFactory.CreateRunspace(rsConfig);
                        powerShellInstance.Runspace.Open();
                    }

                    powerShellInstance.AddScript(scriptContent);

                    foreach (var item in parametersList)
                    {
                        powerShellInstance.AddParameter(item.Key, item.Value);
                    }

                    // invoke execution on the pipeline (collecting output)
                    Collection <PSObject> psOutput = powerShellInstance.Invoke();

                    string sMessage = psOutput == null
                                                ? String.Empty
                                                : (
                        psOutput.LastOrDefault() != null
                                                        ? Regex.Replace(psOutput.LastOrDefault().ToString(), @"[^\u0000-\u007F]", string.Empty)
                                                                : String.Empty);

                    DynamicPowershellApiEvents.Raise.PowerShellScriptFinalised("The powershell has completed - anlaysing results now");

                    // check the other output streams (for example, the error stream)
                    if (powerShellInstance.HadErrors && powerShellInstance.Streams.Error.Count > 0)
                    {
                        var runtimeErrors = new List <PowerShellException>();

                        // Create a string builder for the errors
                        StringBuilder sb = new StringBuilder();

                        // error records were written to the error stream.
                        // do something with the items found.
                        sb.Append("PowerShell script raised errors:" + Environment.NewLine);
                        sb.Append(String.Format("{0}", sMessage));

                        var errors = powerShellInstance.Streams.Error.ReadAll();
                        if (errors != null)
                        {
                            foreach (var error in errors)
                            {
                                if (error.ErrorDetails == null)
                                {
                                    DynamicPowershellApiEvents.Raise.UnhandledException("error.ErrorDetails is null");
                                }

                                string errorDetails = error.ErrorDetails != null ? error.ErrorDetails.Message : String.Empty;
                                string scriptStack  = error.ScriptStackTrace ?? String.Empty;
                                string commandPath  = error.InvocationInfo.PSCommandPath ?? String.Empty;

                                if (error.ScriptStackTrace == null)
                                {
                                    DynamicPowershellApiEvents.Raise.UnhandledException("error.ScriptStackTrace is null");
                                }

                                if (error.InvocationInfo == null)
                                {
                                    DynamicPowershellApiEvents.Raise.UnhandledException("error.InvocationInfo is null");
                                }
                                else
                                {
                                    if (error.InvocationInfo.PSCommandPath == null)
                                    {
                                        DynamicPowershellApiEvents.Raise.UnhandledException("error.InvocationInfo.PSCommandPath is null");
                                    }
                                }

                                if (error.Exception == null)
                                {
                                    DynamicPowershellApiEvents.Raise.UnhandledException("error.Exception is null");
                                }

                                DynamicPowershellApiEvents.Raise.PowerShellError(
                                    errorDetails,
                                    scriptStack,
                                    commandPath,
                                    error.InvocationInfo.ScriptLineNumber);

                                runtimeErrors.Add(new PowerShellException
                                {
                                    StackTrace   = scriptStack,
                                    ErrorMessage = errorDetails,
                                    LineNumber   = error.InvocationInfo != null ? error.InvocationInfo.ScriptLineNumber : 0,
                                    ScriptName   = filename
                                });

                                if (error.Exception != null)
                                {
                                    sb.Append(String.Format("PowerShell Exception {0} : {1}", error.Exception.Message, error.Exception.StackTrace));
                                }

                                sb.Append(String.Format("Error {0}", error.ScriptStackTrace));
                            }
                        }
                        else
                        {
                            sb.Append(sMessage);
                        }

                        DynamicPowershellApiEvents.Raise.PowerShellScriptFinalised(String.Format("An error was rasied {0}", sb));

                        throw new PowerShellExecutionException(sb.ToString())
                              {
                                  Exceptions = runtimeErrors,
                                  LogTime    = DateTime.Now
                              };
                    }

                    var psGood = new PowershellReturn
                    {
                        PowerShellReturnedValidData = true,
                        ActualPowerShellData        = sMessage
                    };

                    DynamicPowershellApiEvents.Raise.PowerShellScriptFinalised(String.Format("The powershell returned the following {0}", psGood.ActualPowerShellData));

                    return(Task.FromResult(psGood));
                }
            }
            catch (Exception runnerException)
            {
                if (runnerException.GetType() == typeof(PowerShellExecutionException))
                {
                    throw;
                }

                DynamicPowershellApiEvents.Raise.UnhandledException(runnerException.Message, runnerException.StackTrace);
                throw new PowerShellExecutionException(runnerException.Message)
                      {
                          Exceptions = new List <PowerShellException>
                          {
                              new PowerShellException
                              {
                                  ErrorMessage = runnerException.Message,
                                  LineNumber   = 0,
                                  ScriptName   = "PowerShellRunner.cs",
                                  StackTrace   = runnerException.StackTrace
                              }
                          },
                          LogTime = DateTime.Now
                      };
            }
        }
        public async Task <HttpResponseMessage> ProcessRequestAsync(HttpRequestMessage request = null)
        {
            PSCommand psCommand;

            if (request.Properties.TryGetValue("APP_PSCommand", out object psc) && psc is PSCommand)
            {
                psCommand = (PSCommand)psc;
            }
            else
            {
                PowerShellRestApiEvents.Raise.VerboseMessaging("Unable to retrieve the PowerShell command");
                throw new PScommandNotFoundException("Unable to retrieve the PowerShell command");
            }

            Guid activityId = Guid.NewGuid();

            bool asJob = psCommand.AsJob;

            //var inParams = new Dictionary<string, object>();
            var inParams = new List <KeyValuePair <string, object> >();
            List <PSParameter> allowedParams;

            #region ----- Body parameters -----
            allowedParams = psCommand.GetParametersByLocation(RestLocation.Body);

            string documentContents = await Request.Content.ReadAsStringAsync();

            documentContents = documentContents.ToString().Trim();

            if (!string.IsNullOrWhiteSpace(documentContents))
            {
                // If only one parameter is defined in parameter file, not name needed

                /*if (allowedParams.Count == 1)
                 * {
                 *  if (documentContents.StartsWith("["))
                 *  {
                 *      JArray tokenArray = JArray.Parse(documentContents);
                 *      Object value = JsonHelper.Convert(tokenArray);
                 *      inParams.Add(new KeyValuePair<string, object>(allowedParams.First().Name, value));
                 *  }
                 *  else if (documentContents.StartsWith("{"))
                 *  {
                 *      JObject obj = JObject.Parse(documentContents);
                 *      Object value = JsonHelper.Convert(obj);
                 *      inParams.Add(new KeyValuePair<string, object>(allowedParams.First().Name, value));
                 *  }
                 *  else
                 *  {
                 *      inParams.Add(new KeyValuePair<string, object>(allowedParams.First().Name, documentContents));
                 *  }
                 * }
                 * else if(allowedParams.Count > 1)
                 * {
                 */
                if (documentContents.StartsWith("["))     // if more one parameter are defined in config file, array is not allow
                {
                    PowerShellRestApiEvents.Raise.VerboseMessaging(String.Format("Body cannot be a json array."));
                    throw new MissingParametersException("Body cannot be a json array.");
                }
                else if (documentContents.StartsWith("{"))     // it's an object. Let's just treat it as an object
                {
                    JObject obj = JObject.Parse(documentContents);

                    foreach (var detail in obj)
                    {
                        String name  = detail.Key;
                        Object value = JsonHelper.Convert(detail.Value);

                        if (allowedParams.FirstOrDefault(x => x.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)) != null)
                        {
                            inParams.Add(new KeyValuePair <string, object>(name, value));
                        }
                        else
                        {
                            PowerShellRestApiEvents.Raise.VerboseMessaging(String.Format("Parameter {0} is not allow in body.", name));
                            throw new MissingParametersException(String.Format("Parameter {0} is not allow in body.", name));
                        }
                    }
                }
                else
                {
                    PowerShellRestApiEvents.Raise.VerboseMessaging(String.Format("Boby must be a json object with {0} properties.", allowedParams.Count));
                    throw new MissingParametersException(String.Format("Boby must be a json object with {0} properties.", allowedParams.Count));
                }
                //}
            }
            #endregion

            #region ----- QueryString parameters -----
            allowedParams = psCommand.GetParametersByLocation(RestLocation.Query);

            foreach (var p in Request.GetQueryNameValuePairs())
            {
                var param = allowedParams.FirstOrDefault(x => x.Name.Equals(p.Key, StringComparison.CurrentCultureIgnoreCase));

                if (param != null)
                {
                    var value = Convert.ChangeType(p.Value, param.Type);

                    inParams.Add(new KeyValuePair <string, object>(param.Name, value));
                }
                else
                {
                    PowerShellRestApiEvents.Raise.VerboseMessaging(String.Format("Parameter {0} is not allow in QueryString.", p.Key));
                    throw new MissingParametersException(String.Format("Parameter {0} is not allow in QueryString.", p.Key));
                }
            }
            #endregion

            #region ----- URI Path parameters -----
            allowedParams = psCommand.GetParametersByLocation(RestLocation.Path);

            if (Request.RequestUri.Segments.Length - 4 <= allowedParams.Count)
            {
                for (int i = 4; i < Request.RequestUri.Segments.Length; i++)
                {
                    string uriValue = Request.RequestUri.Segments[i].Replace("/", string.Empty);

                    var param = allowedParams.Skip(i - 4).FirstOrDefault();
                    var value = Convert.ChangeType(uriValue, param.Type);

                    inParams.Add(new KeyValuePair <string, object>(param.Name, value));
                }
            }
            else if (Request.RequestUri.Segments.Length - 4 > allowedParams.Count)
            {
                PowerShellRestApiEvents.Raise.VerboseMessaging(String.Format("Too many parameters in Path."));
                throw new MissingParametersException(String.Format("Too many parameters in Path."));
            }
            #endregion

            #region ----- Header parameters -----
            List <string> allowedParamNames = psCommand.GetParametersByLocation(RestLocation.Header).Select(x => x.Name.ToLower()).ToList();

            /*
             * Request.Headers.Where(x => allowedParamNames.Contains(x.Key.ToLower()))
             *             .ToList()
             *             .ForEach(x => inParams.Add(new KeyValuePair<string, object>(x.Key, x.Value)));
             */

            foreach (var p in Request.Headers)
            {
                var param = allowedParams.FirstOrDefault(x => x.Name.Equals(p.Key, StringComparison.CurrentCultureIgnoreCase));

                if (param != null)
                {
                    var value = Convert.ChangeType(p.Value, param.Type);
                    inParams.Add(new KeyValuePair <string, object>(param.Name, value));
                }
            }

            #endregion

            #region ----- ConfigFile parameters -----
            foreach (var param in psCommand.GetParametersByLocation(RestLocation.ConfigFile, true))
            {
                inParams.Add(new KeyValuePair <string, object>(param.Name, param.Value));
            }

            #endregion

            #region ----- User parameter -----
            if (!string.IsNullOrWhiteSpace(psCommand.ParameterForUser))
            {
                string userName = this.User.Identity != null ? this.User.Identity.Name : "Anonymous";

                inParams.Add(new KeyValuePair <string, object>(psCommand.ParameterForUser, userName));
            }
            #endregion

            #region ----- Roles parameter -----
            if (!string.IsNullOrWhiteSpace(psCommand.ParameterForRoles))
            {
                string[] userRoles = this.User.Identity == null
                                            ? new string[0]
                                            : (this.User.Identity as ClaimsIdentity)
                                     .Claims
                                     .Where(c => c.Type == ClaimTypes.Role)
                                     .Select(c => c.Value)
                                     .ToArray();

                inParams.Add(new KeyValuePair <string, object>(psCommand.ParameterForRoles, userRoles));
            }
            #endregion

            #region ----- Claims parameter -----
            if (!string.IsNullOrWhiteSpace(psCommand.ParameterForClaims))
            {
                Claim[] userClaims = this.User.Identity == null
                                            ? new Claim[0]
                                            : (this.User.Identity as ClaimsIdentity)
                                     .Claims
                                     .ToArray();


                inParams.Add(new KeyValuePair <string, object>(psCommand.ParameterForClaims, userClaims));
            }
            #endregion


            #region ----- Check if all parameters required are found -----
            if (psCommand.GetParametersRequired().Select(x => x.Name).Any(requiedName => inParams.All(q => q.Key != requiedName)))
            {
                PowerShellRestApiEvents.Raise.VerboseMessaging(String.Format("Cannot find all parameters required."));
                throw new MissingParametersException("Cannot find all parameters required.");
            }
            #endregion

            // We now catch an exception from the runner
            try
            {
                PowerShellRestApiEvents.Raise.VerboseMessaging(String.Format("Started Executing the runner"));

                if (!asJob)
                {
                    PowershellReturn output =
                        await _powershellRunner.ExecuteAsync(psCommand.Name, psCommand.Snapin, psCommand.Module, inParams, asJob);

                    JToken token = string.IsNullOrWhiteSpace(output.ActualPowerShellData)
                        ? new JObject()
                        : output.ActualPowerShellData.StartsWith("[")
                            ? (JToken)JArray.Parse(output.ActualPowerShellData)
                            : output.ActualPowerShellData.StartsWith("{")
                                ? JObject.Parse(output.ActualPowerShellData)
                                : JObject.Parse("{\"Message\":" + output.ActualPowerShellData + "}");

                    JToken token2 = "";

                    return(new HttpResponseMessage
                    {
                        Content = new JsonContent(token)
                    });
                }
                else // run as job.
                {
                    Guid   jobId         = Guid.NewGuid();
                    string requestedHost = String.Empty;

                    if (Request.Properties.ContainsKey("MS_OwinContext"))
                    {
                        requestedHost = ((OwinContext)Request.Properties["MS_OwinContext"]).Request.RemoteIpAddress;
                    }

                    _jobListProvider.AddRequestedJob(jobId, requestedHost);

                    // Go off and run this job please sir.
                    var task = Task <bool> .Factory.StartNew(
                        () =>
                    {
                        try
                        {
                            Task <PowershellReturn> goTask =
                                _powershellRunner.ExecuteAsync(
                                    psCommand.Name,
                                    psCommand.Snapin,
                                    psCommand.Module,
                                    inParams,
                                    true);

                            goTask.Wait();
                            var output = goTask.Result;

                            JToken token = output.ActualPowerShellData.StartsWith("[")
                                ? (JToken)JArray.Parse(output.ActualPowerShellData)
                                : JObject.Parse(output.ActualPowerShellData);

                            _jobListProvider.CompleteJob(jobId, output.PowerShellReturnedValidData, String.Empty);

                            string outputPath = Path.Combine(WebApiConfiguration.Instance.Jobs.JobStorePath, jobId + ".json");

                            using (TextWriter writer = File.CreateText(outputPath))
                            {
                                JsonSerializer serializer = new JsonSerializer
                                {
                                    Formatting = Formatting.Indented     // Make it readable for Ops sake!
                                };
                                serializer.Serialize(writer, token);
                            }

                            return(true);
                        }
                        catch (PowerShellExecutionException poException)
                        {
                            CrashLogEntry entry = new CrashLogEntry
                            {
                                Exceptions     = poException.Exceptions,
                                LogTime        = poException.LogTime,
                                RequestAddress = requestedHost,
                                RequestMethod  = psCommand.Name,
                                RequestUrl     = Request.RequestUri.ToString()
                            };
                            entry.SetActivityId(activityId);
                            string logFile = _crashLogger.SaveLog(entry);

                            PowerShellRestApiEvents.Raise.InvalidPowerShellOutput(poException.Message + " logged to " + logFile);

                            ErrorResponse response =
                                new ErrorResponse
                            {
                                ActivityId = activityId,
                                LogFile    = logFile,
                                Message    = poException.Message
                            };

                            JToken token = new JObject(response);

                            _jobListProvider.CompleteJob(jobId, false, String.Empty);

                            string outputPath = Path.Combine(WebApiConfiguration.Instance.Jobs.JobStorePath, jobId + ".json");

                            using (TextWriter writer = File.CreateText(outputPath))
                            {
                                JsonSerializer serializer = new JsonSerializer
                                {
                                    Formatting = Formatting.Indented     // Make it readable for Ops sake!
                                };
                                serializer.Serialize(writer, token);
                            }
                            return(true);
                        }
                    }
                        );

                    // return the Job ID.
                    return(new HttpResponseMessage
                    {
                        Content = new JsonContent(new JValue(jobId))
                    });
                }
            }
            catch (PowerShellClientException ex)
            {
                PowerShellRestApiEvents.Raise.InvalidPowerShellOutput("[" + ex.Category.ToString() + "]" + ex.Message);
                switch (ex.Category)
                {
                case ErrorCategory.PermissionDenied: return(Request.CreateErrorResponse(HttpStatusCode.Forbidden, ex.Message));

                case ErrorCategory.ObjectNotFound: return(Request.CreateErrorResponse(HttpStatusCode.NotFound, ex.Message));

                case ErrorCategory.InvalidArgument: return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message));

                case ErrorCategory.ResourceExists: return(Request.CreateErrorResponse(HttpStatusCode.Conflict, ex.Message));
                }
                return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "[" + ex.Category.ToString() + "]" + ex.Message));
            }
            catch (PowerShellExecutionException poException)
            {
                string requestedHost = String.Empty;
                if (Request.Properties.ContainsKey("MS_OwinContext"))
                {
                    requestedHost = ((OwinContext)Request.Properties["MS_OwinContext"]).Request.RemoteIpAddress;
                }

                CrashLogEntry entry = new CrashLogEntry
                {
                    Exceptions     = poException.Exceptions,
                    LogTime        = poException.LogTime,
                    RequestAddress = requestedHost,
                    RequestMethod  = psCommand.Name,
                    RequestUrl     = Request.RequestUri.ToString()
                };
                entry.SetActivityId(activityId);
                string logFile = _crashLogger.SaveLog(entry);

                PowerShellRestApiEvents.Raise.InvalidPowerShellOutput(poException.Message + " logged to " + logFile);

                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.InternalServerError,
                                                                      new ErrorResponse
                {
                    ActivityId = activityId,
                    LogFile    = logFile,
                    Message    = poException.Message
                }
                                                                      );

                return(response);
            }
            catch (Exception ex)
            {
                CrashLogEntry entry = new CrashLogEntry
                {
                    Exceptions = new List <PowerShellException>
                    {
                        new PowerShellException
                        {
                            ErrorMessage = ex.Message,
                            LineNumber   = 0,
                            ScriptName   = "GenericController.cs",
                            StackTrace   = ex.StackTrace
                        }
                    },
                    LogTime        = DateTime.Now,
                    RequestAddress = String.Empty, // TODO: Find a way of getting the request host.
                    RequestMethod  = psCommand.Name,
                    RequestUrl     = Request.RequestUri.ToString()
                };
                entry.SetActivityId(activityId);
                string logFile = _crashLogger.SaveLog(entry);

                PowerShellRestApiEvents.Raise.UnhandledException(ex.Message + " logged to " + logFile, ex.StackTrace ?? String.Empty);

                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.InternalServerError,
                                                                      new ErrorResponse
                {
                    ActivityId = activityId,
                    LogFile    = logFile,
                    Message    = ex.Message
                }
                                                                      );

                return(response);
            }
        }