ข้อความแสดงข้อผิดพลาดเมื่อคุณใส่สมาร์ทการ์ดในเครื่องอ่านในคอมพิวเตอร์ที่ใช้ Windows 7 หรือใช้ Windows Server 2008 R2: "ซอฟต์แวร์โปรแกรมควบคุมอุปกรณ์ไม่ถูกติดสำเร็จตั้ง"

การแปลบทความ การแปลบทความ
หมายเลขบทความ (Article ID): 976832 - ผลิตภัณฑ์ที่เกี่ยวข้องในบทความนี้
ขยายทั้งหมด | ยุบทั้งหมด

เนื้อหาบนหน้านี้

อาการ

เมื่อคุณใส่สมาร์ทการ์ดเข้าไปในเครื่องอ่านสมาร์ทการ์ด Windows พยายามดาวน์โหลด และติดตั้ง minidrivers สมาร์ทการ์ดที่อยู่สำหรับบัตรผ่านบริการแบบพลักแอนด์เพลย์ ถ้าโปรแกรมควบคุมสำหรับสมาร์ทการ์ดไม่พร้อมใช้งานเมื่อใดก็ได้ที่ตั้งที่กำหนดไว้ล่วงหน้า เช่น Windows Update, WSUS หรือเส้น ทางอินทราเน็ต และผู้ให้บริการการเข้ารหัสลับที่กำหนดเองไม่ได้อยู่แล้วติดตั้งบนระบบ คุณได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้ในพื้นที่แจ้งเตือน:
ซอฟต์แวร์โปรแกรมควบคุมอุปกรณ์ไม่ได้ติดตั้งเสร็จเรียบร้อยแล้ว
คลิกที่นี่สำหรับรายละเอียด
ข้อความแสดงข้อผิดพลาดนี้หายไปหลังจากเป็นเวลาหลายวินาที

นอกจากนี้ ในตัวจัดการอุปกรณ์ ภายใต้ อุปกรณ์อื่น ๆอุปกรณ์สมาร์ทการ์ดมีสถานะเป็น "DNF" (ไม่พบโปรแกรมควบคุม)

มักต้องการให้ผู้ใช้ได้รับสินค้าต่อไปนี้อย่างใดอย่างหนึ่งจากผู้ออกสมาร์ทการ์ดเมื่อต้องแก้ไขข้อผิดพลาดนี้:
  1. การ minidriver logoed สมาร์ทการ์ดของ Windows
  2. ผู้ให้บริการแบบกำหนดเองที่เข้ารหัสลับ (CSP) สำหรับสมาร์ทการ์ด
  3. การ minidriver สมาร์ทการ์ดที่ไม่ใช่ logoed ของ Windows
  4. มิดเดิลแวร์อื่นเช่นตัวควบคุม ActiveX ซอฟต์แวร์ #11 pkcs # หรือซอฟต์แวร์ที่กำหนดเองอื่น ๆ
อย่างไรก็ตาม ถ้าผู้ใช้ที่มาพร้อมกับสินค้าเพียง 3 หรือ 4 จากรายการนี้ สมาร์ทการ์ดดำเนินการทำงานบนระบบ อย่างไรก็ตาม ผู้ใช้จะได้รับข้อความแสดงข้อผิดพลาดที่กล่าวถึงในส่วนนี้ทุกครั้งที่ พวกเขาใส่สมาร์ทการ์ด

ปัญหานี้มีผลต่อการนำออกใช้ทั้งหมด ของ Windows 7, Windows Server 2008 R2 และ ในทั้งสองระบบปฏิบัติการรุ่นที่ใหม่กว่า

สาเหตุ

สมาร์ทการ์ดทั้งหมดจำเป็นต้องใช้ซอฟต์แวร์เพิ่มเติมเพื่อให้สามารถทำงานใน Windows ยกเว้นว่าไม่มีโปรแกรมควบคุมที่กล่องขาเข้าที่ช่วยให้ผู้ใช้ใช้บัตรโดยไม่ต้องติดตั้งซอฟต์แวร์เพิ่มเติม กรอบงานสมาร์ทการ์ดของ Windows ถูกปรับปรุงใน Windows 7 เมื่อต้องการเปิดใช้งานการดาวน์โหลดอัตโนมัติของสมาร์ทการ์ด minidrivers จาก Windows Update หรือ จากตำแหน่งที่ตั้งอื่น ๆ คล้ายกันเช่นเซิร์ฟเวอร์ WSUS เมื่อใส่ลงในเครื่องอ่านสมาร์ทการ์ด สมาร์ทการ์ดทั้งหมดที่ส่งผ่านข้อกำหนดของ logo เสร็จเรียบร้อยแล้วในขณะที่เผยแพร่ โดย Windows Logo Program ได้รับประโยชน์จากคุณลักษณะนี้

อย่างไรก็ตาม ถ้าซอฟต์แวร์ที่จำเป็นต้องใช้สมาร์ทการ์ดใน Windows ที่ไม่ logoed หรือเป็นชนิดที่แตกต่างจากการ minidriver เช่นโปรแกรมควบคุม pkcs # #11, CSP กำหนดเอง มิด หรือตัว ควบคุม ActiveX โดยอัตโนมัติดาวน์โหลดตัวเลือกการล้มเหลวเนื่องจาก Microsoft รับรองสมาร์ทการ์ด minidrivers เท่านั้น ดังนั้น ถ้าผู้ใช้แทรกไพ่ที่ CSP กำหนดเองจะไม่ได้ลงทะเบียน ผู้ใช้ได้รับข้อผิดพลาดที่ระบุว่า ซอฟต์แวร์โปรแกรมควบคุมสำหรับอุปกรณ์ของสมาร์ทการ์ดแม้ว่าผู้ใช้สามารถใช้สมาร์ทการ์ดผ่านซอฟต์แวร์เพิ่มเติมที่ติดตั้งบนคอมพิวเตอร์ของผู้ใช้จากการติดตั้งแบบกำหนดเอง

การแก้ไข

แม้ว่าจะมีการใส่สมาร์ทการ์ดยังคงทำงานแม้ว่าจะ มีข้อผิดพลาดที่ผู้ใช้เห็น ผู้ออกสมาร์ทการ์ด จำหน่าย หรือผู้ผลิตสามารถใช้หนึ่งในวิธีต่อไปนี้เพื่อแก้ไขข้อผิดพลาดนี้

ปฏิบัติการ minidriver สมาร์ทการ์ด

เราขอแนะนำว่าผู้ออกบัตร ผู้ขาย ผู้ผลิต ได้นำโปรแกรมควบคุมขนาดเล็กของสมาร์ทการ์ดมาใช้และเข้าร่วมในโปรแกรมโลโก้ Windows เพื่อที่ได้รับประโยชน์จากการปรับปรุงที่จะนำมาใช้ในแพลตฟอร์มเช่น Smart Card Plug and Play, Device Stage for Smart Cards และอื่นๆ

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลจำเพาะเกี่ยวกับการ minidriver สมาร์ทการ์ดสำหรับ Windows แวะไปที่เว็บไซต์ต่อไปนี้ของ Microsoft:
http://www.microsoft.com/whdc/device/input/smartcard/sc-minidriver.mspx
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการเริ่มต้น ด้วยขั้นตอนการขอรับโลโก้สำหรับ minidrivers สมาร์ทการ์ดของคุณ แวะไปที่ไซต์เว็บโปรแกรมโลโก้ของ Windows ต่อไปนี้:
http://www.microsoft.com/whdc/winlogo/default.mspx

ใช้ค่า NULL โปรแกรมควบคุมสำหรับสมาร์ทการ์ดของคุณ

ถ้าซอฟต์แวร์ที่กำหนดเองดังกล่าวโปรแกรมควบคุม pkcs # #11 ตัวควบคุม ActiveX หรือมิดเดิลแวร์อื่น ๆ ไม่จำเป็นต้องมีการเปิดใช้งานการใช้สมาร์ทการ์ดบน Windows และปฏิบัติตามแบบ minidriver สมาร์ทการ์ดหรือ CSP กำหนดเองไม่ตัวเลือกที่ดี เราขอแนะนำว่า ปฏิบัตร ผู้ขาย หรือผู้ผลิตพิจารณาส่งไดรเวอร์ NULL เมื่อต้องการปรับปรุงของ Windows กระบวนการทั่วไปสำหรับการทำให้แน่ใจว่าโปรแกรมควบคุม NULL พร้อมใช้งานบน Windows Update จำเป็นต้องมีการส่งเป็นอุปกรณ์ที่ไม่ได้จัดระดับประสบความสำเร็จผ่าน Winqual ถ้า ในอนาคต มี minidriver ที่พร้อมใช้งานสำหรับบัตรเหล่านี้ ไดรเวอร์ใหม่สามารถอัพโหลดไปที่ Windows Update โดยเข้าร่วมในโปรแกรมโลโก้ Windows ไดรเวอร์ NULL สามารถดึงข้อมูลได้ด้วยตนเอง โดยที่ผู้ใช้แล้ว หรือสามารถทำให้ใช้งาน โดยใช้การปรับปรุงเพิ่มเติม

ต่อไปนี้คือ แม่แบบตัวอย่างสำหรับโปรแกรมควบคุมค่า NULL สำหรับสมาร์ทการ์ด
;
; Null Driver for Fabrikam Smartcard installation x86 and x64 package.
;

[Version]
Signature="$Windows NT$"
Class=SmartCard
ClassGuid={990A2BD7-E738-46c7-B26F-1CF8FB9F1391}
Provider=%ProviderName%
CatalogFile=delta.cat
DriverVer=4/21/2006,1.0.0.0

[Manufacturer]
%ProviderName%=Minidriver,NTamd64,NTamd64.6.1,NTx86,NTx86.6.1

[Minidriver.NTamd64]
;This driver has no applicability on OS versions earlier than Windows 7

[Minidriver.NTx86]
;This driver has no applicability on OS versions earlier than Windows 7


[Minidriver.NTamd64.6.1]
%CardDeviceName%=Minidriver64_Install,<DEVICE_ID>
;%CardDeviceName%=Minidriver64_Install,<DEVICE_ID2>
;%CardDeviceName%=Minidriver64_Install,<DEVICE_ID3>
;...

[Minidriver.NTx86.6.1]
%CardDeviceName%=Minidriver32_Install,<DEVICE_ID>
;%CardDeviceName%=Minidriver32_Install,<DEVICE_ID2>
;%CardDeviceName%=Minidriver32_Install,<DEVICE_ID3>
;...


;Leave the following sections blank
[DefaultInstall]
[DefaultInstall.ntamd64]
[DefaultInstall.NTx86]
[DefaultInstall.ntamd64.6.1]
[DefaultInstall.NTx86.6.1]
[Minidriver64_Install.NT]
[Minidriver64_61_Install.NT]
[Minidriver32_Install.NT]
[Minidriver32_61_Install.NT]


[Minidriver64_61_Install.NT.Services]
AddService = ,2

[Minidriver32_61_Install.NT.Services]
AddService = ,2


; =================== Generic ==================================

[Strings]
ProviderName ="Microsoft"
CardDeviceName="Fabrikam Generic Smart card"
เมื่อต้องสร้างหมายเลขของอุปกรณ์ฮาร์ดแวร์ที่ถูกอ้างอิง ด้วยสายอักขระ DEVICE_ID ในตัวอย่าง ทำตามคำแนะนำในข้อมูลจำเพาะของ minidriver สมาร์ทการ์ด เมื่อต้องการทำเช่นนี้ แวะไปที่เว็บไซต์ต่อไปนี้ของ Microsoft:
http://www.microsoft.com/whdc/device/input/smartcard/sc-minidriver.mspx


สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการที่ส่งค่า NULL โปรแกรมควบคุมไปยัง Microsoft กรุณาติดต่อบริการสนับสนุนลูกค้าของ Microsoft

ปิดการใช้งานสมาร์ทการ์ด Plug and Play ผ่านทางนโยบายกลุ่มสำหรับคอมพิวเตอร์ที่ได้รับการจัดการ

ตัวเลือกนี้จะแนะนำสำหรับการจัดวางเว็บไซต์องค์กรซึ่งคอมพิวเตอร์จะถูกจัดการ โดยผู้ดูแลระบบและทั้งหมดที่มีการติดตั้งซอฟต์แวร์จำเป็นทำให้การทำงานกับสมาร์ทการ์ดที่ใช้ในองค์กร โดยใช้เครื่องมือการจัดการซอฟต์แวร์เช่น SMS เท่านั้น

ขั้นตอนนี้จะขอ discouraged ในสภาพแวดล้อมที่ต่อไปนี้ได้เนื่องจากจะมีผลกระทบต่อทั้งหมดสมาร์ทการ์ดในสภาพแวดล้อมของคุณ:
  • การจัดวางทางการค้าที่กำหนดเป้าหมายผู้ใช้ เช่นธนาคารออนไลน์
  • สภาพแวดล้อมที่มีทั้งสองเสียบ and เล่นสมาร์ทการ์ดและที่ไม่ใช่แบบพลักแอนด์เพลย์สมาร์ทการ์ดที่ใช้ Group Policy เพื่อปิดใช้งานแบบพลักแอนด์เพลย์สำหรับสมาร์ทการ์ด
สมาร์ทการ์ด Plug and Play สามารถถูกปิดใช้อย่างสมบูรณ์งานในกิจการที่สิ้นสุดของผู้ใช้คอมพิวเตอร์มีจัดการ โดยกลไกเช่นนโยบายกลุ่ม

ถ้ามีการปรับใช้ของคุณใช้วิธีแก้ไขปัญหาที่ไม่ใช่แบบพลักแอนด์เพลย์สมาร์ทการ์ดเท่านั้น สมาร์ทการ์ด Plug and Play สามารถถูกปิดใช้งาน โดยผู้ดูแลระบบท้องถิ่นบนคอมพิวเตอร์แบบไคลเอ็นต์ การปิดการใช้งานสมาร์ทการ์ด Plug and Play ทำให้สามารถควบคุมสมาร์ทการ์ด หรือเรียกอีกอย่างหนึ่งว่า"สมาร์ทการ์ด minidrivers", ดาวน์โหลด นอกจากนี้ป้องกันการแสดงพร้อมท์ Plug and Play สมาร์ทการ์ด

เมื่อต้องการปิดการใช้งานสมาร์ทการ์ด Plug and Play ในนโยบายกลุ่มภายใน ทำตามขั้นตอนเหล่านี้:
  1. คลิก เริ่มชนิด gpedit.msc ในการ ค้นหาโปรแกรมและแฟ้ม กล่อง และจากนั้น กด ENTER
  2. ในคอนโซลทรีภายใต้ ตั้งค่าคอนฟิกของคอมพิวเตอร์คลิก แม่แบบการดูแล.
  3. ในบานหน้าต่างรายละเอียด คลิกสองครั้ง คอมโพเนนต์ของ Windowsแล้ว คลิกสองครั้ง สมาร์ทการ์ด.
  4. คลิกขวา เปิดบริการแบบพลักแอนด์เพลย์ของสมาร์ทการ์ดแล้ว คลิก แก้ไข.
  5. คลิก ปิดการใช้งานแล้ว คลิก ตกลง.

-ของผู้ใช้ระบบการเปลี่ยนแปลง และปิดการใช้งานสมาร์ทการ์ด Plug and Play สำหรับบัตรเฉพาะ

นี่คือตัวเลือกที่ขอแนะนำให้น้อยที่สุด คุณควรใช้ตัวเลือกนี้ก็ต่อเมื่อบัตรเป็นบัตรแบบดั้งเดิม และจะไม่มีแผนการใช้สมาร์ทการ์ด minidrivers ในอนาคต ตัวเลือกนี้จำเป็นต้องมีการแจ้งให้ทราบว่า ซอฟต์แวร์ที่มีอยู่ซึ่งถูกติดตั้งบนระบบแล้วถึง Windows ว่า เป็น CSP ที่กำหนดเองติดตั้งอยู่บนระบบแม้ว่า CSP ดังกล่าวไม่มีอยู่บนระบบของผู้ใช้ปลายทาง ทันทีที่ Windows กำหนดว่า ไม่มี CSP ที่กำหนดเองที่ติดตั้งบนระบบ Windows ลองดาวน์โหลด และติดตั้งโปรแกรมควบคุม โดยใช้สมาร์ทการ์ด Plug and Play ไม่ได้ โหนดที่ไม่มีอุปกรณ์สำหรับอุปกรณ์ของสมาร์ทการ์ดถูกสร้างขึ้นโดยจะมองเห็นได้ใน'ตัวจัดการอุปกรณ์' ตัวเลือกนี้ผลลัพธ์ต่อไปนี้เปลี่ยนแปลงรีจิสทรีของระบบ:

คีย์ย่อย:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card="" name=""></Smart>
รายการรีจิสทรีคีย์ย่อย:
  • ATR = DWORD เลขฐานสิบหก: เครื่องหมายจุลภาคเป็นตัวคั่น ATR ของสมาร์ทการ์ด
  • ATRMask = DWORD เลขฐานสิบหก: เครื่องหมายจุลภาคคั่นด้วยรูปแบบการนำไปใช้กับ ATR ที่กับรูปแบบการออกแบบ ATR ไบต์ไม่สำคัญ
  • ผู้ให้บริการการเข้ารหัสลับ =ค่าสตริงที่: สายอักขระบางตัวที่เกี่ยวข้องกับสมาร์ทการ์ดของคุณ
ตัวอย่าง:
คีย์ย่อย:
บัตร HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM
รายการรีจิสทรีคีย์ย่อย:
  • ATR = DWORD เลขฐานสิบหก: 3b, dc, 13, 00, 40, 3a, 49, 54, 47, 5f, 4 d, 53, 43, 53, 50, 5f, 56, 32
  • ATRMask = DWORD เลขฐานสิบหก: ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff
  • ผู้ให้บริการการเข้ารหัสลับ =ค่าสตริงที่: "Fabrikam ATM Dummy บริการ"
สำหรับ x ระบบ 64 บิต การเปลี่ยนแปลงที่เหมือนกันต้องทำภายใต้คีย์ย่อยต่อไปนี้:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


เราขอแนะนำว่า แทนการเปลี่ยนแปลงรีจิสทรีของระบบได้โดยตรง คุณใช้ Api ที่ WinSCard เพื่อแนะนำการเปลี่ยนแปลงเหล่านี้ไปยังระบบ ต่อไปนี้คือตัวอย่างรหัสตัวอย่างที่ตรวจพบการใส่สมาร์ทการ์ด และจากนั้น ปิดใช้งานสมาร์ทการ์ด Plug and Play สำหรับบัตรเฉพาะ โดยการสร้างเป็นรายการรีจิสทรีที่กำหนดความสัมพันธ์ของบัตรกับผู้ให้บริการที่ไม่มีอยู่

Microsoft ให้ตัวอย่างการเขียนโปรแกรมเพื่อประกอบการอธิบายเท่านั้น โดยไม่มีการรับประกันอย่างใดอย่างหนึ่ง หรือโดยนัย ซึ่งรวมถึง แต่ไม่จำกัดเฉพาะ การรับประกันโดยนัยของสามารถเชิงพาณิชย์หรือความเหมาะสมสำหรับวัตถุประสงค์เฉพาะ บทความนี้อนุมานว่า คุณมีความคุ้นเคย กับภาษาการเขียนโปรแกรมที่ถูกแสดง และ มีเครื่องมือที่ใช้ใน การสร้าง และ แก้จุดบกพร่องกระบวน วิศวกรฝ่ายสนับสนุนของ Microsoft สามารถช่วยอธิบายฟังก์ชันการทำงานของกระบวนการเฉพาะ อย่างไรก็ตาม พวกเขาจะไม่สามารถปรับเปลี่ยนการตัวอย่างเหล่านี้เพื่อให้มีเพิ่มฟังก์ชันการทำงาน หรือสร้างกระบวนงานเพื่อตอบสนองความต้องการเฉพาะของคุณ
//==============================================================;
//
//  Disable Smart card Plug and Play for specific cards
//
//  Abstract:
//      This is an example of how to create a new
//      Smart Card Database entry when a smart card is inserted
//      into the computer.
//
//  This source code is only intended as a supplement to existing Microsoft
//  documentation.
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED. THIS INCLUDES BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE.
//
//  Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//==============================================================;

// This code must be compiled with UNICODE support to work correctly
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <winscard.h>
#include <stdio.h>
#include <strsafe.h>
#include <rpc.h>

// Change this prefix to specify what the beginning of the
// introduced card name in the registry will be. This is
// be prepended to a GUID value.
#define CARD_NAME_PREFIX    L"MyCustomCard"

// This is the name that will be provided as the CSP for 
// the card when introduced to the system. This is provided
// in order to disable Smart Card Plug and Play for this
// card.
#define CARD_CSP            L"$DisableSCPnP$"

// This special reader name is used to be notified when
// a reader is added to or removed from the system through
// SCardGetStatusChange.
#define PNP_READER_NAME     L"\\\\?PnP?\\Notification"

// Maximum ATR length plus alignment bytes. This value is
// used in the SCARD_READERSTATE structure
#define MAX_ATR_LEN         36

LONG GenerateCardName(
    __deref_out LPWSTR  *ppwszCardName)
{
    LONG        lReturn = NO_ERROR;
    HRESULT     hr = S_OK;
    DWORD       cchFinalString = 0;
    WCHAR       wszCardNamePrefix[] = CARD_NAME_PREFIX;
    LPWSTR      pwszFinalString = NULL;
    UUID        uuidCardGuid = {0};
    RPC_WSTR    pwszCardGuid = NULL;
    RPC_STATUS  rpcStatus = RPC_S_OK;

    // Parameter check
    if (NULL == ppwszCardName)
    {
        wprintf(L"Invalid parameter in GenerateCardName.\n");
        return ERROR_INVALID_PARAMETER;
    }

    // Generate GUID
    rpcStatus = UuidCreate(&uuidCardGuid);
    if (RPC_S_OK != rpcStatus)
    {
        wprintf(L"Failed to create new GUID with error 0x%x.\n");
        lReturn = (DWORD)rpcStatus;
    }
    else
    {
        // Convert GUID to string
        rpcStatus = UuidToString(&uuidCardGuid, &pwszCardGuid);
        if (RPC_S_OK != rpcStatus)
        {
            wprintf(L"Failed to convert new GUID to string with error 0x%x.\n", rpcStatus);
            lReturn = (DWORD)rpcStatus;
        }
        else
        {
            // Allocate memory for final string
            // Template is <prefix>-<guid>
            cchFinalString = (DWORD)(wcslen(wszCardNamePrefix) + 1 + wcslen((LPWSTR)pwszCardGuid) + 1);
            pwszFinalString = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchFinalString * sizeof(WCHAR));
            if (NULL == pwszFinalString)
            {
                wprintf(L"Out of memory.\n");
                lReturn = ERROR_OUTOFMEMORY;
            }
            else
            {
                // Create final string
                hr = StringCchPrintf(
                            pwszFinalString,
                            cchFinalString,
                            L"%s-%s",
                            wszCardNamePrefix,
                            pwszCardGuid);
                if (FAILED(hr))
                {
                    wprintf(L"Failed to create card name with error 0x%x.\n", hr);
                    lReturn = (DWORD)hr;
                }
                else
                {
                    // Set output params
                    *ppwszCardName = pwszFinalString;
                    pwszFinalString = NULL;
                }
            }
        }
    }

    if (NULL != pwszCardGuid)
    {
        RpcStringFree(&pwszCardGuid);
    }

    if (NULL != pwszFinalString)
    {
        HeapFree(GetProcessHeap(), 0, pwszFinalString);
    }

    return lReturn;
}

LONG IntroduceCardATR(
    __in SCARDCONTEXT   hSC,
    __in LPBYTE         pbAtr,
    __in DWORD          cbAtr)
{
    LONG    lReturn = NO_ERROR;
    LPWSTR  pwszCardName = NULL;
    
    // Parameter checks
    if (NULL == hSC || NULL == pbAtr || 0 == cbAtr)
    {
        wprintf(L"Invalid parameter in IntroduceCardATR.\n");
        return ERROR_INVALID_PARAMETER;
    }

    // Generate a name for the card
    lReturn = GenerateCardName(&pwszCardName);
    if (NO_ERROR != lReturn)
    {
        wprintf(L"Failed to generate card name with error 0x%x.\n", lReturn);
    }
    else
    {
        // Introduce the card to the system
        lReturn = SCardIntroduceCardType(
                                hSC,
                                pwszCardName,
                                NULL,
                                NULL,
                                0,
                                pbAtr,
                                NULL,
                                cbAtr);
        if (SCARD_S_SUCCESS != lReturn)
        {
            wprintf(L"Failed to introduce card '%s' to system with error 0x%x.\n", pwszCardName, lReturn);
        }
        else
        {
            // Set the provider name
            lReturn = SCardSetCardTypeProviderName(
                                        hSC,
                                        pwszCardName,
                                        SCARD_PROVIDER_CSP,
                                        CARD_CSP);
            if (SCARD_S_SUCCESS != lReturn)
            {
                wprintf(L"Failed to set CSP for card '%s' with error 0x%x.\n", pwszCardName, lReturn);
            }
            else
            {
                wprintf(L"Card '%s' has been successfully introduced to the system and has had Plug and Play disabled.\n", pwszCardName);
            }
        }
    }

    if (NULL != pwszCardName)
    {
        HeapFree(GetProcessHeap(), 0, pwszCardName);
    }

    return lReturn;
}

LONG ProcessCard(
    __in SCARDCONTEXT           hSC,
    __in LPSCARD_READERSTATE    pRdr)
{
    LONG        lReturn = NO_ERROR;
    DWORD       dwActiveProtocol = 0;
    DWORD       cbAtr = MAX_ATR_LEN;
    DWORD       dwIndex = 0;
    DWORD       cchCards = SCARD_AUTOALLOCATE;
    LPWSTR      pmszCards = NULL;
    BYTE        rgbAtr[MAX_ATR_LEN] = {0};
    SCARDHANDLE hSCard = NULL;

    // Parameter checks
    if (NULL == hSC || NULL == pRdr)
    {
        wprintf(L"Invalid parameter in ProcessCard.\n");
        return ERROR_INVALID_PARAMETER;
    }

    // Connect to the card in the provided reader in shared mode
    lReturn = SCardConnect(
                    hSC,
                    pRdr->szReader,
                    SCARD_SHARE_SHARED,
                    SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
                    &hSCard,
                    &dwActiveProtocol);
    if (SCARD_S_SUCCESS != lReturn)
    {
        wprintf(L"Failed to connect to card in reader '%s' with error 0x%x.\n", pRdr->szReader, lReturn);
    }
    else
    {
        wprintf(L"Connected to card in reader '%s'.\n", pRdr->szReader);

        /*
         * In this spot, put any necessary calls needed to identify that this
         * is the type of card you are looking for. Usually this is done via
         * SCardTransmit calls. For this example, we will grab the ATR of every
         * inserted card.
         */

        // Obtain the ATR of the inserted card
        lReturn = SCardGetAttrib(
                            hSCard,
                            SCARD_ATTR_ATR_STRING,
                            rgbAtr,
                            &cbAtr);
        if (SCARD_S_SUCCESS != lReturn)
        {
            wprintf(L"Failed to obtain ATR of card in reader '%s' with error 0x%x.\n", pRdr->szReader, lReturn);
        }
        else
        {
            // Output the ATR
            wprintf(L"ATR of card in reader '%s':", pRdr->szReader);
            for (dwIndex = 0; dwIndex < cbAtr; dwIndex++)
            {
                wprintf(L" %02x", rgbAtr[dwIndex]);
            }
            wprintf(L"\n");

            // Determine if the ATR is already in the Smart Card Database
            lReturn = SCardListCards(
                                hSC,
                                rgbAtr,
                                NULL,
                                0,
                                (LPWSTR)&pmszCards,
                                &cchCards);
            if (SCARD_S_SUCCESS != lReturn)
            {
                wprintf(L"Failed to determine if card in reader '%s' is currently recognized by the system with error 0x%x. Skipping.\n", pRdr->szReader, lReturn);
            }
            else if (NULL == pmszCards || 0 == *pmszCards)
            {
                // Card not found. We need to add it.
                wprintf(L"Card in reader '%s' is not currently recognized by the system. Adding ATR.\n", pRdr->szReader);
                lReturn = IntroduceCardATR(
                                    hSC, 
                                    rgbAtr, 
                                    cbAtr);

                // If an error occurs here, we will continue so we can try the next time
                // the card is inserted as well as examine other readers.
            }
            else
            {
                wprintf(L"Card in reader '%s' is already known by the system. Not adding ATR.\n", pRdr->szReader);
            }
        }
    }

    // Disconnect from the card. We do not need to reset it.
    if (NULL != hSCard)
    {
        SCardDisconnect(hSCard, SCARD_LEAVE_CARD);
    }

    // Free resources
    if (NULL != pmszCards)
    {
        SCardFreeMemory(hSC, pmszCards);
    }

    return lReturn;
}


LONG MonitorReaders(
        __in SCARDCONTEXT hSC)
{
    LPWSTR              pwszReaders = NULL;
    LPWSTR              pwszOldReaders = NULL;
    LPWSTR              pwszRdr = NULL;
    DWORD               dwRet = ERROR_SUCCESS;
    DWORD               cchReaders = SCARD_AUTOALLOCATE;
    DWORD               dwRdrCount = 0;
    DWORD               dwOldRdrCount = 0;
    DWORD               dwIndex = 0;
    LONG                lReturn = NO_ERROR;
    BOOL                fDone = FALSE;
    SCARD_READERSTATE   rgscState[MAXIMUM_SMARTCARD_READERS+1] = {0};
    SCARD_READERSTATE   rgscOldState[MAXIMUM_SMARTCARD_READERS+1] = {0};
    LPSCARD_READERSTATE pRdr = NULL;

    // Parameter check
    if (NULL == hSC)
    {
        wprintf(L"Invalid parameter in MonitorReaders.\n");
        return ERROR_INVALID_PARAMETER;
    }

    // One of the entries for monitoring will be to detect new readers
    // The first time through the loop will be to detect whether
    // the system has any readers.
    rgscState[0].szReader = PNP_READER_NAME;
    rgscState[0].dwCurrentState = SCARD_STATE_UNAWARE;
    dwRdrCount = 1;

    while (!fDone)
    {
        while (!fDone)
        {
            // Wait for status changes to occur
            wprintf(L"Monitoring for changes.\n");
            lReturn = SCardGetStatusChange(
                                    hSC,
                                    INFINITE,
                                    rgscState,
                                    dwRdrCount);
            switch (lReturn)
            {
                case SCARD_S_SUCCESS:
                    // Success
                    break;
                case SCARD_E_CANCELLED:
                    // Monitoring is being cancelled
                    wprintf(L"Monitoring cancelled. Exiting.\n");
                    fDone = TRUE;
                    break;
                default:
                    // Error occurred
                    wprintf(L"Error 0x%x occurred while monitoring reader states.\n", lReturn);
                    fDone = TRUE;
                    break;
            }

            if (!fDone)
            {
                // Examine the status change for each reader, skipping the PnP notification reader
                for (dwIndex = 1; dwIndex < dwRdrCount; dwIndex++)
                {
                    pRdr = &rgscState[dwIndex];

                    // Determine if a card is now present in the reader and
                    // it can be communicated with.
                    if ((pRdr->dwCurrentState & SCARD_STATE_EMPTY ||
                         SCARD_STATE_UNAWARE == pRdr->dwCurrentState) &&
                        pRdr->dwEventState & SCARD_STATE_PRESENT &&
                        !(pRdr->dwEventState & SCARD_STATE_MUTE))
                    {
                        // A card has been inserted and is available.
                        // Grab its ATR for addition to the database.
                        wprintf(L"A card has been inserted into reader '%s'. Grabbing its ATR.\n", pRdr->szReader);
                        lReturn = ProcessCard(hSC, pRdr);

                        // If an error occurs here, we will continue so we can try the next time
                        // the card is inserted as well as examine other readers.
                    }

                    // Save off the new state of the reader
                    pRdr->dwCurrentState = pRdr->dwEventState;
                }

                // Now see if the number of readers in the system has changed.
                // Save its new state as the current state for the next loop.
                pRdr = &rgscState[0];
                pRdr->dwCurrentState = pRdr->dwEventState;
                if (pRdr->dwEventState & SCARD_STATE_CHANGED)
                {
                    wprintf(L"Reader change detected.\n");
                    break;
                }
            }   
        }

        if (!fDone)
        {
            // Clean up previous loop
            if (NULL != pwszOldReaders)
            {
                SCardFreeMemory(hSC, pwszOldReaders);
                pwszOldReaders = NULL;
            }
            pwszReaders = NULL;
            cchReaders = SCARD_AUTOALLOCATE;
            
            // Save off PnP notification reader state and and list of readers previously found in the system
            memcpy_s(&rgscOldState[0], sizeof(SCARD_READERSTATE), &rgscState[0], sizeof(SCARD_READERSTATE));
            memset(rgscState, 0, sizeof(rgscState));
            dwOldRdrCount = dwRdrCount;
            pwszOldReaders = pwszReaders;
            
            // Obtain a list of all readers in the system
            wprintf(L"Building reader list.\n");
            lReturn = SCardListReaders(
                                hSC,
                                NULL,
                                (LPWSTR)&pwszReaders,
                                &cchReaders);
            switch (lReturn)
            {
                case SCARD_S_SUCCESS:
                    // Success
                    break;
                case SCARD_E_NO_READERS_AVAILABLE:
                    // No readers in the system. This is OK.
                    lReturn = SCARD_S_SUCCESS;
                    break;
                default:
                    // Error occurred
                    wprintf(L"Failed to obtain list of readers with error 0x%x.\n", lReturn);
                    fDone = TRUE;
                    break;
            }

            // Build the reader list for monitoring - NULL indicates end-of-list
            // First entry is the PnP Notification entry.
            pRdr = rgscState;
            memcpy_s(&rgscState[0], sizeof(SCARD_READERSTATE), &rgscOldState[0], sizeof(SCARD_READERSTATE));
            pRdr++;
            pwszRdr = pwszReaders;
            while ((NULL != pwszRdr) && (0 != *pwszRdr))
            {
                BOOL fFound = FALSE;
                dwRdrCount++;

                // Look for an existing reader state from a previous loop
                for (dwIndex = 1; dwIndex < dwOldRdrCount; dwIndex++)
                {
                    if ((lstrlen(pwszRdr) == lstrlen(rgscOldState[dwIndex].szReader)) &&
                        (0 == lstrcmpi(pwszRdr, rgscOldState[dwIndex].szReader)))
                    {
                        // Found a match. Copy it.
                        memcpy_s(pRdr, sizeof(SCARD_READERSTATE), &rgscOldState[dwIndex], sizeof(SCARD_READERSTATE));
                        fFound = TRUE;
                        break;
                    }
                }

                if (!fFound)
                {
                    // New reader
                    pRdr->szReader = pwszRdr;
                    pRdr->dwCurrentState = SCARD_STATE_UNAWARE;
                }

                // Increment reader indices
                pRdr++;
                pwszRdr += lstrlen(pwszRdr)+1;
            }
        }
    }

    // Clean up resources
    if (NULL != pwszReaders)
    {
        SCardFreeMemory(hSC, pwszReaders);
    }

    if (NULL != pwszOldReaders)
    {
        SCardFreeMemory(hSC, pwszOldReaders);
    }

    return lReturn;
}

LONG __cdecl main(
        VOID)
{
    DWORD               dwRet = ERROR_SUCCESS;
    SCARDCONTEXT        hSC = NULL;
    LONG                lReturn = NO_ERROR;
    HANDLE              hStartedEvent = NULL;

    // Get handle to event that will be signaled when the Smart Card Service is available
    hStartedEvent = SCardAccessStartedEvent();

    // Wait for the Smart Card Service to become available
    dwRet = WaitForSingleObject(hStartedEvent, INFINITE);
    if (WAIT_OBJECT_0 != dwRet)
    {
        wprintf(L"Wait for Smart Card Service failed with error 0x%x.\n", dwRet);
        lReturn = dwRet;
    }
    else
    {
        // Establish a system-level context with the Smart Card Service
        lReturn = SCardEstablishContext(
                                SCARD_SCOPE_SYSTEM,
                                NULL,
                                NULL,
                                &hSC);
        if (SCARD_S_SUCCESS != lReturn)
        {
            wprintf(L"Failed to establish context with the Smart Card Service with error 0x%x.\n", lReturn);
        }
        else
        {
            // Begin monitoring the readers in the system
            // This routine could be done in a separate thread so it can be cancelled via SCardCancel().
            lReturn = MonitorReaders(hSC);
        }
    }   

    // Cleanup resources
    if (NULL != hSC)
    {
        SCardReleaseContext(hSC);
    }

    if (NULL != hStartedEvent)
    {
        SCardReleaseStartedEvent();
    }

    wprintf(L"Done.\n");

    return lReturn;
}

ข้อมูลอ้างอิง

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการแก้ไขปัญหาสมาร์ทการ์ด Plug and Play ดู TechNet บทความต่อไปนี้:
สมาร์ทการ์ด Plug and Play คำแนะนำในการแก้ไขปัญหา
http://technet.microsoft.com/en-us/library/dd979536 (WS.10) .aspx

คุณสมบัติ

หมายเลขบทความ (Article ID): 976832 - รีวิวครั้งสุดท้าย: 5 พฤศจิกายน 2555 - Revision: 4.0
ใช้กับ
  • Windows Server 2008 R2 Datacenter
  • Windows Server 2008 R2 Enterprise
  • Windows Server 2008 R2 Standard
  • Windows 7 Enterprise
  • Windows 7 Home Basic
  • Windows 7 Home Premium
  • Windows 7 Professional
  • Windows 7 Starter
  • Windows 7 Ultimate
Keywords: 
kbsmartcard kbcodesnippet kbtshoot kbexpertiseinter kbsurveynew kbprb kbmt KB976832 KbMtth
แปลโดยคอมพิวเตอร์
ข้อมูลสำคัญ: บทความนี้แปลโดยซอฟต์แวร์การแปลด้วยคอมพิวเตอร์ของ Microsoft แทนที่จะเป็นนักแปลที่เป็นบุคคล Microsoft มีบทความที่แปลโดยนักแปลและบทความที่แปลด้วยคอมพิวเตอร์ เพื่อให้คุณสามารถเข้าถึงบทความทั้งหมดในฐานความรู้ของเรา ในภาษาของคุณเอง อย่างไรก็ตาม บทความที่แปลด้วยคอมพิวเตอร์นั้นอาจมีข้อบกพร่อง โดยอาจมีข้อผิดพลาดในคำศัพท์ รูปแบบการใช้ภาษาและไวยากรณ์ เช่นเดียวกับกรณีที่ชาวต่างชาติพูดผิดเมื่อพูดภาษาของคุณ Microsoft ไม่มีส่วนรับผิดชอบต่อความคลาดเคลื่อน ความผิดพลาดหรือความเสียหายที่เกิดจากการแปลเนื้อหาผิดพลาด หรือการใช้บทแปลของลูกค้า และ Microsoft มีการปรับปรุงซอฟต์แวร์การแปลด้วยคอมพิวเตอร์อยู่เป็นประจำ
ต่อไปนี้เป็นฉบับภาษาอังกฤษของบทความนี้:976832

ให้ข้อเสนอแนะ

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com