/// <summary> /// Background task entrypoint. Voice Commands using the <VoiceCommandService Target="..."> /// tag will invoke this when they are recognized by Cortana, passing along details of the /// invocation. /// /// Background tasks must respond to activation by Cortana within 0.5 seconds, and must /// report progress to Cortana every 5 seconds (unless Cortana is waiting for user /// input). There is no execution time limit on the background task managed by Cortana, /// but developers should use plmdebug (https://msdn.microsoft.com/en-us/library/windows/hardware/jj680085%28v=vs.85%29.aspx) /// on the Cortana app package in order to prevent Cortana timing out the task during /// debugging. /// /// Cortana dismisses its UI if it loses focus. This will cause it to terminate the background /// task, even if the background task is being debugged. Use of Remote Debugging is recommended /// in order to debug background task behaviors. In order to debug background tasks, open the /// project properties for the app package (not the background task project), and enable /// Debug -> "Do not launch, but debug my code when it starts". Alternatively, add a long /// initial progress screen, and attach to the background task process while it executes. /// </summary> /// <param name="taskInstance">Connection to the hosting background service process.</param> public async void Run(IBackgroundTaskInstance taskInstance) { serviceDeferral = taskInstance.GetDeferral(); // Register to receive an event if Cortana dismisses the background task. This will // occur if the task takes too long to respond, or if Cortana's UI is dismissed. // Any pending operations should be cancelled or waited on to clean up where possible. taskInstance.Canceled += OnTaskCanceled; var triggerDetails = taskInstance.TriggerDetails as AppServiceTriggerDetails; // Load localized resources for strings sent to Cortana to be displayed to the user. cortanaResourceMap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources"); // Select the system language, which is what Cortana should be running as. cortanaContext = ResourceContext.GetForViewIndependentUse(); // Get the currently used system date format dateFormatInfo = CultureInfo.CurrentCulture.DateTimeFormat; // This should match the uap:AppService and VoiceCommandService references from the // package manifest and VCD files, respectively. Make sure we've been launched by // a Cortana Voice Command. if (triggerDetails != null && triggerDetails.Name == "SeleniumBotVoiceService") { try { voiceServiceConnection = VoiceCommandServiceConnection.FromAppServiceTriggerDetails( triggerDetails); voiceServiceConnection.VoiceCommandCompleted += OnVoiceCommandCompleted; // GetVoiceCommandAsync establishes initial connection to Cortana, and must be called prior to any // messages sent to Cortana. Attempting to use ReportSuccessAsync, ReportProgressAsync, etc // prior to calling this will produce undefined behavior. VoiceCommand voiceCommand = await voiceServiceConnection.GetVoiceCommandAsync(); // Depending on the operation (defined in AdventureWorks:AdventureWorksCommands.xml) // perform the appropriate command. switch (voiceCommand.CommandName) { /* * case "whenIsTripToDestination": * var destination = voiceCommand.Properties["destination"][0]; * await SendCompletionMessageForDestination(destination); * break; * case "cancelTripToDestination": * var cancelDestination = voiceCommand.Properties["destination"][0]; * await SendCompletionMessageForCancellation(cancelDestination); * break; */ case "openBrowser": { var message = new VoiceCommandUserMessage() { DisplayMessage = "opened edge", SpokenMessage = "opened edge" }; await ShowProgressScreen("launching Edge"); await control.OpenBrowser(); var response = VoiceCommandResponse.CreateResponse(message); await voiceServiceConnection.ReportSuccessAsync(response); } break; case "closeBrowser": { var message2 = new VoiceCommandUserMessage() { DisplayMessage = "closed edge", SpokenMessage = "closed edge" }; await ShowProgressScreen("closing edge"); await control.CloseBrowser(); var response2 = VoiceCommandResponse.CreateResponse(message2); await voiceServiceConnection.ReportSuccessAsync(response2); } break; case "navTo": { var arg = voiceCommand.Properties["wildcardArgs"][0]; if (arg == null) { await ShowProgressScreen($"arg can't be null"); break; } await ShowProgressScreen($"navigating to {arg}"); await control.Nav(new Lib.DTOs.Nav() { urlOrName = arg }); var message2 = new VoiceCommandUserMessage() { DisplayMessage = "navigated", SpokenMessage = "navigated" }; var response2 = VoiceCommandResponse.CreateResponse(message2); await voiceServiceConnection.ReportSuccessAsync(response2); } break; default: // As with app activation VCDs, we need to handle the possibility that // an app update may remove a voice command that is still registered. // This can happen if the user hasn't run an app since an update. LaunchAppInForeground(); break; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Handling Voice Command failed " + ex.ToString()); await ShowProgressScreen("error, " + ex.Message); } } }