Feststellen ob Smartcard im Gerätemanager gelistet ist (Win 10)

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von NoIde.

    Feststellen ob Smartcard im Gerätemanager gelistet ist (Win 10)

    Hallo Leute,

    ich müsste mit einer simplen Abfrage ermitteln ob an den PC eine Smartcard angeschlossen ist. Dabei ist es irrelevant ob ein oder mehrere Smartcards. Es muss nur ermittelt werden

    a) ja es ist eine Smartcard angesteckt
    b) nein es keine Smartcard angesteckt

    Dabei möchte ich aber nicht "testweise" die Smartcard oder den Reader per API ansprechen, da ich diesen dann für eine andere Anwendung blockieren würde.
    Also würde es wohl am Besten sein irgendwie ermitteln zu können, ob ein Eintrag im Gerätemanager existiert.

    Hintergrund warum ich das brauche:
    Meine Anwendung spricht über eine Fremdhersteller-Funktion eine Smartcard an. Ich verwende aber einen Bluetooth-Reader und wenn dieser nach 3 Minuten in den Standby fällt, ist die Smartcard für die Fremdhersteller-Funktion nicht mehr verfügbar und es kommt zu weiterführenden Problemen.
    Daher möchte ich vor dem Aufruf der Fremdhersteller-Funktion einfach abfragen ob die Smartcard noch im Gerätemanager gelistet ist (und somit aktiv ist).

    Danke für Eure Hilfe.
    LG Roland

    *Topic verschoben*
    Bilder
    • 17082018101237.jpg

      17,75 kB, 305×78, 74 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Schau mal ob die Smartcards so auch aufgelistet werden.
    Setze einen Verweis auf System.Management!

    VB.NET-Quellcode

    1. Imports System.Management
    2. Imports System.Runtime.InteropServices
    3. Public Class Form1
    4. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
    5. Dim mos As New ManagementObjectSearcher("\root\cimv2", "SELECT * FROM Win32_PnPEntity")
    6. Dim moc As ManagementObjectCollection = mos.Get()
    7. For Each mo As ManagementObject In moc
    8. Try
    9. Debug.WriteLine(mo("Name").ToString())
    10. Catch ex As COMException
    11. Debug.WriteLine("COM-EX " & ex.Message)
    12. Catch ex As Exception
    13. Debug.WriteLine("EX " & ex.Message)
    14. End Try
    15. Next
    16. End Sub
    17. End Class

    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    Vielen lieben Dank.
    Probiere ich später gleich aus. Muss nun mal meinen Entwicklungsrechner wieder herrichten - spinnt gerade ;)
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Falls die Smartcards so aufgelistet werden, kannst du den Query anpassen, so das nur die SmartCards(odr. reader) gelistet werden, die ClassGUID kannste dir vom mo.ClassGuid hohlen.

    VB.NET-Quellcode

    1. 'mit beispiel classguid
    2. "SELECT * FROM Win32_PnPEntity WHERE ClassGuid = '{00000000-0000-0000-0000-000000000000}'")"
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    Vielen Dank lieber Nolde. Das war genau das was ich gesucht habe.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Ich habe nun die GUID ermittelt. Jedoch gibts ja keine Collection wenn nur ein Gerät (oder keines) der Abfrage entspricht. Somit bringt mir die For Each / Next Schleife einen Fehler. Wie lese ich das (theoretisch) einzige Element aus der ManagementObjectCollection aus?

    Sorry, hatte damit noch nicht viel zu tun.

    VB.NET-Quellcode

    1. Public Function SmartCardIstGesteckt() As String
    2. Dim SmartCardName As String = ""
    3. 'Dim mos As New ManagementObjectSearcher("\root\cimv2", "SELECT * FROM Win32_PnPEntity WHERE ClassGuid = {990a2bd7-e738-46c7-b26f-1cf8fb9f1391}")
    4. Dim mos As New ManagementObjectSearcher("\root\cimv2", "SELECT * FROM Win32_PnPEntity")
    5. Dim moc As ManagementObjectCollection = mos.Get()
    6. For Each mo As ManagementObject In moc
    7. Try
    8. SmartCardName = UCase((mo("Name").ToString()))
    9. If InStr(SmartCardName, "UNKNOWN SMART CARD") Or InStr(SmartCardName, "UNBEKANNTE SMARTCARD") Or InStr(SmartCardName, "A-TRUST SIGNATURKARTE") Then
    10. If SmartCardName = "UNKNOWN SMART CARD" Then SmartCardName = "A-Trust Signaturkarte"
    11. 'InputBox("", "", mo("ClassGuid").ToString()) 'Nur zur Ermittlung der GUID
    12. Return SmartCardName
    13. Exit For
    14. End If
    15. Catch
    16. End Try
    17. Next
    18. Return ""
    19. End Function

    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dive26“ ()

    dive26 schrieb:

    Jedoch gibts ja keine Collection wenn nur ein Gerät (oder keines) der Abfrage entspricht.


    Eine Collection kann auch nur 1 Element haben. Wenn kein Element drin, findet auch kein durchlauf der For-Each Schleife statt. Bei einem gibt es 1 loop.

    dive26 schrieb:

    einen Fehler


    Welchen?

    In deinem Code(auskommentiert) sehe ich auch noch einen kleinen Fehler. Die ClassGuid im Query muss noch in ' gepackt werden.

    VB.NET-Quellcode

    1. Dim mos As New ManagementObjectSearcher("\root\cimv2", "SELECT * FROM Win32_PnPEntity WHERE ClassGuid = '{990a2bd7-e738-46c7-b26f-1cf8fb9f1391}'")



    Ich würde das in eine Klasse auslagern, welche dir die nötigen Funktionen bietet, so in etwa.

    VB.NET-Quellcode

    1. Imports System.Management
    2. Imports System.Runtime.InteropServices
    3. Public Class Form1
    4. Private SC As New SmartCardStuff
    5. Private Sub Form1_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
    6. For i = 0 To SC.GetSmartCardCount - 1
    7. MessageBox.Show(SC.GetSmartCardNameCorrected(i))
    8. Next
    9. End Sub
    10. End Class
    11. Class SmartCardStuff
    12. Private Cards As List(Of String)
    13. Public Sub New()
    14. RefreshList()
    15. End Sub
    16. Public Sub RefreshList()
    17. Cards = New List(Of String)
    18. Dim mos As New ManagementObjectSearcher("\root\cimv2", "SELECT * FROM Win32_PnPEntity WHERE ClassGuid = '{990a2bd7-e738-46c7-b26f-1cf8fb9f1391}'")
    19. Dim moc As ManagementObjectCollection = mos.Get()
    20. For Each mo As ManagementObject In moc
    21. Try
    22. For Each prop In mo.Properties
    23. If prop.Name.ToLower.Equals("name") Then
    24. Cards.Add(mo("Name").ToString())
    25. End If
    26. Next
    27. Catch ex As ManagementException
    28. Debug.WriteLine(ex.ErrorInformation.ToString())
    29. Catch ex As COMException
    30. Debug.WriteLine(ex.ErrorCode.ToString())
    31. Catch ex As Exception
    32. Debug.WriteLine(ex.Message.ToString())
    33. End Try
    34. Next
    35. End Sub
    36. Public Function GetSmartCardNameOriginal(ByVal index As Integer) As String
    37. If index > 0 AndAlso index < Cards.Count Then
    38. Return Cards(index)
    39. End If
    40. Return ""
    41. End Function
    42. Public Function GetSmartCardNameCorrected(ByVal index As Integer) As String
    43. If index > 0 AndAlso index < Cards.Count Then
    44. Dim SmartCardName As String = Cards(index).ToUpper
    45. Dim illegals() As String = {"UNKNOWN SMART CARD", "UNBEKANNTE SMARTCARD", "A-TRUST SIGNATURKARTE"}
    46. For i = 0 To illegals.Length - 1
    47. If SmartCardName.Contains(illegals(i)) Then 'SmartCardName.Equals(illegals(i)) auch moglich, je nach dem ob exakt gleich oder nur beinhaltet sein soll
    48. SmartCardName = "A-Trust Signaturkarte"
    49. End If
    50. Next
    51. Return SmartCardName
    52. End If
    53. Return ""
    54. End Function
    55. Public Function GetSmartCardCount() As Integer
    56. Return Cards.Count
    57. End Function
    58. Public Function SmartCardFound() As Boolean
    59. Return Cards.Count > 0
    60. End Function
    61. End Class

    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „NoIde“ ()

    In deinem Code(auskommentiert) sehe ich auch noch einen kleinen Fehler. Die ClassGuid im Query muss noch in ' gepackt werden.


    Vielen Dank. Das war der Fehler. Jetzt funktioniert es ohne die ganze Collection des Gerätemanagers durchlaufen zu müssen.

    Danke auch für den umfangreichen Quellcode. Jedoch ist so viel Aufwand nicht nötig, da es sich dabei um eine Registrierkasse handelt wo zu 100% immer nur eine (oder keine) Smartcard angesteckt ist.

    Das hätte ich auch nicht gewußt. Man lernt nie aus ;)
    Da sieht man, dass Du Profiprogrammierer bist.
    If SmartCardName.Contains(illegals(i)) Then
    Bilder
    • 17082018154857.jpg

      211,2 kB, 718×523, 71 mal angesehen
    • 17082018154921.jpg

      30,26 kB, 464×162, 67 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „dive26“ ()

    dive26 schrieb:

    Da sieht man, dass Du Profiprogrammierer bist.


    Danke, sehr schmeichelhaft. ^^ Aber so weit bin ich noch nicht. Für mich ist das nur ein Hobby, das Profi-Level ist das Ziel.

    dive26 schrieb:

    Wie lese ich das (theoretisch) einzige Element aus der ManagementObjectCollection aus?


    Da brauchst du einen IEnumerator, hier dran kommste durch moc.GetEnumerator. Mit dem "DeinEnumerator" kannst du dann selbst dadurch iterieren, mit DeinEnumerator.MoveNext geht es zum nächsten(mit DeinEnumerator.Reset, geht es von vorne los). DeinEnumerator.Current, ist das aktuelle Element.

    Indexbasiert ist hier nicht so einfach möglich, ausser wenn man beim iterieren mitzählt.

    Edit: @dive26
    String.Contains, ist weniger passend, String.Equals testet ob der string gleich ist, Contains nur ob ein string im String vorhanden ist. Kleiner Flüchtigkeitsfehler.
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „NoIde“ ()