UWP BarcodeScanner预览:CaptureElement不显示任何预览

时间:2019-07-31 12:20:11

标签: c# uwp barcode-scanner pointofservice

我的CaptureElements显示奇怪的行为。当我将实例化的MediaCapture设置为CaptureElements源,然后调用MediaCapture.StartPreviewAsync()时,CaptureElement不显示任何内容。

我在LoginPage上有一个带有功能性BarcodeScanner的应用程序(主应用程序)。 ->有效!

然后我想将相同的代码进行少量修改就复制到SettingsPage,以便在连接多个摄像机的情况下可以设置默认摄像机。 ->不起作用

然后,我尝试在远程调试器的帮助下,在与我的计算机具有相同Windows 10版本的其他Windows平板电脑上运行main-app(请记住,登录屏幕上的BarcodeScanner在我的计算机上可以运行)。 ->不起作用

由于这些失败,我将正在运行的代码从主应用程序LoginPage复制到了一个全新的解决方案(称为test-app),其设置与原始解决方案相同。我什至尝试引用相同的Dll,实现相同的设计模式等。 ->不起作用

我的机器: 赢10 Pro 1809版 内部版本17763.652

DevEnv: MS Visual Studio 2019专业版 版本16.1.6

  

编辑:作为最低要求的Windows版本,我选择了Build 16229和   我的目标版本是Build 17763(我的系统Win版本)

     

“寡妇设置”中的“允许应用程序访问您的相机”选项已打开,因此所有应用程序都可以访问相机。

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>

CodeBehind

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

                }
            }
        }

ViewModel:

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个工作日。上面的代码是从test-app复制而来的,但它与主应用程序LoginPage上的代码基本相同(“ if (Like_MP_PAT_UWP){...}”。

每个提示都是欢迎的。

谢谢。

2 个答案:

答案 0 :(得分:2)

问题是卡巴斯基网络安全专家(Kaspersky Endpoint Security)的“高级威胁防护/主机入侵防御”设置。它阻止了开发硬盘驱动器(即平板电脑上或网络驱动器上)以外的所有应用访问摄像机(Dev-Drive =“受信任区域”)。

有必要在整个环境中重新配置Kaspersky Endpoint Security中的功能(将必要的位置/客户端声明为受信任的区域)。

希望,这可能会帮助遇到类似问题的人,或者至少给某人一些提示。

答案 1 :(得分:1)

这里只是吐口水,但我建议尝试将测试减少为尽可能控制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 StackOverflowQrTest
{
    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="StackOverflowQrTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:StackOverflowQrTest"
    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>