【问题标题】:UWP BarcodeScanner Preview: CaptureElement doesn't show any PreviewUWP BarcodeScanner 预览:CaptureElement 不显示任何预览
【发布时间】:2019-12-08 23:08:59
【问题描述】:

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

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

然后我想将相同的代码复制到 SettingsPage 并稍作修改,以便在连接多个摄像头的情况下,可以设置默认的一个。 -> 不工作

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

由于这些故障,我将运行代码从 main-apps LoginPage 复制到了一个全新的解决方案(我们称之为 test-app),其设置与原始解决方案相同。我什至尝试引用相同的 Dll,实现相同的设计模式等。 -> 不工作

我的机器: 赢 10 专业版 版本 1809 构建 17763.652

开发环境: 微软视觉工作室 2019 专业版 版本。 16.1.6

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

Widows 设置中的“允许应用访问您的相机”-选项被切换为开启,因此所有应用都可以访问相机。

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 个工作日来比较解决方案、代码等。上面的代码是从测试应用程序复制的,但它与主应用程序 LoginPage 上的代码基本相同(除了“如果(Like_MP_PAT_UWP) {...}"。

欢迎任何提示。

提前谢谢你。

【问题讨论】:

  • 您好,您是否开启了Package.appxmanifest 中的Pointer of Services 权限?
  • 你好,是的。 PointOfService 以及网络摄像头。在测试应用程序中,我授予了 appxmanifest 中的所有可用权限。我什至尝试了几个代码签名证书。没有任何帮助。附加信息:作为最低要求的 Windows 版本,我选择了 Build 16229,我的目标 Build 是 17763(我的系统 Win 版本)
  • 你在程序运行的时候加了断点吗?由于您的代码缺少关键功能GetFisrtDeviceAsync,因此我无法判断问题是否存在。可以尝试单步执行程序,看是否能顺利运行到captureManager.StartPreviewAsync()
  • 是的,我已经设置了数千个调试点。我在 CodeBehind 中调用 GetFirstDeviceAsync()。请查看第二个代码块。你会看到:scanner = await DeviceHelpers.GetFirstDeviceAsync(
  • 我明白了。我在微软提供的example中找到了类似的方法,不知道你是不是这样实现的。

标签: c# uwp barcode-scanner pointofservice


【解决方案1】:

问题在于 Kaspersky Endpoint Security 的“高级威胁防护/主机入侵防护”设置。它阻止了我们的开发硬盘驱动器(即我们的平板电脑或我们的网络驱动器)之外的所有应用程序访问相机(Dev-Drive = “Trusted Zone”)。

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

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

【讨论】:

    【解决方案2】:

    只是在这里吐口水,但我建议尝试将您的测试减少为尽可能控制 MediaCapture 对象的代码,因为这似乎是您描述主要问题的症状。

    之后,尝试将相机的共享模式降低为只读,以防其他应用程序正在使用具有独占访问权限的相机。此外,您可以将弹出同意检查减少到仅相机,而不是麦克风同意。有时,如果您在同意弹出窗口中不小心不同意,应用程序将被拒绝访问相机,直到您从系统设置(设置 -> 隐私 -> 相机)再次允许它。

    以下是您上述内容的次优和精简版本,但包括所有部分。我试图将您开始条形码会话与处理物品分开。使用 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;
            }
        }
    }
    
    

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

    【讨论】:

    • 感谢汤姆的回复和您花费的时间。我假设您的代码正在您的机器上运行?不幸的是不在我的(主应用程序 LoginPages Scanner 运行的地方)。是的,我的代码很乱。我也从 Microsoft 样本开始,但这是数千次实验的结果。顺便说一句:除了我调用 ClaimedBarcodeScanners StartPreviewAsync-Method(弹出窗口)之外,Microsoft 示例没有为我显示任何预览。如果您有兴趣并想交叉检查我的 sln:cutt.ly/T8ACTy(我的谷歌驱动器)请问您的 Windows 10 版本是什么?
    • 好的,我把不同版本的测试项目带回家了,每个人都工作得很好。我看到了两个原因: 1. 我的私人系统不受我们愤怒的管理员任意性的影响 2. 我的私人系统运行 1903(内部版本:18362.239)并具有最新的 Windows 更新。两个系统都有 Windows 专业版一旦我找到了这种奇怪行为的正确原因,我会在这里写一个答案。
    • 我的是 1903,它也在 1809 上运行。如果 MS 示例不起作用,那确实指向您的环境而不是应用程序。
    • 只是猜测,但“允许应用程序访问您的相机”设置是打开还是关闭?它位于设置 -> 隐私 -> 相机中。关闭它会给您带来预览似乎不起作用的症状。相机访问需要将其打开,并为您的应用程序在该全局设置下方列出。您可以在 MS App Store 中试用 JustScanIt 之类的应用,然后尝试使用该设置以及 MS 示例应用。
    • 您好 Tom,这是一个很好的观点,但我打开了该选项,因此它适用于所有应用程序。否则 Main-Apps LoginPage 也不会工作,我猜 :) 我应该在最初的帖子中提到过。让我编辑它,这样其他人就可以直接看到它,而无需挖掘所有的 cmets。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-26
    • 2019-05-15
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 2017-01-25
    相关资源
    最近更新 更多