程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#(.Net) 配合WQL實現並口讀寫

C#(.Net) 配合WQL實現並口讀寫

編輯:關於C#

最近做開發,要對POS打印機就進行編程,說白了,也就是一個端口讀寫,再根據打印機說明實現幾個 POS指令就OK了,但是遇到了一個困難的問題,因為是無人系統,一個打印機打印客戶單據,一個打印歷 史單據,這個還不是最要命的,最要命的是一個是串口的,一個是並口的,對於串口還好辦,因為.Net裡 有現成的SerialPort類,可是並口就難了。

搜了一下網上的資料,不外乎兩種方法。

第一種是用win32 API來實現。見

http://support.microsoft.com/kb/823179/zh-cn

另一種方式是用第三方的動態連接庫inpout32.dll

http://www.codeproject.com/KB/vb/Inpout32_read.aspx

兩種方式,各有優劣。

如果用win32 API的話,操作固然方便,但是有一個死穴,就是無法讀並口的數據。

如果用inpout32呢,到是能讀能寫,但是並口的地址(0x378,0x379,0x37a)並不是一個固定值。

參見文檔

http://www.cnblogs.com/thunderdanky/articles/795010.html

但是客戶要求能實時檢測打印機狀態 。。 這個問題可是難住了一天。

怎麼辦?讓客戶自己到設備管理器裡去找並口基址?MS有點太土了。

後來看了一些資料,突然發現WQL好像可以實現查找串口基址的功能,實驗了一下,還真實現了,嘿嘿

好了,現在就貼代碼

1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Runtime.InteropServices;
5using System.Management;
6
7namespace SFTech.POSPrint
8{
9    /**//// <summary>
10    /// 串口類,IPort是抽像的端口類
11    /// </summary>
12    public class ParallelPort : IPort ,IDisposable
13    {
14
15        inpout32相關#region inpout32相關
16        [DllImport("inpout32.dll", EntryPoint = "Out32")]
17        public static extern void Output(uint adress, int value);
18
19        [DllImport("inpout32.dll", EntryPoint = "Inp32")]
20        public static extern int Input(uint adress);
21        [StructLayout(LayoutKind.Sequential)]
22        private struct OVERLAPPED
23        {
24            int Internal;
25            int InternalHigh;
26            int Offset;
27            int OffSetHigh;
28            int hEvent;
29        }
30        #endregion
31
32        win32 API#region win32 API
33        [DllImport("kernel32.dll ")]
34        private static extern int CreateFile(
35          string lpFileName,
36          uint dwDesiredAccess,
37          int dwShareMode,
38          int lpSecurityAttributes,
39          int dwCreationDisposition,
40          int dwFlagsAndAttributes,
41          int hTemplateFile
42          );
43        [DllImport("kernel32.dll ")]
44        private static extern bool WriteFile(
45          int hFile,
46          byte[] lpBuffer,
47          int nNumberOfBytesToWrite,
48          ref   int lpNumberOfBytesWritten,
49          ref   OVERLAPPED lpOverlapped
50          );
51        [DllImport("kernel32.dll ")]
52        private static extern bool CloseHandle(
53          int hObject
54          );
55        [DllImport("kernel32.dll ")]
56       private static extern bool ReadFile(
57          int hFile,
58          out byte[] lpBuffer,
59          int nNumberOfBytesToRead,
60          ref int lpNumberOfBytesRead,
61          ref OVERLAPPED lpOverlapped
62        );
63
64        private int iHandle;
65
66        private bool _isWork;
67
68        private const uint  GENERIC_READ = 0x80000000;
69        private const uint GENERIC_WRITE = 0x40000000;
70        #endregion
71        IPort 成員#region IPort 成員
72
73
74        private bool _IsOpen;
75        public bool IsOpen
76        {
77            get
78            {
79                return _IsOpen;
80            }
81            private set
82            {
83                _IsOpen = value;
84            }
85        }
86
87        private string _Name;
88        public string Name
89        {
90            get
91            {
92                return _Name;
93            }
94            set
95            {
96                _Name = value;
97            }
98        }
99
100        public bool WriteData(byte[] Data)
101        {
102            //for (int i = 0; i < Data.Length; i++)
103            //    Output(BasePort, Data[i]); 這裡原來也想用inpout32實現, 但是從字節到int轉換比較麻煩,試了幾次沒達到效果
104            //return true;
105
106            if (iHandle != -1)
107            {
108                OVERLAPPED x = new OVERLAPPED();
109                int i = 0;
110                WriteFile(iHandle, Data, Data.Length,
111                  ref   i, ref   x);
112                return true;
113            }
114            else
115            {
116                //throw new Exception("不能連接到打印機! ");
117                return false;
118            }
119        }
120
121
122        /**//// <summary>
123        /// 讀狀態
124        /// 用inpout32
125        /// </summary>
126        /// <param name="Len"></param>
127        /// <returns></returns>
128        public byte[] ReadData(int Len)
129        {
130            byte[] result ;//= new byte[Len];
131            result = new byte[Len];
132            for (int i = 0; i < result.Length; i++)
133                result[i] = (byte)Input(BasePort + 1);
134            return result;
135        }
136
137
138        /**//// <summary>
139        /// 打開端口
140        /// </summary>
141        public void Open()
142       {
143           iHandle = CreateFile(Name, 0x40000000, 0, 0, 3, 0, 0);
144           if (iHandle != -1)
145           {
146               this.IsOpen = true;
147           }
148           else
149           {
150               this.IsOpen = false;
151           }
152
153           this.IsOpen = true;
154           _isWork = true;
155           //開一個線程檢測狀態口狀態
156           new System.Threading.Thread(new System.Threading.ThreadStart (ReadState)).Start();
157        }
158
159
160        /**//// <summary>
161        /// 關閉端口
162        /// </summary>
163        public void Close()
164        {
165           this.IsOpen =  !CloseHandle(iHandle);
166           _isWork = false;
167        }
168
169        /**//// <summary>
170        /// 端口基址
171        /// </summary>
172        private uint BasePort { get; set; }
173        internal ParallelPort(String portName)
174        {
175            this.Name = portName;
176            iHandle = -1;
177
178            /**////用wql查詢串口基址
179            ManagementObjectSearcher search2 =
180                    new ManagementObjectSearcher(
181                        "ASSOCIATORS OF {Win32_ParallelPort.DeviceID='" + this.Name  + "'}");
182            //本來最佳的wql是ASSOCIATORS OF {Win32_ParallelPort.DeviceID='" + this.Name  + "'} WHERE ASSCICLASS = Win32_PortResource
183            //但是不知道為什麼不返回結果,所以就做一個簡單的遍歷吧
184            foreach (var i in search2.Get())
185            {
186
187                if (i.ClassPath.ClassName == "Win32_PortResource")
188                {
189                    //得到串口基址 大多數是0x378H
190                    this.BasePort = System.Convert.ToUInt32( i.Properties["StartingAddress"].Value.ToString());
191
192                    break;
193                }
194
195
196            }
197            if (BasePort == 0)
198                throw new Exception("不是有效端口");
199            IsOpen = false;
200        }
201
202        #endregion
203
204        IPort Members#region IPort Members
205
206        public event PortStateChanged StateChanged;
207
208        public event PortDataReceived DataReceive;
209
210        public System.Windows.Forms.Form Parent
211        {
212            get
213            {
214                throw new NotImplementedException();
215            }
216            set
217            {
218                throw new NotImplementedException();
219            }
220        }
221
222        private int a { get; set; }
223
224        /**//// <summary>
225        /// 檢測線程,當狀態改變時,引發事件
226        /// </summary>
227        private void ReadState()
228        {
229
230            a = 0;
231            int lastRead =a;
232            while (_isWork)
233            {
234                lastRead = a;
235                a = Input(BasePort + 1);
236                if (a != lastRead)
237                {
238                    if (this.StateChanged != null)
239                    {
240                        PortChangedEvntAvrgs e = new PortChangedEvntAvrgs();
241                        e.PortStatusByte = a;
242                        this.StateChanged(this, e);
243                    }
244                  
245                }
246                System.Threading.Thread.Sleep(500);
247
248            }
249        }
250        #endregion
251
252        IDisposable Members#region IDisposable Members
253
254        public void Dispose()
255        {
256            this.Close();
257        }
258
259        #endregion
260
261        IPort Members#region IPort Members
262
263
264        public void Update()
265        {
266            a = 0;
267        }
268
269        #endregion
270    }
271}
272

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved