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); } }
/// <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); } }