科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道C# 使用WIN32API来获取打印机

C# 使用WIN32API来获取打印机

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

     主要使用到winspool.drv中的EnumPrinters函数,代码如下:   [DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]   [re

作者:中国IT实验室 来源:中国IT实验室 2007年9月10日

关键字: 使用 C# 编程

  • 评论
  • 分享微博
  • 分享邮件
  

  主要使用到winspool.drv中的EnumPrinters函数,代码如下:

  [DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]

  [return: MarshalAs(UnmanagedType.Bool)]

  private static extern bool EnumPrinters ([MarshalAs(UnmanagedType.U4)] PRINTER_ENUM flags,

  [MarshalAs(UnmanagedType.LPStr)] string sName,

  uint iLevel,

  IntPtr pPrinterDesc,

  uint iSize,

  [MarshalAs(UnmanagedType.U4)] ref uint iNeeded,

  [MarshalAs(UnmanagedType.U4)] ref uint iReturned

  );   

  说明:Marshal属性提供了对托管代码与非托管代码见数据封送。  

  EnumPrinters 的 WIN32 API的定义如下:   

  BOOL EnumPrinters(

  DWORD Flags, // printer object types

  LPTSTR Name, // name of printer object

  DWORD Level, // information level

  LPBYTE pPrinterEnum, // printer information buffer

  DWORD cbBuf, // size of printer information buffer

  LPDWORD pcbNeeded, // bytes received or required

  LPDWORD pcReturned // number of printers enumerated

  );

  问题又来啦,EnumPrinters通过Level来获取PRINTER_INFO,而能获得打印机驱动的是PRINTER_INFO_2,而C#中又没有PRINTER_INFO_2结构,偶又开始晕了。。。。。

  查了半天资料,网上基本上都是PRINTER_INFO_1的定义,而PRINTER_INFO_2不同与PRINTER_INFO_1,其中还包括DEVMODE结构,非托管的结构套结构,偶开始飘了~~~~  

  最后发现与其在C#中定义结构来对应非托管的结构,还不如直接用类来替代。所以定义了两个类

  PRINTER_INFO_2以及DEVMODE(注:由于PRINTER_INFO_2中只用到了DEVMODE结构来接收打印机驱动的信息,所以只定义了这个类,对于其他类都没有做具体实现)。  

  在PRINTER_INFO_2中,对于所有的DWORD类型数据,全部对应到Int32类型上面,而对于所有LPTSTR、LPDEVMODE以及PSECURITY_DESCRIPTOR一律对应到IntPtr指针类型。  

  为了获取非托管中的数据,使用了一下函数获取打印机信息

  .

  PRINTER_INFO_2 pi = new PRINTER_INFO_2();

  //把数据从非托管内存传送到到托管内存  

  for(int i = 0; i < numPrinters; i++)

  {

  Marshal.PtrToStructure( prInfo, pi ); //prInfo是由上面EnumPrinters获得的打印机  

  string driver = Marshal.PtrToStringAuto( pi.pDriverName );  

  if ( printerdriver == "" driver.ToLower().IndexOf( printerdriver ) != -1)

  {  

  // 做相关处理 

  }

  prInfo = new IntPtr(prInfo.ToInt32() + Marshal.SizeOf(typeof(PRINTER_INFO_2))); // 获取下一个打印机信息段开始

  }

  .  

  问题至此基本解决。但C#中对非托管函数的调用,以及相互之间的数据封装还是一个比较难的地方,有空还需要整理一下。
  

  文章来源:http://spaces.msn.com/sharkoo/Blog/cns!D8E832CE4545AF!158.entry   

  补充:在2.0中,fixed关键字可以用于定义一个固定大小的数组缓存,而不是像1.x中那样还需要定义一个数字大小。但这种方式只能用于结构(struct)而不能用于类(class)的定义

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章