Windows 10 RTM Release - May 2016 Update

This commit is contained in:
Raymond Chen 2016-05-18 17:00:00 -07:00
Родитель 2d839d3090
Коммит 6b625670fa
90 изменённых файлов: 2370 добавлений и 2381 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -74,6 +74,8 @@ ipch/
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess

Просмотреть файл

@ -34,7 +34,7 @@ Array<Scenario>^ MainPage::scenariosInner = ref new Array<Scenario>
{
// 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)
{

Просмотреть файл

@ -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;

Просмотреть файл

@ -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)
/// <param name="task">The task to attach progress and completed handlers to.</param>
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);
}
/// <summary>
@ -110,6 +94,31 @@ void SampleBackgroundTask::UnregisterBackgroundTask(Platform::Object^ sender, Wi
UpdateUI();
}
/// <summary>
/// Handle background task progress.
/// </summary>
/// <param name="task">The task that is reporting progress.</param>
/// <param name="args">Arguments of the progress report.</param>
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();
}));
}
/// <summary>
/// Handle background task completion.
/// </summary>
/// <param name="task">The task that is reporting completion.</param>
/// <param name="args">Arguments of the completion report.</param>
void SampleBackgroundTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args)
{
UpdateUI();
}
/// <summary>
/// Update the scenario UI.
/// </summary>

Просмотреть файл

@ -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();
};
}

Просмотреть файл

@ -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)
/// <param name="task">The task to attach progress and completed handlers to.</param>
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);
}
/// <summary>
@ -110,6 +94,31 @@ void SampleBackgroundTaskWithCondition::UnregisterBackgroundTask(Platform::Objec
UpdateUI();
}
/// <summary>
/// Handle background task progress.
/// </summary>
/// <param name="task">The task that is reporting progress.</param>
/// <param name="args">Arguments of the progress report.</param>
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();
}));
}
/// <summary>
/// Handle background task completion.
/// </summary>
/// <param name="task">The task that is reporting completion.</param>
/// <param name="args">Arguments of the completion report.</param>
void SampleBackgroundTaskWithCondition::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args)
{
UpdateUI();
}
/// <summary>
/// Update the scenario UI.
/// </summary>

Просмотреть файл

@ -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();
};
}

Просмотреть файл

@ -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)
/// <param name="task">The task to attach progress and completed handlers to.</param>
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);
}
/// <summary>
@ -111,6 +95,31 @@ void ServicingCompleteTask::UnregisterBackgroundTask(Platform::Object^ sender, W
UpdateUI();
}
/// <summary>
/// Handle background task progress.
/// </summary>
/// <param name="task">The task that is reporting progress.</param>
/// <param name="args">Arguments of the progress report.</param>
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();
}));
}
/// <summary>
/// Handle background task completion.
/// </summary>
/// <param name="task">The task that is reporting completion.</param>
/// <param name="args">Arguments of the completion report.</param>
void ServicingCompleteTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args)
{
UpdateUI();
}
/// <summary>
/// Update the scenario UI.
/// </summary>

Просмотреть файл

@ -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();
};
}

Просмотреть файл

@ -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)
/// <param name="task">The task to attach progress and completed handlers to.</param>
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);
}
/// <summary>
@ -110,6 +94,31 @@ void TimeTriggeredTask::UnregisterBackgroundTask(Platform::Object^ sender, Windo
UpdateUI();
}
/// <summary>
/// Handle background task progress.
/// </summary>
/// <param name="task">The task that is reporting progress.</param>
/// <param name="args">Arguments of the progress report.</param>
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();
}));
}
/// <summary>
/// Handle background task completion.
/// </summary>
/// <param name="task">The task that is reporting completion.</param>
/// <param name="args">Arguments of the completion report.</param>
void TimeTriggeredTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args)
{
UpdateUI();
}
/// <summary>
/// Update the scenario UI.
/// </summary>

Просмотреть файл

@ -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();
};
}

Просмотреть файл

@ -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)
/// <param name="task">The task to attach progress and completed handlers to.</param>
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);
}
/// <summary>
@ -136,6 +120,31 @@ void ApplicationTriggerTask::SignalBackgroundTask(Platform::Object^ sender, Wind
UpdateUI();
}
/// <summary>
/// Handle background task progress.
/// </summary>
/// <param name="task">The task that is reporting progress.</param>
/// <param name="args">Arguments of the progress report.</param>
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();
}));
}
/// <summary>
/// Handle background task completion.
/// </summary>
/// <param name="task">The task that is reporting completion.</param>
/// <param name="args">Arguments of the completion report.</param>
void ApplicationTriggerTask::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args)
{
UpdateUI();
}
/// <summary>
/// Update the scenario UI.
/// </summary>

Просмотреть файл

@ -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();
};
}

Просмотреть файл

@ -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.

Просмотреть файл

@ -10,32 +10,22 @@
#pragma once
#include "pch.h"
#include <agile.h>
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<Windows::ApplicationModel::Background::BackgroundTaskDeferral> TaskDeferral;
ThreadPoolTimer^ PeriodicTimer;
unsigned int Progress;
IBackgroundTaskInstance^ TaskInstance;
Windows::ApplicationModel::Background::BackgroundTaskCancellationReason CancelReason = Windows::ApplicationModel::Background::BackgroundTaskCancellationReason::Abort;
volatile bool CancelRequested = false;
Platform::Agile<Windows::ApplicationModel::Background::BackgroundTaskDeferral> TaskDeferral = nullptr;
Windows::System::Threading::ThreadPoolTimer^ PeriodicTimer = nullptr;
unsigned int Progress = 0;
Windows::ApplicationModel::Background::IBackgroundTaskInstance^ TaskInstance = nullptr;
};
}

Просмотреть файл

@ -74,11 +74,12 @@ namespace SDKTemplate
/// <param name="name">A name for the background task.</param>
/// <param name="trigger">The trigger for the background task.</param>
/// <param name="condition">An optional conditional event that must be true for the task to fire.</param>
public static async Task<BackgroundTaskRegistration> 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 @@ namespace SDKTemplate
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 @@ namespace SDKTemplate
}
}
UpdateBackgroundTaskStatus(name, false);
UpdateBackgroundTaskRegistrationStatus(name, false);
}
/// <summary>
@ -137,7 +138,7 @@ namespace SDKTemplate
/// </summary>
/// <param name="name">Name of background task to store registration status for.</param>
/// <param name="registered">TRUE if registered, FALSE if unregistered.</param>
public static void UpdateBackgroundTaskStatus(String name, bool registered)
public static void UpdateBackgroundTaskRegistrationStatus(String name, bool registered)
{
switch (name)
{
@ -188,10 +189,11 @@ namespace SDKTemplate
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;

Просмотреть файл

@ -48,7 +48,7 @@ namespace SDKTemplate
if (task.Value.Name == BackgroundTaskSample.SampleBackgroundTaskName)
{
AttachProgressAndCompletedHandlers(task.Value);
BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.SampleBackgroundTaskName, true);
BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.SampleBackgroundTaskName, true);
break;
}
}
@ -61,14 +61,13 @@ namespace SDKTemplate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 @@ namespace SDKTemplate
/// <param name="e">Arguments of the progress report.</param>
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();
});
}
/// <summary>

Просмотреть файл

@ -49,7 +49,7 @@ namespace SDKTemplate
if (task.Value.Name == BackgroundTaskSample.SampleBackgroundTaskWithConditionName)
{
AttachProgressAndCompletedHandlers(task.Value);
BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.SampleBackgroundTaskWithConditionName, true);
BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.SampleBackgroundTaskWithConditionName, true);
break;
}
}
@ -62,14 +62,13 @@ namespace SDKTemplate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 @@ namespace SDKTemplate
/// <param name="e">Arguments of the progress report.</param>
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();
});
}
/// <summary>

Просмотреть файл

@ -48,7 +48,7 @@ namespace SDKTemplate
if (task.Value.Name == BackgroundTaskSample.ServicingCompleteTaskName)
{
AttachProgressAndCompletedHandlers(task.Value);
BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.ServicingCompleteTaskName, true);
BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.ServicingCompleteTaskName, true);
break;
}
}
@ -61,14 +61,13 @@ namespace SDKTemplate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 @@ namespace SDKTemplate
/// <param name="e">Arguments of the progress report.</param>
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();
});
}
/// <summary>

Просмотреть файл

@ -48,7 +48,7 @@ namespace SDKTemplate
if (task.Value.Name == BackgroundTaskSample.TimeTriggeredTaskName)
{
AttachProgressAndCompletedHandlers(task.Value);
BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.TimeTriggeredTaskName, true);
BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.TimeTriggeredTaskName, true);
break;
}
}
@ -61,14 +61,13 @@ namespace SDKTemplate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 @@ namespace SDKTemplate
/// <param name="e">Arguments of the progress report.</param>
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();
});
}
/// <summary>

Просмотреть файл

@ -51,7 +51,7 @@ namespace SDKTemplate
if (task.Value.Name == BackgroundTaskSample.ApplicationTriggerTaskName)
{
AttachProgressAndCompletedHandlers(task.Value);
BackgroundTaskSample.UpdateBackgroundTaskStatus(BackgroundTaskSample.ApplicationTriggerTaskName, true);
BackgroundTaskSample.UpdateBackgroundTaskRegistrationStatus(BackgroundTaskSample.ApplicationTriggerTaskName, true);
break;
}
}
@ -64,7 +64,7 @@ namespace SDKTemplate
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void RegisterBackgroundTask(object sender, RoutedEventArgs e)
private void RegisterBackgroundTask(object sender, RoutedEventArgs e)
{
trigger = new ApplicationTrigger();
@ -72,8 +72,7 @@ namespace SDKTemplate
BackgroundTaskSample.ApplicationTriggerTaskName,
trigger,
null);
await task;
AttachProgressAndCompletedHandlers(task.Result);
AttachProgressAndCompletedHandlers(task);
UpdateUI();
}
@ -123,9 +122,12 @@ namespace SDKTemplate
/// <param name="e">Arguments of the progress report.</param>
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();
});
}
/// <summary>

Просмотреть файл

@ -91,13 +91,14 @@ namespace Tasks
{
_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]);
//

Просмотреть файл

@ -81,9 +81,10 @@ Namespace Global.SDKTemplate
''' <param name="name">A name for the background task.</param>
''' <param name="trigger">The trigger for the background task.</param>
''' <param name="condition">An optional conditional event that must be true for the task to fire.</param>
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
''' <summary>
@ -124,7 +125,7 @@ Namespace Global.SDKTemplate
''' </summary>
''' <param name="name">Name of background task to store registration status for.</param>
''' <param name="registered">TRUE if registered, FALSE if unregistered.</param>
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
''' </summary>
''' <param name="name">Name of background task to query background access requirement.</param>
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

Просмотреть файл

@ -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
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
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
''' <param name="task">The task that is reporting progress.</param>
''' <param name="e">Arguments of the progress report.</param>
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
''' <summary>

Просмотреть файл

@ -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
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
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
''' <param name="task">The task that is reporting progress.</param>
''' <param name="e">Arguments of the progress report.</param>
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
''' <summary>

Просмотреть файл

@ -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
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
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
''' <param name="task">The task that is reporting progress.</param>
''' <param name="e">Arguments of the progress report.</param>
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
''' <summary>

Просмотреть файл

@ -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
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
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
''' <param name="task">The task that is reporting progress.</param>
''' <param name="e">Arguments of the progress report.</param>
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
''' <summary>

Просмотреть файл

@ -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
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
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
''' <param name="task">The task that is reporting progress.</param>
''' <param name="e">Arguments of the progress report.</param>
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
''' <summary>

Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

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

Просмотреть файл

@ -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<Scenario>^ scenariosInner;

Просмотреть файл

@ -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 + "'");
}
});
}

Просмотреть файл

@ -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<StorageFile^> 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);
}
});
}

Просмотреть файл

@ -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 + "'");
}
});
}

Просмотреть файл

@ -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 + "'");
}
});
}

Просмотреть файл

@ -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 + "'");
}
});
}

Просмотреть файл

@ -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<BasicProperties^> 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<String^>();
propertiesName->Append(dateAccessedProperty);
@ -83,6 +74,16 @@ void Scenario6::ShowPropertiesButton_Click(Object^ sender, RoutedEventArgs^ e)
}
rootPage->NotifyUser(*outputText, NotifyType::StatusMessage);
}).then([this, file](task<void> task)
{
try
{
task.get();
}
catch (COMException^ ex)
{
rootPage->HandleIoException(ex, "Error retrieving properties for '" + file->Name + "'");
}
});
}
else

Просмотреть файл

@ -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)
{
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;
}
}
rootPage->NotifyUser(outputText, statusOrError);
listName = "MRU";
entries = StorageApplicationPermissions::MostRecentlyUsedList->Entries;
}
else
{
rootPage->NotifyUserFileNotExist();
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)
{
outputText += "\n" + entry.Metadata; // Application previously chose to store sampleFile->Name in this field
}
rootPage->NotifyUser(outputText, NotifyType::StatusMessage);
}
else
{
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<StorageFile^> fileTask = task_from_result<StorageFile^>(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<StorageFile^> 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<StorageFile^> 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<StorageFile^> 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<String^> 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");
}
});
}
});
}

Просмотреть файл

@ -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 + "'");
}
});
}

Просмотреть файл

@ -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

Просмотреть файл

@ -53,6 +53,11 @@ namespace SDKTemplate
{
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
{

Просмотреть файл

@ -38,8 +38,16 @@ namespace SDKTemplate
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);
}
}
}
}

Просмотреть файл

@ -60,6 +60,11 @@ namespace SDKTemplate
{
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 @@ namespace SDKTemplate
{
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
{

Просмотреть файл

@ -74,6 +74,11 @@ namespace SDKTemplate
{
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 @@ namespace SDKTemplate
{
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
{

Просмотреть файл

@ -69,6 +69,11 @@ namespace SDKTemplate
{
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 @@ namespace SDKTemplate
{
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
{

Просмотреть файл

@ -82,6 +82,11 @@ namespace SDKTemplate
{
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
{

Просмотреть файл

@ -28,6 +28,8 @@ namespace SDKTemplate
{
MainPage rootPage;
const int FA_E_MAX_PERSISTED_ITEMS_REACHED = unchecked((int)0x80270220);
public Scenario7()
{
this.InitializeComponent();
@ -54,10 +56,18 @@ namespace SDKTemplate
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 @@ namespace SDKTemplate
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
}
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)
{
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);
}
}
listName = "MRU";
entries = StorageApplicationPermissions.MostRecentlyUsedList.Entries;
}
else
{
rootPage.NotifyUserFileNotExist();
listName = "FAL";
entries = StorageApplicationPermissions.FutureAccessList.Entries;
}
if (entries.Count > 0)
{
StringBuilder outputText = new StringBuilder("The " + listName + " 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 " + 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);
}
}
}
}

Просмотреть файл

@ -51,6 +51,11 @@ namespace SDKTemplate
{
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
{

Просмотреть файл

@ -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");

Просмотреть файл

@ -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 () {

Просмотреть файл

@ -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);

Просмотреть файл

@ -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");
});
}
});
}
})();

Просмотреть файл

@ -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

Просмотреть файл

@ -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<Scenario>^ MainPage::scenariosInner = ref new Platform::Array<Scenario>
{
// 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();
}
}

Просмотреть файл

@ -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<Scenario>^ 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<unsigned int>(last - first));
}
};
}

Просмотреть файл

@ -1,50 +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.
//
//*********************************************************
-->
<Page x:Class="SDKTemplate.WebSocket.Scenario1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:SDKTemplate.WebSocket" xmlns:common="using:SDKTemplate.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Input" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" HorizontalAlignment="Left"> This shows how to use a MessageWebSocket to send UTF-8 strings.</TextBlock>
<TextBlock Grid.Row="1" Text="Server Address:" HorizontalAlignment="Left" Style="{StaticResource BasicTextStyle}"/>
<TextBox Grid.Row="2" Name="ServerAddressField" InputScope="Url" Text="ws://localhost/WebSocketSample/EchoWebSocket.ashx" HorizontalAlignment="Stretch"/>
<TextBlock Grid.Row="3" TextWrapping="Wrap" HorizontalAlignment="Left" Style="{StaticResource BasicTextStyle}">Enter text to send to the server.</TextBlock>
<TextBox Grid.Row="4" Name="InputField" Text="Hello World" TextWrapping="Wrap" AcceptsReturn="True" HorizontalAlignment="Stretch"/>
<StackPanel Grid.Row="5" Orientation="Horizontal" Margin="0,10,0,0">
<Button Name="StartButton" Content="Start" Margin="0,0,10,0" Click="Start_Click"/>
<Button Name="CloseButton" Content="Close" Margin="0,0,10,0" Click="Close_Click"/>
</StackPanel>
<ScrollViewer Grid.Row="6" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
<TextBox Name="OutputField" HorizontalAlignment="Stretch" MaxHeight="160" TextWrapping="Wrap" IsReadOnly="True"/>
</ScrollViewer>
</Grid>
<!-- Add Storyboards to the visual states below as necessary for supporting the various layouts -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultLayout"/>
<VisualState x:Name="Below768Layout"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -1,217 +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.
//
//*********************************************************
//
// Scenario1.xaml.cpp
// Implementation of the Scenario1 class
//
#include "pch.h"
#include <strsafe.h>
#include "Scenario1.xaml.h"
using namespace concurrency;
using namespace SDKTemplate::WebSocket;
using namespace Windows::UI::Core;
Scenario1::Scenario1()
{
InitializeComponent();
}
Scenario1::~Scenario1()
{
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
void Scenario1::OnNavigatedTo(NavigationEventArgs^ e)
{
// A pointer back to the main page. This is needed if you want to call methods in MainPage such
// as NotifyUser()
rootPage = MainPage::Current;
}
void SDKTemplate::WebSocket::Scenario1::Start_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
// Make a local copy to avoid races with Closed events.
MessageWebSocket^ webSocket = messageWebSocket;
if (InputField->Text == "")
{
rootPage->NotifyUser("Please specify text to send", NotifyType::ErrorMessage);
return;
}
// Have we connected yet?
if (webSocket == nullptr)
{
// Validating the URI is required since it was received from an untrusted source (user input).
// The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
// valid WebSocket URIs.
// Note that when enabling the text box users may provide URIs to machines on the intrAnet or intErnet. In
// these cases the app requires the "Home or Work Networking" or "Internet (Client)" capability respectively.
Uri^ server;
if (!rootPage->TryGetUri(ServerAddressField->Text, &server))
{
return;
}
rootPage->NotifyUser("Connecting to: " + server->DisplayUri, NotifyType::StatusMessage);
webSocket = ref new MessageWebSocket();
webSocket->Control->MessageType = SocketMessageType::Utf8;
webSocket->MessageReceived += ref new TypedEventHandler<MessageWebSocket^, MessageWebSocketMessageReceivedEventArgs^>(this, &Scenario1::MessageReceived);
webSocket->Closed += ref new TypedEventHandler<IWebSocket^, WebSocketClosedEventArgs^>(this, &Scenario1::Closed);
task<void>(webSocket->ConnectAsync(server)).then([this, webSocket] (task<void> previousTask)
{
try
{
// Try getting all exceptions from the continuation chain above this point.
previousTask.get();
messageWebSocket = webSocket; // Only store it after successfully connecting.
messageWriter = ref new DataWriter(webSocket->OutputStream);
rootPage->NotifyUser("Connected", NotifyType::StatusMessage);
SendMessage();
}
catch (Exception^ exception)
{
HandleException(exception);
}
});
}
else
{
rootPage->NotifyUser("Already connected", NotifyType::StatusMessage);
SendMessage();
}
}
void SDKTemplate::WebSocket::Scenario1::HandleException(Exception^ exception)
{
WebErrorStatus status = WebSocketError::GetStatus(exception->HResult);
if (status == WebErrorStatus::CannotConnect ||
status == WebErrorStatus::NotFound ||
status == WebErrorStatus::RequestTimeout)
{
rootPage->NotifyUser("Cannot connect to the server. Please make sure "
"to run the server setup script before running the sample.", NotifyType::ErrorMessage);
}
else
{
rootPage->NotifyUser("Error: " + status.ToString(), NotifyType::ErrorMessage);
}
OutputField->Text += exception->Message + "\r\n";
}
void SDKTemplate::WebSocket::Scenario1::SendMessage()
{
String^ message = InputField->Text;
OutputField->Text += "Sending Message:\r\n" + message + "\r\n";
// Buffer any data we want to send.
messageWriter->WriteString(message);
// Send the data as one complete message.
task<unsigned int>(messageWriter->StoreAsync()).then([this] (unsigned int)
{
rootPage->NotifyUser("Send Complete", NotifyType::StatusMessage);
}).then([this] (task<void> previousTask)
{
try
{
// Try getting all exceptions from the continuation chain above this point.
previousTask.get();
}
catch (Exception^ exception)
{
HandleException(exception);
}
});
}
void SDKTemplate::WebSocket::Scenario1::MessageReceived(MessageWebSocket^ sender, MessageWebSocketMessageReceivedEventArgs^ args)
{
MarshalText(OutputField, "Message Received; Type: " + args->MessageType.ToString() + "\r\n");
DataReader^ reader = args->GetDataReader();
reader->UnicodeEncoding = UnicodeEncoding::Utf8;
String^ read = reader->ReadString(reader->UnconsumedBufferLength);
MarshalText(OutputField, read + "\r\n");
}
void SDKTemplate::WebSocket::Scenario1::Close_Click(Object^ sender, RoutedEventArgs^ e)
{
try
{
if (messageWebSocket != nullptr)
{
rootPage->NotifyUser("Closing", NotifyType::StatusMessage);
messageWebSocket->Close(1000, "Closed due to user request.");
messageWebSocket = nullptr;
}
else
{
rootPage->NotifyUser("No active WebSocket, send something first", NotifyType::StatusMessage);
}
}
catch (Exception^ exception)
{
HandleException(exception);
}
}
void SDKTemplate::WebSocket::Scenario1::Closed(IWebSocket^ sender, WebSocketClosedEventArgs^ args)
{
// The method may be triggered remotely by the server sending unsolicited close frame or locally by Close()/delete operator.
// Dispatch the event to the UI thread so we do not need to synchronize access to messageWebSocket.
Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args] ()
{
OutputField->Text += "Closed; Code: " + args->Code.ToString() + ", Reason: " + args->Reason + "\r\n";
if (messageWebSocket != nullptr)
{
delete messageWebSocket;
messageWebSocket = nullptr;
}
}));
}
void SDKTemplate::WebSocket::Scenario1::MarshalText(TextBox^ output, String^ value)
{
MarshalText(output, value, true);
}
// When operations happen on a background thread we have to marshal UI updates back to the UI thread.
void SDKTemplate::WebSocket::Scenario1::MarshalText(TextBox^ output, String^ value, bool append)
{
Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, output, value, append] ()
{
if (append)
{
output->Text += value;
}
else
{
output->Text = value;
}
}));
}

Просмотреть файл

@ -1,65 +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.
//
//*********************************************************
//
// Scenario1.xaml.h
// Declaration of the Scenario1 class
//
#pragma once
#include "pch.h"
#include "Scenario1.g.h"
#include "MainPage.xaml.h"
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Networking::Sockets;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::Web;
namespace SDKTemplate
{
namespace WebSocket
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
[Windows::Foundation::Metadata::WebHostHidden]
public ref class Scenario1 sealed
{
public:
Scenario1();
protected:
virtual void OnNavigatedTo(NavigationEventArgs^ e) override;
private:
~Scenario1();
MainPage^ rootPage;
MessageWebSocket^ messageWebSocket;
DataWriter^ messageWriter;
CRITICAL_SECTION criticalSection;
void Start_Click(Object^ sender, RoutedEventArgs^ e);
void Close_Click(Object^ sender, RoutedEventArgs^ e);
void SendMessage();
void MessageReceived(MessageWebSocket^ sender, MessageWebSocketMessageReceivedEventArgs^ args);
void Closed(IWebSocket^ sender, WebSocketClosedEventArgs^ args);
void MarshalText(TextBox^ output, String^ value);
void MarshalText(TextBox^ output, String^ value, bool append);
void HandleException(Exception^ exception);
};
}
}

Просмотреть файл

@ -0,0 +1,242 @@
//*********************************************************
//
// 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.
//
//*********************************************************
//
// Scenario1.xaml.cpp
// Implementation of the Scenario1 class
//
#include "pch.h"
#include "Scenario1_UTF8.xaml.h"
using namespace concurrency;
using namespace Platform;
using namespace SDKTemplate;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Networking::Sockets;
using namespace Windows::Security::Cryptography::Certificates;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::Web;
Scenario1::Scenario1()
{
InitializeComponent();
UpdateVisualState();
}
void Scenario1::OnNavigatedFrom(NavigationEventArgs^ e)
{
CloseSocket();
}
void Scenario1::UpdateVisualState()
{
if (busy)
{
VisualStateManager::GoToState(this, "Busy", false);
}
else
{
bool connected = (messageWebSocket != nullptr);
VisualStateManager::GoToState(this, connected ? "Connected" : "Disconnected", false);
}
}
void Scenario1::SetBusy(bool value)
{
busy = value;
UpdateVisualState();
}
void Scenario1::OnConnect()
{
SetBusy(true);
ConnectAsync().then([this]()
{
SetBusy(false);
});
}
task<void> Scenario1::ConnectAsync()
{
if (InputField->Text == "")
{
rootPage->NotifyUser("Please specify text to send", NotifyType::ErrorMessage);
return task_from_result();
}
// Validating the URI is required since it was received from an untrusted source (user input).
// The URI is validated by calling TryGetUri() that will return 'nullptr' for strings that are not
// valid WebSocket URIs.
// Note that when enabling the text box users may provide URIs to machines on the intrAnet or intErnet. In
// these cases the app requires the "Home or Work Networking" or "Internet (Client)" capability respectively.
Uri^ server = rootPage->TryGetUri(ServerAddressField->Text);
if (!server)
{
return task_from_result();
}
messageWebSocket = ref new MessageWebSocket();
messageWebSocket->Control->MessageType = SocketMessageType::Utf8;
messageWebSocket->MessageReceived +=
ref new TypedEventHandler<
MessageWebSocket^,
MessageWebSocketMessageReceivedEventArgs^>(this, &Scenario1::MessageReceived);
messageWebSocket->Closed += ref new TypedEventHandler<IWebSocket^, WebSocketClosedEventArgs^>(this, &Scenario1::OnClosed);
AppendOutputLine("Connecting to " + server->DisplayUri + "...");
return create_task(messageWebSocket->ConnectAsync(server))
.then([this](task<void> previousTask)
{
try
{
// Reraise any exception that occurred in the task.
previousTask.get();
}
catch (Exception^ ex)
{
// Error happened during connect operation.
delete messageWebSocket;
messageWebSocket = nullptr;
AppendOutputLine(MainPage::BuildWebSocketError(ex));
AppendOutputLine(ex->Message);
return;
}
// The default DataWriter encoding is Utf8.
messageWriter = ref new DataWriter(messageWebSocket->OutputStream);
rootPage->NotifyUser("Connected", NotifyType::StatusMessage);
});
}
void Scenario1::OnSend()
{
SetBusy(true);
SendAsync().then([this]()
{
SetBusy(false);
});
}
task<void> Scenario1::SendAsync()
{
String^ message = InputField->Text;
if (message == "")
{
rootPage->NotifyUser("Please specify text to send", NotifyType::ErrorMessage);
return task_from_result();
}
AppendOutputLine("Sending Message: " + message);
// Buffer any data we want to send.
messageWriter->WriteString(message);
// Send the data as one complete message.
return create_task(messageWriter->StoreAsync())
.then([this](task<unsigned int> previousTask)
{
try
{
// Reraise any exception that occurred in the task.
previousTask.get();
}
catch (Exception^ ex)
{
AppendOutputLine(MainPage::BuildWebSocketError(ex));
AppendOutputLine(ex->Message);
return;
}
rootPage->NotifyUser("Send Complete", NotifyType::StatusMessage);
});
}
void Scenario1::MessageReceived(MessageWebSocket^ sender, MessageWebSocketMessageReceivedEventArgs^ args)
{
// Dispatch the event to the UI thread so we can update UI.
Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args]()
{
AppendOutputLine("Message Received; Type: " + args->MessageType.ToString());
DataReader^ reader = args->GetDataReader();
reader->UnicodeEncoding = UnicodeEncoding::Utf8;
try
{
String^ read = reader->ReadString(reader->UnconsumedBufferLength);
AppendOutputLine(read);
}
catch (Exception^ ex)
{
AppendOutputLine(MainPage::BuildWebSocketError(ex));
AppendOutputLine(ex->Message);
}
delete reader;
}));
}
void Scenario1::OnDisconnect()
{
SetBusy(true);
rootPage->NotifyUser("Closing", NotifyType::StatusMessage);
CloseSocket();
SetBusy(false);
}
// The method may be triggered remotely by the server sending unsolicited close frame or locally by Close()/delete operator.
void Scenario1::OnClosed(IWebSocket^ sender, WebSocketClosedEventArgs^ args)
{
// Dispatch the event to the UI thread so we do not need to synchronize access to messageWebSocket.
Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, sender, args] ()
{
AppendOutputLine("Closed; Code: " + args->Code.ToString() + ", Reason: " + args->Reason);
if (messageWebSocket == sender)
{
CloseSocket();
UpdateVisualState();
}
}));
}
void Scenario1::CloseSocket()
{
if (messageWebSocket != nullptr)
{
try
{
messageWebSocket->Close(1000, "Closed due to user request.");
}
catch (Exception^ ex)
{
AppendOutputLine(MainPage::BuildWebSocketError(ex));
AppendOutputLine(ex->Message);
}
messageWebSocket = nullptr;
}
if (messageWriter != nullptr)
{
delete messageWriter;
messageWriter = nullptr;
}
}
void Scenario1::AppendOutputLine(String^ value)
{
OutputField->Text += value + "\r\n";
}

Просмотреть файл

@ -0,0 +1,56 @@
//*********************************************************
//
// 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.
//
//*********************************************************
//
// Scenario1.xaml.h
// Declaration of the Scenario1 class
//
#pragma once
#include "pch.h"
#include "Scenario1_UTF8.g.h"
#include "MainPage.xaml.h"
namespace SDKTemplate
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
[Windows::Foundation::Metadata::WebHostHidden]
public ref class Scenario1 sealed
{
public:
Scenario1();
protected:
void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
void OnConnect();
void OnSend();
void OnDisconnect();
private:
MainPage^ rootPage = MainPage::Current;
Windows::Networking::Sockets::MessageWebSocket^ messageWebSocket;
Windows::Storage::Streams::DataWriter^ messageWriter;
bool busy = false;
void UpdateVisualState();
void SetBusy(bool value);
Concurrency::task<void> ConnectAsync();
Concurrency::task<void> SendAsync();
void MessageReceived(Windows::Networking::Sockets::MessageWebSocket^ sender, Windows::Networking::Sockets::MessageWebSocketMessageReceivedEventArgs^ args);
void OnClosed(Windows::Networking::Sockets::IWebSocket^ sender, Windows::Networking::Sockets::WebSocketClosedEventArgs^ args);
void CloseSocket();
void AppendOutputLine(Platform::String^ value);
};
}

Просмотреть файл

@ -1,56 +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.
//
//*********************************************************
-->
<Page x:Class="SDKTemplate.WebSocket.Scenario2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:SDKTemplate.WebSocket" xmlns:common="using:SDKTemplate.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Input" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" x:Name="InputTextBlock1" TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left"> This shows how to use a StreamWebSocket to send binary data.</TextBlock>
<TextBlock Grid.Row="1" Text="Server Address:" HorizontalAlignment="Left" Style="{StaticResource BasicTextStyle}"/>
<TextBox Grid.Row="2" Name="ServerAddressField" InputScope="Url" Text="ws://localhost/WebSocketSample/EchoWebSocket.ashx" HorizontalAlignment="Stretch"/>
<StackPanel Grid.Row="3" Orientation="Horizontal" Margin="0,10,0,0">
<Button Name="StartButton" Content="Start" Margin="0,0,10,0" Click="Start_Click"/>
<Button Name="StopButton" Content="Stop" Margin="0,0,10,0" Click="Stop_Click"/>
</StackPanel>
<StackPanel Grid.Row="4" Orientation="Horizontal" Margin="0,0,0,10">
<TextBlock Text="Data Sent:" Width="100" Margin="10,7,10,0" Style="{StaticResource BasicTextStyle}"/>
<TextBox Name="DataSentField" MinWidth="100" IsReadOnly="True"/>
</StackPanel>
<StackPanel Grid.Row="5" Orientation="Horizontal" Margin="0,0,0,10">
<TextBlock Text="Data Received:" Width="100" Margin="10,7,10,0" Style="{StaticResource BasicTextStyle}"/>
<TextBox Name="DataReceivedField" MinWidth="100" IsReadOnly="True"/>
</StackPanel>
<ScrollViewer Grid.Row="6" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
<TextBox Name="OutputField" HorizontalAlignment="Stretch" MaxHeight="140" TextWrapping="Wrap" IsReadOnly="True"/>
</ScrollViewer>
</Grid>
<!-- Add Storyboards to the visual states below as necessary for supporting the various layouts -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultLayout"/>
<VisualState x:Name="Below768Layout"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -1,296 +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.
//
//*********************************************************
//
// Scenario2.xaml.cpp
// Implementation of the Scenario2 class
//
#include "pch.h"
#include "Scenario2.xaml.h"
using namespace concurrency;
using namespace SDKTemplate::WebSocket;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::UI::Core;
using namespace Windows::System::Threading;
using namespace Windows::Security::Cryptography;
Scenario2::Scenario2()
{
InitializeComponent();
}
Scenario2::~Scenario2()
{
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
void Scenario2::OnNavigatedTo(NavigationEventArgs^ e)
{
// A pointer back to the main page. This is needed if you want to call methods in MainPage such
// as NotifyUser()
rootPage = MainPage::Current;
}
void SDKTemplate::WebSocket::Scenario2::Start_Click(Platform::Object^ sender, RoutedEventArgs^ e)
{
// Make a local copy to avoid races with the Closed event.
StreamWebSocket^ webSocket = this->streamWebSocket;
// Have we connected yet?
if (webSocket != nullptr)
{
rootPage->NotifyUser("Already connected", NotifyType::StatusMessage);
return;
}
// Validating the URI is required since it was received from an untrusted source (user input).
// The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
// valid WebSocket URIs.
// Note that when enabling the text box users may provide URIs to machines on the intrAnet or intErnet. In
// these cases the app requires the "Home or Work Networking" or "Internet (Client)" capability respectively.
Uri^ server;
if (!rootPage->TryGetUri(ServerAddressField->Text, &server))
{
return;
}
rootPage->NotifyUser("Connecting to: " + server->DisplayUri, NotifyType::StatusMessage);
webSocket = ref new StreamWebSocket();
webSocket->Closed += ref new TypedEventHandler<IWebSocket^, WebSocketClosedEventArgs^>(this, &Scenario2::Scenario2Closed);
task<void>(webSocket->ConnectAsync(server)).then([this, webSocket] (task<void> previousTask)
{
try
{
// Try getting all exceptions from the continuation chain above this point.
previousTask.get();
rootPage->NotifyUser("Connected", NotifyType::StatusMessage);
streamWebSocket = webSocket; // Only store it after successfully connecting.
this->readBuffer = ref new Buffer(1000);
OutputField->Text += "Background read starting.\r\n";
bytesReceived = 0;
// Start a loop to continuously read for incoming data.
Scenario2ReceiveData();
// Start a loop to continuously write outgoing data.
BYTE bytes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
auto data = ref new Platform::Array<byte>(ARRAYSIZE(bytes));
memcpy(data->Data, bytes, ARRAYSIZE(bytes));
sendBuffer = CryptographicBuffer::CreateFromByteArray(data);
MarshalText(OutputField, "Background sending data in " + sendBuffer->Length.ToString()
+ " byte chunks each second.\r\n");
dataSent = 0;
Scenario2SendData();
}
catch(Exception^ exception)
{
HandleException(exception);
}
});
}
void SDKTemplate::WebSocket::Scenario2::HandleException(Exception^ exception)
{
WebErrorStatus status = WebSocketError::GetStatus(exception->HResult);
if (status == WebErrorStatus::CannotConnect ||
status == WebErrorStatus::NotFound ||
status == WebErrorStatus::RequestTimeout)
{
rootPage->NotifyUser("Cannot connect to the server. Please make sure "
"to run the server setup script before running the sample.", NotifyType::ErrorMessage);
}
else
{
rootPage->NotifyUser("Error: " + status.ToString(), NotifyType::ErrorMessage);
}
OutputField->Text += exception->Message + "\r\n";
}
void SDKTemplate::WebSocket::Scenario2::Scenario2SendData()
{
// Make a local copy to avoid races with the Closed event.
StreamWebSocket^ webSocket = this->streamWebSocket;
if (webSocket == nullptr)
{
return;
}
try
{
IOutputStream^ writeStream = webSocket->OutputStream;
task<UINT32>(writeStream->WriteAsync(sendBuffer)).then([this] (UINT32 sent)
{
dataSent += sent;
MarshalText(DataSentField, dataSent.ToString(), false);
// Delay so the user can watch what's going on.
TimeSpan time = { 10000000 }; // 1 second.
ThreadPoolTimer::CreateTimer(ref new TimerElapsedHandler([this](ThreadPoolTimer^ timer) {
Scenario2SendData();
}), time);
}).then([this] (task<void> previousTask)
{
try
{
// Try getting all exceptions from the continuation chain above this point.
previousTask.get();
}
catch (Exception^ exception)
{
MarshalText(OutputField, exception->Message + "\r\n");
}
});
}
catch (Exception^ exception)
{
if (exception->HResult == RO_E_CLOSED)
{
MarshalText(OutputField, "Output stream already closed by the user\r\n");
}
else
{
throw;
}
}
}
// Continuously read incoming data. For reading data we'll show how to use webSocket.InputStream.AsStream()
// to get a .NET stream. Alternatively you could call readBuffer.AsBuffer() to use IBuffer with
// webSocket->InputStream->ReadAsync.
void SDKTemplate::WebSocket::Scenario2::Scenario2ReceiveData()
{
// Make a local copy to avoid races with the Closed event.
StreamWebSocket^ webSocket = this->streamWebSocket;
if (webSocket == nullptr)
{
return;
}
try
{
IInputStream^ readStream = webSocket->InputStream;
task<IBuffer^>(readStream->ReadAsync(readBuffer, readBuffer->Capacity, InputStreamOptions::Partial)).then([this] (IBuffer^ buffer)
{
bytesReceived += buffer->Length;
DataReceivedField->Text = bytesReceived.ToString();
// Do something with the data.
}).then([this] (task<void> previousTask)
{
try
{
// Try getting all exceptions from the continuation chain above this point.
previousTask.get();
}
catch (Exception^ exception)
{
WebErrorStatus status = WebSocketError::GetStatus(exception->HResult);
if (status == WebErrorStatus::OperationCanceled)
{
OutputField->Text += "Background read canceled.\r\n";
}
else
{
HandleException(exception);
}
}
// Continue reading until closed and ReadAsync fails.
Scenario2ReceiveData();
});
}
catch (Exception^ exception)
{
if (exception->HResult == RO_E_CLOSED)
{
OutputField->Text += "Input stream already closed by the user\r\n";
}
else
{
throw;
}
}
}
void SDKTemplate::WebSocket::Scenario2::Stop_Click(Platform::Object^ sender, RoutedEventArgs^ e)
{
try
{
if (streamWebSocket != nullptr)
{
rootPage->NotifyUser("Stopping", NotifyType::StatusMessage);
streamWebSocket->Close(1000, "Closed due to user request.");
streamWebSocket = nullptr;
}
else
{
rootPage->NotifyUser("There is no active socket to stop.", NotifyType::StatusMessage);
}
}
catch (Exception^ exception)
{
HandleException(exception);
}
}
void SDKTemplate::WebSocket::Scenario2::Scenario2Closed(IWebSocket^ sender, WebSocketClosedEventArgs^ args)
{
// The method may be triggered remotely by the server sending unsolicited close frame or locally by Close()/delete operator.
// Dispatch the event to the UI thread so we do not need to synchronize access to streamWebSocket.
Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, args] ()
{
OutputField->Text += "Closed; Code: " + args->Code.ToString() + ", Reason: " + args->Reason + "\r\n";
if (streamWebSocket != nullptr)
{
delete streamWebSocket;
streamWebSocket = nullptr;
}
}));
}
void SDKTemplate::WebSocket::Scenario2::MarshalText(TextBox^ output, String^ value)
{
MarshalText(output, value, true);
}
// When operations happen on a background thread we have to marshal UI updates back to the UI thread.
void SDKTemplate::WebSocket::Scenario2::MarshalText(TextBox^ output, String^ value, bool append)
{
Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, output, value, append] ()
{
if (append)
{
output->Text += value;
}
else
{
output->Text = value;
}
}, CallbackContext::Any));
}

Просмотреть файл

@ -1,68 +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.
//
//*********************************************************
//
// Scenario2.xaml.h
// Declaration of the Scenario2 class
//
#pragma once
#include "pch.h"
#include "Scenario2.g.h"
#include "MainPage.xaml.h"
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Networking::Sockets;
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::Web;
namespace SDKTemplate
{
namespace WebSocket
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
[Windows::Foundation::Metadata::WebHostHidden]
public ref class Scenario2 sealed
{
public:
Scenario2();
protected:
virtual void OnNavigatedTo(NavigationEventArgs^ e) override;
private:
~Scenario2();
MainPage^ rootPage;
StreamWebSocket^ streamWebSocket;
IBuffer^ readBuffer;
IBuffer^ sendBuffer;
int bytesReceived;
int dataSent;
CRITICAL_SECTION criticalSection;
void Start_Click(Object^ sender, RoutedEventArgs^ e);
void Stop_Click(Object^ sender, RoutedEventArgs^ e);
void Scenario2ReceiveData();
void Scenario2SendData();
void Scenario2Closed(IWebSocket^ sender, WebSocketClosedEventArgs^ args);
void HandleException(Exception^ exception);
void MarshalText(TextBox^ output, String^ value);
void MarshalText(TextBox^ output, String^ value, bool append);
};
}
}

Просмотреть файл

@ -0,0 +1,262 @@
//*********************************************************
//
// 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.
//
//*********************************************************
//
// Scenario2.xaml.cpp
// Implementation of the Scenario2 class
//
#include "pch.h"
#include "Scenario2_Binary.xaml.h"
using namespace concurrency;
using namespace Platform;
using namespace SDKTemplate;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Networking::Sockets;
using namespace Windows::Security::Cryptography;
using namespace Windows::Security::Cryptography::Certificates;
using namespace Windows::Storage::Streams;
using namespace Windows::System::Threading;
using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::Web;
Scenario2::Scenario2()
{
InitializeComponent();
UpdateVisualState();
}
void Scenario2::OnNavigatedFrom(NavigationEventArgs^ e)
{
CloseSocket();
}
void Scenario2::UpdateVisualState()
{
if (busy)
{
VisualStateManager::GoToState(this, "Busy", false);
}
else
{
bool connected = (streamWebSocket != nullptr);
VisualStateManager::GoToState(this, connected ? "Connected" : "Disconnected", false);
}
}
void Scenario2::SetBusy(bool value)
{
busy = value;
UpdateVisualState();
}
void Scenario2::OnStart()
{
SetBusy(true);
StartAsync().then([this]()
{
SetBusy(false);
});
}
task<void> Scenario2::StartAsync()
{
// Validating the URI is required since it was received from an untrusted source (user input).
// The URI is validated by calling TryGetUri() that will return 'nullptr' for strings that are not
// valid WebSocket URIs.
// Note that when enabling the text box users may provide URIs to machines on the intrAnet or intErnet. In
// these cases the app requires the "Home or Work Networking" or "Internet (Client)" capability respectively.
Uri^ server = rootPage->TryGetUri(ServerAddressField->Text);
if (!server)
{
return task_from_result();
}
streamWebSocket = ref new StreamWebSocket();
streamWebSocket->Closed += ref new TypedEventHandler<IWebSocket^, WebSocketClosedEventArgs^>(this, &Scenario2::OnClosed);
AppendOutputLine("Connecting to " + server->DisplayUri + "...");
return create_task(streamWebSocket->ConnectAsync(server))
.then([this](task<void> previousTask)
{
try
{
// Reraise any exception that occurred in the task.
previousTask.get();
}
catch (Exception^ ex)
{
// Error happened during connect operation.
delete streamWebSocket;
streamWebSocket = nullptr;
AppendOutputLine(MainPage::BuildWebSocketError(ex));
AppendOutputLine(ex->Message);
return;
}
// Start a task to continuously read for incoming data
StartReceiveData(streamWebSocket);
// Start a task to continuously write outgoing data
StartSendData(streamWebSocket);
});
}
void Scenario2::StartSendData(StreamWebSocket^ activeSocket)
{
// Start a loop to continuously write outgoing data.
BYTE bytes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
auto data = ref new Platform::Array<byte>(ARRAYSIZE(bytes));
memcpy(data->Data, bytes, ARRAYSIZE(bytes));
IBuffer^ sendBuffer = CryptographicBuffer::CreateFromByteArray(data);
AppendOutputLine("Background write starting.");
SendDataLoop(streamWebSocket, sendBuffer, 0);
}
void Scenario2::SendDataLoop(StreamWebSocket^ activeSocket, IBuffer^ sendBuffer, UINT32 bytesSentSoFar)
{
if (streamWebSocket != activeSocket) {
// Our socket is no longer active. Stop sending.
AppendOutputLine("Background write stopped.");
return;
}
create_task(activeSocket->OutputStream->WriteAsync(sendBuffer))
.then([this, activeSocket, sendBuffer, bytesSentSoFar](task<UINT32> previousTask)
{
UINT32 bytesSentThisCall = 0;
try
{
// Reraise any exception that occurred in the task.
bytesSentThisCall = previousTask.get();
}
catch (Exception^ ex)
{
WebErrorStatus status = WebSocketError::GetStatus(ex->HResult);
if (status == WebErrorStatus::OperationCanceled)
{
AppendOutputLine("Background write canceled.");
}
else
{
AppendOutputLine("Error: " + status.ToString());
AppendOutputLine(ex->Message);
}
return;
}
UINT32 totalBytesSent = bytesSentSoFar + bytesSentThisCall;
DataSentField->Text = totalBytesSent.ToString();
// Delay so the user can watch what's going on.
ThreadPoolTimer::CreateTimer(ref new TimerElapsedHandler(
[this, activeSocket, sendBuffer, totalBytesSent](ThreadPoolTimer^ timer)
{
SendDataLoop(activeSocket, sendBuffer, totalBytesSent);
}, CallbackContext::Same), TimeSpan{ 10000000 }); // 1 second
});
}
// Continuously read incoming data.
void Scenario2::StartReceiveData(StreamWebSocket^ activeSocket)
{
AppendOutputLine("Background read starting.");
ReceiveDataLoop(activeSocket, ref new Buffer(1000), 0);
}
void Scenario2::ReceiveDataLoop(StreamWebSocket^ activeSocket, IBuffer^ readBuffer, UINT32 bytesReceivedSoFar)
{
if (streamWebSocket != activeSocket) {
// Our socket is no longer active. Stop reading.
AppendOutputLine("Background read stopped.");
return;
}
create_task(activeSocket->InputStream->ReadAsync(readBuffer, readBuffer->Capacity, InputStreamOptions::Partial))
.then([this, activeSocket, readBuffer, bytesReceivedSoFar](task<IBuffer^> previousTask)
{
IBuffer^ resultBuffer;
try
{
// Reraise any exception that occurred in the task.
resultBuffer = previousTask.get();
}
catch (Exception^ ex)
{
AppendOutputLine("During read: " + rootPage->BuildWebSocketError(ex));
AppendOutputLine(ex->Message);
return;
}
UINT32 totalBytesReceived = bytesReceivedSoFar + resultBuffer->Length;
DataReceivedField->Text = totalBytesReceived.ToString();
// Do something with the data.
// Continue reading until closed and ReadAsync fails.
ReceiveDataLoop(activeSocket, readBuffer, totalBytesReceived);
});
}
void Scenario2::OnStop()
{
SetBusy(true);
rootPage->NotifyUser("Stopping", NotifyType::StatusMessage);
CloseSocket();
SetBusy(false);
}
// The method may be triggered remotely by the server sending unsolicited close frame or locally by Close()/delete operator.
void Scenario2::OnClosed(IWebSocket^ sender, WebSocketClosedEventArgs^ args)
{
// Dispatch the event to the UI thread so we do not need to synchronize access to streamWebSocket.
Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, sender, args]()
{
AppendOutputLine("Closed; Code: " + args->Code.ToString() + ", Reason: " + args->Reason);
if (streamWebSocket == sender)
{
CloseSocket();
UpdateVisualState();
}
}));
}
void Scenario2::CloseSocket()
{
if (streamWebSocket != nullptr)
{
try
{
streamWebSocket->Close(1000, "Closed due to user request.");
}
catch (Exception^ ex)
{
AppendOutputLine(MainPage::BuildWebSocketError(ex));
AppendOutputLine(ex->Message);
}
streamWebSocket = nullptr;
}
}
void Scenario2::AppendOutputLine(String^ value)
{
OutputField->Text += value + "\r\n";
}

Просмотреть файл

@ -0,0 +1,65 @@
//*********************************************************
//
// 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.
//
//*********************************************************
//
// Scenario2.xaml.h
// Declaration of the Scenario2 class
//
#pragma once
#include "pch.h"
#include "Scenario2_Binary.g.h"
#include "MainPage.xaml.h"
namespace SDKTemplate
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
[Windows::Foundation::Metadata::WebHostHidden]
public ref class Scenario2 sealed
{
public:
Scenario2();
protected:
void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
void OnStart();
void OnStop();
private:
MainPage^ rootPage = MainPage::Current;
Windows::Networking::Sockets::StreamWebSocket^ streamWebSocket;
bool busy = false;
void UpdateVisualState();
void SetBusy(bool value);
Concurrency::task<void> StartAsync();
Concurrency::task<void> StopAsync();
void StartReceiveData(Windows::Networking::Sockets::StreamWebSocket^ activeSocket);
void ReceiveDataLoop(
Windows::Networking::Sockets::StreamWebSocket^ activeSocket,
Windows::Storage::Streams::IBuffer^ readBuffer,
UINT32 bytesReceivedSoFar);
void StartSendData(Windows::Networking::Sockets::StreamWebSocket^ activeSocket);
void SendDataLoop(
Windows::Networking::Sockets::StreamWebSocket^ activeSocket,
Windows::Storage::Streams::IBuffer^ sendBuffer,
UINT32 bytesSentSoFar);
void OnClosed(Windows::Networking::Sockets::IWebSocket^ sender, Windows::Networking::Sockets::WebSocketClosedEventArgs^ args);
void CloseSocket();
void AppendOutputLine(Platform::String^ value);
};
}

Просмотреть файл

@ -145,11 +145,11 @@
<DependentUpon>..\..\..\SharedContent\cpp\MainPage.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="SampleConfiguration.h" />
<ClInclude Include="Scenario1.xaml.h">
<DependentUpon>Scenario1.xaml</DependentUpon>
<ClInclude Include="Scenario1_UTF8.xaml.h">
<DependentUpon>..\shared\Scenario1_UTF8.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Scenario2.xaml.h">
<DependentUpon>Scenario2.xaml</DependentUpon>
<ClInclude Include="Scenario2_Binary.xaml.h">
<DependentUpon>..\shared\Scenario2_Binary.xaml</DependentUpon>
</ClInclude>
</ItemGroup>
<ItemGroup>
@ -159,8 +159,8 @@
<Page Include="..\..\..\SharedContent\cpp\MainPage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Scenario1.xaml" />
<Page Include="Scenario2.xaml" />
<Page Include="..\shared\Scenario1_UTF8.xaml" />
<Page Include="..\shared\Scenario2_Binary.xaml" />
<Page Include="..\..\..\SharedContent\xaml\Styles.xaml">
<Link>Styles\Styles.xaml</Link>
</Page>
@ -186,11 +186,11 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SampleConfiguration.cpp" />
<ClCompile Include="Scenario1.xaml.cpp">
<DependentUpon>Scenario1.xaml</DependentUpon>
<ClCompile Include="Scenario1_UTF8.xaml.cpp">
<DependentUpon>..\shared\Scenario1_UTF8.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="Scenario2.xaml.cpp">
<DependentUpon>Scenario2.xaml</DependentUpon>
<ClCompile Include="Scenario2_Binary.xaml.cpp">
<DependentUpon>..\shared\Scenario2_Binary.xaml</DependentUpon>
</ClCompile>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -8,16 +8,16 @@
<ClCompile Include="..\..\..\SharedContent\cpp\MainPage.xaml.cpp" />
<ClCompile Include="pch.cpp" />
<ClCompile Include="SampleConfiguration.cpp" />
<ClCompile Include="Scenario1.xaml.cpp" />
<ClCompile Include="Scenario2.xaml.cpp" />
<ClCompile Include="Scenario1_UTF8.xaml.cpp" />
<ClCompile Include="Scenario2_Binary.xaml.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="..\..\..\SharedContent\cpp\App.xaml.h" />
<ClInclude Include="..\..\..\SharedContent\cpp\MainPage.xaml.h" />
<ClInclude Include="SampleConfiguration.h" />
<ClInclude Include="Scenario1.xaml.h" />
<ClInclude Include="Scenario2.xaml.h" />
<ClInclude Include="Scenario1_UTF8.xaml.h" />
<ClInclude Include="Scenario2_Binary.xaml.h" />
</ItemGroup>
<ItemGroup>
<Image Include="..\..\..\SharedContent\media\microsoft-sdk.png">
@ -47,8 +47,8 @@
</ItemGroup>
<ItemGroup>
<Page Include="..\..\..\SharedContent\cpp\MainPage.xaml" />
<Page Include="Scenario1.xaml" />
<Page Include="Scenario2.xaml" />
<Page Include="..\shared\Scenario1_UTF8.xaml" />
<Page Include="..\shared\Scenario2_Binary.xaml" />
<Page Include="..\..\..\SharedContent\xaml\Styles.xaml">
<Filter>Styles</Filter>
</Page>

Просмотреть файл

@ -9,45 +9,40 @@
//
//*********************************************************
using System;
using System.Collections.Generic;
using Windows.UI.Xaml.Controls;using System;
using Microsoft.Samples.Networking.WebSocket;
using System.Threading.Tasks;
using Windows.Networking.Sockets;
using Windows.Security.Cryptography.Certificates;
using Windows.UI.Xaml.Controls;
using Windows.Web;
namespace SDKTemplate
{
public partial class MainPage : Page
{
// Change the string below to reflect the name of your sample.
// This is used on the main page as the title of the sample.
public const string FEATURE_NAME = "WebSocket";
public const string FEATURE_NAME = "WebSocket C# Sample";
// Change the array below to reflect the name of your scenarios.
// This will be used to populate the list of scenarios on the main page with
// which the user will choose the specific scenario that they are interested in.
// These should be in the form: "Navigating to a web page".
// The code in MainPage will take care of turning this into: "1) Navigating to a web page"
List<Scenario> scenarios = new List<Scenario>
{
new Scenario() { Title = "UTF-8 text messages", ClassType = typeof(Scenario1) },
new Scenario() { Title = "Binary data stream", ClassType = typeof(Scenario2) },
};
public bool TryGetUri(string uriString, out Uri uri)
public Uri TryGetUri(string uriString)
{
uri = null;
Uri webSocketUri;
if (!Uri.TryCreate(uriString.Trim(), UriKind.Absolute, out webSocketUri))
{
NotifyUser("Error: Invalid URI", NotifyType.ErrorMessage);
return false;
return null;
}
// Fragments are not allowed in WebSocket URIs.
if (!String.IsNullOrEmpty(webSocketUri.Fragment))
{
NotifyUser("Error: URI fragments not supported in WebSocket URIs.", NotifyType.ErrorMessage);
return false;
return null;
}
// Uri.SchemeName returns the canonicalized scheme name so we can use case-sensitive, ordinal string
@ -55,12 +50,33 @@ namespace SDKTemplate
if ((webSocketUri.Scheme != "ws") && (webSocketUri.Scheme != "wss"))
{
NotifyUser("Error: WebSockets only support ws:// and wss:// schemes.", NotifyType.ErrorMessage);
return false;
return null;
}
uri = webSocketUri;
return webSocketUri;
}
return true;
public static string BuildWebSocketError(Exception ex)
{
ex = ex.GetBaseException();
WebErrorStatus status = WebSocketError.GetStatus(ex.HResult);
// 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.
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;
default:
return "Error: " + status;
}
}
}

Просмотреть файл

@ -1,50 +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.
//
//*********************************************************
-->
<Page x:Class="Microsoft.Samples.Networking.WebSocket.Scenario1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Microsoft.Samples.Networking.WebSocket" xmlns:common="using:SDKTemplate.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Input" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" HorizontalAlignment="Left"> This shows how to use a MessageWebSocket to send UTF-8 strings. </TextBlock>
<TextBlock Grid.Row="1" Text="Server Address:" HorizontalAlignment="Left" Style="{StaticResource BasicTextStyle}"/>
<TextBox Grid.Row="2" Name="ServerAddressField" InputScope="Url" Text="ws://localhost/WebSocketSample/EchoWebSocket.ashx" HorizontalAlignment="Stretch"/>
<TextBlock Grid.Row="3" TextWrapping="Wrap" HorizontalAlignment="Left" Style="{StaticResource BasicTextStyle}">Enter text to send to the server.</TextBlock>
<TextBox Grid.Row="4" Name="InputField" Text="Hello World" TextWrapping="Wrap" AcceptsReturn="True" HorizontalAlignment="Stretch"/>
<StackPanel Grid.Row="5" Orientation="Horizontal" Margin="0,10,0,0">
<Button Name="StartButton" Content="Start" Margin="0,0,10,0" Click="Start_Click"/>
<Button Name="CloseButton" Content="Close" Margin="0,0,10,0" Click="Close_Click"/>
</StackPanel>
<ScrollViewer Grid.Row="6" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
<TextBox Name="OutputField" HorizontalAlignment="Stretch" MaxHeight="160" TextWrapping="Wrap" IsReadOnly="True"/>
</ScrollViewer>
</Grid>
<!-- Add Storyboards to the visual states below as necessary for supporting the various layouts -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultLayout"/>
<VisualState x:Name="Below768Layout"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -9,17 +9,17 @@
//
//*********************************************************
using SDKTemplate;
using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Web;
namespace Microsoft.Samples.Networking.WebSocket
namespace SDKTemplate
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
@ -32,22 +32,46 @@ namespace Microsoft.Samples.Networking.WebSocket
private MessageWebSocket messageWebSocket;
private DataWriter messageWriter;
private bool busy;
public Scenario1()
{
this.InitializeComponent();
UpdateVisualState();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
CloseSocket();
}
private async void Start_Click(object sender, RoutedEventArgs e)
private void UpdateVisualState()
{
if (busy)
{
VisualStateManager.GoToState(this, "Busy", false);
}
else
{
bool connected = (messageWebSocket != null);
VisualStateManager.GoToState(this, connected ? "Connected" : "Disconnected", false);
}
}
private void SetBusy(bool value)
{
busy = value;
UpdateVisualState();
}
private async void OnConnect()
{
SetBusy(true);
await ConnectAsync();
SetBusy(false);
}
private async Task ConnectAsync()
{
if (String.IsNullOrEmpty(InputField.Text))
{
@ -55,185 +79,153 @@ namespace Microsoft.Samples.Networking.WebSocket
return;
}
bool connecting = true;
// Validating the URI is required since it was received from an untrusted source (user input).
// The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
// valid WebSocket URIs.
// Note that when enabling the text box users may provide URIs to machines on the intrAnet
// or intErnet. In these cases the app requires the "Home or Work Networking" or
// "Internet (Client)" capability respectively.
Uri server = rootPage.TryGetUri(ServerAddressField.Text);
if (server == null)
{
return;
}
messageWebSocket = new MessageWebSocket();
messageWebSocket.Control.MessageType = SocketMessageType.Utf8;
messageWebSocket.MessageReceived += MessageReceived;
messageWebSocket.Closed += OnClosed;
AppendOutputLine($"Connecting to {server}...");
try
{
// Have we connected yet?
if (messageWebSocket == null)
{
// Validating the URI is required since it was received from an untrusted source (user input).
// The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
// valid WebSocket URIs.
// Note that when enabling the text box users may provide URIs to machines on the intrAnet
// or intErnet. In these cases the app requires the "Home or Work Networking" or
// "Internet (Client)" capability respectively.
Uri server;
if (!rootPage.TryGetUri(ServerAddressField.Text, out server))
{
return;
}
rootPage.NotifyUser("Connecting to: " + server, NotifyType.StatusMessage);
messageWebSocket = new MessageWebSocket();
messageWebSocket.Control.MessageType = SocketMessageType.Utf8;
messageWebSocket.MessageReceived += MessageReceived;
// Dispatch close event on UI thread. This allows us to avoid synchronizing access to messageWebSocket.
messageWebSocket.Closed += async (senderSocket, args) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Closed(senderSocket, args));
};
await messageWebSocket.ConnectAsync(server);
messageWriter = new DataWriter(messageWebSocket.OutputStream);
rootPage.NotifyUser("Connected", NotifyType.StatusMessage);
}
else
{
rootPage.NotifyUser("Already connected", NotifyType.StatusMessage);
}
connecting = false;
string message = InputField.Text;
OutputField.Text += "Sending Message:\r\n" + message + "\r\n";
// Buffer any data we want to send.
messageWriter.WriteString(message);
// Send the data as one complete message.
await messageWriter.StoreAsync();
rootPage.NotifyUser("Send Complete", NotifyType.StatusMessage);
await messageWebSocket.ConnectAsync(server);
}
catch (Exception ex) // For debugging
{
// Error happened during connect operation.
if (connecting && messageWebSocket != null)
{
messageWebSocket.Dispose();
messageWebSocket = null;
}
messageWebSocket.Dispose();
messageWebSocket = null;
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
switch (status)
{
case WebErrorStatus.CannotConnect:
case WebErrorStatus.NotFound:
case WebErrorStatus.RequestTimeout:
rootPage.NotifyUser("Cannot connect to the server. Please make sure " +
"to run the server setup script before running the sample.", NotifyType.ErrorMessage);
break;
case WebErrorStatus.Unknown:
throw;
default:
rootPage.NotifyUser("Error: " + status, NotifyType.ErrorMessage);
break;
}
OutputField.Text += ex.Message + "\r\n";
AppendOutputLine(MainPage.BuildWebSocketError(ex));
AppendOutputLine(ex.Message);
return;
}
// The default DataWriter encoding is Utf8.
messageWriter = new DataWriter(messageWebSocket.OutputStream);
rootPage.NotifyUser("Connected", NotifyType.StatusMessage);
}
async void OnSend()
{
SetBusy(true);
await SendAsync();
SetBusy(false);
}
async Task SendAsync()
{
string message = InputField.Text;
if (String.IsNullOrEmpty(message))
{
rootPage.NotifyUser("Please specify text to send", NotifyType.ErrorMessage);
return;
}
AppendOutputLine("Sending Message: " + message);
// Buffer any data we want to send.
messageWriter.WriteString(message);
try
{
// Send the data as one complete message.
await messageWriter.StoreAsync();
}
catch (Exception ex)
{
AppendOutputLine(MainPage.BuildWebSocketError(ex));
AppendOutputLine(ex.Message);
return;
}
rootPage.NotifyUser("Send Complete", NotifyType.StatusMessage);
}
private void MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
{
try
// Dispatch the event to the UI thread so we can update UI.
var ignore = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MarshalText(OutputField, "Message Received; Type: " + args.MessageType + "\r\n");
AppendOutputLine("Message Received; Type: " + args.MessageType);
using (DataReader reader = args.GetDataReader())
{
reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
reader.UnicodeEncoding = UnicodeEncoding.Utf8;
string read = reader.ReadString(reader.UnconsumedBufferLength);
MarshalText(OutputField, read + "\r\n");
}
}
catch (Exception ex) // For debugging
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
if (status == WebErrorStatus.Unknown)
{
throw;
}
// Normally we'd use the status to test for specific conditions we want to handle specially,
// and only use ex.Message for display purposes. In this sample, we'll just output the
// status for debugging here, but still use ex.Message below.
MarshalText(OutputField, "Error: " + status + "\r\n");
MarshalText(OutputField, ex.Message + "\r\n");
}
}
private void Close_Click(object sender, RoutedEventArgs e)
{
try
{
if (messageWebSocket != null)
{
rootPage.NotifyUser("Closing", NotifyType.StatusMessage);
messageWebSocket.Close(1000, "Closed due to user request.");
messageWebSocket = null;
}
else
{
rootPage.NotifyUser("No active WebSocket, send something first", NotifyType.StatusMessage);
}
}
catch (Exception ex)
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
if (status == WebErrorStatus.Unknown)
{
throw;
}
// Normally we'd use the status to test for specific conditions we want to handle specially,
// and only use ex.Message for display purposes. In this sample, we'll just output the
// status for debugging here, but still use ex.Message below.
rootPage.NotifyUser("Error: " + status, NotifyType.ErrorMessage);
OutputField.Text += ex.Message + "\r\n";
}
}
// This may be triggered remotely by the server or locally by Close/Dispose()
private void Closed(IWebSocket sender, WebSocketClosedEventArgs args)
{
MarshalText(OutputField, "Closed; Code: " + args.Code + ", Reason: " + args.Reason + "\r\n");
if (messageWebSocket != null)
{
messageWebSocket.Dispose();
messageWebSocket = null;
}
}
private void MarshalText(TextBox output, string value)
{
MarshalText(output, value, true);
}
// When operations happen on a background thread we have to marshal UI updates back to the UI thread.
private void MarshalText(TextBox output, string value, bool append)
{
var ignore = output.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (append)
{
output.Text += value;
}
else
{
output.Text = value;
try
{
string read = reader.ReadString(reader.UnconsumedBufferLength);
AppendOutputLine(read);
}
catch (Exception ex)
{
AppendOutputLine(MainPage.BuildWebSocketError(ex));
AppendOutputLine(ex.Message);
}
}
});
}
private void OnDisconnect()
{
SetBusy(true);
rootPage.NotifyUser("Closing", NotifyType.StatusMessage);
CloseSocket();
SetBusy(false);
}
// This may be triggered remotely by the server or locally by Close/Dispose()
private async void OnClosed(IWebSocket sender, WebSocketClosedEventArgs args)
{
// Dispatch the event to the UI thread so we do not need to synchronize access to messageWebSocket.
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
AppendOutputLine("Closed; Code: " + args.Code + ", Reason: " + args.Reason);
if (messageWebSocket == sender)
{
CloseSocket();
UpdateVisualState();
}
});
}
private void CloseSocket()
{
if (messageWebSocket != null)
{
try
{
messageWebSocket.Close(1000, "Closed due to user request.");
}
catch (Exception ex)
{
AppendOutputLine(MainPage.BuildWebSocketError(ex));
AppendOutputLine(ex.Message);
}
messageWebSocket = null;
}
if (messageWriter != null)
{
messageWriter.Dispose();
messageWriter = null;
}
}
private void AppendOutputLine(string value)
{
OutputField.Text += value + "\r\n";
}
}
}

Просмотреть файл

@ -1,56 +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.
//
//*********************************************************
-->
<Page x:Class="Microsoft.Samples.Networking.WebSocket.Scenario2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Microsoft.Samples.Networking.WebSocket" xmlns:common="using:SDKTemplate.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Input" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" x:Name="InputTextBlock1" TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left"> This shows how to use a StreamWebSocket to send binary data. </TextBlock>
<TextBlock Grid.Row="1" Text="Server Address:" HorizontalAlignment="Left" Style="{StaticResource BasicTextStyle}"/>
<TextBox Grid.Row="2" Name="ServerAddressField" InputScope="Url" Text="ws://localhost/WebSocketSample/EchoWebSocket.ashx" HorizontalAlignment="Stretch"/>
<StackPanel Grid.Row="3" Orientation="Horizontal" Margin="0,10,0,0">
<Button Name="StartButton" Content="Start" Margin="0,0,10,0" Click="Start_Click"/>
<Button Name="StopButton" Content="Stop" Margin="0,0,10,0" Click="Stop_Click"/>
</StackPanel>
<StackPanel Grid.Row="4" Orientation="Horizontal" Margin="0,0,0,10">
<TextBlock Text="Data Sent:" Width="100" Margin="10,7,10,0" Style="{StaticResource BasicTextStyle}"/>
<TextBox Name="DataSentField" MinWidth="100" IsReadOnly="True"/>
</StackPanel>
<StackPanel Grid.Row="5" Orientation="Horizontal" Margin="0,0,0,10">
<TextBlock Text="Data Received:" Width="100" Margin="10,7,10,0" Style="{StaticResource BasicTextStyle}"/>
<TextBox Name="DataReceivedField" MinWidth="100" IsReadOnly="True"/>
</StackPanel>
<ScrollViewer Grid.Row="6" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
<TextBox Name="OutputField" HorizontalAlignment="Stretch" MaxHeight="140" TextWrapping="Wrap" IsReadOnly="True"/>
</ScrollViewer>
</Grid>
<!-- Add Storyboards to the visual states below as necessary for supporting the various layouts -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultLayout"/>
<VisualState x:Name="Below768Layout"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -9,21 +9,19 @@
//
//*********************************************************
using SDKTemplate;
using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Web;
namespace Microsoft.Samples.Networking.WebSocket
namespace SDKTemplate
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
@ -35,132 +33,116 @@ namespace Microsoft.Samples.Networking.WebSocket
MainPage rootPage = MainPage.Current;
private StreamWebSocket streamWebSocket;
private byte[] readBuffer;
private bool busy;
public Scenario2()
{
this.InitializeComponent();
UpdateVisualState();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
CloseSocket();
}
private async void Start_Click(object sender, RoutedEventArgs e)
private void UpdateVisualState()
{
// Have we connected yet?
if (streamWebSocket != null)
if (busy)
{
rootPage.NotifyUser("Already connected", NotifyType.StatusMessage);
return;
VisualStateManager.GoToState(this, "Busy", false);
}
else
{
bool connected = (streamWebSocket != null);
VisualStateManager.GoToState(this, connected ? "Connected" : "Disconnected", false);
}
}
private void SetBusy(bool value)
{
busy = value;
UpdateVisualState();
}
private async void OnStart()
{
SetBusy(true);
await StartAsync();
SetBusy(false);
}
private async Task StartAsync()
{
// Validating the URI is required since it was received from an untrusted source (user input).
// The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
// valid WebSocket URIs.
// Note that when enabling the text box users may provide URIs to machines on the intrAnet
// or intErnet. In these cases the app requires the "Home or Work Networking" or
// "Internet (Client)" capability respectively.
Uri server;
if (!rootPage.TryGetUri(ServerAddressField.Text, out server))
Uri server = rootPage.TryGetUri(ServerAddressField.Text);
if (server == null)
{
return;
}
streamWebSocket = new StreamWebSocket();
streamWebSocket.Closed += OnClosed;
AppendOutputLine($"Connecting to {server}...");
try
{
rootPage.NotifyUser("Connecting to: " + server, NotifyType.StatusMessage);
streamWebSocket = new StreamWebSocket();
// Dispatch close event on UI thread. This allows us to avoid synchronizing access to streamWebSocket.
streamWebSocket.Closed += async (senderSocket, args) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Closed(senderSocket, args));
};
await streamWebSocket.ConnectAsync(server);
readBuffer = new byte[1000];
// Start a background task to continuously read for incoming data
Task receiving = Task.Factory.StartNew(Scenario2ReceiveData,
streamWebSocket.InputStream.AsStreamForRead(), TaskCreationOptions.LongRunning);
// Start a background task to continuously write outgoing data
Task sending = Task.Factory.StartNew(Scenario2SendData,
streamWebSocket.OutputStream, TaskCreationOptions.LongRunning);
rootPage.NotifyUser("Connected", NotifyType.StatusMessage);
}
catch (Exception ex) // For debugging
{
if (streamWebSocket != null)
{
streamWebSocket.Dispose();
streamWebSocket = null;
}
streamWebSocket.Dispose();
streamWebSocket = null;
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
switch (status)
{
case WebErrorStatus.CannotConnect:
case WebErrorStatus.NotFound:
case WebErrorStatus.RequestTimeout:
rootPage.NotifyUser("Cannot connect to the server. Please make sure " +
"to run the server setup script before running the sample.", NotifyType.ErrorMessage);
break;
case WebErrorStatus.Unknown:
throw;
default:
rootPage.NotifyUser("Error: " + status, NotifyType.ErrorMessage);
break;
}
OutputField.Text += ex.Message + "\r\n";
AppendOutputLine(MainPage.BuildWebSocketError(ex));
AppendOutputLine(ex.Message);
return;
}
rootPage.NotifyUser("Connected", NotifyType.StatusMessage);
// Start a task to continuously read for incoming data
Task receiving = ReceiveDataAsync(streamWebSocket);
// Start a task to continuously write outgoing data
Task sending = SendDataAsync(streamWebSocket);
}
// Continuously write outgoing data. For writing data we'll show how to use data.AsBuffer() to get an
// IBuffer for use with webSocket.OutputStream.WriteAsync. Alternatively you can call
// webSocket.OutputStream.AsStreamForWrite() to use .NET streams.
private async void Scenario2SendData(object state)
// IBuffer for use with activeSocket.OutputStream.WriteAsync. Alternatively you can call
// activeSocket.OutputStream.AsStreamForWrite() to use .NET streams.
private async Task SendDataAsync(StreamWebSocket activeSocket)
{
int dataSent = 0;
int bytesSent = 0;
byte[] data = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
MarshalText(OutputField, "Background sending data in " + data.Length
+ " byte chunks each second.\r\n");
AppendOutputLine($"Background sending data in {data.Length} byte chunks each second.");
try
{
IOutputStream writeStream = (IOutputStream)state;
// Send until the socket gets closed/stopped
while (true)
{
// using System.Runtime.InteropServices.WindowsRuntime;
await writeStream.WriteAsync(data.AsBuffer());
if (streamWebSocket != activeSocket)
{
// Our socket is no longer active. Stop sending.
AppendOutputLine("Background write stopped.");
return;
}
dataSent += data.Length;
MarshalText(DataSentField, dataSent.ToString(), false);
await activeSocket.OutputStream.WriteAsync(data.AsBuffer());
bytesSent += data.Length;
DataSentField.Text = bytesSent.ToString();
// Delay so the user can watch what's going on.
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
catch (ObjectDisposedException)
{
MarshalText(OutputField, "Background write stopped.\r\n");
}
catch (Exception ex)
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
@ -168,44 +150,48 @@ namespace Microsoft.Samples.Networking.WebSocket
switch (status)
{
case WebErrorStatus.OperationCanceled:
MarshalText(OutputField, "Background write canceled.\r\n");
AppendOutputLine("Background write canceled.");
break;
case WebErrorStatus.Unknown:
throw;
default:
MarshalText(OutputField, "Error: " + status + "\r\n");
MarshalText(OutputField, ex.Message + "\r\n");
AppendOutputLine("Error: " + status);
AppendOutputLine(ex.Message);
break;
}
}
}
// Continuously read incoming data. For reading data we'll show how to use webSocket.InputStream.AsStream()
// Continuously read incoming data. For reading data we'll show how to use activeSocket.InputStream.AsStream()
// to get a .NET stream. Alternatively you could call readBuffer.AsBuffer() to use IBuffer with
// webSocket.InputStream.ReadAsync.
private async void Scenario2ReceiveData(object state)
// activeSocket.InputStream.ReadAsync.
private async Task ReceiveDataAsync(StreamWebSocket activeSocket)
{
Stream readStream = streamWebSocket.InputStream.AsStreamForRead();
int bytesReceived = 0;
try
{
Stream readStream = (Stream)state;
MarshalText(OutputField, "Background read starting.\r\n");
AppendOutputLine("Background read starting.");
while (true) // Until closed and ReadAsync fails.
byte[] readBuffer = new byte[1000];
while (true)
{
if (streamWebSocket != activeSocket)
{
// Our socket is no longer active. Stop reading.
AppendOutputLine("Background read stopped.");
return;
}
int read = await readStream.ReadAsync(readBuffer, 0, readBuffer.Length);
bytesReceived += read;
MarshalText(DataReceivedField, bytesReceived.ToString(), false);
// Do something with the data.
// This sample merely reports that the data was received.
bytesReceived += read;
DataReceivedField.Text = bytesReceived.ToString();
}
}
catch (ObjectDisposedException)
{
MarshalText(OutputField, "Background read stopped.\r\n");
}
catch (Exception ex)
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
@ -213,84 +199,61 @@ namespace Microsoft.Samples.Networking.WebSocket
switch (status)
{
case WebErrorStatus.OperationCanceled:
MarshalText(OutputField, "Background write canceled.\r\n");
AppendOutputLine("Background read canceled.");
break;
case WebErrorStatus.Unknown:
throw;
default:
MarshalText(OutputField, "Error: " + status + "\r\n");
MarshalText(OutputField, ex.Message + "\r\n");
AppendOutputLine("Error: " + status);
AppendOutputLine(ex.Message);
break;
}
}
}
private void Stop_Click(object sender, RoutedEventArgs e)
private void OnStop()
{
try
{
if (streamWebSocket != null)
{
rootPage.NotifyUser("Stopping", NotifyType.StatusMessage);
streamWebSocket.Close(1000, "Closed due to user request.");
streamWebSocket = null;
}
else
{
rootPage.NotifyUser("There is no active socket to stop.", NotifyType.StatusMessage);
}
}
catch (Exception ex)
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
if (status == WebErrorStatus.Unknown)
{
throw;
}
// Normally we'd use the status to test for specific conditions we want to handle specially,
// and only use ex.Message for display purposes. In this sample, we'll just output the
// status for debugging here, but still use ex.Message below.
rootPage.NotifyUser("Error: " + status, NotifyType.ErrorMessage);
OutputField.Text += ex.Message + "\r\n";
}
SetBusy(true);
rootPage.NotifyUser("Stopping", NotifyType.StatusMessage);
CloseSocket();
SetBusy(false);
}
// This may be triggered remotely by the server or locally by Close/Dispose()
private void Closed(IWebSocket sender, WebSocketClosedEventArgs args)
private async void OnClosed(IWebSocket sender, WebSocketClosedEventArgs args)
{
MarshalText(OutputField, "Closed; Code: " + args.Code + ", Reason: " + args.Reason + "\r\n");
// Dispatch the event to the UI thread so we do not need to synchronize access to streamWebSocket.
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
AppendOutputLine("Closed; Code: " + args.Code + ", Reason: " + args.Reason);
if (streamWebSocket == sender)
{
CloseSocket();
UpdateVisualState();
}
});
}
private void CloseSocket()
{
if (streamWebSocket != null)
{
streamWebSocket.Dispose();
try
{
streamWebSocket.Close(1000, "Closed due to user request.");
}
catch (Exception ex)
{
AppendOutputLine(MainPage.BuildWebSocketError(ex));
AppendOutputLine(ex.Message);
}
streamWebSocket = null;
}
}
private void MarshalText(TextBox output, string value)
private void AppendOutputLine(string value)
{
MarshalText(output, value, true);
}
// When operations happen on a background thread we have to marshal UI updates back to the UI thread.
private void MarshalText(TextBox output, string value, bool append)
{
var ignore = output.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (append)
{
output.Text += value;
}
else
{
output.Text = value;
}
});
OutputField.Text += value + "\r\n";
}
}
}

Просмотреть файл

@ -7,7 +7,7 @@
<ProjectGuid>{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WebSocketSample</RootNamespace>
<RootNamespace>SDKTemplate</RootNamespace>
<AssemblyName>WebSocket</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
@ -126,11 +126,13 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Scenario1_UTF8.xaml">
<Page Include="..\shared\Scenario1_UTF8.xaml">
<Link>Scenario1_UTF8.xaml</Link>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Scenario2_Binary.xaml">
<Page Include="..\shared\Scenario2_Binary.xaml">
<Link>Scenario2_Binary.xaml</Link>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>

Просмотреть файл

@ -54,13 +54,11 @@
<AppxManifest Include="package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<Content Include="css\scenario1_Download.css" />
<Content Include="css\scenario2_Upload.css" />
<Content Include="..\..\..\SharedContent\js\default.html">
<Link>default.html</Link>
</Content>
<Content Include="html\scenario1_Download.html" />
<Content Include="html\scenario2_Upload.html" />
<Content Include="html\scenario1-utf8.html" />
<Content Include="html\scenario2-binary.html" />
<Content Include="..\..\..\SharedContent\media\microsoft-sdk.png">
<Link>images\microsoft-sdk.png</Link>
</Content>
@ -85,10 +83,9 @@
<Content Include="..\..\..\SharedContent\js\css\default.css">
<Link>css\default.css</Link>
</Content>
<Content Include="js\helpers.js" />
<Content Include="js\sample-configuration.js" />
<Content Include="js\scenario1_Download.js" />
<Content Include="js\scenario2_Upload.js" />
<Content Include="js\scenario1-utf8.js" />
<Content Include="js\scenario2-binary.js" />
<Content Include="..\..\..\SharedContent\js\Microsoft.WinJS\css\ui-dark.css">
<Link>Microsoft.WinJS.4.0\css\ui-dark.css</Link>
</Content>

Просмотреть файл

Просмотреть файл

@ -1,7 +0,0 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved
*/
#serverAddress {
width: auto;
}

Просмотреть файл

@ -1,7 +0,0 @@
/*
Copyright (c) Microsoft Corporation. All rights reserved
*/
#serverAddress {
width: auto;
}

Просмотреть файл

@ -0,0 +1,54 @@
<!--
//*********************************************************
//
// 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.
//
//*********************************************************
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="/js/scenario1-utf8.js"></script>
</head>
<body class="win-type-body">
<div>
<h2 id="sampleHeader" class="win-type-subheader">Description:</h2>
<div id="scenarioDescription">UTF-8 text messages</div>
</div>
<p>
This scenario uses a MessageWebSocket to send UTF-8 strings.
The sample server supports both plaintext WebSocket (ws://) and secure WebSocket (wss://) server endpoints.
</p>
<p>
<label>Server address:
<input type="text" id="serverAddressField" value="ws://localhost/WebSocketSample/EchoWebSocket.ashx" class="win-textbox" size="60" style="width: auto">
</label>
</p>
<p>
<button id="connectButton" class="win-button">Connect</button>
<button id="disconnectButton" class="win-button">Disconnect</button>
</p>
<p>
<label>
Enter text to send to the server:
<input type="text" id="inputField" value="Hello World" class="win-textbox">
</label>
</p>
<p>
<button id="sendButton" class="win-button">Send</button>
</p>
<p id="outputField">
</p>
</body>
</html>

Просмотреть файл

@ -1,46 +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.
//
//*********************************************************
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link rel="stylesheet" href="/css/scenario1_Download.css">
<script src="/js/helpers.js"></script>
<script src="/js/scenario1_Download.js"></script>
</head>
<body class="win-type-body">
<div data-win-control="SdkSample.ScenarioInput">
<p>This shows how to use a MessageWebSocket to send UTF-8 strings.</p>
<p>
<label for="serverAddress">Server address: </label>
<input type="text" id="serverAddress" value="ws://localhost/WebSocketSample/EchoWebSocket.ashx" size="60" class="win-textbox">
</p>
<p>
<label for="inputField">Enter text to send to the server: </label>
<input type="text" id="inputField" value="Hello World" class="win-textbox">
</p>
<p>
<button id="startButton" class="win-button">Start</button>
<button id="closeButton" class="win-button">Close</button>
</p>
</div>
<div data-win-control="SdkSample.ScenarioOutput">
<div id="outputField">
</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,47 @@
<!--
//*********************************************************
//
// 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.
//
//*********************************************************
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="/js/scenario2-binary.js"></script>
</head>
<body class="win-type-body">
<div>
<h2 id="sampleHeader" class="win-type-subheader">Description:</h2>
<div id="scenarioDescription">Binary data stream</div>
</div>
<p>This shows how to use a StreamWebSocket to send and receive binary data.</p>
<p>
<label>
Server address:
<input type="text" id="serverAddressField" value="ws://localhost/WebSocketSample/EchoWebSocket.ashx" class="win-textbox" size="60" style="width: auto">
</label>
</p>
<p>
<button id="startButton" class="win-button">Start</button>
<button id="stopButton" class="win-button">Stop</button>
</p>
<div>
<p>Data Sent: <span id="dataSent"></span></p>
<p>Data Received: <span id="dataReceived"></span></p>
<p id="outputField">
</p>
</div>
</body>
</html>

Просмотреть файл

@ -1,50 +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.
//
//*********************************************************
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link rel="stylesheet" href="/css/scenario2_Upload.css">
<script src="/js/helpers.js"></script>
<script src="/js/scenario2_Upload.js"></script>
</head>
<body class="win-type-body">
<div data-win-control="SdkSample.ScenarioInput">
<p>This shows how to use a StreamWebSocket to send and receive binary data.</p>
<p>
<label for="serverAddress">Server address: </label>
<input type="text" id="serverAddress" value="ws://localhost/WebSocketSample/EchoWebSocket.ashx" size="60" class="win-textbox">
</p>
<p>
<button id="startButton" class="win-button">Start</button>
<button id="closeButton" class="win-button">Close</button>
</p>
</div>
<div data-win-control="SdkSample.ScenarioOutput">
<p>
<label for="dataSent">Data Sent:</label>
<input type="text" id="dataSent" class="win-textbox">
</p>
<p>
<label for="dataReceived">Data Received:</label>
<input type="text" id="dataReceived" class="win-textbox">
</p>
<div id="outputField">
</div>
</div>
</body>
</html>

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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
});
})();

Просмотреть файл

@ -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;
}
})();

Просмотреть файл

@ -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 + "<br>";
}
}
})();

Просмотреть файл

@ -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;
}
})();

Просмотреть файл

@ -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 + "<br>";
}
}
})();

Просмотреть файл

@ -0,0 +1,72 @@
<!--
//*********************************************************
//
// 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.
//
//*********************************************************
-->
<Page
x:Class="SDKTemplate.Scenario1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="12,10,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap" Text="UTF-8 text messages"/>
<TextBlock TextWrapping="Wrap" Margin="0,10,0,0">
This scenario uses a MessageWebSocket to send UTF-8 strings.
The sample server supports both plaintext WebSocket (ws://) and secure WebSocket (wss://) server endpoints.
</TextBlock>
<TextBlock Text="Server Address:" Margin="0,10,0,0"/>
<TextBox x:Name="ServerAddressField" InputScope="Url" Text="ws://localhost/WebSocketSample/EchoWebSocket.ashx" Margin="0,10,0,0"/>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<Button x:Name="ConnectButton" Content="Connect" Margin="0,0,10,0" Click="{x:Bind OnConnect}"/>
<Button x:Name="DisconnectButton" Content="Disconnect" Margin="0,0,10,0" Click="{x:Bind OnDisconnect}"/>
</StackPanel>
<TextBlock TextWrapping="Wrap" Margin="0,10,0,0">Enter text to send to the server.</TextBlock>
<TextBox x:Name="InputField" Text="Hello World" Margin="0,10,0,0"/>
<Button x:Name="SendButton" Content="Send" Margin="0,10,0,0" Click="{x:Bind OnSend}"/>
</StackPanel>
<ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" Margin="0,10,0,0">
<TextBox x:Name="OutputField" TextWrapping="Wrap" IsReadOnly="True"/>
</ScrollViewer>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Disconnected">
<VisualState.Setters>
<Setter Target="DisconnectButton.IsEnabled" Value="False"/>
<Setter Target="InputField.IsEnabled" Value="False"/>
<Setter Target="SendButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Connected">
<VisualState.Setters>
<Setter Target="ServerAddressField.IsEnabled" Value="False"/>
<Setter Target="ConnectButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Busy">
<VisualState.Setters>
<Setter Target="ServerAddressField.IsEnabled" Value="False"/>
<Setter Target="ConnectButton.IsEnabled" Value="False"/>
<Setter Target="DisconnectButton.IsEnabled" Value="False"/>
<Setter Target="InputField.IsEnabled" Value="False"/>
<Setter Target="SendButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,65 @@
<!--
//*********************************************************
//
// 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.
//
//*********************************************************
-->
<Page
x:Class="SDKTemplate.Scenario2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="12,10,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBlock Text="Description:" Style="{StaticResource SampleHeaderTextStyle}"/>
<TextBlock Style="{StaticResource ScenarioDescriptionTextStyle}" TextWrapping="Wrap" Text="Binary data stream"/>
<TextBlock TextWrapping="Wrap" Margin="0,10,0,0">
This scenario shows how to use a StreamWebSocket to send binary data.
The sample server supports both plaintext WebSocket (ws://) and secure WebSocket (wss://) server endpoints.
</TextBlock>
<TextBlock Text="Server Address:" Margin="0,10,0,0"/>
<TextBox x:Name="ServerAddressField" InputScope="Url" Text="ws://localhost/WebSocketSample/EchoWebSocket.ashx" Margin="0,10,0,0"/>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<Button x:Name="StartButton" Content="Start" Margin="0,0,10,0" Click="{x:Bind OnStart}"/>
<Button x:Name="StopButton" Content="Stop" Margin="0,0,10,0" Click="{x:Bind OnStop}"/>
</StackPanel>
<TextBlock Margin="0,10,0,0">Bytes sent: <Run x:Name="DataSentField"/></TextBlock>
<TextBlock Margin="0,10,0,0">Bytes received: <Run x:Name="DataReceivedField"/></TextBlock>
</StackPanel>
<ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" Margin="0,10,0,0">
<TextBox Name="OutputField" HorizontalAlignment="Stretch" TextWrapping="Wrap" IsReadOnly="True"/>
</ScrollViewer>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Disconnected">
<VisualState.Setters>
<Setter Target="StopButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Connected">
<VisualState.Setters>
<Setter Target="StartButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Busy">
<VisualState.Setters>
<Setter Target="StartButton.IsEnabled" Value="False"/>
<Setter Target="StopButton.IsEnabled" Value="False"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>