From 6b625670fa390adc7e293db879d1d58f0df779cd Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Wed, 18 May 2016 17:00:00 -0700 Subject: [PATCH] Windows 10 RTM Release - May 2016 Update --- .gitignore | 2 + .../BackgroundTask/SampleConfiguration.cpp | 10 +- .../cpp/BackgroundTask/SampleConfiguration.h | 2 +- .../Scenario1_SampleBackgroundTask.xaml.cpp | 55 ++-- .../Scenario1_SampleBackgroundTask.xaml.h | 2 + ...SampleBackgroundTaskWithCondition.xaml.cpp | 55 ++-- ...2_SampleBackgroundTaskWithCondition.xaml.h | 2 + .../Scenario3_ServicingCompleteTask.xaml.cpp | 55 ++-- .../Scenario3_ServicingCompleteTask.xaml.h | 2 + .../Scenario4_TimeTriggeredTask.xaml.cpp | 55 ++-- .../Scenario4_TimeTriggeredTask.xaml.h | 2 + .../Scenario5_ApplicationTriggerTask.xaml.cpp | 55 ++-- .../Scenario5_ApplicationTriggerTask.xaml.h | 2 + .../cpp/Tasks/SampleBackgroundTask.cpp | 18 +- .../cpp/Tasks/SampleBackgroundTask.h | 28 +- .../cs/BackgroundTask/SampleConfiguration.cs | 18 +- .../Scenario1_SampleBackgroundTask.xaml.cs | 16 +- ..._SampleBackgroundTaskWithCondition.xaml.cs | 16 +- .../Scenario3_ServicingCompleteTask.xaml.cs | 16 +- .../Scenario4_TimeTriggeredTask.xaml.cs | 16 +- .../Scenario5_ApplicationTriggerTask.xaml.cs | 16 +- .../cs/Tasks/SampleBackgroundTask.cs | 7 +- .../vb/BackgroundTask/SampleConfiguration.vb | 20 +- .../Scenario1_SampleBackgroundTask.xaml.vb | 15 +- ..._SampleBackgroundTaskWithCondition.xaml.vb | 15 +- .../Scenario3_ServicingCompleteTask.xaml.vb | 15 +- .../Scenario4_TimeTriggeredTask.xaml.vb | 15 +- .../Scenario5_ApplicationTriggerTask.xaml.vb | 15 +- .../vb/Tasks/SampleBackgroundTask.vb | 7 +- Samples/BarcodeScanner/README.md | 15 +- .../FileAccess/cpp/SampleConfiguration.cpp | 7 +- Samples/FileAccess/cpp/SampleConfiguration.h | 2 +- .../cpp/Scenario10_DeleteAFile.xaml.cpp | 2 +- ...1_CreateAFileInThePicturesLibrary.xaml.cpp | 16 +- ...Scenario3_WriteAndReadTextInAFile.xaml.cpp | 4 +- ...cenario4_WriteAndReadBytesInAFile.xaml.cpp | 4 +- ...io5_WriteAndReadAFileUsingAStream.xaml.cpp | 4 +- .../Scenario6_DisplayFileProperties.xaml.cpp | 29 +- ...OrFolderSoThatYouCanAccessItLater.xaml.cpp | 180 +++++------ .../cpp/Scenario8_CopyAFile.xaml.cpp | 2 +- ...pareTwoFilesToSeeIfTheyAreTheSame.xaml.cpp | 2 +- .../cs/Scenario10_DeleteAFile.xaml.cs | 5 + ...o1_CreateAFileInThePicturesLibrary.xaml.cs | 12 +- .../Scenario3_WriteAndReadTextInAFile.xaml.cs | 10 + ...Scenario4_WriteAndReadBytesInAFile.xaml.cs | 10 + ...rio5_WriteAndReadAFileUsingAStream.xaml.cs | 10 + .../Scenario6_DisplayFileProperties.xaml.cs | 5 + ...eOrFolderSoThatYouCanAccessItLater.xaml.cs | 144 +++++---- .../FileAccess/cs/Scenario8_CopyAFile.xaml.cs | 5 + .../js/scenario3_WriteAndReadTextInAFile.js | 2 +- .../js/scenario4_WriteAndReadBytesInAFile.js | 2 +- ...scenario5_WriteAndReadAFileUsingAStream.js | 2 +- ...kAFileOrFolderSoThatYouCanAccessItLater.js | 139 ++++---- Samples/GlobalizationPreferences/README.md | 2 +- Samples/WebSocket/cpp/SampleConfiguration.cpp | 74 ++++- Samples/WebSocket/cpp/SampleConfiguration.h | 73 +---- Samples/WebSocket/cpp/Scenario1.xaml | 50 --- Samples/WebSocket/cpp/Scenario1.xaml.cpp | 217 ------------- Samples/WebSocket/cpp/Scenario1.xaml.h | 65 ---- Samples/WebSocket/cpp/Scenario1_UTF8.xaml.cpp | 242 ++++++++++++++ Samples/WebSocket/cpp/Scenario1_UTF8.xaml.h | 56 ++++ Samples/WebSocket/cpp/Scenario2.xaml | 56 ---- Samples/WebSocket/cpp/Scenario2.xaml.cpp | 296 ------------------ Samples/WebSocket/cpp/Scenario2.xaml.h | 68 ---- .../WebSocket/cpp/Scenario2_Binary.xaml.cpp | 262 ++++++++++++++++ Samples/WebSocket/cpp/Scenario2_Binary.xaml.h | 65 ++++ Samples/WebSocket/cpp/WebSocket.vcxproj | 20 +- .../WebSocket/cpp/WebSocket.vcxproj.filters | 12 +- Samples/WebSocket/cs/SampleConfiguration.cs | 54 ++-- Samples/WebSocket/cs/Scenario1_UTF8.xaml | 50 --- Samples/WebSocket/cs/Scenario1_UTF8.xaml.cs | 286 ++++++++--------- Samples/WebSocket/cs/Scenario2_Binary.xaml | 56 ---- Samples/WebSocket/cs/Scenario2_Binary.xaml.cs | 269 +++++++--------- Samples/WebSocket/cs/WebSocket.csproj | 8 +- Samples/WebSocket/js/WebSocket.jsproj | 11 +- Samples/WebSocket/js/css/placeholder.txt | 0 .../WebSocket/js/css/scenario1_Download.css | 7 - Samples/WebSocket/js/css/scenario2_Upload.css | 7 - Samples/WebSocket/js/html/scenario1-utf8.html | 54 ++++ .../WebSocket/js/html/scenario1_Download.html | 46 --- .../WebSocket/js/html/scenario2-binary.html | 47 +++ .../WebSocket/js/html/scenario2_Upload.html | 50 --- Samples/WebSocket/js/js/helpers.js | 98 ------ .../WebSocket/js/js/sample-configuration.js | 71 ++++- Samples/WebSocket/js/js/scenario1-utf8.js | 184 +++++++++++ Samples/WebSocket/js/js/scenario1_Download.js | 155 --------- Samples/WebSocket/js/js/scenario2-binary.js | 194 ++++++++++++ Samples/WebSocket/js/js/scenario2_Upload.js | 180 ----------- Samples/WebSocket/shared/Scenario1_UTF8.xaml | 72 +++++ .../WebSocket/shared/Scenario2_Binary.xaml | 65 ++++ 90 files changed, 2338 insertions(+), 2349 deletions(-) delete mode 100644 Samples/WebSocket/cpp/Scenario1.xaml delete mode 100644 Samples/WebSocket/cpp/Scenario1.xaml.cpp delete mode 100644 Samples/WebSocket/cpp/Scenario1.xaml.h create mode 100644 Samples/WebSocket/cpp/Scenario1_UTF8.xaml.cpp create mode 100644 Samples/WebSocket/cpp/Scenario1_UTF8.xaml.h delete mode 100644 Samples/WebSocket/cpp/Scenario2.xaml delete mode 100644 Samples/WebSocket/cpp/Scenario2.xaml.cpp delete mode 100644 Samples/WebSocket/cpp/Scenario2.xaml.h create mode 100644 Samples/WebSocket/cpp/Scenario2_Binary.xaml.cpp create mode 100644 Samples/WebSocket/cpp/Scenario2_Binary.xaml.h delete mode 100644 Samples/WebSocket/cs/Scenario1_UTF8.xaml delete mode 100644 Samples/WebSocket/cs/Scenario2_Binary.xaml create mode 100644 Samples/WebSocket/js/css/placeholder.txt delete mode 100644 Samples/WebSocket/js/css/scenario1_Download.css delete mode 100644 Samples/WebSocket/js/css/scenario2_Upload.css create mode 100644 Samples/WebSocket/js/html/scenario1-utf8.html delete mode 100644 Samples/WebSocket/js/html/scenario1_Download.html create mode 100644 Samples/WebSocket/js/html/scenario2-binary.html delete mode 100644 Samples/WebSocket/js/html/scenario2_Upload.html delete mode 100644 Samples/WebSocket/js/js/helpers.js create mode 100644 Samples/WebSocket/js/js/scenario1-utf8.js delete mode 100644 Samples/WebSocket/js/js/scenario1_Download.js create mode 100644 Samples/WebSocket/js/js/scenario2-binary.js delete mode 100644 Samples/WebSocket/js/js/scenario2_Upload.js create mode 100644 Samples/WebSocket/shared/Scenario1_UTF8.xaml create mode 100644 Samples/WebSocket/shared/Scenario2_Binary.xaml diff --git a/.gitignore b/.gitignore index 677dfa66c3..c5d6618e09 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,8 @@ ipch/ *.opensdf *.sdf *.cachefile +*.VC.db +*.VC.VC.opendb # Visual Studio profiler *.psess diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp index 255743be2e..df8a0fb668 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp +++ b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.cpp @@ -34,7 +34,7 @@ Array^ MainPage::scenariosInner = ref new Array { // The format here is the following: // { "Description for the sample", "Fully quaified name for the class that implements the scenario" } - { "Background task", "SDKTemplate.SampleBackgroundTask" }, + { "Background task", "SDKTemplate.SampleBackgroundTask" }, { "Background task with a condition", "SDKTemplate.SampleBackgroundTaskWithCondition" }, { "Servicing complete task", "SDKTemplate.ServicingCompleteTask" }, { "Background task with time trigger", "SDKTemplate.TimeTriggeredTask" }, @@ -102,7 +102,7 @@ BackgroundTaskRegistration^ BackgroundTaskSample::RegisterBackgroundTask(String^ auto task = builder->Register(); - UpdateBackgroundTaskStatus(name, true); + UpdateBackgroundTaskRegistrationStatus(name, true); // // Remove previous completion status from local settings. @@ -142,17 +142,17 @@ void BackgroundTaskSample::UnregisterBackgroundTasks(String^ name) { auto cur = iter->Current->Value; - if(cur->Name == name) + if (cur->Name == name) { cur->Unregister(true); - UpdateBackgroundTaskStatus(name, false); + UpdateBackgroundTaskRegistrationStatus(name, false); } hascur = iter->MoveNext(); } } -void BackgroundTaskSample::UpdateBackgroundTaskStatus(String^ name, bool registered) +void BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(String^ name, bool registered) { if (name == SampleBackgroundTaskName) { diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h index 46fbe95240..b53e43482a 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h +++ b/Samples/BackgroundTask/cpp/BackgroundTask/SampleConfiguration.h @@ -61,7 +61,7 @@ namespace SDKTemplate static BackgroundTaskRegistration^ RegisterBackgroundTask(String^ taskEntryPoint, String^ name, IBackgroundTrigger^ trigger, IBackgroundCondition^ condition); static bool TaskRequiresBackgroundAccess(String^ name); static void UnregisterBackgroundTasks(String^ name); - static void UpdateBackgroundTaskStatus(String^ name, bool registered); + static void UpdateBackgroundTaskRegistrationStatus(String^ name, bool registered); static String^ SampleBackgroundTaskProgress; static bool SampleBackgroundTaskRegistered; diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cpp index f8fe642c59..c3d4ea6e8c 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cpp +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cpp @@ -44,20 +44,15 @@ void SampleBackgroundTask::OnNavigatedTo(NavigationEventArgs^ e) // // Attach progress and completed handlers to any existing tasks. // - auto iter = BackgroundTaskRegistration::AllTasks->First(); - auto hascur = iter->HasCurrent; - while (hascur) + for (auto pair : BackgroundTaskRegistration::AllTasks) { - auto cur = iter->Current->Value; - - if (cur->Name == SampleBackgroundTaskName) + auto task = pair->Value; + if (task->Name == SampleBackgroundTaskName) { - BackgroundTaskSample::UpdateBackgroundTaskStatus(cur->Name, true); - AttachProgressAndCompletedHandlers(cur); + BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(task->Name, true); + AttachProgressAndCompletedHandlers(task); break; } - - hascur = iter->MoveNext(); } UpdateUI(); @@ -69,19 +64,8 @@ void SampleBackgroundTask::OnNavigatedTo(NavigationEventArgs^ e) /// The task to attach progress and completed handlers to. void SampleBackgroundTask::AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration^ task) { - auto progress = [this](BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) - { - auto progress = "Progress: " + args->Progress + "%"; - BackgroundTaskSample::SampleBackgroundTaskProgress = progress; - UpdateUI(); - }; - task->Progress += ref new BackgroundTaskProgressEventHandler(progress); - - auto completed = [this](BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) - { - UpdateUI(); - }; - task->Completed += ref new BackgroundTaskCompletedEventHandler(completed); + task->Progress += ref new BackgroundTaskProgressEventHandler(this, &SampleBackgroundTask::OnProgress); + task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &SampleBackgroundTask::OnCompleted); } /// @@ -110,6 +94,31 @@ void SampleBackgroundTask::UnregisterBackgroundTask(Platform::Object^ sender, Wi UpdateUI(); } +/// +/// Handle background task progress. +/// +/// The task that is reporting progress. +/// Arguments of the progress report. +void SampleBackgroundTask::OnProgress(BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) +{ + Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args]() + { + auto progress = "Progress: " + args->Progress + "%"; + BackgroundTaskSample::SampleBackgroundTaskProgress = progress; + UpdateUI(); + })); +} + +/// +/// Handle background task completion. +/// +/// The task that is reporting completion. +/// Arguments of the completion report. +void SampleBackgroundTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) +{ + UpdateUI(); +} + /// /// Update the scenario UI. /// diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.h b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.h index 382bda2b2d..1bc29293df 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.h +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.h @@ -38,6 +38,8 @@ namespace SDKTemplate void AttachProgressAndCompletedHandlers(Windows::ApplicationModel::Background::IBackgroundTaskRegistration^ task); void RegisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void UnregisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void OnProgress(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskProgressEventArgs^ args); + void OnCompleted(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs^ args); void UpdateUI(); }; } diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cpp index 6e663d4384..35eb8cba54 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cpp +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cpp @@ -44,20 +44,15 @@ void SampleBackgroundTaskWithCondition::OnNavigatedTo(NavigationEventArgs^ e) // // Attach progress and completed handlers to any existing tasks. // - auto iter = BackgroundTaskRegistration::AllTasks->First(); - auto hascur = iter->HasCurrent; - while (hascur) + for (auto pair : BackgroundTaskRegistration::AllTasks) { - auto cur = iter->Current->Value; - - if (cur->Name == SampleBackgroundTaskWithConditionName) + auto task = pair->Value; + if (task->Name == SampleBackgroundTaskWithConditionName) { - BackgroundTaskSample::UpdateBackgroundTaskStatus(cur->Name, true); - AttachProgressAndCompletedHandlers(cur); + BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(task->Name, true); + AttachProgressAndCompletedHandlers(task); break; } - - hascur = iter->MoveNext(); } UpdateUI(); @@ -69,19 +64,8 @@ void SampleBackgroundTaskWithCondition::OnNavigatedTo(NavigationEventArgs^ e) /// The task to attach progress and completed handlers to. void SampleBackgroundTaskWithCondition::AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration^ task) { - auto progress = [this](BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) - { - auto progress = "Progress: " + args->Progress + "%"; - BackgroundTaskSample::SampleBackgroundTaskWithConditionProgress = progress; - UpdateUI(); - }; - task->Progress += ref new BackgroundTaskProgressEventHandler(progress); - - auto completed = [this](BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) - { - UpdateUI(); - }; - task->Completed += ref new BackgroundTaskCompletedEventHandler(completed); + task->Progress += ref new BackgroundTaskProgressEventHandler(this, &SampleBackgroundTaskWithCondition::OnProgress); + task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &SampleBackgroundTaskWithCondition::OnCompleted); } /// @@ -110,6 +94,31 @@ void SampleBackgroundTaskWithCondition::UnregisterBackgroundTask(Platform::Objec UpdateUI(); } +/// +/// Handle background task progress. +/// +/// The task that is reporting progress. +/// Arguments of the progress report. +void SampleBackgroundTaskWithCondition::OnProgress(BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) +{ + Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args]() + { + auto progress = "Progress: " + args->Progress + "%"; + BackgroundTaskSample::SampleBackgroundTaskWithConditionProgress = progress; + UpdateUI(); + })); +} + +/// +/// Handle background task completion. +/// +/// The task that is reporting completion. +/// Arguments of the completion report. +void SampleBackgroundTaskWithCondition::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) +{ + UpdateUI(); +} + /// /// Update the scenario UI. /// diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.h b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.h index 72b2d85d14..2296673413 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.h +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.h @@ -38,6 +38,8 @@ namespace SDKTemplate void AttachProgressAndCompletedHandlers(Windows::ApplicationModel::Background::IBackgroundTaskRegistration^ task); void RegisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void UnregisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void OnProgress(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskProgressEventArgs^ args); + void OnCompleted(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs^ args); void UpdateUI(); }; } diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cpp index 0c19ff811e..99de7fd227 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cpp +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cpp @@ -44,20 +44,15 @@ void ServicingCompleteTask::OnNavigatedTo(NavigationEventArgs^ e) // // Attach progress and completed handlers to any existing tasks. // - auto iter = BackgroundTaskRegistration::AllTasks->First(); - auto hascur = iter->HasCurrent; - while (hascur) + for (auto pair : BackgroundTaskRegistration::AllTasks) { - auto cur = iter->Current->Value; - - if (cur->Name == ServicingCompleteTaskName) + auto task = pair->Value; + if (task->Name == ServicingCompleteTaskName) { - BackgroundTaskSample::UpdateBackgroundTaskStatus(cur->Name, true); - AttachProgressAndCompletedHandlers(cur); + BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(task->Name, true); + AttachProgressAndCompletedHandlers(task); break; } - - hascur = iter->MoveNext(); } UpdateUI(); @@ -69,19 +64,8 @@ void ServicingCompleteTask::OnNavigatedTo(NavigationEventArgs^ e) /// The task to attach progress and completed handlers to. void ServicingCompleteTask::AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration^ task) { - auto progress = [this](BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) - { - auto progress = "Progress: " + args->Progress + "%"; - BackgroundTaskSample::ServicingCompleteTaskProgress = progress; - UpdateUI(); - }; - task->Progress += ref new BackgroundTaskProgressEventHandler(progress); - - auto completed = [this](BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) - { - UpdateUI(); - }; - task->Completed += ref new BackgroundTaskCompletedEventHandler(completed); + task->Progress += ref new BackgroundTaskProgressEventHandler(this, &ServicingCompleteTask::OnProgress); + task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &ServicingCompleteTask::OnCompleted); } /// @@ -111,6 +95,31 @@ void ServicingCompleteTask::UnregisterBackgroundTask(Platform::Object^ sender, W UpdateUI(); } +/// +/// Handle background task progress. +/// +/// The task that is reporting progress. +/// Arguments of the progress report. +void ServicingCompleteTask::OnProgress(BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) +{ + Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args]() + { + auto progress = "Progress: " + args->Progress + "%"; + BackgroundTaskSample::ServicingCompleteTaskProgress = progress; + UpdateUI(); + })); +} + +/// +/// Handle background task completion. +/// +/// The task that is reporting completion. +/// Arguments of the completion report. +void ServicingCompleteTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) +{ + UpdateUI(); +} + /// /// Update the scenario UI. /// diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.h b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.h index 879c2fd863..3d39d33948 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.h +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.h @@ -38,6 +38,8 @@ namespace SDKTemplate void AttachProgressAndCompletedHandlers(Windows::ApplicationModel::Background::IBackgroundTaskRegistration^ task); void RegisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void UnregisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void OnProgress(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskProgressEventArgs^ args); + void OnCompleted(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs^ args); void UpdateUI(); }; } diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cpp index 2f93188d29..bc7f15e190 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cpp +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cpp @@ -44,20 +44,15 @@ void TimeTriggeredTask::OnNavigatedTo(NavigationEventArgs^ e) // // Attach progress and completed handlers to any existing tasks. // - auto iter = BackgroundTaskRegistration::AllTasks->First(); - auto hascur = iter->HasCurrent; - while (hascur) + for (auto pair : BackgroundTaskRegistration::AllTasks) { - auto cur = iter->Current->Value; - - if (cur->Name == TimeTriggeredTaskName) + auto task = pair->Value; + if (task->Name == TimeTriggeredTaskName) { - BackgroundTaskSample::UpdateBackgroundTaskStatus(cur->Name, true); - AttachProgressAndCompletedHandlers(cur); + BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(task->Name, true); + AttachProgressAndCompletedHandlers(task); break; } - - hascur = iter->MoveNext(); } UpdateUI(); @@ -69,19 +64,8 @@ void TimeTriggeredTask::OnNavigatedTo(NavigationEventArgs^ e) /// The task to attach progress and completed handlers to. void TimeTriggeredTask::AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration^ task) { - auto progress = [this](BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) - { - auto progress = "Progress: " + args->Progress + "%"; - BackgroundTaskSample::TimeTriggeredTaskProgress = progress; - UpdateUI(); - }; - task->Progress += ref new BackgroundTaskProgressEventHandler(progress); - - auto completed = [this](BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) - { - UpdateUI(); - }; - task->Completed += ref new BackgroundTaskCompletedEventHandler(completed); + task->Progress += ref new BackgroundTaskProgressEventHandler(this, &TimeTriggeredTask::OnProgress); + task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &TimeTriggeredTask::OnCompleted); } /// @@ -110,6 +94,31 @@ void TimeTriggeredTask::UnregisterBackgroundTask(Platform::Object^ sender, Windo UpdateUI(); } +/// +/// Handle background task progress. +/// +/// The task that is reporting progress. +/// Arguments of the progress report. +void TimeTriggeredTask::OnProgress(BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) +{ + Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args]() + { + auto progress = "Progress: " + args->Progress + "%"; + BackgroundTaskSample::TimeTriggeredTaskProgress = progress; + UpdateUI(); + })); +} + +/// +/// Handle background task completion. +/// +/// The task that is reporting completion. +/// Arguments of the completion report. +void TimeTriggeredTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) +{ + UpdateUI(); +} + /// /// Update the scenario UI. /// diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.h b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.h index 8461c2b4a3..827c69c3d9 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.h +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.h @@ -38,6 +38,8 @@ namespace SDKTemplate void AttachProgressAndCompletedHandlers(Windows::ApplicationModel::Background::IBackgroundTaskRegistration^ task); void RegisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void UnregisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void OnProgress(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskProgressEventArgs^ args); + void OnCompleted(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs^ args); void UpdateUI(); }; } diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cpp b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cpp index 2067080fc5..f0e42d282a 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cpp +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cpp @@ -44,20 +44,15 @@ void ApplicationTriggerTask::OnNavigatedTo(NavigationEventArgs^ e) // // Attach progress and completed handlers to any existing tasks. // - auto iter = BackgroundTaskRegistration::AllTasks->First(); - auto hascur = iter->HasCurrent; - while (hascur) + for (auto pair : BackgroundTaskRegistration::AllTasks) { - auto cur = iter->Current->Value; - - if (cur->Name == ApplicationTriggerTaskName) + auto task = pair->Value; + if (task->Name == ApplicationTriggerTaskName) { - BackgroundTaskSample::UpdateBackgroundTaskStatus(cur->Name, true); - AttachProgressAndCompletedHandlers(cur); + BackgroundTaskSample::UpdateBackgroundTaskRegistrationStatus(task->Name, true); + AttachProgressAndCompletedHandlers(task); break; } - - hascur = iter->MoveNext(); } UpdateUI(); @@ -69,19 +64,8 @@ void ApplicationTriggerTask::OnNavigatedTo(NavigationEventArgs^ e) /// The task to attach progress and completed handlers to. void ApplicationTriggerTask::AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration^ task) { - auto progress = [this](BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) - { - auto progress = "Progress: " + args->Progress + "%"; - BackgroundTaskSample::ApplicationTriggerTaskProgress = progress; - UpdateUI(); - }; - task->Progress += ref new BackgroundTaskProgressEventHandler(progress); - - auto completed = [this](BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) - { - UpdateUI(); - }; - task->Completed += ref new BackgroundTaskCompletedEventHandler(completed); + task->Progress += ref new BackgroundTaskProgressEventHandler(this, &ApplicationTriggerTask::OnProgress); + task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &ApplicationTriggerTask::OnCompleted); } /// @@ -136,6 +120,31 @@ void ApplicationTriggerTask::SignalBackgroundTask(Platform::Object^ sender, Wind UpdateUI(); } +/// +/// Handle background task progress. +/// +/// The task that is reporting progress. +/// Arguments of the progress report. +void ApplicationTriggerTask::OnProgress(BackgroundTaskRegistration^ task, BackgroundTaskProgressEventArgs^ args) +{ + Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args]() + { + auto progress = "Progress: " + args->Progress + "%"; + BackgroundTaskSample::ApplicationTriggerTaskProgress = progress; + UpdateUI(); + })); +} + +/// +/// Handle background task completion. +/// +/// The task that is reporting completion. +/// Arguments of the completion report. +void ApplicationTriggerTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args) +{ + UpdateUI(); +} + /// /// Update the scenario UI. /// diff --git a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.h b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.h index 994baa2b85..a97656d57f 100644 --- a/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.h +++ b/Samples/BackgroundTask/cpp/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.h @@ -41,6 +41,8 @@ namespace SDKTemplate void RegisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void UnregisterBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void SignalBackgroundTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void OnProgress(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskProgressEventArgs^ args); + void OnCompleted(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs^ args); void UpdateUI(); }; } diff --git a/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.cpp b/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.cpp index 869dd46a8c..3bc5ab2f3f 100644 --- a/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.cpp +++ b/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.cpp @@ -13,17 +13,10 @@ #include "SampleBackgroundTask.h" using namespace Tasks; +using namespace Windows::ApplicationModel::Background; using namespace Windows::Foundation; using namespace Windows::Storage; - -SampleBackgroundTask::SampleBackgroundTask() : - CancelReason(BackgroundTaskCancellationReason::Abort), CancelRequested(false), TaskDeferral(nullptr), PeriodicTimer(nullptr), Progress(0), TaskInstance(nullptr) -{ -} - -SampleBackgroundTask::~SampleBackgroundTask() -{ -} +using namespace Windows::System::Threading; void SampleBackgroundTask::Run(IBackgroundTaskInstance^ taskInstance) { @@ -60,11 +53,12 @@ void SampleBackgroundTask::Run(IBackgroundTaskInstance^ taskInstance) PeriodicTimer->Cancel(); // - // Write to LocalSettings to indicate that this background task ran. + // Record that this background task ran. // - auto settings = ApplicationData::Current->LocalSettings; + auto taskStatus = (Progress < 100) ? "Canceled with reason: " + CancelReason.ToString() : "Completed"; auto key = TaskInstance->Task->Name; - settings->Values->Insert(key, (Progress < 100) ? "Canceled with reason: " + CancelReason.ToString() : "Completed"); + auto settings = ApplicationData::Current->LocalSettings; + settings->Values->Insert(key, taskStatus); // // Indicate that the background task has completed. diff --git a/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.h b/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.h index 85685bb6af..60c0222597 100644 --- a/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.h +++ b/Samples/BackgroundTask/cpp/Tasks/SampleBackgroundTask.h @@ -10,32 +10,22 @@ #pragma once -#include "pch.h" -#include - -using namespace Windows::ApplicationModel::Background; -using namespace Windows::System::Threading; - namespace Tasks { [Windows::Foundation::Metadata::WebHostHidden] - public ref class SampleBackgroundTask sealed : public IBackgroundTask + public ref class SampleBackgroundTask sealed : public Windows::ApplicationModel::Background::IBackgroundTask { public: - SampleBackgroundTask(); - - virtual void Run(IBackgroundTaskInstance^ taskInstance); - void OnCanceled(IBackgroundTaskInstance^ taskInstance, BackgroundTaskCancellationReason reason); + virtual void Run(Windows::ApplicationModel::Background::IBackgroundTaskInstance^ taskInstance); + void OnCanceled(Windows::ApplicationModel::Background::IBackgroundTaskInstance^ taskInstance, Windows::ApplicationModel::Background::BackgroundTaskCancellationReason reason); private: - ~SampleBackgroundTask(); - - BackgroundTaskCancellationReason CancelReason; - volatile bool CancelRequested; - Platform::Agile TaskDeferral; - ThreadPoolTimer^ PeriodicTimer; - unsigned int Progress; - IBackgroundTaskInstance^ TaskInstance; + Windows::ApplicationModel::Background::BackgroundTaskCancellationReason CancelReason = Windows::ApplicationModel::Background::BackgroundTaskCancellationReason::Abort; + volatile bool CancelRequested = false; + Platform::Agile TaskDeferral = nullptr; + Windows::System::Threading::ThreadPoolTimer^ PeriodicTimer = nullptr; + unsigned int Progress = 0; + Windows::ApplicationModel::Background::IBackgroundTaskInstance^ TaskInstance = nullptr; }; } \ No newline at end of file diff --git a/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs b/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs index 0ac79793f8..09bc8d3d46 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs +++ b/Samples/BackgroundTask/cs/BackgroundTask/SampleConfiguration.cs @@ -74,11 +74,12 @@ class BackgroundTaskSample /// A name for the background task. /// The trigger for the background task. /// An optional conditional event that must be true for the task to fire. - public static async Task RegisterBackgroundTask(String taskEntryPoint, String name, IBackgroundTrigger trigger, IBackgroundCondition condition) + public static BackgroundTaskRegistration RegisterBackgroundTask(String taskEntryPoint, String name, IBackgroundTrigger trigger, IBackgroundCondition condition) { if (TaskRequiresBackgroundAccess(name)) { - await BackgroundExecutionManager.RequestAccessAsync(); + // If the user denies access, the task will not run. + var requestTask = BackgroundExecutionManager.RequestAccessAsync(); } var builder = new BackgroundTaskBuilder(); @@ -100,10 +101,10 @@ public static async Task RegisterBackgroundTask(Stri BackgroundTaskRegistration task = builder.Register(); - UpdateBackgroundTaskStatus(name, true); + UpdateBackgroundTaskRegistrationStatus(name, true); // - // Remove previous completion status from local settings. + // Remove previous completion status. // var settings = ApplicationData.Current.LocalSettings; settings.Values.Remove(name); @@ -129,7 +130,7 @@ public static void UnregisterBackgroundTasks(String name) } } - UpdateBackgroundTaskStatus(name, false); + UpdateBackgroundTaskRegistrationStatus(name, false); } /// @@ -137,7 +138,7 @@ public static void UnregisterBackgroundTasks(String name) /// /// Name of background task to store registration status for. /// TRUE if registered, FALSE if unregistered. - public static void UpdateBackgroundTaskStatus(String name, bool registered) + public static void UpdateBackgroundTaskRegistrationStatus(String name, bool registered) { switch (name) { @@ -188,10 +189,11 @@ public static String GetBackgroundTaskStatus(String name) var status = registered ? "Registered" : "Unregistered"; + object taskStatus; var settings = ApplicationData.Current.LocalSettings; - if (settings.Values.ContainsKey(name)) + if (settings.Values.TryGetValue(name, out taskStatus)) { - status += " - " + settings.Values[name].ToString(); + status += " - " + taskStatus.ToString(); } return status; diff --git a/Samples/BackgroundTask/cs/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cs b/Samples/BackgroundTask/cs/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cs index a3034d05b9..63f86d4108 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cs +++ b/Samples/BackgroundTask/cs/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.cs @@ -48,7 +48,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) if (task.Value.Name == BackgroundTaskSample.SampleBackgroundTaskName) { AttachProgressAndCompletedHandlers(task.Value); - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.SampleBackgroundTaskName, true); + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.SampleBackgroundTaskName, true); break; } } @@ -61,14 +61,13 @@ protected override void OnNavigatedTo(NavigationEventArgs e) /// /// /// - private async void RegisterBackgroundTask(object sender, RoutedEventArgs e) + private void RegisterBackgroundTask(object sender, RoutedEventArgs e) { var task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.SampleBackgroundTaskName, new SystemTrigger(SystemTriggerType.TimeZoneChange, false), null); - await task; - AttachProgressAndCompletedHandlers(task.Result); + AttachProgressAndCompletedHandlers(task); UpdateUI(); } @@ -100,9 +99,12 @@ private void AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration task /// Arguments of the progress report. private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args) { - var progress = "Progress: " + args.Progress + "%"; - BackgroundTaskSample.SampleBackgroundTaskProgress = progress; - UpdateUI(); + var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + var progress = "Progress: " + args.Progress + "%"; + BackgroundTaskSample.SampleBackgroundTaskProgress = progress; + UpdateUI(); + }); } /// diff --git a/Samples/BackgroundTask/cs/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cs b/Samples/BackgroundTask/cs/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cs index b17ce211c3..52805f238b 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cs +++ b/Samples/BackgroundTask/cs/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.cs @@ -49,7 +49,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) if (task.Value.Name == BackgroundTaskSample.SampleBackgroundTaskWithConditionName) { AttachProgressAndCompletedHandlers(task.Value); - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.SampleBackgroundTaskWithConditionName, true); + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.SampleBackgroundTaskWithConditionName, true); break; } } @@ -62,14 +62,13 @@ protected override void OnNavigatedTo(NavigationEventArgs e) /// /// /// - private async void RegisterBackgroundTask(object sender, RoutedEventArgs e) + private void RegisterBackgroundTask(object sender, RoutedEventArgs e) { var task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.SampleBackgroundTaskWithConditionName, new SystemTrigger(SystemTriggerType.TimeZoneChange, false), new SystemCondition(SystemConditionType.InternetAvailable)); - await task; - AttachProgressAndCompletedHandlers(task.Result); + AttachProgressAndCompletedHandlers(task); UpdateUI(); } @@ -101,9 +100,12 @@ private void AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration task /// Arguments of the progress report. private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args) { - var progress = "Progress: " + args.Progress + "%"; - BackgroundTaskSample.SampleBackgroundTaskWithConditionProgress = progress; - UpdateUI(); + var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + var progress = "Progress: " + args.Progress + "%"; + BackgroundTaskSample.SampleBackgroundTaskWithConditionProgress = progress; + UpdateUI(); + }); } /// diff --git a/Samples/BackgroundTask/cs/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cs b/Samples/BackgroundTask/cs/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cs index 6ba206876d..df9936c56c 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cs +++ b/Samples/BackgroundTask/cs/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.cs @@ -48,7 +48,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) if (task.Value.Name == BackgroundTaskSample.ServicingCompleteTaskName) { AttachProgressAndCompletedHandlers(task.Value); - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.ServicingCompleteTaskName, true); + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.ServicingCompleteTaskName, true); break; } } @@ -61,14 +61,13 @@ protected override void OnNavigatedTo(NavigationEventArgs e) /// /// /// - private async void RegisterBackgroundTask(object sender, RoutedEventArgs e) + private void RegisterBackgroundTask(object sender, RoutedEventArgs e) { var task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.ServicingCompleteTaskEntryPoint, BackgroundTaskSample.ServicingCompleteTaskName, new SystemTrigger(SystemTriggerType.ServicingComplete, false), null); - await task; - AttachProgressAndCompletedHandlers(task.Result); + AttachProgressAndCompletedHandlers(task); UpdateUI(); } @@ -100,9 +99,12 @@ private void AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration task /// Arguments of the progress report. private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args) { - var progress = "Progress: " + args.Progress + "%"; - BackgroundTaskSample.ServicingCompleteTaskProgress = progress; - UpdateUI(); + var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + var progress = "Progress: " + args.Progress + "%"; + BackgroundTaskSample.ServicingCompleteTaskProgress = progress; + UpdateUI(); + }); } /// diff --git a/Samples/BackgroundTask/cs/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cs b/Samples/BackgroundTask/cs/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cs index 535cb3ccda..641ce6b3b5 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cs +++ b/Samples/BackgroundTask/cs/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.cs @@ -48,7 +48,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) if (task.Value.Name == BackgroundTaskSample.TimeTriggeredTaskName) { AttachProgressAndCompletedHandlers(task.Value); - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.TimeTriggeredTaskName, true); + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.TimeTriggeredTaskName, true); break; } } @@ -61,14 +61,13 @@ protected override void OnNavigatedTo(NavigationEventArgs e) /// /// /// - private async void RegisterBackgroundTask(object sender, RoutedEventArgs e) + private void RegisterBackgroundTask(object sender, RoutedEventArgs e) { var task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.TimeTriggeredTaskName, new TimeTrigger(15, false), null); - await task; - AttachProgressAndCompletedHandlers(task.Result); + AttachProgressAndCompletedHandlers(task); UpdateUI(); } @@ -100,9 +99,12 @@ private void AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration task /// Arguments of the progress report. private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args) { - var progress = "Progress: " + args.Progress + "%"; - BackgroundTaskSample.TimeTriggeredTaskProgress = progress; - UpdateUI(); + var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + var progress = "Progress: " + args.Progress + "%"; + BackgroundTaskSample.TimeTriggeredTaskProgress = progress; + UpdateUI(); + }); } /// diff --git a/Samples/BackgroundTask/cs/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cs b/Samples/BackgroundTask/cs/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cs index 1dab288804..a0f7b25b4c 100644 --- a/Samples/BackgroundTask/cs/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cs +++ b/Samples/BackgroundTask/cs/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.cs @@ -51,7 +51,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) if (task.Value.Name == BackgroundTaskSample.ApplicationTriggerTaskName) { AttachProgressAndCompletedHandlers(task.Value); - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.ApplicationTriggerTaskName, true); + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.ApplicationTriggerTaskName, true); break; } } @@ -64,7 +64,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) /// /// /// - private async void RegisterBackgroundTask(object sender, RoutedEventArgs e) + private void RegisterBackgroundTask(object sender, RoutedEventArgs e) { trigger = new ApplicationTrigger(); @@ -72,8 +72,7 @@ private async void RegisterBackgroundTask(object sender, RoutedEventArgs e) BackgroundTaskSample.ApplicationTriggerTaskName, trigger, null); - await task; - AttachProgressAndCompletedHandlers(task.Result); + AttachProgressAndCompletedHandlers(task); UpdateUI(); } @@ -123,9 +122,12 @@ private void AttachProgressAndCompletedHandlers(IBackgroundTaskRegistration task /// Arguments of the progress report. private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args) { - var progress = "Progress: " + args.Progress + "%"; - BackgroundTaskSample.ApplicationTriggerTaskProgress = progress; - UpdateUI(); + var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + var progress = "Progress: " + args.Progress + "%"; + BackgroundTaskSample.ApplicationTriggerTaskProgress = progress; + UpdateUI(); + }); } /// diff --git a/Samples/BackgroundTask/cs/Tasks/SampleBackgroundTask.cs b/Samples/BackgroundTask/cs/Tasks/SampleBackgroundTask.cs index 85aacf42a1..d9d16c9c7e 100644 --- a/Samples/BackgroundTask/cs/Tasks/SampleBackgroundTask.cs +++ b/Samples/BackgroundTask/cs/Tasks/SampleBackgroundTask.cs @@ -91,13 +91,14 @@ private void PeriodicTimerCallback(ThreadPoolTimer timer) { _periodicTimer.Cancel(); - var settings = ApplicationData.Current.LocalSettings; var key = _taskInstance.Task.Name; // - // Write to LocalSettings to indicate that this background task ran. + // Record that this background task ran. // - settings.Values[key] = (_progress < 100) ? "Canceled with reason: " + _cancelReason.ToString() : "Completed"; + String taskStatus = (_progress < 100) ? "Canceled with reason: " + _cancelReason.ToString() : "Completed"; + var settings = ApplicationData.Current.LocalSettings; + settings.Values[key] = taskStatus; Debug.WriteLine("Background " + _taskInstance.Task.Name + settings.Values[key]); // diff --git a/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb b/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb index a2ef55f568..0fa21b4e4c 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb +++ b/Samples/BackgroundTask/vb/BackgroundTask/SampleConfiguration.vb @@ -81,9 +81,10 @@ Namespace Global.SDKTemplate ''' A name for the background task. ''' The trigger for the background task. ''' An optional conditional event that must be true for the task to fire. - Public Shared Async Function RegisterBackgroundTask(taskEntryPoint As String, name As String, trigger As IBackgroundTrigger, condition As IBackgroundCondition) As Task(Of BackgroundTaskRegistration) + Public Shared Function RegisterBackgroundTask(taskEntryPoint As String, name As String, trigger As IBackgroundTrigger, condition As IBackgroundCondition) As BackgroundTaskRegistration If TaskRequiresBackgroundAccess(name) Then - Await BackgroundExecutionManager.RequestAccessAsync() + ' If the user denies access, the task will not run. + Dim requestTask = BackgroundExecutionManager.RequestAccessAsync() End If Dim builder = New BackgroundTaskBuilder() @@ -96,9 +97,9 @@ Namespace Global.SDKTemplate End If Dim task As BackgroundTaskRegistration = builder.Register() - UpdateBackgroundTaskStatus(name, True) + UpdateBackgroundTaskRegistrationStatus(name, True) ' - ' Remove previous completion status from local settings. + ' Remove previous completion status. ' Dim settings = ApplicationData.Current.LocalSettings settings.Values.Remove(name) @@ -116,7 +117,7 @@ Namespace Global.SDKTemplate End If Next - UpdateBackgroundTaskStatus(name, False) + UpdateBackgroundTaskRegistrationStatus(name, False) End Sub ''' @@ -124,7 +125,7 @@ Namespace Global.SDKTemplate ''' ''' Name of background task to store registration status for. ''' TRUE if registered, FALSE if unregistered. - Public Shared Sub UpdateBackgroundTaskStatus(name As String, registered As Boolean) + Public Shared Sub UpdateBackgroundTaskRegistrationStatus(name As String, registered As Boolean) Select name Case SampleBackgroundTaskName SampleBackgroundTaskRegistered = registered @@ -160,9 +161,10 @@ Namespace Global.SDKTemplate End Select Dim status = If(registered, "Registered", "Unregistered") + Dim taskStatus As Object = Nothing Dim settings = ApplicationData.Current.LocalSettings - If settings.Values.ContainsKey(name) Then - status &= " - " & settings.Values(name).ToString() + If settings.Values.TryGetValue(name, taskStatus) Then + status &= " - " & taskStatus.ToString() End If Return status @@ -173,7 +175,7 @@ Namespace Global.SDKTemplate ''' ''' Name of background task to query background access requirement. Public Shared Function TaskRequiresBackgroundAccess(name As String) As Boolean - If(name = TimeTriggeredTaskName) OrElse (name = ApplicationTriggerTaskName) Then + If (name = TimeTriggeredTaskName) OrElse (name = ApplicationTriggerTaskName) Then Return True Else Return False diff --git a/Samples/BackgroundTask/vb/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.vb b/Samples/BackgroundTask/vb/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.vb index 265b69b5d7..783ef7c2a0 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.vb +++ b/Samples/BackgroundTask/vb/BackgroundTask/Scenario1_SampleBackgroundTask.xaml.vb @@ -42,7 +42,7 @@ Namespace Global.SDKTemplate For Each task In BackgroundTaskRegistration.AllTasks If task.Value.Name = BackgroundTaskSample.SampleBackgroundTaskName Then AttachProgressAndCompletedHandlers(task.Value) - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.SampleBackgroundTaskName, True) + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.SampleBackgroundTaskName, True) Exit For End If Next @@ -55,10 +55,9 @@ Namespace Global.SDKTemplate ''' ''' ''' - Private Async Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) + Private Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) Dim task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.SampleBackgroundTaskName, New SystemTrigger(SystemTriggerType.TimeZoneChange, False), Nothing) - Await task - AttachProgressAndCompletedHandlers(task.Result) + AttachProgressAndCompletedHandlers(task) UpdateUI() End Sub @@ -87,9 +86,11 @@ Namespace Global.SDKTemplate ''' The task that is reporting progress. ''' Arguments of the progress report. Private Sub OnProgress(task As IBackgroundTaskRegistration, args As BackgroundTaskProgressEventArgs) - Dim progress = "Progress: " & args.Progress & "%" - BackgroundTaskSample.SampleBackgroundTaskProgress = progress - UpdateUI() + Dim ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() + Dim progress = "Progress: " & args.Progress & "%" + BackgroundTaskSample.SampleBackgroundTaskProgress = progress + UpdateUI() + End Sub) End Sub ''' diff --git a/Samples/BackgroundTask/vb/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.vb b/Samples/BackgroundTask/vb/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.vb index b8bf311732..9503255e84 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.vb +++ b/Samples/BackgroundTask/vb/BackgroundTask/Scenario2_SampleBackgroundTaskWithCondition.xaml.vb @@ -40,7 +40,7 @@ Namespace Global.SDKTemplate For Each task In BackgroundTaskRegistration.AllTasks If task.Value.Name = BackgroundTaskSample.SampleBackgroundTaskWithConditionName Then AttachProgressAndCompletedHandlers(task.Value) - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.SampleBackgroundTaskWithConditionName, True) + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.SampleBackgroundTaskWithConditionName, True) Exit For End If Next @@ -53,10 +53,9 @@ Namespace Global.SDKTemplate ''' ''' ''' - Private Async Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) + Private Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) Dim task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.SampleBackgroundTaskWithConditionName, New SystemTrigger(SystemTriggerType.TimeZoneChange, False), New SystemCondition(SystemConditionType.InternetAvailable)) - Await task - AttachProgressAndCompletedHandlers(task.Result) + AttachProgressAndCompletedHandlers(task) UpdateUI() End Sub @@ -85,9 +84,11 @@ Namespace Global.SDKTemplate ''' The task that is reporting progress. ''' Arguments of the progress report. Private Sub OnProgress(task As IBackgroundTaskRegistration, args As BackgroundTaskProgressEventArgs) - Dim progress = "Progress: " & args.Progress & "%" - BackgroundTaskSample.SampleBackgroundTaskWithConditionProgress = progress - UpdateUI() + Dim ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() + Dim progress = "Progress: " & args.Progress & "%" + BackgroundTaskSample.SampleBackgroundTaskWithConditionProgress = progress + UpdateUI() + End Sub) End Sub ''' diff --git a/Samples/BackgroundTask/vb/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.vb b/Samples/BackgroundTask/vb/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.vb index dad6a2fcc4..54b17caaa2 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.vb +++ b/Samples/BackgroundTask/vb/BackgroundTask/Scenario3_ServicingCompleteTask.xaml.vb @@ -40,7 +40,7 @@ Namespace Global.SDKTemplate For Each task In BackgroundTaskRegistration.AllTasks If task.Value.Name = BackgroundTaskSample.ServicingCompleteTaskName Then AttachProgressAndCompletedHandlers(task.Value) - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.ServicingCompleteTaskName, True) + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.ServicingCompleteTaskName, True) Exit For End If Next @@ -53,10 +53,9 @@ Namespace Global.SDKTemplate ''' ''' ''' - Private Async Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) + Private Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) Dim task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.ServicingCompleteTaskEntryPoint, BackgroundTaskSample.ServicingCompleteTaskName, New SystemTrigger(SystemTriggerType.ServicingComplete, False), Nothing) - Await task - AttachProgressAndCompletedHandlers(task.Result) + AttachProgressAndCompletedHandlers(task) UpdateUI() End Sub @@ -85,9 +84,11 @@ Namespace Global.SDKTemplate ''' The task that is reporting progress. ''' Arguments of the progress report. Private Sub OnProgress(task As IBackgroundTaskRegistration, args As BackgroundTaskProgressEventArgs) - Dim progress = "Progress: " & args.Progress & "%" - BackgroundTaskSample.ServicingCompleteTaskProgress = progress - UpdateUI() + Dim ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() + Dim progress = "Progress: " & args.Progress & "%" + BackgroundTaskSample.ServicingCompleteTaskProgress = progress + UpdateUI() + End Sub) End Sub ''' diff --git a/Samples/BackgroundTask/vb/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.vb b/Samples/BackgroundTask/vb/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.vb index 3e38b13cd6..6591f98b46 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.vb +++ b/Samples/BackgroundTask/vb/BackgroundTask/Scenario4_TimeTriggeredTask.xaml.vb @@ -40,7 +40,7 @@ Namespace Global.SDKTemplate For Each task In BackgroundTaskRegistration.AllTasks If task.Value.Name = BackgroundTaskSample.TimeTriggeredTaskName Then AttachProgressAndCompletedHandlers(task.Value) - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.TimeTriggeredTaskName, True) + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.TimeTriggeredTaskName, True) Exit For End If Next @@ -53,10 +53,9 @@ Namespace Global.SDKTemplate ''' ''' ''' - Private Async Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) + Private Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) Dim task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.TimeTriggeredTaskName, New TimeTrigger(15, False), Nothing) - Await task - AttachProgressAndCompletedHandlers(task.Result) + AttachProgressAndCompletedHandlers(task) UpdateUI() End Sub @@ -85,9 +84,11 @@ Namespace Global.SDKTemplate ''' The task that is reporting progress. ''' Arguments of the progress report. Private Sub OnProgress(task As IBackgroundTaskRegistration, args As BackgroundTaskProgressEventArgs) - Dim progress = "Progress: " & args.Progress & "%" - BackgroundTaskSample.TimeTriggeredTaskProgress = progress - UpdateUI() + Dim ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() + Dim progress = "Progress: " & args.Progress & "%" + BackgroundTaskSample.TimeTriggeredTaskProgress = progress + UpdateUI() + End Sub) End Sub ''' diff --git a/Samples/BackgroundTask/vb/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.vb b/Samples/BackgroundTask/vb/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.vb index 2221301c02..25315e06c6 100644 --- a/Samples/BackgroundTask/vb/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.vb +++ b/Samples/BackgroundTask/vb/BackgroundTask/Scenario5_ApplicationTriggerTask.xaml.vb @@ -42,7 +42,7 @@ Namespace Global.SDKTemplate For Each task In BackgroundTaskRegistration.AllTasks If task.Value.Name = BackgroundTaskSample.ApplicationTriggerTaskName Then AttachProgressAndCompletedHandlers(task.Value) - BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.ApplicationTriggerTaskName, True) + BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.ApplicationTriggerTaskName, True) Exit For End If Next @@ -55,11 +55,10 @@ Namespace Global.SDKTemplate ''' ''' ''' - Private Async Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) + Private Sub RegisterBackgroundTask(sender As Object, e As RoutedEventArgs) trigger = New ApplicationTrigger() Dim task = BackgroundTaskSample.RegisterBackgroundTask(BackgroundTaskSample.SampleBackgroundTaskEntryPoint, BackgroundTaskSample.ApplicationTriggerTaskName, trigger, Nothing) - Await task - AttachProgressAndCompletedHandlers(task.Result) + AttachProgressAndCompletedHandlers(task) UpdateUI() End Sub @@ -104,9 +103,11 @@ Namespace Global.SDKTemplate ''' The task that is reporting progress. ''' Arguments of the progress report. Private Sub OnProgress(task As IBackgroundTaskRegistration, args As BackgroundTaskProgressEventArgs) - Dim progress = "Progress: " & args.Progress & "%" - BackgroundTaskSample.ApplicationTriggerTaskProgress = progress - UpdateUI() + Dim ignored = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() + Dim progress = "Progress: " & args.Progress & "%" + BackgroundTaskSample.ApplicationTriggerTaskProgress = progress + UpdateUI() + End Sub) End Sub ''' diff --git a/Samples/BackgroundTask/vb/Tasks/SampleBackgroundTask.vb b/Samples/BackgroundTask/vb/Tasks/SampleBackgroundTask.vb index a7c75d8952..2a9f8aa313 100644 --- a/Samples/BackgroundTask/vb/Tasks/SampleBackgroundTask.vb +++ b/Samples/BackgroundTask/vb/Tasks/SampleBackgroundTask.vb @@ -72,10 +72,11 @@ Namespace Global.Tasks _taskInstance.Progress = _progress Else _periodicTimer.Cancel() - Dim settings = ApplicationData.Current.LocalSettings + Dim status As String = If((_progress < 100), "Canceled with reason: " & _cancelReason.ToString(), "Completed") Dim key = _taskInstance.Task.Name - settings.Values(key) = If((_progress < 100), "Canceled with reason: " & _cancelReason.ToString(), "Completed") - Debug.WriteLine("Background " & _taskInstance.Task.Name & settings.Values(key)) + Dim settings = ApplicationData.Current.LocalSettings + settings.Values(key) = status + Debug.WriteLine("Background " & _taskInstance.Task.Name & status) _deferral.Complete() End If End Sub diff --git a/Samples/BarcodeScanner/README.md b/Samples/BarcodeScanner/README.md index a29e2d597d..a98db996e0 100644 --- a/Samples/BarcodeScanner/README.md +++ b/Samples/BarcodeScanner/README.md @@ -5,17 +5,18 @@ # Barcode scanner sample -This sample shows how to create a barcode scanner, claim it for exclusive use, enable it to receive data, and read a barcode. This sample uses [**Windows.Devices.PointOfService**](http://msdn.microsoft.com/library/windows/apps/dn298071) API. +This sample shows how to obtain a barcode scanner, +claim it for exclusive use, enable it to receive data, and read a barcode. Specifically, this sample shows how to: -1. **Create the barcode scanner** +1. **Obtain the barcode scanner** - Uses the [**BarcodeScanner.GetDefaultAsync**](http://msdn.microsoft.com/library/windows/apps/dn263790) to get the first available barcode scanner. + Uses [**BarcodeScanner.GetDefaultAsync**](http://msdn.microsoft.com/library/windows/apps/dn263790) to get the first available barcode scanner. 2. **Claim the barcode scanner for exclusive use** - Uses the [**ClaimScannerAsync**](http://msdn.microsoft.com/library/windows/apps/dn297696) to claim the device. + Uses [**ClaimScannerAsync**](http://msdn.microsoft.com/library/windows/apps/dn297696) to claim the device. 3. **Add event handlers** @@ -41,13 +42,9 @@ To obtain information about Microsoft Visual Studio 2015 and the tools for devel ## Related topics -### Samples - -[Barcode Scanner sample](/Samples/BarcodeScanner) - ### Reference -[Windows.Devices.PointOfService](http://msdn.microsoft.com/library/windows/apps/dn298071) +[Windows.Devices.PointOfService namespace](http://msdn.microsoft.com/library/windows/apps/dn298071) [USB HID POS Scanner specification](http://go.microsoft.com/fwlink/p/?linkid=309230) diff --git a/Samples/FileAccess/cpp/SampleConfiguration.cpp b/Samples/FileAccess/cpp/SampleConfiguration.cpp index 4f5eab06ce..202007fd66 100644 --- a/Samples/FileAccess/cpp/SampleConfiguration.cpp +++ b/Samples/FileAccess/cpp/SampleConfiguration.cpp @@ -50,14 +50,15 @@ void MainPage::NotifyUserFileNotExist() NotifyUser("The file '" + Filename + "' does not exist. Use scenario one to create this file.", NotifyType::ErrorMessage); } -void MainPage::HandleFileNotFoundException(Platform::COMException^ e) +// I/O errors are reported as exceptions. +void MainPage::HandleIoException(Platform::COMException^ e, Platform::String^ description) { - if (e->HResult == 0x80070002) // Catch FileNotExistException + if (e->HResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { NotifyUserFileNotExist(); } else { - throw e; + NotifyUser(description + ": " + e->Message, NotifyType::ErrorMessage); } } diff --git a/Samples/FileAccess/cpp/SampleConfiguration.h b/Samples/FileAccess/cpp/SampleConfiguration.h index 675acf0540..48b5e2ca56 100644 --- a/Samples/FileAccess/cpp/SampleConfiguration.h +++ b/Samples/FileAccess/cpp/SampleConfiguration.h @@ -74,7 +74,7 @@ namespace SDKTemplate void Initialize(); void ValidateFile(); void NotifyUserFileNotExist(); - void HandleFileNotFoundException(Platform::COMException^ e); + void HandleIoException(Platform::COMException^ e, Platform::String^ description); private: static Platform::Array^ scenariosInner; diff --git a/Samples/FileAccess/cpp/Scenario10_DeleteAFile.xaml.cpp b/Samples/FileAccess/cpp/Scenario10_DeleteAFile.xaml.cpp index 034d533123..f27a44d4b3 100644 --- a/Samples/FileAccess/cpp/Scenario10_DeleteAFile.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario10_DeleteAFile.xaml.cpp @@ -44,7 +44,7 @@ void Scenario10::DeleteFileButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error deleting file '" + fileName + "'"); } }); } diff --git a/Samples/FileAccess/cpp/Scenario1_CreateAFileInThePicturesLibrary.xaml.cpp b/Samples/FileAccess/cpp/Scenario1_CreateAFileInThePicturesLibrary.xaml.cpp index 3b4f137242..c9c25445a6 100644 --- a/Samples/FileAccess/cpp/Scenario1_CreateAFileInThePicturesLibrary.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario1_CreateAFileInThePicturesLibrary.xaml.cpp @@ -15,6 +15,7 @@ using namespace SDKTemplate; using namespace concurrency; +using namespace Platform; using namespace Windows::Storage; using namespace Windows::UI::Xaml; @@ -27,9 +28,18 @@ Scenario1::Scenario1() : rootPage(MainPage::Current) void Scenario1::CreateFileButton_Click(Object^ sender, RoutedEventArgs^ e) { - create_task(KnownFolders::PicturesLibrary->CreateFileAsync(rootPage->Filename, CreationCollisionOption::ReplaceExisting)).then([this](StorageFile^ file) + create_task(KnownFolders::PicturesLibrary->CreateFileAsync(rootPage->Filename, CreationCollisionOption::ReplaceExisting)).then([this](task task) { - rootPage->SampleFile = file; - rootPage->NotifyUser("The file '" + file->Name + "' was created.", NotifyType::StatusMessage); + try + { + StorageFile^ file = task.get(); + rootPage->SampleFile = file; + rootPage->NotifyUser("The file '" + file->Name + "' was created.", NotifyType::StatusMessage); + } + catch (Exception^ e) + { + // I/O errors are reported as exceptions. + rootPage->NotifyUser("Error creating file '" + MainPage::Filename + "': " + e->Message, NotifyType::ErrorMessage); + } }); } diff --git a/Samples/FileAccess/cpp/Scenario3_WriteAndReadTextInAFile.xaml.cpp b/Samples/FileAccess/cpp/Scenario3_WriteAndReadTextInAFile.xaml.cpp index 323d169131..be08117f78 100644 --- a/Samples/FileAccess/cpp/Scenario3_WriteAndReadTextInAFile.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario3_WriteAndReadTextInAFile.xaml.cpp @@ -45,7 +45,7 @@ void Scenario3::WriteTextButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error writing to '" + file->Name + "'"); } }); } @@ -74,7 +74,7 @@ void Scenario3::ReadTextButton_Click(Object^ sender, RoutedEventArgs^ e) } catch(COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error reading from '" + file->Name + "'"); } }); } diff --git a/Samples/FileAccess/cpp/Scenario4_WriteAndReadBytesInAFile.xaml.cpp b/Samples/FileAccess/cpp/Scenario4_WriteAndReadBytesInAFile.xaml.cpp index 5b66f222f8..c13dbd6b1b 100644 --- a/Samples/FileAccess/cpp/Scenario4_WriteAndReadBytesInAFile.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario4_WriteAndReadBytesInAFile.xaml.cpp @@ -56,7 +56,7 @@ void Scenario4::WriteBytesButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error writing to '" + file->Name + "'"); } }); } @@ -88,7 +88,7 @@ void Scenario4::ReadBytesButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error reading from '" + file->Name + "'"); } }); } diff --git a/Samples/FileAccess/cpp/Scenario5_WriteAndReadAFileUsingAStream.xaml.cpp b/Samples/FileAccess/cpp/Scenario5_WriteAndReadAFileUsingAStream.xaml.cpp index 235af1978c..bf21a91da5 100644 --- a/Samples/FileAccess/cpp/Scenario5_WriteAndReadAFileUsingAStream.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario5_WriteAndReadAFileUsingAStream.xaml.cpp @@ -57,7 +57,7 @@ void Scenario5::WriteToStreamButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error writing to '" + file->Name + "'"); } }); } @@ -101,7 +101,7 @@ void Scenario5::ReadFromStreamButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error reading from '" + file->Name + "'"); } }); } diff --git a/Samples/FileAccess/cpp/Scenario6_DisplayFileProperties.xaml.cpp b/Samples/FileAccess/cpp/Scenario6_DisplayFileProperties.xaml.cpp index 22912935e5..26f5cbc277 100644 --- a/Samples/FileAccess/cpp/Scenario6_DisplayFileProperties.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario6_DisplayFileProperties.xaml.cpp @@ -47,22 +47,13 @@ void Scenario6::ShowPropertiesButton_Click(Object^ sender, RoutedEventArgs^ e) *outputText += "\nFile type: " + file->FileType; // Get basic properties - create_task(file->GetBasicPropertiesAsync()).then([this, outputText](task task) + create_task(file->GetBasicPropertiesAsync()).then([this, file, outputText](BasicProperties^ basicProperties) { - try - { - BasicProperties^ basicProperties = task.get(); - *outputText += "\nFile size: " + basicProperties->Size.ToString() + " bytes"; + *outputText += "\nFile size: " + basicProperties->Size.ToString() + " bytes"; + + String^ dateModifiedString = dateFormat->Format(basicProperties->DateModified) + " " + timeFormat->Format(basicProperties->DateModified); + *outputText += "\nDate modified: " + dateModifiedString; - String^ dateModifiedString = dateFormat->Format(basicProperties->DateModified) + " " + timeFormat->Format(basicProperties->DateModified); - *outputText += "\nDate modified: " + dateModifiedString; - } - catch (COMException^ ex) - { - rootPage->HandleFileNotFoundException(ex); - } - }).then([this, file]() - { // Get extra properties auto propertiesName = ref new Vector(); propertiesName->Append(dateAccessedProperty); @@ -83,6 +74,16 @@ void Scenario6::ShowPropertiesButton_Click(Object^ sender, RoutedEventArgs^ e) } rootPage->NotifyUser(*outputText, NotifyType::StatusMessage); + }).then([this, file](task task) + { + try + { + task.get(); + } + catch (COMException^ ex) + { + rootPage->HandleIoException(ex, "Error retrieving properties for '" + file->Name + "'"); + } }); } else diff --git a/Samples/FileAccess/cpp/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cpp b/Samples/FileAccess/cpp/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cpp index 484054ac95..ddbfe2fcba 100644 --- a/Samples/FileAccess/cpp/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cpp @@ -42,11 +42,26 @@ void Scenario7::AddToListButton_Click(Object^ sender, RoutedEventArgs^ e) rootPage->MruToken = StorageApplicationPermissions::MostRecentlyUsedList->Add(file, file->Name, visibility); rootPage->NotifyUser("The file '" + file->Name + "' was added to the MRU list and a token was stored.", NotifyType::StatusMessage); } - else if (FALRadioButton->IsChecked->Value) + else { - // Add the file to the MRU - rootPage->FalToken = StorageApplicationPermissions::FutureAccessList->Add(file, file->Name); - rootPage->NotifyUser("The file '" + file->Name + "' was added to the FAL list and a token was stored.", NotifyType::StatusMessage); + // Add the file to the FAL + try + { + rootPage->FalToken = StorageApplicationPermissions::FutureAccessList->Add(file, file->Name); + rootPage->NotifyUser("The file '" + file->Name + "' was added to the FAL list and a token was stored.", NotifyType::StatusMessage); + } + catch (COMException^ ex) + { + if (ex->HResult == FA_E_MAX_PERSISTED_ITEMS_REACHED) + { + // A real program would call Remove() to create room in the FAL. + rootPage->NotifyUser("The file '" + file->Name + "' was not added to the FAL list because the FAL list is full.", NotifyType::ErrorMessage); + } + else + { + throw; + } + } } } else @@ -57,115 +72,94 @@ void Scenario7::AddToListButton_Click(Object^ sender, RoutedEventArgs^ e) void Scenario7::ShowListButton_Click(Object^ sender, RoutedEventArgs^ e) { - StorageFile^ file = rootPage->SampleFile; - if (file != nullptr) + AccessListEntryView^ entries = nullptr; + String^ listName; + + if (MRURadioButton->IsChecked->Value) { - String^ outputText; - NotifyType statusOrError = NotifyType::StatusMessage; - if (MRURadioButton->IsChecked->Value) - { - AccessListEntryView^ entries = StorageApplicationPermissions::MostRecentlyUsedList->Entries; - if (entries->Size > 0) - { - outputText = "The MRU list contains the following item(s):"; - std::for_each(begin(entries), end(entries), [this, &outputText](const AccessListEntry& entry) - { - outputText += "\n" + entry.Metadata; // Application previously chose to store sampleFile->Name in this field - }); - } - else - { - outputText = "The MRU list is empty, please select 'Most Recently Used' list and click 'Add to List' to add a file to the MRU list."; - statusOrError = NotifyType::ErrorMessage; - } - } - else if (FALRadioButton->IsChecked->Value) + listName = "MRU"; + entries = StorageApplicationPermissions::MostRecentlyUsedList->Entries; + } + else + { + listName = "FAL"; + entries = StorageApplicationPermissions::FutureAccessList->Entries; + } + + if (entries->Size > 0) + { + String^ outputText = "The " + listName + " + list contains the following item(s):"; + for (const AccessListEntry& entry : entries) { - AccessListEntryView^ entries = StorageApplicationPermissions::FutureAccessList->Entries; - if (entries->Size > 0) - { - outputText = "The FAL list contains the following item(s):"; - std::for_each(begin(entries), end(entries), [this, &outputText](const AccessListEntry& entry) - { - outputText += "\n" + entry.Metadata; // Application previously chose to store sampleFile->Name in this field - }); - } - else - { - outputText = "The FAL list is empty, please select 'Future Access List' list and click 'Add to List' to add a file to the FAL list."; - statusOrError = NotifyType::ErrorMessage; - } + outputText += "\n" + entry.Metadata; // Application previously chose to store sampleFile->Name in this field } - rootPage->NotifyUser(outputText, statusOrError); + rootPage->NotifyUser(outputText, NotifyType::StatusMessage); } else { - rootPage->NotifyUserFileNotExist(); + rootPage->NotifyUser("The " + listName + " list is empty.", NotifyType::ErrorMessage); } } void Scenario7::OpenFromListButton_Click(Object^ sender, RoutedEventArgs^ e) { - StorageFile^ file = rootPage->SampleFile; - if (file != nullptr) + task fileTask = task_from_result(nullptr); + + if (MRURadioButton->IsChecked->Value) { - if (MRURadioButton->IsChecked->Value) + if (rootPage->MruToken != nullptr) { - if (rootPage->MruToken != nullptr) + // Open the file via the token that was stored when adding this file into the MRU list + fileTask = create_task(StorageApplicationPermissions::MostRecentlyUsedList->GetFileAsync(rootPage->MruToken)).then([this](task task) { - // Open the file via the token that was stored when adding this file into the MRU list - create_task(StorageApplicationPermissions::MostRecentlyUsedList->GetFileAsync(rootPage->MruToken)).then([this](task task) + StorageFile^ file = nullptr; + try { - try - { - StorageFile^ file = task.get(); - // Read the file - create_task(FileIO::ReadTextAsync(file)).then([this, file](String^ fileContent) - { - rootPage->NotifyUser("The file '" + file->Name + "' was opened by a stored token from the MRU list, it contains the following text:\n" + fileContent, NotifyType::StatusMessage); - }); - } - catch (COMException^ ex) - { - rootPage->HandleFileNotFoundException(ex); - } - }); - } - else - { - rootPage->NotifyUser("The MRU list is empty, please select 'Most Recently Used' list and click 'Add to List' to add a file to the MRU list.", NotifyType::ErrorMessage); - } + file = task.get(); + } + catch (InvalidArgumentException^) + { + // When the MRU becomes full, older entries are automatically deleted. + rootPage->NotifyUser("The token is no longer valid.", NotifyType::ErrorMessage); + } + return file; + }); } - else if (FALRadioButton->IsChecked->Value) + else { - if (rootPage->FalToken != nullptr) - { - // Open the file via the token that was stored when adding this file into the FAL list - create_task(StorageApplicationPermissions::FutureAccessList->GetFileAsync(rootPage->FalToken)).then([this](task task) - { - try - { - StorageFile^ file = task.get(); - // Read the file - create_task(FileIO::ReadTextAsync(file)).then([this, file](String^ fileContent) - { - rootPage->NotifyUser("The file '" + file->Name + "' was opened by a stored token from the FAL list, it contains the following text:\n" + fileContent, NotifyType::StatusMessage); - }); - } - catch (COMException^ ex) - { - rootPage->HandleFileNotFoundException(ex); - } - }); - } - else - { - rootPage->NotifyUser("The FAL list is empty, please select 'Future Access List' list and click 'Add to List' to add a file to the FAL list.", NotifyType::ErrorMessage); - } + rootPage->NotifyUser("This operation requires a token. Add file to the MRU list first.", NotifyType::ErrorMessage); } } else { - rootPage->NotifyUserFileNotExist(); + if (rootPage->FalToken != nullptr) + { + // Open the file via the token that was stored when adding this file into the FAL list + fileTask = create_task(StorageApplicationPermissions::FutureAccessList->GetFileAsync(rootPage->FalToken)); + } + else + { + rootPage->NotifyUser("This operation requires a token. Add file to the FAL list first.", NotifyType::ErrorMessage); + } } + + fileTask.then([this](StorageFile^ file) + { + if (file != nullptr) + { + create_task(FileIO::ReadTextAsync(file)).then([this, file](task task) + { + try + { + String^ fileContent = task.get(); + rootPage->NotifyUser("The file '" + file->Name + "' was opened by a stored token. It contains the following text:\n" + fileContent, NotifyType::StatusMessage); + } + catch (COMException^ ex) + { + // I/O errors are reported as exceptions. + rootPage->HandleIoException(ex, "Error reading file opened from list"); + } + }); + } + }); } diff --git a/Samples/FileAccess/cpp/Scenario8_CopyAFile.xaml.cpp b/Samples/FileAccess/cpp/Scenario8_CopyAFile.xaml.cpp index a5fb028e27..4641d06b44 100644 --- a/Samples/FileAccess/cpp/Scenario8_CopyAFile.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario8_CopyAFile.xaml.cpp @@ -43,7 +43,7 @@ void Scenario8::CopyFileButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error copying file '" + file->Name + "'"); } }); } diff --git a/Samples/FileAccess/cpp/Scenario9_CompareTwoFilesToSeeIfTheyAreTheSame.xaml.cpp b/Samples/FileAccess/cpp/Scenario9_CompareTwoFilesToSeeIfTheyAreTheSame.xaml.cpp index 410779be16..ef232ed482 100644 --- a/Samples/FileAccess/cpp/Scenario9_CompareTwoFilesToSeeIfTheyAreTheSame.xaml.cpp +++ b/Samples/FileAccess/cpp/Scenario9_CompareTwoFilesToSeeIfTheyAreTheSame.xaml.cpp @@ -54,7 +54,7 @@ void Scenario9::CompareFilesButton_Click(Object^ sender, RoutedEventArgs^ e) } catch (COMException^ ex) { - rootPage->HandleFileNotFoundException(ex); + rootPage->HandleIoException(ex, "Error determining whether two files are the same"); } } else diff --git a/Samples/FileAccess/cs/Scenario10_DeleteAFile.xaml.cs b/Samples/FileAccess/cs/Scenario10_DeleteAFile.xaml.cs index c1c5458abe..b1ae8385fe 100644 --- a/Samples/FileAccess/cs/Scenario10_DeleteAFile.xaml.cs +++ b/Samples/FileAccess/cs/Scenario10_DeleteAFile.xaml.cs @@ -53,6 +53,11 @@ private async void DeleteFileButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error deleting file '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { diff --git a/Samples/FileAccess/cs/Scenario1_CreateAFileInThePicturesLibrary.xaml.cs b/Samples/FileAccess/cs/Scenario1_CreateAFileInThePicturesLibrary.xaml.cs index 8fbc9c157e..6eb436dea3 100644 --- a/Samples/FileAccess/cs/Scenario1_CreateAFileInThePicturesLibrary.xaml.cs +++ b/Samples/FileAccess/cs/Scenario1_CreateAFileInThePicturesLibrary.xaml.cs @@ -38,8 +38,16 @@ protected override void OnNavigatedTo(NavigationEventArgs e) private async void CreateFileButton_Click(object sender, RoutedEventArgs e) { StorageFolder storageFolder = KnownFolders.PicturesLibrary; - rootPage.sampleFile = await storageFolder.CreateFileAsync(MainPage.filename, CreationCollisionOption.ReplaceExisting); - rootPage.NotifyUser(String.Format("The file '{0}' was created.", rootPage.sampleFile.Name), NotifyType.StatusMessage); + try + { + rootPage.sampleFile = await storageFolder.CreateFileAsync(MainPage.filename, CreationCollisionOption.ReplaceExisting); + rootPage.NotifyUser(String.Format("The file '{0}' was created.", rootPage.sampleFile.Name), NotifyType.StatusMessage); + } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error creating file '{0}': {1}", MainPage.filename, ex.Message), NotifyType.ErrorMessage); + } } } } diff --git a/Samples/FileAccess/cs/Scenario3_WriteAndReadTextInAFile.xaml.cs b/Samples/FileAccess/cs/Scenario3_WriteAndReadTextInAFile.xaml.cs index 46cdc46755..a5c01657a2 100644 --- a/Samples/FileAccess/cs/Scenario3_WriteAndReadTextInAFile.xaml.cs +++ b/Samples/FileAccess/cs/Scenario3_WriteAndReadTextInAFile.xaml.cs @@ -60,6 +60,11 @@ private async void WriteTextButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error writing to '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { @@ -81,6 +86,11 @@ private async void ReadTextButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error reading from '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { diff --git a/Samples/FileAccess/cs/Scenario4_WriteAndReadBytesInAFile.xaml.cs b/Samples/FileAccess/cs/Scenario4_WriteAndReadBytesInAFile.xaml.cs index 7f58466e4b..298e92a3ea 100644 --- a/Samples/FileAccess/cs/Scenario4_WriteAndReadBytesInAFile.xaml.cs +++ b/Samples/FileAccess/cs/Scenario4_WriteAndReadBytesInAFile.xaml.cs @@ -74,6 +74,11 @@ private async void WriteBytesButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error writing to '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { @@ -99,6 +104,11 @@ private async void ReadBytesButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error reading from '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { diff --git a/Samples/FileAccess/cs/Scenario5_WriteAndReadAFileUsingAStream.xaml.cs b/Samples/FileAccess/cs/Scenario5_WriteAndReadAFileUsingAStream.xaml.cs index 25e49130d8..54b9c0ef9c 100644 --- a/Samples/FileAccess/cs/Scenario5_WriteAndReadAFileUsingAStream.xaml.cs +++ b/Samples/FileAccess/cs/Scenario5_WriteAndReadAFileUsingAStream.xaml.cs @@ -69,6 +69,11 @@ private async void WriteToStreamButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error writing to '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { @@ -105,6 +110,11 @@ private async void ReadFromStreamButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error reading from '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { diff --git a/Samples/FileAccess/cs/Scenario6_DisplayFileProperties.xaml.cs b/Samples/FileAccess/cs/Scenario6_DisplayFileProperties.xaml.cs index bdd4fda2b8..663a6afe2c 100644 --- a/Samples/FileAccess/cs/Scenario6_DisplayFileProperties.xaml.cs +++ b/Samples/FileAccess/cs/Scenario6_DisplayFileProperties.xaml.cs @@ -82,6 +82,11 @@ private async void ShowPropertiesButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error retrieving properties for '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { diff --git a/Samples/FileAccess/cs/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cs b/Samples/FileAccess/cs/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cs index 7ddeec05a0..595c3da702 100644 --- a/Samples/FileAccess/cs/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cs +++ b/Samples/FileAccess/cs/Scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.xaml.cs @@ -28,6 +28,8 @@ public sealed partial class Scenario7 : Page { MainPage rootPage; + const int FA_E_MAX_PERSISTED_ITEMS_REACHED = unchecked((int)0x80270220); + public Scenario7() { this.InitializeComponent(); @@ -54,10 +56,18 @@ private void AddToListButton_Click(object sender, RoutedEventArgs e) rootPage.mruToken = StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Name, visibility); rootPage.NotifyUser(String.Format("The file '{0}' was added to the MRU list and a token was stored.", file.Name), NotifyType.StatusMessage); } - else if (FALRadioButton.IsChecked.Value) + else { - rootPage.falToken = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); - rootPage.NotifyUser(String.Format("The file '{0}' was added to the FAL list and a token was stored.", file.Name), NotifyType.StatusMessage); + try + { + rootPage.falToken = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); + rootPage.NotifyUser(String.Format("The file '{0}' was added to the FAL list and a token was stored.", file.Name), NotifyType.StatusMessage); + } + catch (Exception ex) when (ex.HResult == FA_E_MAX_PERSISTED_ITEMS_REACHED) + { + // A real program would call Remove() to create room in the FAL. + rootPage.NotifyUser(String.Format("The file '{0}' was not added to the FAL list because the FAL list is full.", file.Name), NotifyType.ErrorMessage); + } } } else @@ -68,101 +78,87 @@ private void AddToListButton_Click(object sender, RoutedEventArgs e) private void ShowListButton_Click(object sender, RoutedEventArgs e) { - StorageFile file = rootPage.sampleFile; - if (file != null) + AccessListEntryView entries; + string listName; + if (MRURadioButton.IsChecked.Value) { - if (MRURadioButton.IsChecked.Value) - { - AccessListEntryView entries = StorageApplicationPermissions.MostRecentlyUsedList.Entries; - if (entries.Count > 0) - { - StringBuilder outputText = new StringBuilder("The MRU list contains the following item(s):"); - foreach (AccessListEntry entry in entries) - { - outputText.AppendLine(); - outputText.Append(entry.Metadata); // Application previously chose to store file.Name in this field - } + listName = "MRU"; + entries = StorageApplicationPermissions.MostRecentlyUsedList.Entries; + } + else + { + listName = "FAL"; + entries = StorageApplicationPermissions.FutureAccessList.Entries; + } - rootPage.NotifyUser(outputText.ToString(), NotifyType.StatusMessage); - } - else - { - rootPage.NotifyUser("The MRU list is empty, please select 'Most Recently Used' list and click 'Add to List' to add a file to the MRU list.", NotifyType.ErrorMessage); - } - } - else if (FALRadioButton.IsChecked.Value) + if (entries.Count > 0) + { + StringBuilder outputText = new StringBuilder("The " + listName + " list contains the following item(s):"); + foreach (AccessListEntry entry in entries) { - AccessListEntryView entries = StorageApplicationPermissions.FutureAccessList.Entries; - if (entries.Count > 0) - { - StringBuilder outputText = new StringBuilder("The FAL list contains the following item(s):"); - foreach (AccessListEntry entry in entries) - { - outputText.AppendLine(); - outputText.Append(entry.Metadata); // Application previously chose to store file.Name in this field - } - - rootPage.NotifyUser(outputText.ToString(), NotifyType.StatusMessage); - } - else - { - rootPage.NotifyUser("The FAL list is empty, please select 'Future Access List' list and click 'Add to List' to add a file to the FAL list.", NotifyType.ErrorMessage); - } + outputText.AppendLine(); + outputText.Append(entry.Metadata); // Application previously chose to store file.Name in this field } + + rootPage.NotifyUser(outputText.ToString(), NotifyType.StatusMessage); } else { - rootPage.NotifyUserFileNotExist(); + rootPage.NotifyUser("The " + listName + " list is empty.", NotifyType.ErrorMessage); } } private async void OpenFromListButton_Click(object sender, RoutedEventArgs e) { - if (rootPage.sampleFile != null) + StorageFile file = null; + + if (MRURadioButton.IsChecked.Value) { - try + if (rootPage.mruToken != null) { - if (MRURadioButton.IsChecked.Value) + try { - if (rootPage.mruToken != null) - { - // Open the file via the token that was stored when adding this file into the MRU list - StorageFile file = await StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync(rootPage.mruToken); - - // Read the file - string fileContent = await FileIO.ReadTextAsync(file); - rootPage.NotifyUser(String.Format("The file '{0}' was opened by a stored token from the MRU list, it contains the following text:{1}{2}", file.Name, Environment.NewLine, fileContent), NotifyType.StatusMessage); - } - else - { - rootPage.NotifyUser("The MRU list is empty, please select 'Most Recently Used' list and click 'Add to List' to add a file to the MRU list.", NotifyType.ErrorMessage); - } + // Open the file via the token that was stored when adding this file into the MRU list + file = await StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync(rootPage.mruToken); } - else if (FALRadioButton.IsChecked.Value) + catch (ArgumentException) { - if (rootPage.falToken != null) - { - // Open the file via the token that was stored when adding this file into the FAL list - StorageFile file = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(rootPage.falToken); - - // Read the file - string fileContent = await FileIO.ReadTextAsync(file); - rootPage.NotifyUser(String.Format("The file '{0}' was opened by a stored token from the FAL list, it contains the following text:{1}{2}", file.Name, Environment.NewLine, fileContent), NotifyType.StatusMessage); - } - else - { - rootPage.NotifyUser("The FAL list is empty, please select 'Future Access List' list and click 'Add to List' to add a file to the FAL list.", NotifyType.ErrorMessage); - } + // When the MRU becomes full, older entries are automatically deleted. + rootPage.NotifyUser("The token is no longer valid.", NotifyType.ErrorMessage); } } - catch (FileNotFoundException) + else { - rootPage.NotifyUserFileNotExist(); + rootPage.NotifyUser("This operation requires a token. Add file to the MRU list first.", NotifyType.ErrorMessage); } } else { - rootPage.NotifyUserFileNotExist(); + if (rootPage.falToken != null) + { + // Open the file via the token that was stored when adding this file into the FAL list. + file = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(rootPage.falToken); + } + else + { + rootPage.NotifyUser("This operation requires a token. Add file to the FAL list first.", NotifyType.ErrorMessage); + } + } + + if (file != null) + { + try + { + // Read the file + string fileContent = await FileIO.ReadTextAsync(file); + rootPage.NotifyUser(String.Format("The file '{0}' was opened by a stored token. It contains the following text:{1}{2}", file.Name, Environment.NewLine, fileContent), NotifyType.StatusMessage); + + } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error reading file opened from list: {0}", ex.Message), NotifyType.ErrorMessage); + } } } } diff --git a/Samples/FileAccess/cs/Scenario8_CopyAFile.xaml.cs b/Samples/FileAccess/cs/Scenario8_CopyAFile.xaml.cs index 71b09789e3..4372a3f159 100644 --- a/Samples/FileAccess/cs/Scenario8_CopyAFile.xaml.cs +++ b/Samples/FileAccess/cs/Scenario8_CopyAFile.xaml.cs @@ -51,6 +51,11 @@ private async void CopyFileButton_Click(object sender, RoutedEventArgs e) { rootPage.NotifyUserFileNotExist(); } + catch (Exception ex) + { + // I/O errors are reported as exceptions. + rootPage.NotifyUser(String.Format("Error copying file '{0}': {1}", file.Name, ex.Message), NotifyType.ErrorMessage); + } } else { diff --git a/Samples/FileAccess/js/js/scenario3_WriteAndReadTextInAFile.js b/Samples/FileAccess/js/js/scenario3_WriteAndReadTextInAFile.js index 2cdf1840dc..ab927e09f2 100644 --- a/Samples/FileAccess/js/js/scenario3_WriteAndReadTextInAFile.js +++ b/Samples/FileAccess/js/js/scenario3_WriteAndReadTextInAFile.js @@ -14,7 +14,7 @@ function writeText() { if (SdkSample.sampleFile !== null) { var textArea = document.getElementById("textarea"); - var userContent = textArea.innerText; + var userContent = textArea.value; if (userContent !== "") { Windows.Storage.FileIO.writeTextAsync(SdkSample.sampleFile, userContent).done(function () { WinJS.log && WinJS.log("The following text was written to '" + SdkSample.sampleFile.name + "':\n" + userContent, "sample", "status"); diff --git a/Samples/FileAccess/js/js/scenario4_WriteAndReadBytesInAFile.js b/Samples/FileAccess/js/js/scenario4_WriteAndReadBytesInAFile.js index b8e5eb0ef8..c6ddc5bd8a 100644 --- a/Samples/FileAccess/js/js/scenario4_WriteAndReadBytesInAFile.js +++ b/Samples/FileAccess/js/js/scenario4_WriteAndReadBytesInAFile.js @@ -14,7 +14,7 @@ function writeBytes() { if (SdkSample.sampleFile !== null) { var textArea = document.getElementById("textarea"); - var userContent = textArea.innerText; + var userContent = textArea.value; if (userContent !== "") { var buffer = getBufferFromString(userContent); Windows.Storage.FileIO.writeBufferAsync(SdkSample.sampleFile, buffer).done(function () { diff --git a/Samples/FileAccess/js/js/scenario5_WriteAndReadAFileUsingAStream.js b/Samples/FileAccess/js/js/scenario5_WriteAndReadAFileUsingAStream.js index 0f649c5bfa..ebf32b8df4 100644 --- a/Samples/FileAccess/js/js/scenario5_WriteAndReadAFileUsingAStream.js +++ b/Samples/FileAccess/js/js/scenario5_WriteAndReadAFileUsingAStream.js @@ -14,7 +14,7 @@ function writeToStream() { if (SdkSample.sampleFile !== null) { var textArea = document.getElementById("textarea"); - var userContent = textArea.innerText; + var userContent = textArea.value; if (userContent !== "") { SdkSample.sampleFile.openTransactedWriteAsync().then(function (transaction) { var dataWriter = new Windows.Storage.Streams.DataWriter(transaction.stream); diff --git a/Samples/FileAccess/js/js/scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.js b/Samples/FileAccess/js/js/scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.js index 0576fd7408..2651899d64 100644 --- a/Samples/FileAccess/js/js/scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.js +++ b/Samples/FileAccess/js/js/scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.js @@ -3,12 +3,14 @@ (function () { "use strict"; + var FA_E_MAX_PERSISTED_ITEMS_REACHED = 0x80270220 | 0; + var E_INVALIDARG = 0x80070057 | 0; + var page = WinJS.UI.Pages.define("/html/scenario7_TrackAFileOrFolderSoThatYouCanAccessItLater.html", { ready: function (element, options) { document.getElementById("addToList").addEventListener("click", addToList, false); document.getElementById("showList").addEventListener("click", showList, false); document.getElementById("openFromList").addEventListener("click", openFromList, false); - SdkSample.validateFileExistence(); } }); @@ -16,7 +18,6 @@ if (SdkSample.sampleFile !== null) { var MRUradio = document.getElementById("MRUradio"); var systemMRUcheckbox = document.getElementById("systemMRUcheckbox"); - var FALradio = document.getElementById("FALradio"); if (MRUradio.checked) { // Add the file to app and possibly system MRU var visibility = systemMRUcheckbox.checked ? @@ -25,86 +26,86 @@ SdkSample.mruToken = Windows.Storage.AccessCache.StorageApplicationPermissions.mostRecentlyUsedList.add(SdkSample.sampleFile, SdkSample.sampleFile.name, visibility); WinJS.log && WinJS.log("The file '" + SdkSample.sampleFile.name + "' was added to the MRU list and a token was stored.", "sample", "status"); - } else if (FALradio.checked) { - SdkSample.falToken = Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList.add(SdkSample.sampleFile, SdkSample.sampleFile.name); - WinJS.log && WinJS.log("The file '" + SdkSample.sampleFile.name + "' was added to the FAL list and a token was stored.", "sample", "status"); + } else { + try { + SdkSample.falToken = Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList.add(SdkSample.sampleFile, SdkSample.sampleFile.name); + WinJS.log && WinJS.log("The file '" + SdkSample.sampleFile.name + "' was added to the FAL list and a token was stored.", "sample", "status"); + } catch (error) { + if (error.number == FA_E_MAX_PERSISTED_ITEMS_REACHED) { + // A real program would call remove() to create room in the FAL. + WinJS.log && WinJS.log("The file '" + SdkSample.sampleFile.name + "' was not added to the FAL list because the FAL list is full.", "sample", "error"); + } else { + throw error; + } + } } + } else { + SdkSample.validateFileExistence(); } } function showList() { - if (SdkSample.sampleFile !== null) { - var MRUradio = document.getElementById("MRUradio"); - var FALradio = document.getElementById("FALradio"); - if (MRUradio.checked) { - var mruEntries = Windows.Storage.AccessCache.StorageApplicationPermissions.mostRecentlyUsedList.entries; - if (mruEntries.size > 0) { - var mruOutputText = "The MRU list contains the following item(s):"; - mruEntries.forEach(function (entry) { - mruOutputText += "\n" + entry.metadata; // Application previously chose to store sampleFile.name in this field - }); + var entries; + var listName; + var MRUradio = document.getElementById("MRUradio"); + if (MRUradio.checked) { + listName = "MRU"; + entries = Windows.Storage.AccessCache.StorageApplicationPermissions.mostRecentlyUsedList.entries; + } else { + listName = "FAL"; + entries = Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList.entries; + } - WinJS.log && WinJS.log(mruOutputText, "sample", "status"); - } else { - WinJS.log && WinJS.log("The MRU list is empty, please select 'Most Recently Used' and click 'Add to List' to add a file to the MRU list.", "sample", "error");; - } - } else if (FALradio.checked) { - var falEntries = Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList.entries; - if (falEntries.size > 0) { - var falOutputText = "The FAL list contains the following item(s):"; - falEntries.forEach(function (entry) { - falOutputText += "\n" + entry.metadata; // Application previously chose to store sampleFile.name in this field - }); + if (entries.size > 0) { + var outputText = "The " + listName + " list contains the following item(s):"; + entries.forEach(function (entry) { + outputText += "\n" + entry.metadata; // Application previously chose to store sampleFile.name in this field + }); - WinJS.log && WinJS.log(falOutputText, "sample", "status"); - } else { - WinJS.log && WinJS.log("The FAL list is empty, please select 'Future Access List' and click 'Add to List' to add a file to the FAL list.", "sample", "error"); - } - } + WinJS.log && WinJS.log(outputText, "sample", "status"); + } else { + WinJS.log && WinJS.log("The " + listName + " list is empty.", "sample", "error"); } } function openFromList() { - if (SdkSample.sampleFile !== null) { - var MRUradio = document.getElementById("MRUradio"); - var FALradio = document.getElementById("FALradio"); - if (MRUradio.checked) { - if (SdkSample.mruToken !== null) { - // Open the 'sample.dat' via the token that was stored when adding this file into the MRU list - Windows.Storage.AccessCache.StorageApplicationPermissions.mostRecentlyUsedList.getFileAsync(SdkSample.mruToken).then(function (file) { - // Read the file - Windows.Storage.FileIO.readTextAsync(file).done(function (fileContent) { - WinJS.log && WinJS.log("The file '" + file.name + "' was opened by a stored token from the MRU list, it contains the following text:\n" + fileContent, "sample", "status"); - }, - function (error) { - WinJS.log && WinJS.log(error, "sample", "error"); - }); - }, - function (error) { - WinJS.log && WinJS.log(error, "sample", "error"); - }); - } else { - WinJS.log && WinJS.log("The MRU list is empty, please select 'Most Recently Used' list and click 'Add to List' to add a file to the MRU list.", "sample", "error"); - } - } else if (FALradio.checked) { - if (SdkSample.falToken !== null) { - // Open the 'sample.dat' via the token that was stored when adding this file into the FAL list - Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList.getFileAsync(SdkSample.falToken).then(function (file) { - // Read the file - Windows.Storage.FileIO.readTextAsync(file).done(function (fileContent) { - WinJS.log && WinJS.log("The file '" + file.name + "' was opened by a stored token from the FAL list, it contains the following text:\n" + fileContent, "sample", "status"); - }, - function (error) { - WinJS.log && WinJS.log(error, "sample", "error"); - }); - }, - function (error) { - WinJS.log && WinJS.log(error, "sample", "error"); - }); - } else { - WinJS.log && WinJS.log("The FAL list is empty, please select 'Future Access List' list and click 'Add to List' to add a file to the FAL list.", "sample", "error"); + var fileTask = WinJS.Promise.wrap(); + var MRUradio = document.getElementById("MRUradio"); + if (MRUradio.checked) { + if (SdkSample.mruToken !== null) { + // Open the 'sample.dat' via the token that was stored when adding this file into the MRU list + try { + fileTask = Windows.Storage.AccessCache.StorageApplicationPermissions.mostRecentlyUsedList.getFileAsync(SdkSample.mruToken); + } catch (error) { + // When the MRU becomes full, older entries are automatically deleted. + if (error.number == E_INVALIDARG) { + WinJS.log && WinJS.log("The token is no longer valid.", "sample", "error"); + } else { + throw error; + } } + } else { + WinJS.log && WinJS.log("This operation requires a token. Add file to the MRU list first.", "sample", "error"); + } + } else { + if (SdkSample.falToken !== null) { + // Open the 'sample.dat' via the token that was stored when adding this file into the FAL list + fileTask = Windows.Storage.AccessCache.StorageApplicationPermissions.futureAccessList.getFileAsync(SdkSample.falToken); + } else { + WinJS.log && WinJS.log("This operation requires a token. Add file to the FAL list first.", "sample", "error"); } } + + fileTask.done(function (file) { + if (file) { + // Read the file + Windows.Storage.FileIO.readTextAsync(file).done(function (fileContent) { + WinJS.log && WinJS.log("The file '" + file.name + "' was opened by a stored token. It contains the following text:\n" + fileContent, "sample", "status"); + }, + function (error) { + WinJS.log && WinJS.log(error, "sample", "error"); + }); + } + }); } })(); diff --git a/Samples/GlobalizationPreferences/README.md b/Samples/GlobalizationPreferences/README.md index e3662da4cc..325a44c9b7 100644 --- a/Samples/GlobalizationPreferences/README.md +++ b/Samples/GlobalizationPreferences/README.md @@ -44,7 +44,7 @@ To obtain information about Microsoft Visual Studio 2015 and the tools for devel ### Samples * [**Calendar** sample](../Calendar) -* [**DateTimeFormatting** sample](../DatetimeFormatting) +* [**DateTimeFormatting** sample](../DateTimeFormatting) * [**NumberFormatting** sample](../NumberFormatting) ### Reference diff --git a/Samples/WebSocket/cpp/SampleConfiguration.cpp b/Samples/WebSocket/cpp/SampleConfiguration.cpp index ad5a06212b..cdd0a115d0 100644 --- a/Samples/WebSocket/cpp/SampleConfiguration.cpp +++ b/Samples/WebSocket/cpp/SampleConfiguration.cpp @@ -14,11 +14,77 @@ #include "SampleConfiguration.h" using namespace SDKTemplate; +using namespace Concurrency; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::Networking::Sockets; +using namespace Windows::Security::Cryptography::Certificates; +using namespace Windows::Web; Platform::Array^ MainPage::scenariosInner = ref new Platform::Array { - // The format here is the following: - // { "Description for the sample", "Fully qualified name for the class that implements the scenario" } - { "UTF-8 text messages", "SDKTemplate.WebSocket.Scenario1" }, - { "Binary data stream", "SDKTemplate.WebSocket.Scenario2" } + { "UTF-8 text messages", "SDKTemplate.Scenario1" }, + { "Binary data stream", "SDKTemplate.Scenario2" } }; + +Uri^ MainPage::TryGetUri(String^ uriString) +{ + Windows::Foundation::Uri^ webSocketUri; + + // Create a Uri instance and catch exceptions related to invalid input. This method returns 'true' + // if the Uri instance was successfully created and 'false' otherwise. + try + { + webSocketUri = ref new Uri(uriString); + } + catch (NullReferenceException^) + { + NotifyUser("Error: URI must not be null or empty.", NotifyType::ErrorMessage); + return nullptr; + } + catch (InvalidArgumentException^) + { + NotifyUser("Error: Invalid URI", NotifyType::ErrorMessage); + return nullptr; + } + + if (webSocketUri->Fragment != "") + { + NotifyUser("Error: URI fragments not supported in WebSocket URIs.", NotifyType::ErrorMessage); + return nullptr; + } + + // Uri->SchemeName returns the canonicalized scheme name so we can use case-sensitive, ordinal string + // comparison. + if (webSocketUri->SchemeName != "ws" && webSocketUri->SchemeName != "wss") + { + NotifyUser("Error: WebSockets only support ws:// and wss:// schemes.", NotifyType::ErrorMessage); + return nullptr; + } + + return webSocketUri; +} + +String^ MainPage::BuildWebSocketError(Exception^ ex) +{ + // Normally we'd use the HResult and status to test for specific conditions we want to handle. + // In this sample, we'll just output them for demonstration purposes. + + WebErrorStatus status = WebSocketError::GetStatus(ex->HResult); + + switch (status) + { + case WebErrorStatus::CannotConnect: + case WebErrorStatus::NotFound: + case WebErrorStatus::RequestTimeout: + return "Cannot connect to the server. Please make sure " + + "to run the server setup script before running the sample."; + + case WebErrorStatus::Unknown: + return "COM error: " + ex->HResult.ToString(); + + default: + return "Error: " + status.ToString(); + } +} diff --git a/Samples/WebSocket/cpp/SampleConfiguration.h b/Samples/WebSocket/cpp/SampleConfiguration.h index e422a9d202..8eb7626b57 100644 --- a/Samples/WebSocket/cpp/SampleConfiguration.h +++ b/Samples/WebSocket/cpp/SampleConfiguration.h @@ -28,7 +28,7 @@ namespace SDKTemplate { Platform::String^ get() { - return ref new Platform::String(L"WebSocket"); + return "WebSocket C++ Sample"; } } @@ -40,76 +40,11 @@ namespace SDKTemplate } } - bool TryGetUri(Platform::String^ uriString, Windows::Foundation::Uri^* uri) - { - *uri = nullptr; - - Windows::Foundation::Uri^ webSocketUri; - - // Create a Uri instance and catch exceptions related to invalid input. This method returns 'true' - // if the Uri instance was successfully created and 'false' otherwise. - try - { - webSocketUri = ref new Windows::Foundation::Uri(StringTrimmer::Trim(uriString)); - } - catch (Platform::NullReferenceException^ exception) - { - NotifyUser("Error: URI must not be null or empty.", NotifyType::ErrorMessage); - return false; - } - catch (Platform::InvalidArgumentException^ exception) - { - NotifyUser("Error: Invalid URI", NotifyType::ErrorMessage); - return false; - } - - if (webSocketUri->Fragment != "") - { - NotifyUser("Error: URI fragments not supported in WebSocket URIs.", NotifyType::ErrorMessage); - return false; - } - - Platform::String^ wsScheme = "ws"; - Platform::String^ wssScheme = "wss"; - Platform::String^ scheme = webSocketUri->SchemeName; - - // Uri->SchemeName returns the canonicalized scheme name so we can use case-sensitive, ordinal string - // comparison. - if ((CompareStringOrdinal(scheme->Begin(), scheme->Length(), wsScheme->Begin(), wsScheme->Length(), false) != CSTR_EQUAL) && - (CompareStringOrdinal(scheme->Begin(), scheme->Length(), wssScheme->Begin(), wssScheme->Length(), false) != CSTR_EQUAL)) - { - NotifyUser("Error: WebSockets only support ws:// and wss:// schemes.", NotifyType::ErrorMessage); - return false; - } - - *uri = webSocketUri; - - return true; - } + internal: + Windows::Foundation::Uri^ TryGetUri(Platform::String^ uriString); + static Platform::String^ BuildWebSocketError(Platform::Exception^ ex); private: static Platform::Array^ scenariosInner; }; - - class StringTrimmer - { - public: - static Platform::String^ Trim(Platform::String^ s) - { - const WCHAR* first = s->Begin(); - const WCHAR* last = s->End(); - - while (first != last && iswspace(*first)) - { - ++first; - } - - while (first != last && iswspace(last[-1])) - { - --last; - } - - return ref new Platform::String(first, static_cast(last - first)); - } - }; } diff --git a/Samples/WebSocket/cpp/Scenario1.xaml b/Samples/WebSocket/cpp/Scenario1.xaml deleted file mode 100644 index 492cca86cc..0000000000 --- a/Samples/WebSocket/cpp/Scenario1.xaml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - This shows how to use a MessageWebSocket to send UTF-8 strings. - - - Enter text to send to the server. - - - + +

+

+ +

+

+ +

+

+

+ + + \ No newline at end of file diff --git a/Samples/WebSocket/js/html/scenario1_Download.html b/Samples/WebSocket/js/html/scenario1_Download.html deleted file mode 100644 index 18828e1e19..0000000000 --- a/Samples/WebSocket/js/html/scenario1_Download.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - -
-

This shows how to use a MessageWebSocket to send UTF-8 strings.

-

- - -

-

- - -

-

- - -

-
-
-
-
-
- - - \ No newline at end of file diff --git a/Samples/WebSocket/js/html/scenario2-binary.html b/Samples/WebSocket/js/html/scenario2-binary.html new file mode 100644 index 0000000000..eba167028b --- /dev/null +++ b/Samples/WebSocket/js/html/scenario2-binary.html @@ -0,0 +1,47 @@ + + + + + + + + + + + +
+

Description:

+
Binary data stream
+
+ +

This shows how to use a StreamWebSocket to send and receive binary data.

+

+ +

+

+ + +

+
+

Data Sent:

+

Data Received:

+

+

+
+ + + \ No newline at end of file diff --git a/Samples/WebSocket/js/html/scenario2_Upload.html b/Samples/WebSocket/js/html/scenario2_Upload.html deleted file mode 100644 index 4bad89f38f..0000000000 --- a/Samples/WebSocket/js/html/scenario2_Upload.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - -
-

This shows how to use a StreamWebSocket to send and receive binary data.

-

- - -

-

- - -

-
-
-

- - -

-

- - -

-
-
-
- - - \ No newline at end of file diff --git a/Samples/WebSocket/js/js/helpers.js b/Samples/WebSocket/js/js/helpers.js deleted file mode 100644 index ee3d56efc5..0000000000 --- a/Samples/WebSocket/js/js/helpers.js +++ /dev/null @@ -1,98 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -// Common helper methods - -function getError(e) { - "use strict"; - - var webSocketError = Windows.Networking.Sockets.WebSocketError.getStatus(e.number); - switch (webSocketError) { - case Windows.Web.WebErrorStatus.unknown: return e; - case Windows.Web.WebErrorStatus.certificateCommonNameIsIncorrect: return "CertificateCommonNameIsIncorrect"; - case Windows.Web.WebErrorStatus.certificateExpired: return "CertificateExpired"; - case Windows.Web.WebErrorStatus.certificateContainsErrors: return "CertificateContainsErrors"; - case Windows.Web.WebErrorStatus.certificateRevoked: return "CertificateRevoked"; - case Windows.Web.WebErrorStatus.certificateIsInvalid: return "CertificateIsInvalid"; - case Windows.Web.WebErrorStatus.serverUnreachable: return "ServerUnreachable"; - case Windows.Web.WebErrorStatus.timeout: return "Timeout"; - case Windows.Web.WebErrorStatus.errorHttpInvalidServerResponse: return "ErrorHttpInvalidServerResponse"; - case Windows.Web.WebErrorStatus.connectionAborted: return "ConnectionAborted"; - case Windows.Web.WebErrorStatus.connectionReset: return "ConnectionReset"; - case Windows.Web.WebErrorStatus.disconnected: return "Disconnected"; - case Windows.Web.WebErrorStatus.httpToHttpsOnRedirection: return "HttpToHttpsOnRedirection"; - case Windows.Web.WebErrorStatus.httpsToHttpOnRedirection: return "HttpsToHttpOnRedirection"; - case Windows.Web.WebErrorStatus.cannotConnect: return "CannotConnect"; - case Windows.Web.WebErrorStatus.hostNameNotResolved: return "HostNameNotResolved"; - case Windows.Web.WebErrorStatus.operationCanceled: return "OperationCanceled"; - case Windows.Web.WebErrorStatus.redirectFailed: return "RedirectFailed"; - case Windows.Web.WebErrorStatus.unexpectedStatusCode: return "UnexpectedStatusCode"; - case Windows.Web.WebErrorStatus.unexpectedRedirection: return "UnexpectedRedirection"; - case Windows.Web.WebErrorStatus.unexpectedClientError: return "UnexpectedClientError"; - case Windows.Web.WebErrorStatus.unexpectedServerError: return "UnexpectedServerError"; - case Windows.Web.WebErrorStatus.multipleChoices: return "MultipleChoices (300)"; - case Windows.Web.WebErrorStatus.movedPermanently: return "MovedPermanently (301)"; - case Windows.Web.WebErrorStatus.found: return "Found (302)"; - case Windows.Web.WebErrorStatus.seeOther: return "SeeOther (303)"; - case Windows.Web.WebErrorStatus.notModified: return "NotModified (304)"; - case Windows.Web.WebErrorStatus.useProxy: return "UseProxy (305)"; - case Windows.Web.WebErrorStatus.temporaryRedirect: return "TemporaryRedirect (307)"; - case Windows.Web.WebErrorStatus.badRequest: return "BadRequest (400)"; - case Windows.Web.WebErrorStatus.unauthorized: return "Unauthorized (401)"; - case Windows.Web.WebErrorStatus.paymentRequired: return "PaymentRequired (402)"; - case Windows.Web.WebErrorStatus.forbidden: return "Forbidden (403)"; - case Windows.Web.WebErrorStatus.notFound: return "NotFound (404)"; - case Windows.Web.WebErrorStatus.methodNotAllowed: return "MethodNotAllowed (405)"; - case Windows.Web.WebErrorStatus.notAcceptable: return "NotAcceptable (406)"; - case Windows.Web.WebErrorStatus.proxyAuthenticationRequired: return "ProxyAuthenticationRequired (407)"; - case Windows.Web.WebErrorStatus.requestTimeout: return "RequestTimeout (408)"; - case Windows.Web.WebErrorStatus.conflict: return "Conflict (409)"; - case Windows.Web.WebErrorStatus.gone: return "Gone (410)"; - case Windows.Web.WebErrorStatus.lengthRequired: return "LengthRequired (411)"; - case Windows.Web.WebErrorStatus.preconditionFailed: return "PreconditionFailed (412)"; - case Windows.Web.WebErrorStatus.requestEntityTooLarge: return "RequestEntityTooLarge (413)"; - case Windows.Web.WebErrorStatus.requestUriTooLong: return "RequestUriTooLong (414)"; - case Windows.Web.WebErrorStatus.unsupportedMediaType: return "UnsupportedMediaType (415)"; - case Windows.Web.WebErrorStatus.requestedRangeNotSatisfiable: return "RequestedRangeNotSatisfiable (416)"; - case Windows.Web.WebErrorStatus.expectationFailed: return "ExpectationFailed (417)"; - case Windows.Web.WebErrorStatus.internalServerError: return "InternalServerError (500)"; - case Windows.Web.WebErrorStatus.notImplemented: return "NotImplemented (501)"; - case Windows.Web.WebErrorStatus.badGateway: return "BadGateway (502)"; - case Windows.Web.WebErrorStatus.serviceUnavailable: return "ServiceUnavailable (503)"; - case Windows.Web.WebErrorStatus.gatewayTimeout: return "GatewayTimeout (504)"; - case Windows.Web.WebErrorStatus.httpVersionNotSupported: return "HttpVersionNotSupported (505)"; - default: return e; - } -}; - -function validateAndCreateUri(uriString) { - "use strict"; - - var webSocketUri; - try { - webSocketUri = new Windows.Foundation.Uri(uriString); - } catch (error) { - throw "Error: Invalid URI"; - } - - if (webSocketUri.fragment !== "") { - throw "Error: URI fragments not supported in WebSocket URIs."; - } - - // Uri.schemeName returns the canonicalized scheme name so we can use case-sensitive, ordinal string - // comparison. - var scheme = webSocketUri.schemeName; - if ((scheme !== "ws") && (scheme !== "wss")) { - throw "Error: WebSockets only support ws:// and wss:// schemes."; - } - - return webSocketUri; -} diff --git a/Samples/WebSocket/js/js/sample-configuration.js b/Samples/WebSocket/js/js/sample-configuration.js index 975d7965fd..7c28e49703 100644 --- a/Samples/WebSocket/js/js/sample-configuration.js +++ b/Samples/WebSocket/js/js/sample-configuration.js @@ -12,15 +12,78 @@ (function () { "use strict"; - var sampleTitle = "WebSocket"; + var WebSocketError = Windows.Networking.Sockets.WebSocketError; + var WebErrorStatus = Windows.Web.WebErrorStatus; + + var sampleTitle = "WebSocket JS Sample"; var scenarios = [ - { url: "/html/scenario1_Download.html", title: "UTF-8 text messages" }, - { url: "/html/scenario2_Upload.html", title: "Binary data stream" } + { url: "/html/scenario1-utf8.html", title: "UTF-8 text messages" }, + { url: "/html/scenario2-binary.html", title: "Binary data stream" } ]; + // Look up the name for an enumeration member. + function lookupEnumName(e, value) { + for (var name in e) { + if (e[name] === value) { + return name; + } + } + // No name available; just use the number. + return value.toString(); + } + + function validateAndCreateUri(uriString) { + var webSocketUri; + try { + webSocketUri = new Windows.Foundation.Uri(uriString); + } catch (error) { + WinJS.log && WinJS.log("Error: Invalid URI", "sample", "error"); + return null; + } + + if (webSocketUri.fragment !== "") { + WinJS.log && WinJS.log("Error: URI fragments not supported in WebSocket URIs.", "sample", "error"); + return null; + } + + // Uri.schemeName returns the canonicalized scheme name so we can use case-sensitive, ordinal string + // comparison. + var scheme = webSocketUri.schemeName; + if ((scheme !== "ws") && (scheme !== "wss")) { + WinJS.log && WinJS.log("Error: WebSockets only support ws:// and wss:// schemes.", "sample", "error"); + return null; + } + + return webSocketUri; + } + + function buildWebSocketError(error) { + var hResult = error.number; + var status = WebSocketError.getStatus(hResult); + + // Normally we'd use the error number status to test for specific conditions we want to handle. + // In this sample, we'll just output them for demonstration purposes. + switch (status) { + case WebErrorStatus.cannotConnect: + case WebErrorStatus.notFound: + case WebErrorStatus.requestTimeout: + return "Cannot connect to the server. Please make sure " + + "to run the server setup script before running the sample."; + + case WebErrorStatus.unknown: + return "COM error: " + hResult; + + default: + return "Error: " + lookupEnumName(WebErrorStatus, status); + } + } + WinJS.Namespace.define("SdkSample", { sampleTitle: sampleTitle, - scenarios: new WinJS.Binding.List(scenarios) + scenarios: new WinJS.Binding.List(scenarios), + lookupEnumName: lookupEnumName, + validateAndCreateUri: validateAndCreateUri, + buildWebSocketError: buildWebSocketError }); })(); diff --git a/Samples/WebSocket/js/js/scenario1-utf8.js b/Samples/WebSocket/js/js/scenario1-utf8.js new file mode 100644 index 0000000000..75ab94d91e --- /dev/null +++ b/Samples/WebSocket/js/js/scenario1-utf8.js @@ -0,0 +1,184 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +(function () { + "use strict"; + + var MessageWebSocket = Windows.Networking.Sockets.MessageWebSocket; + var SocketMessageType = Windows.Networking.Sockets.SocketMessageType; + var UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding; + + // Local variables + var messageWebSocket; + var messageWriter; + var busy; + + // DOM elements + var serverAddressField; + var connectButton; + var disconnectButton; + var inputField; + var sendButton; + var outputField; + + var page = WinJS.UI.Pages.define("/html/scenario1-utf8.html", { + ready: function (element, options) { + serverAddressField = document.getElementById("serverAddressField"); + connectButton = document.getElementById("connectButton"); + disconnectButton = document.getElementById("disconnectButton"); + inputField = document.getElementById("inputField"); + sendButton = document.getElementById("sendButton"); + outputField = document.getElementById("outputField"); + + connectButton.addEventListener("click", onConnect, false); + disconnectButton.addEventListener("click", onDisconnect, false); + sendButton.addEventListener("click", onSend, false); + + updateVisualState(); + }, + unload: function (eventObject) { + closeSocket(); + } + }); + + function updateVisualState() { + serverAddressField.disabled = busy || messageWebSocket; + connectButton.disabled = busy || messageWebSocket; + disconnectButton.disabled = busy || !messageWebSocket; + inputField.disabled = busy || !messageWebSocket + sendButton.disabled = busy || !messageWebSocket + } + + function setBusy(value) { + busy = value; + updateVisualState(); + } + + function onConnect() { + setBusy(true); + connectAsync().done(function () { + setBusy(false); + }); + } + + function connectAsync() { + // Validating the URI is required since it was received from an untrusted source (user + // input). The URI is validated by calling validateAndCreateUri() that will return null + // for strings that are not valid WebSocket URIs. + // Note that when enabling the text box users may provide URIs to machines on the local network + // or internet. In these cases the app requires the "Home or Work Networking" or + // "Internet (Client)" capability respectively. + var server = SdkSample.validateAndCreateUri(serverAddressField.value); + if (!server) + { + return WinJS.Promise.wrap(); + } + + // Set up the socket data format and callbacks + messageWebSocket = new MessageWebSocket(); + messageWebSocket.control.messageType = SocketMessageType.utf8; + messageWebSocket.addEventListener("messagereceived", onMessageReceived); + messageWebSocket.addEventListener("closed", onClosed); + + appendOutputLine("Connecting to: " + server.absoluteUri); + + return messageWebSocket.connectAsync(server).then(function () { + // The default DataWriter encoding is utf8. + messageWriter = new Windows.Storage.Streams.DataWriter(messageWebSocket.outputStream); + WinJS.log && WinJS.log("Connected", "sample", "status"); + }, function (error) { + messageWebSocket.close(); + messageWebSocket = null; + + appendOutputLine(SdkSample.buildWebSocketError(error)); + appendOutputLine(error.message); + }); + } + + function onSend() { + setBusy(true); + sendAsync().done(function () { + setBusy(false); + }); + } + + function sendAsync() { + var message = inputField.value; + if (message === "") { + WinJS.log && WinJS.log("Please specify text to send", "sample", "error"); + return WinJS.Promise.wrap(); + } + + appendOutputLine("Sending Message: " + message); + + // Buffer any data we want to send. + messageWriter.writeString(message); + + // Send the data as one complete message. + return messageWriter.storeAsync().then(function() { + WinJS.log && WinJS.log("Send Complete", "sample", "status"); + }, function(error) { + appendOutputLine(SdkSample.buildWebSocketError(error)); + appendOutputLine(error.message); + }); + } + + function onMessageReceived(args) { + appendOutputLine("Message Received; Type: " + SdkSample.lookupEnumName(SocketMessageType, args.messageType)); + + // The incoming message is already buffered. + var reader = args.getDataReader(); + reader.unicodeEncoding = UnicodeEncoding.utf8; + + try { + appendOutputLine(reader.readString(reader.unconsumedBufferLength)); + } catch (error) { + appendOutputLine(SdkSample.buildWebSocketError(error)); + appendOutputLine(error.message); + } + } + + function onDisconnect() { + setBusy(true); + WinJS.log && WinJS.log("Closing", "sample", "status"); + closeSocket(); + setBusy(false); + } + + function onClosed(e) { + appendOutputLine("Closed; Code: " + e.code + " Reason: " + e.reason); + if (messageWebSocket) { + closeSocket(); + updateVisualState(); + } + } + + function closeSocket() { + if (messageWebSocket) { + try { + messageWebSocket.close(1000, "Closed due to user request."); + } catch (error) { + appendOutputLine(SdkSample.buildWebSocketError(error)); + appendOutputLine(error.message); + } + messageWebSocket = null; + } + if (messageWriter) { + messageWriter.close(); + messageWriter = null; + } + } + + function appendOutputLine(text) { + outputField.innerText += "\r\n" + text; + } + +})(); diff --git a/Samples/WebSocket/js/js/scenario1_Download.js b/Samples/WebSocket/js/js/scenario1_Download.js deleted file mode 100644 index ce8b07794f..0000000000 --- a/Samples/WebSocket/js/js/scenario1_Download.js +++ /dev/null @@ -1,155 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -(function () { - "use strict"; - - var messageWebSocket; - var messageWriter; - - var page = WinJS.UI.Pages.define("/html/scenario1_Download.html", { - ready: function (element, options) { - document.getElementById("startButton").addEventListener("click", startSend, false); - document.getElementById("closeButton").addEventListener("click", closeSocket, false); - }, - unload: function (eventObject) { - closeSocket(eventObject); - } - }); - - function startSend(eventObject) { - if (document.getElementById("inputField").value === "") { - WinJS.log && WinJS.log("Please specify text to send", "sample", "error"); - return; - } - - if (!messageWebSocket) { - // Set up the socket data format and callbacks - var webSocket = new Windows.Networking.Sockets.MessageWebSocket(); - // Both utf8 and binary message types are supported. If utf8 is specified then the developer - // promises to only send utf8 encoded data. - webSocket.control.messageType = Windows.Networking.Sockets.SocketMessageType.utf8; - webSocket.onmessagereceived = onMessageReceived; - webSocket.onclosed = onClosed; - - // Validating the URI is required since it was received from an untrusted source (user - // input). The URI is validated by calling validateAndCreateUri() that will throw an exception for - // strings that are not valid WebSocket URIs. - // Note that when enabling the text box users may provide URIs to machines in the LAN - // or internet. In these cases the app requires the "Home or Work Networking" or - // "Internet (Client)" capability respectively. - var uri; - try { - uri = validateAndCreateUri(document.getElementById("serverAddress").value); - } catch (error) { - WinJS.log && WinJS.log(error, "sample", "error"); - return; - } - - WinJS.log && WinJS.log("Connecting to: " + uri.absoluteUri, "sample", "status"); - - webSocket.connectAsync(uri).done(function () { - - WinJS.log && WinJS.log("Connected", "sample", "status"); - - messageWebSocket = webSocket; - // The default DataWriter encoding is utf8. - messageWriter = new Windows.Storage.Streams.DataWriter(webSocket.outputStream); - sendMessage(); - - }, function (error) { - var errorStatus = Windows.Networking.Sockets.WebSocketError.getStatus(error.number); - if (errorStatus === Windows.Web.WebErrorStatus.cannotConnect || - errorStatus === Windows.Web.WebErrorStatus.notFound || - errorStatus === Windows.Web.WebErrorStatus.requestTimeout) { - WinJS.log && WinJS.log("Cannot connect to the server. Please make sure " + - "to run the server setup script before running the sample.", "sample", "error"); - } else { - WinJS.log && WinJS.log("Failed to connect: " + getError(error), "sample", "error"); - } - }); - } else { - WinJS.log && WinJS.log("Already Connected", "sample", "status"); - sendMessage(); - } - } - - function onMessageReceived(eventArguments) { - // The incoming message is already buffered. - var dataReader = eventArguments.getDataReader(); - log("Message Received; Type: " + getMessageTypeName(eventArguments.messageType) - + ", Bytes: " + dataReader.unconsumedBufferLength + ", Text: "); - log(dataReader.readString(dataReader.unconsumedBufferLength)); - } - - function getMessageTypeName(messageType) { - switch (messageType) { - case Windows.Networking.Sockets.SocketMessageType.utf8: - return "UTF-8"; - case Windows.Networking.Sockets.SocketMessageType.binary: - return "Binary"; - default: - return "Unknown"; - } - } - - function sendMessage() { - log("Sending message"); - messageWriter.writeString(document.getElementById("inputField").value); - messageWriter.storeAsync().done("", sendError); - } - - function sendError(error) { - log("Send error: " + getError(error)); - } - - function onClosed(closedEventInfo) { - log("Closed; Code: " + closedEventInfo.code + " Reason: " + closedEventInfo.reason); - if (!messageWebSocket) { - return; - } - - closeSocketCore(Number(null), String(null)); - } - - function closeSocket(eventObject) { - if (!messageWebSocket) { - WinJS.log && WinJS.log("Not connected", "sample", "status"); - return; - } - - WinJS.log && WinJS.log("Closing", "sample", "status"); - closeSocketCore(1000, "Closed due to user request."); - } - - function closeSocketCore(closeCode, closeStatus) { - if (closeCode && closeStatus) { - messageWebSocket.close(closeCode, closeStatus); - } else { - messageWebSocket.close(); - } - - messageWebSocket = null; - - if (messageWriter) { - messageWriter.close(); - messageWriter = null; - } - } - - function log(text) { - var outputFiled = document.getElementById("outputField"); - if (outputFiled !== null) { - outputFiled.innerHTML += text + "
"; - } - } - -})(); diff --git a/Samples/WebSocket/js/js/scenario2-binary.js b/Samples/WebSocket/js/js/scenario2-binary.js new file mode 100644 index 0000000000..80a4142f74 --- /dev/null +++ b/Samples/WebSocket/js/js/scenario2-binary.js @@ -0,0 +1,194 @@ +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License (MIT). +// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY +// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR +// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. +// +//********************************************************* + +(function () { + "use strict"; + + // Local variables + var streamWebSocket; + var busy; + + // DOM elements + var serverAddressField; + var startButton; + var stopButton; + var outputField; + + var page = WinJS.UI.Pages.define("/html/scenario2-binary.html", { + ready: function (element, options) { + serverAddressField = document.getElementById("serverAddressField"); + startButton = document.getElementById("startButton"); + stopButton = document.getElementById("stopButton"); + outputField = document.getElementById("outputField"); + + startButton.addEventListener("click", onStart, false); + stopButton.addEventListener("click", onStop, false); + + updateVisualState(); + }, + unload: function () { + closeSocket(); + } + }); + + function updateVisualState() { + serverAddressField.disabled = busy || streamWebSocket; + startButton.disabled = busy || streamWebSocket; + stopButton.disabled = busy || !streamWebSocket; + } + + function setBusy(value) { + busy = value; + updateVisualState(); + } + + function onStart() { + setBusy(true); + startAsync().done(function () { + setBusy(false); + }); + } + + function startAsync() { + // Validating the URI is required since it was received from an untrusted source (user + // input). The URI is validated by calling validateAndCreateUri() that will return null + // for strings that are not valid WebSocket URIs. + // Note that when enabling the text box users may provide URIs to machines on the local network + // or internet. In these cases the app requires the "Home or Work Networking" or + // "Internet (Client)" capability respectively. + var server = SdkSample.validateAndCreateUri(serverAddressField.value); + if (!server) { + return WinJS.Promise.wrap(); + } + + streamWebSocket = new Windows.Networking.Sockets.StreamWebSocket(); + streamWebSocket.addEventListener("closed", onClosed); + + appendOutputLine("Connecting to: " + server.absoluteUri); + + return streamWebSocket.connectAsync(server).then(function () { + WinJS.log && WinJS.log("Connected", "sample", "status"); + + // Start a loop to continuously read incoming data. + receiveData(streamWebSocket); + + // Start a loop to continuously write outgoing data. + sendData(streamWebSocket); + }, function (error) { + streamWebSocket.close(); + streamWebSocket = null; + + appendOutputLine(SdkSample.buildWebSocketError(error)); + appendOutputLine(error.message); + }); + } + + function sendData(activeSocket) { + var dataWriter = new Windows.Storage.Streams.DataWriter(activeSocket.outputStream); + var bytesSent = 0; + var data = "Hello World"; + + function loopAsync() { + if (streamWebSocket != activeSocket) { + // Our socket is no longer active. Stop sending. + return; + } + var size = dataWriter.measureString(data); + + dataWriter.writeString(data); + return dataWriter.storeAsync().then(function () { + bytesSent += size; + dataSent.innerText = bytesSent; + + // Add a 1 second delay so the user can see what's going on. + return WinJS.Promise.timeout(1000); + }).then(loopAsync); + } + + loopAsync().then(function () { + }, function (error) { + appendOutputLine("During write: " + SdkSample.buildWebSocketError(error)); + appendOutputLine(error.message); + }).done(function () { + dataWriter.close(); + }); + } + + function receiveData(activeSocket) { + var dataReader = new Windows.Storage.Streams.DataReader(activeSocket.inputStream); + var bytesReceived = 0; + + // When buffering, return as soon as any data is available. + dataReader.inputStreamOptions = Windows.Storage.Streams.InputStreamOptions.partial; + + function loopAsync() { + if (streamWebSocket != activeSocket) { + // Our socket is no longer active. Stop reading. + appendOutputLine("Background read stopped."); + return; + } + // Buffer as much data as you require for your protocol. + return dataReader.loadAsync(100).then(function (sizeBytesRead) { + bytesReceived += sizeBytesRead; + dataReceived.innerText = bytesReceived; + + var incomingBytes = new Array(sizeBytesRead); + dataReader.readBytes(incomingBytes); + + // Do something with the data. + // Alternatively you can use DataReader to read out individual booleans, + // ints, strings, etc. + + // Start another read. + return loopAsync(); + }); + } + + loopAsync().then(function () { + }, function (error) { + appendOutputLine("During read: " + SdkSample.buildWebSocketError(error)); + appendOutputLine(error.message); + }).done(function () { + dataReader.close(); + }); + } + + function onStop() { + setBusy(true); + WinJS.log && WinJS.log("Closing", "sample", "status"); + closeSocket(); + setBusy(false); + } + + function onClosed(e) { + appendOutputLine("Closed; Code: " + e.code + " Reason: " + e.reason); + if (streamWebSocket === e.target) { + closeSocket(); + updateVisualState(); + } + } + + function closeSocket() { + if (streamWebSocket) { + try { + streamWebSocket.close(1000, "Closed due to user request."); + } catch (error) { + WinJS.log && WinJS.log(SdkSample.buildWebSocketError(error), "sample", "error"); + appendOutputLine(error.message); + } + streamWebSocket = null; + } + } + + function appendOutputLine(text) { + outputField.innerText += "\r\n" + text; + } +})(); diff --git a/Samples/WebSocket/js/js/scenario2_Upload.js b/Samples/WebSocket/js/js/scenario2_Upload.js deleted file mode 100644 index 9afca97ef6..0000000000 --- a/Samples/WebSocket/js/js/scenario2_Upload.js +++ /dev/null @@ -1,180 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -(function () { - "use strict"; - - var streamWebSocket; - var dataWriter; - var dataReader; - var data = "Hello World"; - var countOfDataSent; - var countOfDataReceived; - - var page = WinJS.UI.Pages.define("/html/scenario2_Upload.html", { - ready: function (element, options) { - document.getElementById("startButton").addEventListener("click", start, false); - document.getElementById("closeButton").addEventListener("click", closeSocket, false); - }, - unload: function (eventObject) { - closeSocket(eventObject); - } - }); - - function start(eventObject) { - if (streamWebSocket) { - WinJS.log && WinJS.log("Already started", "sample", "status"); - return; - } - - var webSocket = new Windows.Networking.Sockets.StreamWebSocket(); - webSocket.onclosed = onClosed; - - // Validating the URI is required since it was received from an untrusted source (user - // input). The URI is validated by calling validateAndCreateUri() that will throw an exception for - // strings that are not valid WebSocket URIs. - // Note that when enabling the text box users may provide URIs to machines in the LAN - // or internet. In these cases the app requires the "Home or Work Networking" or - // "Internet (Client)" capability respectively. - var uri; - try { - uri = validateAndCreateUri(document.getElementById("serverAddress").value); - } catch (error) { - WinJS.log && WinJS.log(error, "sample", "error"); - return; - } - - WinJS.log && WinJS.log("Connecting to: " + uri.absoluteUri, "sample", "status"); - - webSocket.connectAsync(uri).done(function () { - WinJS.log && WinJS.log("Connected", "sample", "status"); - - streamWebSocket = webSocket; - dataWriter = new Windows.Storage.Streams.DataWriter(webSocket.outputStream); - dataReader = new Windows.Storage.Streams.DataReader(webSocket.inputStream); - // When buffering, return as soon as any data is available. - dataReader.inputStreamOptions = Windows.Storage.Streams.InputStreamOptions.partial; - countOfDataSent = 0; - countOfDataReceived = 0; - - // Continuously send data to the server - writeOutgoing(); - - // Continuously listen for a response - readIncoming(); - - }, function (error) { - var errorStatus = Windows.Networking.Sockets.WebSocketError.getStatus(error.number); - if (errorStatus === Windows.Web.WebErrorStatus.cannotConnect || - errorStatus === Windows.Web.WebErrorStatus.notFound || - errorStatus === Windows.Web.WebErrorStatus.requestTimeout) { - WinJS.log && WinJS.log("Cannot connect to the server. Please make sure " + - "that you run the server setup script before running the sample.", "sample", "error"); - } else { - WinJS.log && WinJS.log("Failed to connect: " + getError(error), "sample", "error"); - } - }); - } - - function writeOutgoing() { - try { - var size = dataWriter.measureString(data); - countOfDataSent += size; - if (document.getElementById("dataSent") === null) { - return; // We switched scenarios - } - document.getElementById("dataSent").value = countOfDataSent; - - dataWriter.writeString(data); - dataWriter.storeAsync().done(function () { - // Add a 1 second delay so the user can see what's going on. - setTimeout(writeOutgoing, 1000); - }, writeError); - } - catch (error) { - log("Sync write error: " + getError(error)); - } - } - - function writeError(error) { - log("Write error: " + getError(error)); - } - - function readIncoming() { - // Buffer as much data as you require for your protocol. - dataReader.loadAsync(100).done(function (sizeBytesRead) { - countOfDataReceived += sizeBytesRead; - if (document.getElementById("dataReceived") === null) { - return; // We switched scenarios - } - document.getElementById("dataReceived").value = countOfDataReceived; - - var incomingBytes = new Array(sizeBytesRead); - dataReader.readBytes(incomingBytes); - - // Do something with the data. - // Alternatively you can use DataReader to read out individual booleans, - // ints, strings, etc. - - // Start another read. - readIncoming(); - }, readError); - } - - function readError(error) { - log("Read Error: " + getError(error)); - } - - function onClosed(closedEventInfo) { - log("Closed; Code: " + closedEventInfo.code + " Reason: " + closedEventInfo.reason); - if (!streamWebSocket) { - return; - } - - closeSocketCore(Number(null), String(null)); - } - - function closeSocket(eventObject) { - if (!streamWebSocket) { - WinJS.log && WinJS.log("Not connected", "sample", "status"); - return; - } - - WinJS.log && WinJS.log("Closing", "sample", "status"); - closeSocketCore(1000, "Closed due to user request."); - } - - function closeSocketCore(closeCode, closeStatus) { - if (closeCode && closeStatus) { - streamWebSocket.close(closeCode, closeStatus); - } else { - streamWebSocket.close(); - } - - streamWebSocket = null; - - if (dataWriter) { - dataWriter.close(); - } - - if (dataReader) { - dataReader.close(); - } - } - - function log(text) { - var outputFiled = document.getElementById("outputField"); - if (outputFiled !== null) { - outputFiled.innerHTML += text + "
"; - } - } - -})(); diff --git a/Samples/WebSocket/shared/Scenario1_UTF8.xaml b/Samples/WebSocket/shared/Scenario1_UTF8.xaml new file mode 100644 index 0000000000..fdc5519213 --- /dev/null +++ b/Samples/WebSocket/shared/Scenario1_UTF8.xaml @@ -0,0 +1,72 @@ + + + + + + + + + + + + This scenario uses a MessageWebSocket to send UTF-8 strings. + The sample server supports both plaintext WebSocket (ws://) and secure WebSocket (wss://) server endpoints. + + + + +