SmartCardReader (NF C RFID) не работает в Киоскмоде UWP - PullRequest
0 голосов
/ 12 марта 2020

У меня есть приложение UWP, которое использует устройство чтения смарт-карт (устройство: ACR122u от ACS) для считывания меток RFID. Он работает, когда я запускаю его на своей локальной машине, и работает также на целевом компьютерном устройстве. Но когда я запускаю то же самое, с тем же пользователем, но в режиме киоска (Назначенный доступ), это не работает. И я не знаю, как я могу отладить это в режиме киоска. так что я не нахожу проблему.

Системная информация : развернутая версия: Windows 10 (1903 / Build 18362) Целевой компьютер: Windows 10 (1903)

Мое решение основано на этом Пример :

Mainview:

public sealed partial class MainPage : Page
{

    //RFID
    private RFIDManager _RFIDManager;
    public bool RFIDScannerIsActivated { get; set; }
    public string LastScannedRFID { get; set; }

    // GUI
    public enum StatusGUI { Login }
    private StatusGUI _GUIStatus;
    private StatusGUI GUIStatus
    {
        get { return _GUIStatus; }
        set
        {
            _GUIStatus = value;
            SetStatus(value);
        }
    }
    private PersonDTO _LoggedInPerson;
    public PersonDTO LoggedinPerson
    {
        get { return _LoggedInPerson; }
        set
        {
            _LoggedInPerson = value;
            SetLoggedInAs();
        }
    }

    // Services
    private readonly LendService lendServie;


    public MainPage()
    {
        try
        {
            lendServie = new LendService();
            Translations.Init(ResourceLoader.GetForViewIndependentUse());

            this.InitializeComponent();
            InitTranslations();
            InitializeRFID();

            VersionNumber.Text = VersionHelper.GetVersionFormated();

            GUIStatus = StatusGUI.Login;

        }
        catch (Exception ex)
        {
            ShowErrorAndShutDown();
        }
    }





    #region Init
    private async void InitTranslations()
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            PlsLoginLabel.Text = Translations.Translate(WordKeys.PleaseLoginWhitYourBadge);
            ScentalogyLibraryLabel.Text = Translations.Translate(WordKeys.ScentalogyLibrary);
            PleaseWaitLabel.Text = Translations.Translate(WordKeys.PleaseWait);

        });
    }

    private void InitializeRFID()
    {
        try
        {
            _RFIDManager = new RFIDManager();
            _RFIDManager.ConnectionChangedEvent += RFIDManager_ConnectionStatusChanged;
            _RFIDManager.MessageReceivedEvent += RFIDManager_MessageReceived;
            _RFIDManager.ExceptionRaisedEvent += RFIDManager_ExceptionRaised;

            _RFIDManager.StartRFIDReader();
        }
        catch (Exception e)
        {
            Trace.WriteLine(e.Message);
            throw e;
        }
    }

    #endregion


    #region Input Events
    private async void RFIDManager_MessageReceived(object sender, MessageReceivedEventArgs args)
    {
        ShowLoadingIndicator(true);

        try
        {
            if (LastScannedRFID != args.Data && GUIStatus == StatusGUI.Login)
            {
                LastScannedRFID = args.Data;

                LoggedinPerson = null;
                LoggedinPerson = await lendServie.GetMyUserInfosWithBadgeNumber(LastScannedRFID);
                Trace.WriteLine(LastScannedRFID);
                if (!string.IsNullOrEmpty(LastScannedRFID) && GUIStatus == StatusGUI.Login)
                {
                    SetLoggedInAs();
                }
            }
        }
        catch (Exception ex)
        {
            ShowErrorMessagAndRestart();
        }
        ShowLoadingIndicator(false);
    }

    #endregion


    #region GUI
    private void SetStatus(StatusGUI status)
    {
        CollapseAll();
        switch (status)
        {
            case StatusGUI.Login:
                Login.Visibility = Visibility.Visible;
                LastScannedRFID = null;
                LoggedinPerson = null;
                break;
            default:
                Login.Visibility = Visibility.Visible;
                break;
        }
    }

    private void CollapseAll()
    {
        Login.Visibility = Visibility.Collapsed;
    }
    #endregion


    #region GUI Helper Logic

    private async void SetLoggedInAs()
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            LogedInAsBorder.Visibility = LoggedinPerson != null ? Visibility.Visible : Visibility.Collapsed;
            LogedInAs.Text = LoggedinPerson != null ? Translations.Translate(WordKeys.LoggedInAs) + " " + LoggedinPerson.UserName + " (" + LoggedinPerson.BadgeNumber +")": "";
        });
    }

    private async void ShowLoadingIndicator(bool show)
    {
        Visibility visibility;
        if (show)
        {
            visibility = Visibility.Visible;
        }
        else
        {
            visibility = Visibility.Collapsed;
        }
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            LoadingIndicator.Visibility = visibility;
        });

    }

    private async void ShowErrorMessagAndRestart()
    {
        var messageDialog = new MessageDialog(Translations.Translate(WordKeys.UnknownErrorContactServiceDesk) + Environment.NewLine + Translations.Translate(WordKeys.TheDeviceWillRestart),Translations.Translate(WordKeys.Error));
        await messageDialog.ShowAsync();
        Windows.System.ShutdownManager.BeginShutdown(Windows.System.ShutdownKind.Restart, TimeSpan.FromSeconds(0));
    }


    private async void ShowErrorAndShutDown()
    {
        var messageDialog = new MessageDialog(Translations.Translate(WordKeys.UnknownErrorContactServiceDesk) + Environment.NewLine + Translations.Translate(WordKeys.TheDeviceWillShutDown), Translations.Translate(WordKeys.Error));
        await messageDialog.ShowAsync();
        Windows.System.ShutdownManager.BeginShutdown(Windows.System.ShutdownKind.Shutdown, TimeSpan.FromSeconds(0));
    }
    #endregion


    #region RFID Events Others
    private void RFIDManager_ConnectionStatusChanged(object sender, ConnectionChangedEventArgs args)
    {
        RFIDScannerIsActivated = args.IsConnected;
        Trace.WriteLine("Status changed to: " + args.IsConnected);
    }

    private void RFIDManager_ExceptionRaised(object sender, RFIDExceptionRaisedEventArgs args)
    {
        Trace.WriteLine(args.Exception.Message);
    }
    #endregion

} 

RFID Manager

public class RFIDManager : IDisposable
{
    #region Fields
    private SmartCardReader _smartCardReader;
    private bool _rfidScannerIsActivated;
    private CancellationTokenSource _CancellationTokenSource;
    #endregion

    /// <summary>
    /// Initializes a new instance of the <see cref="RFIDManager"/> class. Start the RFID Reader with <seealso cref="StartRFIDReader"/> and receive the data from event <seealso cref="MessageReceivedEvent"/>
    /// </summary>
    public RFIDManager()
    {
        ReinitializeRFIDReader(false);
    }


    /// <summary>
    /// Reinitializes the rfid reader. Starts the Reader if AutoStart is true
    /// </summary>
    /// <param name="autoStart">if set to <c>true</c> [automatic start].</param>
    public void ReinitializeRFIDReader(bool autoStart = true)
    {
        try
        {
            StopRFIDReader();

            if (autoStart)
            {
                StartRFIDReader();
            }
        }
        catch (Exception e)
        {
            Log(e);
        }
    }
    /// <summary>
    /// Stops the rfid reader.
    /// </summary>
    public void StopRFIDReader()
    {
        try
        {
            _rfidScannerIsActivated = false;
            // Clean up
            if (_smartCardReader != null)
            {
                _smartCardReader.CardAdded -= CardReader_CardAdded;
                _smartCardReader.CardRemoved -= CardReader_CardRemoved;
                _smartCardReader = null; 
            }
            if (_CancellationTokenSource != null)
            {
                _CancellationTokenSource.Dispose();
                _CancellationTokenSource = null;
            }

        }
        catch (Exception e)
        {
            Log(e);
        }
        finally
        {
            NotifyOnConnectionChanged(_rfidScannerIsActivated);
        }
    }
    /// <summary>
    /// Starts the rfid reader.
    /// </summary>
    public void StartRFIDReader()
    {
        //If no reader found, don't start
        if (_rfidScannerIsActivated == true || _smartCardReader != null)
        {
            Log("RFID Reader is already running and can not be started again");
            return;
        }
        InitializeRFID();
        _rfidScannerIsActivated = true;
        NotifyOnConnectionChanged(_rfidScannerIsActivated);
    }

    #region Private Methods        
    /// <summary>
    /// Initializes the rfid reader to overwatch if a card is connected
    /// </summary>
    private async void InitializeRFID()
    {
        try
        {
            _CancellationTokenSource = new CancellationTokenSource();
            // First try to find a reader that advertises as being NFC
            var deviceInfo = await SmartCardReaderUtils.GetFirstSmartCardReaderInfo(SmartCardReaderKind.Nfc);
            if (deviceInfo == null)
            {
                // If we didn't find an NFC reader, let's see if there's a "generic" reader meaning we're not sure what type it is
                deviceInfo = await SmartCardReaderUtils.GetFirstSmartCardReaderInfo(SmartCardReaderKind.Any);
            }

            if (deviceInfo == null)
            {
                Log("NFC card reader mode not supported on this device");
                return;
            }

            if (_smartCardReader == null)
            {
                _smartCardReader = await SmartCardReader.FromIdAsync(deviceInfo.Id);
                _smartCardReader.CardAdded += CardReader_CardAdded;
                _smartCardReader.CardRemoved += CardReader_CardRemoved;
            }
        }
        catch (Exception e)
        {
            SendException(e);
        }
    }
    #region RFID Requests        
    /// <summary>
    /// Handles the card, if one is connected to the reader
    /// </summary>
    /// <param name="card">The card.</param>
    private async Task HandleCard(SmartCard card)
    {
        try
        {
            // Connect to the card
            using (SmartCardConnection connection = await card.ConnectAsync())
            {
                string currentUID = null;
                // Try to identify what type of card it was
                IccDetection cardIdentification = new IccDetection(card, connection);
                await cardIdentification.DetectCardTypeAync();
                Log("Connected to card\r\nPC/SC device class: " + cardIdentification.PcscDeviceClass.ToString());
                Log("Card name: " + cardIdentification.PcscCardName.ToString());
                Log("ATR: " + BitConverter.ToString(cardIdentification.Atr));

                if ((cardIdentification.PcscDeviceClass == Pcsc.Common.DeviceClass.StorageClass) &&
                    (cardIdentification.PcscCardName == Pcsc.CardName.MifareUltralightC
                    || cardIdentification.PcscCardName == Pcsc.CardName.MifareUltralight
                    || cardIdentification.PcscCardName == Pcsc.CardName.MifareUltralightEV1))
                {
                    // Handle MIFARE Ultralight
                    MifareUltralight.AccessHandler mifareULAccess = new MifareUltralight.AccessHandler(connection);

                    // Each read should get us 16 bytes/4 blocks, so doing
                    // 4 reads will get us all 64 bytes/16 blocks on the card
                    for (byte i = 0; i < 4; i++)
                    {
                        byte[] response = await mifareULAccess.ReadAsync((byte)(4 * i));
                        Log("Block " + (4 * i).ToString() + " to Block " + (4 * i + 3).ToString() + " " + BitConverter.ToString(response));
                    }

                    byte[] responseUid = await mifareULAccess.GetUidAsync();
                    currentUID = BitConverter.ToString(responseUid);
                    Log("UID:  " + currentUID);
                }
                else if (cardIdentification.PcscDeviceClass == Pcsc.Common.DeviceClass.MifareDesfire)
                {
                    // Handle MIFARE DESfire
                    Desfire.AccessHandler desfireAccess = new Desfire.AccessHandler(connection);
                    Desfire.CardDetails desfire = await desfireAccess.ReadCardDetailsAsync();

                    currentUID = BitConverter.ToString(desfire.UID);
                    Log("UID:  " + currentUID);
                    Log("DesFire Card Details:  " + Environment.NewLine + desfire.ToString());
                }
                else if (cardIdentification.PcscDeviceClass == Pcsc.Common.DeviceClass.StorageClass
                    && cardIdentification.PcscCardName == Pcsc.CardName.FeliCa)
                {
                    // Handle Felica
                    Log("Felica card detected");
                    var felicaAccess = new Felica.AccessHandler(connection);
                    var uid = await felicaAccess.GetUidAsync();
                    currentUID = BitConverter.ToString(uid);
                    Log("UID:  " + currentUID);
                }
                else if (cardIdentification.PcscDeviceClass == Pcsc.Common.DeviceClass.StorageClass
                    && (cardIdentification.PcscCardName == Pcsc.CardName.MifareStandard1K || cardIdentification.PcscCardName == Pcsc.CardName.MifareStandard4K))
                {
                    // Handle MIFARE Standard/Classic
                    Log("MIFARE Standard/Classic card detected");
                    var mfStdAccess = new MifareStandard.AccessHandler(connection);
                    var uid = await mfStdAccess.GetUidAsync();
                    currentUID = BitConverter.ToString(uid);
                    Log("UID:  " + currentUID);

                    ushort maxAddress = 0;
                    switch (cardIdentification.PcscCardName)
                    {
                        case Pcsc.CardName.MifareStandard1K:
                            maxAddress = 0x3f;
                            break;
                        case Pcsc.CardName.MifareStandard4K:
                            maxAddress = 0xff;
                            break;
                    }
                    await mfStdAccess.LoadKeyAsync(MifareStandard.DefaultKeys.FactoryDefault);

                    for (ushort address = 0; address <= maxAddress; address++)
                    {
                        var response = await mfStdAccess.ReadAsync(address, Pcsc.GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA);
                        Log("Block " + address.ToString() + " " + BitConverter.ToString(response));
                    }
                }
                else if (cardIdentification.PcscDeviceClass == Pcsc.Common.DeviceClass.StorageClass
                    && (cardIdentification.PcscCardName == Pcsc.CardName.ICODE1 ||
                        cardIdentification.PcscCardName == Pcsc.CardName.ICODESLI ||
                        cardIdentification.PcscCardName == Pcsc.CardName.iCodeSL2))
                {
                    // Handle ISO15693
                    Log("ISO15693 card detected");
                    var iso15693Access = new Iso15693.AccessHandler(connection);
                    var uid = await iso15693Access.GetUidAsync();
                    currentUID = BitConverter.ToString(uid);
                    Log("UID:  " + currentUID);
                }
                else
                {
                    // Unknown card type
                    // Note that when using the XDE emulator the card's ATR and type is not passed through, so we'll
                    // end up here even for known card types if using the XDE emulator

                    // Some cards might still let us query their UID with the PC/SC command, so let's try:
                    var apduRes = await connection.TransceiveAsync(new Pcsc.GetUid());
                    if (!apduRes.Succeeded)
                    {
                        Log("Failure getting UID of card, " + apduRes.ToString());
                    }
                    else
                    {
                        currentUID = BitConverter.ToString(apduRes.ResponseData);
                        Log("UID:  " + currentUID);
                    }
                }
            NotifyOnScannedRFID(currentUID);
            }
        }
        catch (Exception ex)
        {
            Log(ex);
        }
    }
    #endregion
    #endregion

    #region Notification and Events
    /// <summary>
    /// Occurs when [The connection has changed].
    /// </summary>
    public event EventHandler<ConnectionChangedEventArgs> ConnectionChangedEvent;
    /// <summary>
    /// Occurs when [message has received].
    /// </summary>
    public event EventHandler<MessageReceivedEventArgs> MessageReceivedEvent;
    /// <summary>
    /// Occurs when [exception has raised].
    /// </summary>
    public event EventHandler<RFIDExceptionRaisedEventArgs> ExceptionRaisedEvent;
    /// <summary>
    /// Occurs when a logentry as information is send
    /// </summary>
    public event EventHandler<InformationNotificationEventArgs> InformationNotificationEvent;
    /// <summary>
    /// Notify Eventlistener for scanned RFID Value
    /// </summary>
    /// <param name="data">The data.</param>
    public void NotifyOnScannedRFID(string data)
    {
        try
        {
            if(!string.IsNullOrWhiteSpace(data))
                TaskHelper.ExecuteTaskOnMainThread(() => MessageReceivedEvent?.Invoke(this, new MessageReceivedEventArgs(data)));
        }
        catch (Exception e)
        {
            Log(e);
        }
    }

    #region Private Eventhandling and Methods
    private void CardReader_CardRemoved(SmartCardReader sender, CardRemovedEventArgs args)
    {
        Trace.WriteLine("Card removed");
    }
    private async void CardReader_CardAdded(SmartCardReader sender, CardAddedEventArgs args)
    {
        await HandleCard(args.SmartCard);
    }
    private void SendException(Exception exception, bool withStayRunning = false, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null, [CallerLineNumber]int lineNumber = 0)
    {
        if (withStayRunning == false)
        {
            TaskHelper.ExecuteTaskOnMainThread(StopRFIDReader);
        }
        NotifyOnExceptionRaised(exception, memberName, filePath, lineNumber);
    }
    private void NotifyOnConnectionChanged(bool isConnected)
    {
        try
        {
            TaskHelper.ExecuteTaskOnMainThread(() => ConnectionChangedEvent?.Invoke(this, new ConnectionChangedEventArgs(isConnected)));
        }
        catch (Exception e)
        {
            Log(e);
        }
    }
    private void NotifyOnExceptionRaised(Exception exception, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null, [CallerLineNumber]int lineNumber = 0)
    {
        try
        {
            Trace.WriteLine(string.Format($"Member: {memberName}{Environment.NewLine}Filepath: {filePath}{Environment.NewLine}Linenumber: {lineNumber}{Environment.NewLine}Message: {exception.Message}"));
            TaskHelper.ExecuteTaskOnMainThread(() => ExceptionRaisedEvent?.Invoke(this, new RFIDExceptionRaisedEventArgs(exception, memberName, filePath, lineNumber)));
        }
        catch (Exception e)
        {
            Trace.WriteLine(e.Message);
        }
    }
    private void NotifyOnInformationNotification(string logText)
    {
        try
        {
            Trace.WriteLine(logText);
            TaskHelper.ExecuteTaskOnMainThread(() => InformationNotificationEvent?.Invoke(this, new InformationNotificationEventArgs(logText)));
        }
        catch (Exception e)
        {
            Trace.WriteLine(e.Message);
        }
    }
    private void Log(Exception exception, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null, [CallerLineNumber]int lineNumber = 0)
    {
        NotifyOnExceptionRaised(exception, memberName, filePath, lineNumber);
    }
    private void Log(string logText, int errorCode, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = 0)
    {
        if (!string.IsNullOrWhiteSpace(logText))
            NotifyOnExceptionRaised(new RFIDReaderException(logText, errorCode), memberName, filePath, lineNumber);
    }
    private void Log(string logText)
    {
        if (!string.IsNullOrWhiteSpace(logText))
            NotifyOnInformationNotification(logText);
    }
    #endregion
    #endregion

    public void Dispose()
    {
        StopRFIDReader();
    }

}
...