1. 程式人生 > >VC++ 動態檢測串列埠的熱插拔

VC++ 動態檢測串列埠的熱插拔

在串列埠程式設計中經常需要知道串列埠號,用來配置串列埠,可是沒有好的辦法,只能進到裝置管理器中去看,那麼如何能夠實現軟體的自動檢測串列埠號,並且可支援熱插拔檢測那?

下面將講述兩種方法來實現這種效果:一種是遍歷裝置列表中的所有串列埠0-255,二是通過讀去登錄檔來實現檢測

在這篇文章中將只講述迴圈遍歷方法的實現,在下一篇文章中將講述利用登錄檔方法的實現

---------------------------------------------------

第一種方法是一種比較簡單也比較笨的方法,對於每一個串列埠一個一個的去試,試完了也就知道了,計算機一般支援0-255即256個串列埠,可是利用CreateFile建立串列埠,只能成功建立COM0-COM9串列埠裝置,而COM10及以上的串列埠建立CreateFile就會返回-1,因為10及以上已經超出的裝置的命名規範,需要使用\$device\COM10方式,作為引數傳遞給CreateFile。

You   can   use   paths   longer   than   MAX_PATH   characters   by   calling   the   wide   (W)   version   of  CreateFile   and   prepending   "\\?\"   to   the   path.   The   "\\?\"   tells   the   function   to   turn   off   path  parsing.   This   lets   you   use   paths   that   are   nearly   32,000   Unicode   characters   long.   However,  each   component   in   the   path   cannot   be   more   than   MAX_PATH   characters   long.   You   must  use   fully-qualified   paths   with   this   technique.   This   also   works   with   UNC   names.   The   "\\?\"   is  ignored   as   part   of   the   path.   For   example,   "\\?\C:\myworld\private"   is   seen   as  "C:\myworld\private",   and   "\\?\UNC\tom_1\hotstuff\coolapps"   is   seen   as   "\\tom_1\hotstuff\coolapps".

1.遍歷所有串列埠原始碼:

OnInitDialog初始化視窗

  1. BOOL CDetectComDlg::OnInitDialog() 
  2.     CDialog::OnInitDialog(); 
  3.     ASSERT((IDM_ABOUTBOX 0xFFF0) == IDM_ABOUTBOX); 
  4.     ASSERT(IDM_ABOUTBOX 0xF000); 
  5.     CMenu* pSysMenu GetSystemMenu(FALSE); 
  6.     if (pSysMenu != NULL) 
  7.     
  8.         CString strAboutMenu; 
  9.         strAboutMenu.LoadString(IDS_ABOUTBOX); 
  10.         if (!strAboutMenu.IsEmpty()) 
  11.         
  12.             pSysMenu->AppendMenu(MF_SEPARATOR); 
  13.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
  14.         
  15.     
  16.     SetIcon(m_hIcon, TRUE);         // 設定大圖示
  17.     SetIcon(m_hIcon, FALSE);        // 設定小圖示
  18.     DWORD sStyle m_ListShow.GetExtendedStyle(); 
  19.     sStyle |= LVS_EX_GRIDLINES; 
  20.     sStyle |= LVS_EX_FULLROWSELECT; 
  21.     m_ListShow.SetExtendedStyle(sStyle); 
  22.     m_ListShow.InsertColumn(0,_T("索引"),LVCFMT_LEFT,100); 
  23.     m_ListShow.InsertColumn(1,_T("串列埠號"),LVCFMT_LEFT,100); 
  24.     TraversalCom(); //遍歷Com口
  25.     return TRUE; 
TraversalCom函式
  1. void CDetectComDlg::TraversalCom(void
  2.     EnumerateSerialPorts(ports,portse,portsu); 
  3.     unsigned short Counter; 
  4.     unsigned short Setcom; 
  5.     CString str; 
  6.     //獲取可用串列埠個數
  7.     Counter portse.GetSize(); 
  8.     //如果個數大於0
  9.     if(Counter 0) 
  10.     
  11.         //初始化串列埠列表框
  12.         for(int i=0; i
  13.         
  14.             Setcom portse.ElementAt(i); 
  15.             str.Format("%d",i); 
  16.             m_ListShow.InsertItem(i,str); 
  17.             str.Format(_T("COM%d "),Setcom); 
  18.             m_ListShow.SetItemText(i,1,str); 
  19.         
  20.     
EnumerateSerialPorts函式
  1. void CDetectComDlg::EnumerateSerialPorts(CUIntArray& ports, CUIntArray& portse, CUIntArray& portsu) 
  2.     //清除串列埠陣列內容
  3.     ports.RemoveAll(); 
  4.     portse.RemoveAll(); 
  5.     portsu.RemoveAll(); 
  6.     //因為至多有255個串列埠,所以依次檢查各串列埠是否存在
  7.     //如果能開啟某一串列埠,或開啟串列埠不成功,但返回的是 ERROR_ACCESS_DENIED錯誤資訊,
  8.     //都認為串列埠存在,只不過後者表明串列埠已經被佔用,否則串列埠不存在
  9.     for (int i=1; i<256; i++) 
  10.     
  11.         //Form the Raw device name
  12.         CString sPort; 
  13.         sPort.Format(_T("\\\\.\\COM%d"), i); 
  14.         //Try to open the port
  15.         BOOL bSuccess FALSE; 
  16.         HANDLE hPort ::CreateFile(sPort, GENERIC_READ GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 
  17.         if (hPort == INVALID_HANDLE_VALUE) 
  18.         
  19.             DWORD dwError GetLastError(); 
  20.             if (dwError == ERROR_ACCESS_DENIED) 
  21.             
  22.                 bSuccess TRUE; 
  23.                 portsu.Add(i);       //已佔用的串列埠
  24.             
  25.         
  26.         else
  27.         
  28.             //The port was opened successfully
  29.             bSuccess TRUE; 
  30.             portse.Add(i);      ////可用的串列埠
  31.             //Don't forget to close the port, since we are going to do nothing with it anyway
  32.             CloseHandle(hPort); 
  33.         
  34.         //Add the port number to the array which will be returned
  35.         if (bSuccess) 
  36.             ports.Add(i);   //所有存在的串列埠
  37.     

這時再剛登陸視窗時便可羅列出可用串列埠。

2.檢測串列埠的熱插拔

這裡主要利用Cwnd的ON_WM_DEVICECHANGE訊息來處理。
ON_WM_DEVICECHANGE訊息在VS是通過手動新增的

注意:此訊息只有頂層視窗可以捕獲到
因此,首先得手動新增ON_WM_DEVICECHANGE訊息:
第一步:在訊息對映BEGIN_MESSAGE_MAP(Ctbox_debug_viewDlg, CDialogEx)中新增:

  1. 相關推薦

    MFC學習筆記 — VC++中自動檢測串列事件

    文章出處:(轉載文章,如有不妥,通知後我會立即刪除) 文章索引1 文章索引2 這裡主要利用Cwnd的ON_WM_DEVICECHANGE訊息來處理。 Windows作業系統傳送WM_DEVICECHANGE有些限制: 1、只有頂層窗體的程式才能收到這個訊息; 2、

    VC++ 動態檢測串列(一)通過登錄檔實現

    在上一篇文章中講述瞭如何通過迴圈遍歷的方法獲取可用串列埠,可是這樣的方法過於暴力,難免會想有沒有其他的辦法那,嘿嘿,那是肯定會有的,不管什麼問題,解決問題的方法永遠都不止一種。下面講述如何通過登錄檔來獲取可用串列埠。 大家都知道,通過裝置管理器我們可以看到可用串列埠號的

    VC++ 動態檢測串列

    在串列埠程式設計中經常需要知道串列埠號,用來配置串列埠,可是沒有好的辦法,只能進到裝置管理器中去看,那麼如何能夠實現軟體的自動檢測串列埠號,並且可支援熱插拔檢測那? 下面將講述兩種方法來實現這種效果:一種是遍歷裝置列表中的所有串列埠0-255,二是通過讀去登錄檔來實現檢測 在這篇文章中

    USB轉串列檢測

             上位機與裝置進行串列埠通訊之前都需要指定PC通訊的串列埠號,這無疑給操作上帶來不便,更痛苦的是每次都得到裝置管理器檢視當前連線的串列埠。          那麼如何通過程式碼獲取當前可用串列埠列表?一是通種登錄檔獲取,操作比較複雜;微軟為我們提供更簡單

    QT第三方串列類Win_QextSerialPort,串列工具後無法繼續使用問題

    if(myCom!=NULL){ myCom->close(); myCom->setParent(NULL); delete myCom; myCom=NULL; } myCom =

    qt linux下自動檢測U盤

    如果用U盤來更新軟體,需要先刪除當前的可執行檔案,但是如果刪除之後,複製失敗的話會導致後續沒有檔案可以運行了。一個方法是將新的可執行檔案放到另一個目錄中,當copy成功後修改linux的啟動檔案,然後reboot.    使用qt自帶的QDBus可以實現。 D-B

    linux app應用如何檢測USB裝置

    框架是這樣的。原理就是建立一個socket捕獲核心發過來的netlink訊息,很簡單的。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <

    MFC檢測串列

    以對話方塊工程為例 標頭檔案中 afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData); cpp中 ON_WM_DEVICECHANGE() 然後實現函式 BOOL CXXDlg::OnDeviceChang

    HDMI/DVI 顯示器檢測原理(HPD)

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

    關於windows檢測的個人理解(使用Qt開發)

    在Qt中每一個視窗類(widget)都有一個處理windows訊息的函式,當windows出現熱插拔事件的時候,會向每個視窗傳送相應的WM_訊息,在Qt下,最終將調到natevieEvent函式;下面以QWidget為例: virtual bool QWidget::nat

    【玩轉開源】Linux C 檢測網口

    int NetDetect(char *net_name, int *statue) { int ret = 0; int skfd = 0; struct ifreq ifr; skfd = socket(AF_INET, SOCK_DGRAM, 0); //建議s

    linux c檢測網線(netlink)

    #include <sys/types.h> #include <sys/socket.h> #include <asm/types.h> #include <linux/netlink.h> #include

    Linux下自動檢測USB

    做嵌入式開發,尤其在閘道器、路由器或者其他支援USB裝置的終端上,為了提高使用者體驗,我們常常需要支援自動識別並掛載USB裝置功能。某些應用程式,在使用USB裝置的過程中,也希望能夠偵測到USB斷開事件,不至於某些工作因為USB已經不存在而白做。在Linux下,我們主要有

    libvirt-內存分配和內存

    簡單的 nbsp mman src 疑惑 get 使用 熱插拔 加載 在使用libvirt給虛擬機分配內存大小時,涉及到memory和currentMemory兩個字段,很多人都有這個疑惑,為什麽需要兩個呢。其實是和內存氣泡動態調整內存有關系的。簡單的來說,me

    【產品功能】配置網卡從此與關機無緣,彈性網卡支持功能

    控制臺摘要: 本文主要介紹了彈性網卡的熱插撥功能改進,彈性網卡插拔對應的實例不再要求必須為 Stopped 狀態,現在只要求是穩定狀態( Running Stopped )即可。以及介紹了控制臺、OpenAPI如何對彈性網卡進行熱插拔操作。背景在雲計算飛速發展的今天,用戶ECS服務器身處的網絡環境越來越復雜,

    記一次U盤導致的問題

    解決 顯示 沒有 設備管理器 網上 提示 導致 電腦 boot 32G U盤拿過來做啟動盤,全部刻印好了,在新電腦上啟動PE,進行分區的時候卡住了,直接就拔出U盤。導致的問題是:之前把U盤刻印啟動盤的電腦,已經新電腦上都識別不出來U盤。問題:電腦上設備管理器上能顯示出U盤,

    在 ESXi 6.x和5.x虛擬機中禁用添加/功能

    客戶端 警告選項 虛機 所有 man nic win manage 下一步 現象:網卡和 SCSI 控制器顯示為可移除設備。與該虛擬硬件對應的“安全移除硬件”選項顯示在 Windows 系統任務欄中。如果正在使用 VMware View,您會註意到具有持久磁盤的 View

    詳解oracle 12c數據庫新特征CDB與PDB(數據庫)以及表空間管理

    dia emp 圖片 朋友 不可 管理 ada pfile esp 表空間概念 表空間是數據庫的邏輯劃分,一個表空間只能屬於一個數據庫。所有的數據庫對象都存放在指定的表空間中。但主要存放的是表, 所以稱作表空間。Oracle數據庫中至少存在一個表空間,即SYSTEM的表空間

    C# Winform下一個的MIS/MRP/ERP框架(多語言方案)

    文件加載 全局 查詢 分享 技術 變量 支持 對象 style 個別時候,我們需要一種多語種切換方案。   我的想方案是這樣的: 1、使用文本文本存儲多語言元素,應用程序啟動時加載到內存表中; 2、應用程序啟動時從配置文件加載語種定義; 3、所有窗體繼承自一個Base

    C# Winform下一個的MIS/MRP/ERP框架11(啟航)

    aer tab chan byname 可能 清理 contex cati break   初學時,有了想法卻完全不知道該從何下指,此序列將拋磚引玉,與大家共同學習進步。   一個程序的初始,必然是啟動。   我的要求:   1、應用程序保持單例;   2、從配置文件加載一