现在的位置: 首页 > 综合 > 正文

设备序列号写入工具

2013年09月03日 ⁄ 综合 ⁄ 共 12567字 ⁄ 字号 评论关闭

工具说明:

此工具是功能是:1)用扫描枪扫描设备的序列号(如在超市买商品都要扫描一样),然后序列号会自动写入到图中的文本框中,序列号要求是:1、它必须是10位数的。2、每位数是0~9

当不能扫描时,手动输入到文本框中,输入要求如上。

2)将设备被序列号用命令发送到设备中去,一共发4条命令,最后一

条命令返回序列号,与输入的序列号进行比对,相同则设备写入成功。(用到智能卡大师软件)

3)为了测试人员方便使用,只要测试人用扫描器扫描,其余的工作由

工具自动完成。

遇到的难点:1)首先没有按钮驱动,在这里用多线程解决了此问题。

2)在此过程中,遇到了杂七杂八的小问题,大多数都是调试解决。

// ReadShoterDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ReadShoter.h"
#include "ReadShoterDlg.h"

#include <Afxwin.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <STRING>
#include "PCSCReader.h"
#include "ToolFun.h"
#include "softenc.h"
#include "Message.h"
#include "MessageW.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
#define MAX_NUM 30
#define MAXSIZE_20 20
#define MAXSIZE_30 30
#define MaxCount 10


// CPCSCReader g_objReader;
// CStringArray objStrArr;


class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CReadShoterDlg dialog

CReadShoterDlg::CReadShoterDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CReadShoterDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CReadShoterDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CReadShoterDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CReadShoterDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CReadShoterDlg, CDialog)
	//{{AFX_MSG_MAP(CReadShoterDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
//	ON_BN_CLICKED(IDC_SN_WRITE, OnSnWrite)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CReadShoterDlg message handlers

BOOL CReadShoterDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	static int flag = 1;
	if(flag==1)
	//修改注册表
	{
		RegeditDevice();
		SetRegedit();
		flag = 0;
	}

	//创建子线程
	CWinThread *pThread = new CWinThread();
	pThread = AfxBeginThread(OnSnWrite,this);
	if (pThread == NULL)
	{
		MessageBox(_T("线程启动失败!"));
	}
//	delete pThread;
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CReadShoterDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CReadShoterDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CReadShoterDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

UINT CReadShoterDlg::OnSnWrite(LPVOID pParam) 
{	

	//线程处理
	CReadShoterDlg* pDlg = (CReadShoterDlg*)pParam;
	ASSERT(pDlg!=NULL);

//	CString								strTemp;
	byteArray							baSN;
	char								tmp[6];
	char								zero[10]={0};
	//SN数组
	char snArray[MAXSIZE_20] = {0}; 
	//厂商代码
	char devid = '\x01';
	//预留
	char devrfu[MAX_NUM] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
	//段内偏移
	char devoff[3] = "\x20\x00";
	//长度
	char devlen = '\x14';
	//密钥
	BYTE authkey[17] = {0};
	//des返回数据
	unsigned char ucOutBlock[8] = {0};
	//随机数存放
	BYTE random[8] = {0}; 
	//命令1格式
	BYTE array[MAXSIZE_20] = "\xF0\x91\x00\x00\x08";
	//命令2格式
	//BYTE array1[MAXSIZE_20] = "\xF0\x92\x00\x00\x08";
	BYTE array1[MAXSIZE_20] = "\xF0\x00\x00\x00\x08";
	//命令3格式
	BYTE array2[MAXSIZE_30] = "\xF0\xA2\x01\x00\x17";
	//命令4格式
	BYTE array3[MAXSIZE_30] = "\xF0\x02\x03\x00\x00";
	
	LPBYTE pcCmdHead;
	DWORD dwDataLen;
	LPBYTE pbRecv;
	LPDWORD pdwRecvLen;
	DWORD dwRecvLen;
	LPWORD pwSW;
	WORD   sW;
//	DWORD dwSlot;

	while(1)
	{	
		CPCSCReader g_objReader;
		CStringArray objStrArr;
		CString		strTemp;
		CReadShoterDlg dlg;
		CWnd wnd;
		Message msg;
		
		//数据合法性判断
		//等待输入成功
		static char lpText[MaxCount];
		int f_flag = 0;

//		static int statue = 0 ;
		pDlg->GetDlgItemText(IDC_SN_NUM,strTemp);
		if(strTemp.GetLength()<10)
		{
			continue;//不满足十个数字则循环等待满10个数字
		}
		if(strTemp.GetLength()==10)
		{	
			Sleep(2000);
			pDlg->GetDlgItemText(IDC_SN_NUM,strTemp);//确认一下是否是10个数字
		}

		if(strTemp.GetLength()>10)
		{
			AfxMessageBox(_T("请输入正确数字个数!"));//大于10个提示错误并清除
			pDlg->SetDlgItemText(IDC_SN_NUM,zero);
			continue;
		}
	

		memcpy(lpText,strTemp.GetBuffer(0),MaxCount);
		for (int j = 0; j<MaxCount; j++)
		{
			if (!((lpText[j] >='\x30') && (lpText[j] <= '\x39')))
			{	
				AfxMessageBox(_T("请输入0~9的正确数字!"));
				pDlg->SetDlgItemText(IDC_SN_NUM,zero);
				f_flag = 1;
				break;
			}
 		}
		if(f_flag == 1)
			continue;

		static int flag = 1;
	


		//设备初始化
		if(flag)
		{
			if (!CPCSCReader::ListPcscReader(objStrArr,CPCSCReader::LPR_TRUST_PAY_PORTABLE))
			{
				AfxMessageBox(_T("获取设备失败,请插入设备!"));
				g_objReader.DisConnect();
				pDlg->SetDlgItemText(IDC_SN_NUM,zero);
				continue;
			}
			std::string strName = "";
			int nCount = objStrArr.GetSize();
			for (int i=0; i<nCount; i++)
			{
				std::string strStr= objStrArr.GetAt(i);
				strStr = strupr((char*)strStr.c_str());
				
	#ifdef _NT_DEV_
				if (strStr.find("NANTIAN") != std::string::npos)
	#else
					if (strStr.find("TIANYU") != std::string::npos)
	#endif
					{
						strName = strStr;
						break;
					}
			}
			
			if (strName.empty())
			{
				AfxMessageBox(_T("没有找到 TIANYU 的设备!"));
				g_objReader.DisConnect();
				pDlg->SetDlgItemText(IDC_SN_NUM,zero);
				continue;
			}
			
			if (!g_objReader.Init(strName.c_str()))
			{
				AfxMessageBox(_T("初始化设备失败!"));
				g_objReader.DisConnect();
				pDlg->SetDlgItemText(IDC_SN_NUM,zero);
				continue;
			}
			if (!g_objReader.Connect(TRUE))
			{
				AfxMessageBox(_T("连接设备失败!"));
				g_objReader.DisConnect();
				pDlg->SetDlgItemText(IDC_SN_NUM,zero);
				continue;
			}
			flag = 1;
		}

		// TODO: Add your control notification handler code here

		//第一次发送命令
		pcCmdHead = array;
		//	LPBYTE pbData;
		dwDataLen = (DWORD)5;
		dwRecvLen = (DWORD)MAXSIZE_20;

		pbRecv = (BYTE*) malloc(dwRecvLen*sizeof(BYTE));
		pdwRecvLen = &dwRecvLen;
		pwSW = &sW;

/*		if(!(g_objReader.SendCommand(pcCmdHead,dwDataLen,pbRecv,pdwRecvLen,pwSW,dwSlot,0,FALSE)))*/
		if(!(g_objReader.SendCommandI(pcCmdHead,dwDataLen,pbRecv,pdwRecvLen,pwSW,TRUE)))
		{
			AfxMessageBox(_T("命令发送失败1!"));
			g_objReader.DisConnect();
			pDlg->SetDlgItemText(IDC_SN_NUM,zero);
			continue;
		}
	//	free(pbRecv);
		//第二次发送命令
		pcCmdHead = array1;
		dwDataLen = (DWORD)13;
		dwRecvLen = (DWORD)MAXSIZE_20;

		pdwRecvLen = &dwRecvLen;
		pwSW = &sW;
		
	//	pbRecv = (BYTE*) malloc(dwRecvLen*sizeof(BYTE));
		//读取文件的密钥id和密钥
		FILE * fd = fopen("key.bin","rb+");
		if (fd == NULL)
		{
			AfxMessageBox(_T("打开key文件失败!"));
			return -1;
		}

		memset(authkey,0,sizeof(authkey));

		if(fread(authkey,17,1,fd) < 1)
		{
			AfxMessageBox(_T("读取key失败!"));
			return -1;
		}

		fclose(fd);

		array1[1] = authkey[0];//密钥id = 0x02;


		//去随机数
		memset(random,0,sizeof(random));
		memcpy(random,pbRecv,sizeof(random));
		

		DES_EDE_Encryption cipher(authkey+1);//3des加密密钥
		cipher.ProcessBlock(random,ucOutBlock);

		memcpy(array1+5,ucOutBlock,sizeof(ucOutBlock));

		if(!(g_objReader.SendCommandI(pcCmdHead,dwDataLen,pbRecv,pdwRecvLen,pwSW,TRUE)))
		{
			AfxMessageBox(_T("命令发送失败2!"));
			g_objReader.DisConnect();
			pDlg->SetDlgItemText(IDC_SN_NUM,zero);
			continue;
		}


		//第3次发送命令
		pcCmdHead = array2;
	//	dwDataLen = (DWORD)28;
		dwRecvLen = (DWORD)MAXSIZE_30;
		
		pdwRecvLen = &dwRecvLen;
		pwSW = &sW;

//		pDlg->GetDlgItemText(IDC_SN_NUM,strTemp);
		StrToHex(strTemp.GetBuffer(0),strTemp.GetLength(),baSN);
		dwDataLen = (DWORD)(23+baSN.GetSize());

		for (int i = 0; i <baSN.GetSize(); i++)
		{
			snArray[i] = *((BYTE*)(baSN.GetData()+i));
		}

		memcpy(array2+5,devoff,strlen(devoff));
		array2[7] = devlen;
		memcpy(array2+8,devrfu,strlen(devrfu));
		array2[22] = devid;
		memcpy(array2+23,snArray,baSN.GetSize());
		
		if(!(g_objReader.SendCommandI(pcCmdHead,dwDataLen,pbRecv,pdwRecvLen,pwSW,TRUE)))
		{
			AfxMessageBox(_T("命令发送失败3!"));
			g_objReader.DisConnect();
			pDlg->SetDlgItemText(IDC_SN_NUM,zero);
			continue;
		}
		
		//第4次发命令
		pcCmdHead = array3;
		dwDataLen = (DWORD)5;
		dwRecvLen = (DWORD)MAXSIZE_30;

		pdwRecvLen = &dwRecvLen;
//		pwSW = &sW;

		if(!(g_objReader.SendCommandI(pcCmdHead,dwDataLen,pbRecv,pdwRecvLen,pwSW,TRUE)))
		{
			AfxMessageBox(_T("命令发送失败4!"));
			g_objReader.DisConnect();
			pDlg->SetDlgItemText(IDC_SN_NUM,zero);
			continue;
		}
		
		memcpy(tmp,pbRecv+15,baSN.GetSize());
		if(strncmp(snArray,tmp,5)==0)

		{	
			dlg.MessageboxDlgRight();
//			AfxMessageBox(_T("√"));
// 			Sleep(3000);
// 			HWND hwnd = ::FindWindow(NULL,"ReadShoter");
		}
		else
		{
//			AfxMessageBox(_T("×"));
			dlg.MessageboxDlgWrong();
		}
		//清除输入框

		pDlg->SetDlgItemText(IDC_SN_NUM,zero);

		free(pbRecv);

		g_objReader.DisConnect();
	}
	
	delete pDlg;

	return 0;
}

void CReadShoterDlg::MessageboxDlgRight()
{
// 模态
// 	Message msg;
// 	msg.DoModal();

//非模态
	Message *pMsg = new Message;
	pMsg->Create(IDD_Message_DIALOG,NULL);
	pMsg->ShowWindow(SW_SHOWNORMAL);
	pMsg->UpdateWindow();
	Sleep(2000);
	pMsg->SendMessage(WM_CLOSE);
	delete pMsg;
} 

void CReadShoterDlg::MessageboxDlgWrong()
{
	// 模态
	// 	Message msg;
	// 	msg.DoModal();
	
	//非模态
	Message *pMsg = new Message;
	pMsg->Create(IDD_MSG_WRONG,NULL);
	pMsg->ShowWindow(SW_SHOWNORMAL);
	pMsg->UpdateWindow();
	Sleep(3000);
	pMsg->SendMessage(WM_CLOSE);
	delete pMsg;
} 


/************************************************************************/
/* 函数功能:设置注册表键值 */
/* 入参:  无 */
/*   */
/* 出参:  无 */
/* 返回值:  无 */
/*   */
/************************************************************************/
void CReadShoterDlg::SetRegedit()
{
	HKEY hKey = 0;
	HKEY hSubKey = 0;
	DWORD dwKeyValue = 1;
	DWORD dwSize =0;
	DWORD dwValue = 0;
	// char* pchPath = "SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_1a2c&Pid_0002&MI_00";
	char acTemp[MAX_PATH] = {0};//\\5&2c5c6891&0&4\\Device Parameters";
	DWORD dwTempLen = 0;
	char abSubKeyName[MAX_PATH] = {0};
	DWORD dwSubKeyNameLen = 0;
	DWORD i = 0;
	DWORD dwRet = 0;
	DWORD dwFlagModify = 0;
	TCHAR athPchPath[MAX_PATH] = {0};
	CString strMidVar;

	BOOL				m_bFirstFlag;

	if (m_strarrMidVar.GetSize()==0)
	{
		AfxMessageBox("CCID读卡器,设置注册表键值失败!");
	}

	for (int j = 0; j < m_strarrMidVar.GetSize(); j++)
	{
		strMidVar = m_strarrMidVar.GetAt(j);
		strcpy(athPchPath,strMidVar.GetBuffer(0)); 

		RegCreateKey(HKEY_LOCAL_MACHINE,athPchPath,&hKey);
		if( !hKey )
		{
			AfxMessageBox("CCID读卡器,设置注册表键值失败!");
			return ;
		}

		i = 0;

		while(1)
		{
			dwTempLen = sizeof(acTemp);
			memset(acTemp,0,dwTempLen);

			dwSubKeyNameLen = sizeof(abSubKeyName);
			memset(abSubKeyName,0,dwSubKeyNameLen);

			if( ERROR_SUCCESS != RegEnumKeyEx(
				hKey, i++,abSubKeyName,&dwSubKeyNameLen, 0,0, 0,0) ||!sprintf(acTemp,"%s\\%s\\Device Parameters",athPchPath,abSubKeyName) ||ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,acTemp,&hSubKey) )
			{
				if(hSubKey)
				{
					RegCloseKey(hSubKey);
				}
				hSubKey = 0;
				
				break;
			}



			if(ERROR_SUCCESS != RegQueryValueEx(hSubKey,"EscapeCommandEnable",0,NULL,NULL,&dwSize))  
			{
				m_bFirstFlag = TRUE;
//				AfxMessageBox("由于您是第一次使用本设备,本设备将进行相关的初始化设置,请稍后...");
//				GetDlgItem(IDC_DOWNLOAD_BUTTON)->EnableWindow(FALSE);
				Sleep(3000);
			}
			else if(ERROR_SUCCESS == RegQueryValueEx(hSubKey,"EscapeCommandEnable",0,NULL,(unsigned char*)&dwValue,&dwSize))
			{
				if (1 != dwValue)
				{
					m_bFirstFlag = TRUE;
//					AfxMessageBox("由于您是第一次使用本设备,本设备将进行相关的初始化设置,请稍后...");
//					GetDlgItem(IDC_DOWNLOAD_BUTTON)->EnableWindow(FALSE);
					Sleep(3000);
				}
				else
				{
					m_bFirstFlag = FALSE;
				}
			}
				else
				{
					m_bFirstFlag = FALSE;
				}

		dwRet = RegSetValueEx(hSubKey,"EscapeCommandEnable",0,REG_DWORD,(unsigned char*)&dwKeyValue,sizeof(dwKeyValue));
		}
	}

	if(hSubKey)
	{
		RegCloseKey(hSubKey);
	}
	hSubKey = 0;
}

/************************************************************************/
/* 函数功能:添加注册表项 */
/* 入参:  无 */
/*   */
/* 出参:  无 */
/* 返回值:  无 */
/*   */
/************************************************************************/
void CReadShoterDlg::RegeditDevice()
{
	HANDLE hToken = NULL;
	CString strPchPath1;
	CString strPchPath2;
	CString strPchPath3;
	CString strPchPath;


	strPchPath1 = _T("SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_a625&Pid_0902");
	strPchPath2 = _T("SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_a625&Pid_0902&MI_00");
	strPchPath3 = _T("SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_a625&Pid_0902&MI_01");

	m_strarrMidVar.Add(strPchPath1);
	m_strarrMidVar.Add(strPchPath2);
	m_strarrMidVar.Add(strPchPath3);

	SetRegedit();
	//StartInteractiveClientProcess(NULL, NULL, NULL, NULL, hToken);
} 

以上是个人的工作小节,写的可能自有自己能看懂。。。。。

【上篇】
【下篇】

抱歉!评论已关闭.