C#(.Net) 配合WQL实现并口读写

作者:控件中国网   出处:控件中国网   2014-09-17 16:10:47   阅读:2

最近做开发,要对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好像可以实现查找串口基址的功能,实验了一下,还真实现了,嘿嘿

好了,现在就贴代码

Code
  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

Copyright© 2006-2015 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 渝ICP备12000264号 法律顾问:元炳律师事务所
客服软件
live chat