UWP BarcodeScanner 预览:CaptureElement 不显示任何预览
UWP BarcodeScanner Preview: CaptureElement doesn't show any Preview
我的 CaptureElements 表现出奇怪的行为。当我将实例化的 MediaCapture 设置为 CaptureElements 源然后调用 MediaCapture.StartPreviewAsync() 时,CaptureElement 不显示任何内容。
我有一个应用程序(主应用程序)在登录页面上有一个功能齐全的 BarcodeScanner。
-> 有效!
然后我想将相同的代码复制到 SettingsPage 并稍作修改,以便在连接多个摄像头的情况下,可以设置默认的。
-> 不起作用
然后我尝试在远程调试器的帮助下 运行 主应用程序在其他 windows 平板电脑上 Windows 10 版本与我的机器相同(记住,登录屏幕上的 BarcodeScanner 在我的机器上工作)。
-> 不起作用
由于这些失败,我将 运行ning 代码从主应用程序登录页面复制到一个全新的解决方案(我们称之为测试应用程序),其设置与原始解决方案相同。我什至尝试引用相同的 Dll,实现相同的设计模式等。
-> 不起作用
我的机器:
赢 10 专业版
版本 1809
内部版本 17763.652
开发环境:
女士 Visual Studio 2019 专业版
版本。 16.1.6
EDIT: As minimum required Windows Version I selected Build 16229 and
my target Version is Build 17763 (my systems Win version)
The "Allow apps to access your camera"-Option in the Widows Settings is switched to ON, so all apps are allowed to access the camera.
Xaml
<Page
x:Class="QrCodeTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:QrCodeTest"
xmlns:vm="using:QrCodeTest.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.DataContext>
<vm:TestViewModel x:Name="ViewModel" />
</Page.DataContext>
<ScrollViewer>
<StackPanel>
<Button Content="Start Preview" HorizontalAlignment="Center" Click="Button_Click" Margin="5" />
<CaptureElement x:Name="capturePreview" HorizontalAlignment="Center" Stretch="Uniform" Width="0" Height="0" Margin="10" />
<Button Content="Stop Preview" HorizontalAlignment="Center" Click="Button_Click_1" Margin="5" />
<TextBlock Text="{Binding Etikett, Mode=TwoWay}" HorizontalAlignment="Center" Margin="5" />
</StackPanel>
</ScrollViewer>
</Page>
代码隐藏
private BarcodeScanner scanner { get; set; }
private ClaimedBarcodeScanner claimedScanner { get; set; }
private MediaCapture captureManager { get; set; }
internal async Task StartScannerAsync () {
capturePreview.Visibility = Visibility.Visible;
capturePreview.Width = 400; capturePreview.Height = 300;
scanner = null;
scanner = await DeviceHelpers.GetFirstDeviceAsync(BarcodeScanner.GetDeviceSelector(connectionTypes), async (id) => await BarcodeScanner.FromIdAsync(id));
if (scanner != null) {
captureManager = new MediaCapture();
claimedScanner = await scanner.ClaimScannerAsync();
if (claimedScanner != null) {
claimedScanner.ReleaseDeviceRequested += claimedScanner_ReleaseDeviceRequested;
claimedScanner.DataReceived += claimedScanner_DataReceived;
claimedScanner.IsDecodeDataEnabled = true;
IReadOnlyList<uint> supportedSymbologies = await scanner.GetSupportedSymbologiesAsync();
foreach (uint symbology in supportedSymbologies) {
listOfSymbologies.Add(new SymbologyListEntry(symbology));
}
await claimedScanner.EnableAsync();
MediaCaptureInitializationSettings _captureInitSettings = new MediaCaptureInitializationSettings {
VideoDeviceId = scanner.VideoDeviceId,
StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo,
PhotoCaptureSource = PhotoCaptureSource.VideoPreview
};
await captureManager.InitializeAsync(_captureInitSettings);
capturePreview.Source = captureManager;
try {
// Change to false, in case you wanna compare different methods of doing the same
bool Like_MP_PAT_UWP = false;
if (Like_MP_PAT_UWP) {
await capturePreview.Source.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
} else {
LocalDataContext.Etikett = "await captureManager.StartPreviewAsync();";
await captureManager.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
await captureManager.StopPreviewAsync();
LocalDataContext.Etikett = "await capturePreview.Source.StartPreviewAsync();";
await capturePreview.Source.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
await capturePreview.Source.StopPreviewAsync();
LocalDataContext.Etikett = "await claimedScanner.ShowVideoPreviewAsync();";
await claimedScanner.ShowVideoPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
claimedScanner.HideVideoPreview();
}
} catch (Exception e) {
Exception x = e; displayRequest.RequestRelease();
} finally {
LocalDataContext.Etikett = string.Empty;
}
}
}
}
视图模型:
public class TestViewModel: INotifyPropertyChanged {
public static TestViewModel Instance { get; set; }
private string _Etikett;
public string Etikett { get { return _Etikett; } set { _Etikett = value; NotifyPropertyChanged(); } }
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged ([CallerMemberName] String propertyName = "") {
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
if (PropertyChanged != null) {
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我已经浪费了 4 个工作日来比较解决方案、代码等。上面的代码是从测试应用程序复制的,但它与主应用程序登录页面上的代码基本相同(除了"if (Like_MP_PAT_UWP) {...}".
欢迎任何提示。
提前致谢。
只是在这里吐口水,但我建议您尝试将测试减少到尽可能多地控制 MediaCapture 对象的代码,因为这似乎是您描述主要问题的症状。
之后,尝试将相机的 SharingMode 降低为只读,以防其他应用正在使用具有独占访问权限的相机。此外,您可以将弹出式同意检查减少到仅摄像头,而不是麦克风同意。有时,如果您在同意弹出窗口中不小心不同意,该应用将被拒绝访问相机,直到您从系统设置(设置 -> 隐私 -> 相机)再次允许它。
以下是您上述内容的次优简化版本,但包含所有部分。我试图将开始条形码会话与处理事物分开。使用 MS 样品作为指导将比这个更可靠。尽管如此,还有更多的跟踪点要添加,但下面有一些跟踪 MediaCapture 失败的地方,以及条码扫描器启用部分中的其他点。希望对你有帮助。
using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.PointOfService;
using System.Threading.Tasks;
using Windows.Media.Capture;
using Windows.Devices.Enumeration;
using System.Diagnostics;
using Windows.Storage.Streams;
namespace WhosebugQrTest
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (claimedScanner == null)
{
await StartScannerAsync();
}
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
await StopScannerAsync();
}
private BarcodeScanner scanner { get; set; }
private ClaimedBarcodeScanner claimedScanner { get; set; }
private MediaCapture captureManager { get; set; }
internal async Task StartScannerAsync()
{
capturePreview.Visibility = Visibility.Visible;
capturePreview.Width = 400; capturePreview.Height = 300;
scanner = await DeviceHelpers.GetFirstDeviceAsync(BarcodeScanner.GetDeviceSelector(), async (id) => await BarcodeScanner.FromIdAsync(id));
if (scanner != null)
{
claimedScanner = await scanner.ClaimScannerAsync();
if (claimedScanner != null)
{
claimedScanner.ReleaseDeviceRequested += ClaimedScanner_ReleaseDeviceRequested;
claimedScanner.DataReceived += ClaimedScanner_DataReceived;
claimedScanner.IsDecodeDataEnabled = true;
await claimedScanner.EnableAsync();
try
{
bool haveAssociatedCamera = !string.IsNullOrEmpty(scanner.VideoDeviceId);
if (haveAssociatedCamera)
{
captureManager = new MediaCapture();
captureManager.Failed += CaptureManager_Failed;
MediaCaptureInitializationSettings _captureInitSettings = new MediaCaptureInitializationSettings
{
VideoDeviceId = scanner.VideoDeviceId,
SharingMode = MediaCaptureSharingMode.SharedReadOnly, // share
StreamingCaptureMode = StreamingCaptureMode.Video // just video
};
await captureManager.InitializeAsync(_captureInitSettings);
capturePreview.Source = captureManager;
}
UpdateMessage("waiting..." + (!haveAssociatedCamera ? "But scanner not camera type" : ""));
if (captureManager != null) await captureManager.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
}
catch (Exception e)
{
UpdateMessage(e.Message);
Debug.WriteLine("EXCEPTION: " + e.Message);
}
}
else
{
UpdateMessage("Could not claim barcode scanner");
}
}
else
{
UpdateMessage("No barcode scanners found");
}
}
private void CaptureManager_Failed(MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs)
{
string msg = string.Format("MediaCapture_Failed: (0x{0:X}) {1}", errorEventArgs.Code, errorEventArgs.Message);
UpdateMessage(msg);
}
internal async Task StopScannerAsync()
{
if (captureManager != null)
{
if (captureManager.CameraStreamState == Windows.Media.Devices.CameraStreamState.Streaming)
{
await captureManager.StopPreviewAsync();
}
captureManager.Dispose();
captureManager = null;
}
if (claimedScanner != null)
{
claimedScanner.Dispose();
claimedScanner = null;
}
if (scanner != null)
{
scanner.Dispose();
scanner = null;
}
}
private void ClaimedScanner_DataReceived(ClaimedBarcodeScanner sender, BarcodeScannerDataReceivedEventArgs args)
{
var scanDataLabelReader = DataReader.FromBuffer(args.Report.ScanDataLabel);
string barcode = scanDataLabelReader.ReadString(args.Report.ScanDataLabel.Length);
UpdateMessage(barcode);
}
private void ClaimedScanner_ReleaseDeviceRequested(object sender, ClaimedBarcodeScanner e)
{
UpdateMessage("Another process is requesting barcode scanner device.");
e.RetainDevice();
}
private async void UpdateMessage (string message)
{
await LastBarcodeRead.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LastBarcodeRead.Text = message;
});
}
}
public partial class DeviceHelpers
{
// We use a DeviceWatcher instead of DeviceInformation.FindAllAsync because
// the DeviceWatcher will let us see the devices as they are discovered,
// whereas FindAllAsync returns results only after discovery is complete.
public static async Task<T> GetFirstDeviceAsync<T>(string selector, Func<string, Task<T>> convertAsync)
where T : class
{
var completionSource = new TaskCompletionSource<T>();
var pendingTasks = new List<Task>();
DeviceWatcher watcher = DeviceInformation.CreateWatcher(selector);
watcher.Added += (DeviceWatcher sender, DeviceInformation device) =>
{
Func<string, Task> lambda = async (id) =>
{
T t = await convertAsync(id);
if (t != null)
{
completionSource.TrySetResult(t);
}
};
pendingTasks.Add(lambda(device.Id));
};
watcher.EnumerationCompleted += async (DeviceWatcher sender, object args) =>
{
// Wait for completion of all the tasks we created in our "Added" event handler.
await Task.WhenAll(pendingTasks);
// This sets the result to "null" if no task was able to produce a device.
completionSource.TrySetResult(null);
};
watcher.Start();
// Wait for enumeration to complete or for a device to be found.
T result = await completionSource.Task;
watcher.Stop();
return result;
}
}
}
其中主要 xaml 是...
<Page
x:Class="WhosebugQrTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WhosebugQrTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer>
<StackPanel>
<Button Content="Start Preview" HorizontalAlignment="Center" Click="Button_Click" Margin="5" />
<CaptureElement x:Name="capturePreview" HorizontalAlignment="Center" Stretch="Uniform" Width="0" Height="0" Margin="10" />
<Button Content="Stop Preview" HorizontalAlignment="Center" Click="Button_Click_1" Margin="5" />
<TextBox Header="LastBarcode" Name="LastBarcodeRead" IsReadOnly="True" HorizontalAlignment="Center" Margin="5" />
</StackPanel>
</ScrollViewer>
</Page>
问题出在 Kaspersky Endpoint Security 的 "advanced Threat Protection/host intrusion prevention" 设置上。它阻止了我们的开发硬盘驱动器(即我们的平板电脑或我们的网络驱动器)之外的所有应用程序访问相机(Dev-Drive = "Trusted Zone")。
有必要在 Kaspersky Endpoint Security 中为整个环境重新配置该功能(声明必要 locations/clients 作为受信任的区域)。
希望这可以帮助遇到类似问题的人,或者至少给某人一些提示。
我的 CaptureElements 表现出奇怪的行为。当我将实例化的 MediaCapture 设置为 CaptureElements 源然后调用 MediaCapture.StartPreviewAsync() 时,CaptureElement 不显示任何内容。
我有一个应用程序(主应用程序)在登录页面上有一个功能齐全的 BarcodeScanner。 -> 有效!
然后我想将相同的代码复制到 SettingsPage 并稍作修改,以便在连接多个摄像头的情况下,可以设置默认的。 -> 不起作用
然后我尝试在远程调试器的帮助下 运行 主应用程序在其他 windows 平板电脑上 Windows 10 版本与我的机器相同(记住,登录屏幕上的 BarcodeScanner 在我的机器上工作)。 -> 不起作用
由于这些失败,我将 运行ning 代码从主应用程序登录页面复制到一个全新的解决方案(我们称之为测试应用程序),其设置与原始解决方案相同。我什至尝试引用相同的 Dll,实现相同的设计模式等。 -> 不起作用
我的机器: 赢 10 专业版 版本 1809 内部版本 17763.652
开发环境: 女士 Visual Studio 2019 专业版 版本。 16.1.6
EDIT: As minimum required Windows Version I selected Build 16229 and my target Version is Build 17763 (my systems Win version)
The "Allow apps to access your camera"-Option in the Widows Settings is switched to ON, so all apps are allowed to access the camera.
Xaml
<Page
x:Class="QrCodeTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:QrCodeTest"
xmlns:vm="using:QrCodeTest.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.DataContext>
<vm:TestViewModel x:Name="ViewModel" />
</Page.DataContext>
<ScrollViewer>
<StackPanel>
<Button Content="Start Preview" HorizontalAlignment="Center" Click="Button_Click" Margin="5" />
<CaptureElement x:Name="capturePreview" HorizontalAlignment="Center" Stretch="Uniform" Width="0" Height="0" Margin="10" />
<Button Content="Stop Preview" HorizontalAlignment="Center" Click="Button_Click_1" Margin="5" />
<TextBlock Text="{Binding Etikett, Mode=TwoWay}" HorizontalAlignment="Center" Margin="5" />
</StackPanel>
</ScrollViewer>
</Page>
代码隐藏
private BarcodeScanner scanner { get; set; }
private ClaimedBarcodeScanner claimedScanner { get; set; }
private MediaCapture captureManager { get; set; }
internal async Task StartScannerAsync () {
capturePreview.Visibility = Visibility.Visible;
capturePreview.Width = 400; capturePreview.Height = 300;
scanner = null;
scanner = await DeviceHelpers.GetFirstDeviceAsync(BarcodeScanner.GetDeviceSelector(connectionTypes), async (id) => await BarcodeScanner.FromIdAsync(id));
if (scanner != null) {
captureManager = new MediaCapture();
claimedScanner = await scanner.ClaimScannerAsync();
if (claimedScanner != null) {
claimedScanner.ReleaseDeviceRequested += claimedScanner_ReleaseDeviceRequested;
claimedScanner.DataReceived += claimedScanner_DataReceived;
claimedScanner.IsDecodeDataEnabled = true;
IReadOnlyList<uint> supportedSymbologies = await scanner.GetSupportedSymbologiesAsync();
foreach (uint symbology in supportedSymbologies) {
listOfSymbologies.Add(new SymbologyListEntry(symbology));
}
await claimedScanner.EnableAsync();
MediaCaptureInitializationSettings _captureInitSettings = new MediaCaptureInitializationSettings {
VideoDeviceId = scanner.VideoDeviceId,
StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo,
PhotoCaptureSource = PhotoCaptureSource.VideoPreview
};
await captureManager.InitializeAsync(_captureInitSettings);
capturePreview.Source = captureManager;
try {
// Change to false, in case you wanna compare different methods of doing the same
bool Like_MP_PAT_UWP = false;
if (Like_MP_PAT_UWP) {
await capturePreview.Source.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
} else {
LocalDataContext.Etikett = "await captureManager.StartPreviewAsync();";
await captureManager.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
await captureManager.StopPreviewAsync();
LocalDataContext.Etikett = "await capturePreview.Source.StartPreviewAsync();";
await capturePreview.Source.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
await capturePreview.Source.StopPreviewAsync();
LocalDataContext.Etikett = "await claimedScanner.ShowVideoPreviewAsync();";
await claimedScanner.ShowVideoPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
Thread.Sleep(2000);
await claimedScanner.StopSoftwareTriggerAsync();
claimedScanner.HideVideoPreview();
}
} catch (Exception e) {
Exception x = e; displayRequest.RequestRelease();
} finally {
LocalDataContext.Etikett = string.Empty;
}
}
}
}
视图模型:
public class TestViewModel: INotifyPropertyChanged {
public static TestViewModel Instance { get; set; }
private string _Etikett;
public string Etikett { get { return _Etikett; } set { _Etikett = value; NotifyPropertyChanged(); } }
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged ([CallerMemberName] String propertyName = "") {
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
if (PropertyChanged != null) {
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我已经浪费了 4 个工作日来比较解决方案、代码等。上面的代码是从测试应用程序复制的,但它与主应用程序登录页面上的代码基本相同(除了"if (Like_MP_PAT_UWP) {...}".
欢迎任何提示。
提前致谢。
只是在这里吐口水,但我建议您尝试将测试减少到尽可能多地控制 MediaCapture 对象的代码,因为这似乎是您描述主要问题的症状。
之后,尝试将相机的 SharingMode 降低为只读,以防其他应用正在使用具有独占访问权限的相机。此外,您可以将弹出式同意检查减少到仅摄像头,而不是麦克风同意。有时,如果您在同意弹出窗口中不小心不同意,该应用将被拒绝访问相机,直到您从系统设置(设置 -> 隐私 -> 相机)再次允许它。
以下是您上述内容的次优简化版本,但包含所有部分。我试图将开始条形码会话与处理事物分开。使用 MS 样品作为指导将比这个更可靠。尽管如此,还有更多的跟踪点要添加,但下面有一些跟踪 MediaCapture 失败的地方,以及条码扫描器启用部分中的其他点。希望对你有帮助。
using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.PointOfService;
using System.Threading.Tasks;
using Windows.Media.Capture;
using Windows.Devices.Enumeration;
using System.Diagnostics;
using Windows.Storage.Streams;
namespace WhosebugQrTest
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (claimedScanner == null)
{
await StartScannerAsync();
}
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
await StopScannerAsync();
}
private BarcodeScanner scanner { get; set; }
private ClaimedBarcodeScanner claimedScanner { get; set; }
private MediaCapture captureManager { get; set; }
internal async Task StartScannerAsync()
{
capturePreview.Visibility = Visibility.Visible;
capturePreview.Width = 400; capturePreview.Height = 300;
scanner = await DeviceHelpers.GetFirstDeviceAsync(BarcodeScanner.GetDeviceSelector(), async (id) => await BarcodeScanner.FromIdAsync(id));
if (scanner != null)
{
claimedScanner = await scanner.ClaimScannerAsync();
if (claimedScanner != null)
{
claimedScanner.ReleaseDeviceRequested += ClaimedScanner_ReleaseDeviceRequested;
claimedScanner.DataReceived += ClaimedScanner_DataReceived;
claimedScanner.IsDecodeDataEnabled = true;
await claimedScanner.EnableAsync();
try
{
bool haveAssociatedCamera = !string.IsNullOrEmpty(scanner.VideoDeviceId);
if (haveAssociatedCamera)
{
captureManager = new MediaCapture();
captureManager.Failed += CaptureManager_Failed;
MediaCaptureInitializationSettings _captureInitSettings = new MediaCaptureInitializationSettings
{
VideoDeviceId = scanner.VideoDeviceId,
SharingMode = MediaCaptureSharingMode.SharedReadOnly, // share
StreamingCaptureMode = StreamingCaptureMode.Video // just video
};
await captureManager.InitializeAsync(_captureInitSettings);
capturePreview.Source = captureManager;
}
UpdateMessage("waiting..." + (!haveAssociatedCamera ? "But scanner not camera type" : ""));
if (captureManager != null) await captureManager.StartPreviewAsync();
await claimedScanner.StartSoftwareTriggerAsync();
}
catch (Exception e)
{
UpdateMessage(e.Message);
Debug.WriteLine("EXCEPTION: " + e.Message);
}
}
else
{
UpdateMessage("Could not claim barcode scanner");
}
}
else
{
UpdateMessage("No barcode scanners found");
}
}
private void CaptureManager_Failed(MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs)
{
string msg = string.Format("MediaCapture_Failed: (0x{0:X}) {1}", errorEventArgs.Code, errorEventArgs.Message);
UpdateMessage(msg);
}
internal async Task StopScannerAsync()
{
if (captureManager != null)
{
if (captureManager.CameraStreamState == Windows.Media.Devices.CameraStreamState.Streaming)
{
await captureManager.StopPreviewAsync();
}
captureManager.Dispose();
captureManager = null;
}
if (claimedScanner != null)
{
claimedScanner.Dispose();
claimedScanner = null;
}
if (scanner != null)
{
scanner.Dispose();
scanner = null;
}
}
private void ClaimedScanner_DataReceived(ClaimedBarcodeScanner sender, BarcodeScannerDataReceivedEventArgs args)
{
var scanDataLabelReader = DataReader.FromBuffer(args.Report.ScanDataLabel);
string barcode = scanDataLabelReader.ReadString(args.Report.ScanDataLabel.Length);
UpdateMessage(barcode);
}
private void ClaimedScanner_ReleaseDeviceRequested(object sender, ClaimedBarcodeScanner e)
{
UpdateMessage("Another process is requesting barcode scanner device.");
e.RetainDevice();
}
private async void UpdateMessage (string message)
{
await LastBarcodeRead.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
LastBarcodeRead.Text = message;
});
}
}
public partial class DeviceHelpers
{
// We use a DeviceWatcher instead of DeviceInformation.FindAllAsync because
// the DeviceWatcher will let us see the devices as they are discovered,
// whereas FindAllAsync returns results only after discovery is complete.
public static async Task<T> GetFirstDeviceAsync<T>(string selector, Func<string, Task<T>> convertAsync)
where T : class
{
var completionSource = new TaskCompletionSource<T>();
var pendingTasks = new List<Task>();
DeviceWatcher watcher = DeviceInformation.CreateWatcher(selector);
watcher.Added += (DeviceWatcher sender, DeviceInformation device) =>
{
Func<string, Task> lambda = async (id) =>
{
T t = await convertAsync(id);
if (t != null)
{
completionSource.TrySetResult(t);
}
};
pendingTasks.Add(lambda(device.Id));
};
watcher.EnumerationCompleted += async (DeviceWatcher sender, object args) =>
{
// Wait for completion of all the tasks we created in our "Added" event handler.
await Task.WhenAll(pendingTasks);
// This sets the result to "null" if no task was able to produce a device.
completionSource.TrySetResult(null);
};
watcher.Start();
// Wait for enumeration to complete or for a device to be found.
T result = await completionSource.Task;
watcher.Stop();
return result;
}
}
}
其中主要 xaml 是...
<Page
x:Class="WhosebugQrTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WhosebugQrTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer>
<StackPanel>
<Button Content="Start Preview" HorizontalAlignment="Center" Click="Button_Click" Margin="5" />
<CaptureElement x:Name="capturePreview" HorizontalAlignment="Center" Stretch="Uniform" Width="0" Height="0" Margin="10" />
<Button Content="Stop Preview" HorizontalAlignment="Center" Click="Button_Click_1" Margin="5" />
<TextBox Header="LastBarcode" Name="LastBarcodeRead" IsReadOnly="True" HorizontalAlignment="Center" Margin="5" />
</StackPanel>
</ScrollViewer>
</Page>
问题出在 Kaspersky Endpoint Security 的 "advanced Threat Protection/host intrusion prevention" 设置上。它阻止了我们的开发硬盘驱动器(即我们的平板电脑或我们的网络驱动器)之外的所有应用程序访问相机(Dev-Drive = "Trusted Zone")。
有必要在 Kaspersky Endpoint Security 中为整个环境重新配置该功能(声明必要 locations/clients 作为受信任的区域)。
希望这可以帮助遇到类似问题的人,或者至少给某人一些提示。