如何发送文件到网络打印机,并打印(使用C#)?

如何发送文件到网络打印机,并打印(使用C#)?,第1张

问题

.Net Framework 1.1给我们提供了一个PrinterSettings类,以提供指定有关文档打印方式的信息,其中包括打印文档的打印机。其中的静态属性InstalledPrinters可以使我们获取安装在计算机上所有打印机的名称。

但是可惜的是,该属性仅仅能够提供已安装的打印机的名称。对于获取该打印机的相关信息(如打印机类型等)却无能为力。问题就产生了,由于客户无法提供打印机的SDK,所以对打印机的筛选(处于商业目的,客户要求软件只能在使用他们的打印机时才能输出)只能通过打印机驱动的辨认来实现。

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

解决方案一 使用WMI获取打印机信息

WMI,全称Windows Management Instrumentation。是可伸缩的系统管理结构,它采用一个统一的、基于标准的、可扩展的面向对象接口。WMI 为您提供与系统管理信息和基础 WMI API 交互的标准方法。WMI 主要由系统管理应用程序开发人员和管理员用来访问和 *** 作系统管理信息。

.Net Framework中System.Management类提供了对WMI的支持,其中ManagementObjectSearcher用于根据指定的查询或枚举检索 ManagementObject 或 ManagementClass 对象的集合。

/**//// <summary>

/// Code 1:WMI搜索示例

/// <summary>

/// <param name="strDrivername">驱动名称</param>

/// <returns>返回找到的打印机列表</returns>

/// <remarks>strDrivername支持”%“以及”_“通配符查询,类似于SQL语句中的查询<remarks>

public StringCollection GetPrintsWithDrivername( string strDrivername )

{

StringCollection scPrinters = new StringCollection()

string strcheck = ""

if( strDrivername !="" &&strDrivername != "*" )

strcheck = " where DriverName like \'" + strDrivername + "\'"

string searchQuery = "SELECT Name FROM Win32_Printer" + strcheck

ManagementObjectSearcher searchPrinters =

new ManagementObjectSearcher(searchQuery)

ManagementObjectCollection printerCollection = searchPrinters.Get()

foreach(ManagementObject printer in printerCollection)

{

string printname = printer.Properties["Name"].Value.ToString()

scPrinters.Add(printname)

}

searchPrinters.Dispose()

printerCollection.Dispose()

return scPrinters

}

问题看上去基本解决了,运行程序的确是获得了正确的打印机列表。可是用户用了一段时间后发现,有的时候打印机无法正确获得,看来DOTNET调用WMI稳定性的确有点问题啊。。。。。。

WMI本身功能还是相当强大的,通过VBS基本可以涵盖WINDOWS最基本的 *** 作。详细可以参加MSDN的文档。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp

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

解决方案二 使用WIN32API获取打印机

转来转去,又回到WIN32API上来了,无奈啊。。。。。。怪不得C++依然这么吃香 啊。。。。。

.Net给我们提供了DllImport来 *** 作非托管的DLL(发现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 = 0i <numPrintersi++)

{

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)的定义。

DOS 命令 PRINT 可以打印 文本文件。

例如:

PRINT /D:\\MYNETWORK\PS_Printer A.IN

/D:\\MYNETWORK\PS_Printer -- 打印设备,我的网络上的打印机

A.IN -- 要打的文件名,可以含路径

C 语言中函数 system("命令字符串")

把DOS命令字符串填入,就执行DOS命令。

网络打印机的使用方法

在NOVELL NETWARE网络系统中,有一个网络打印命令NP

RINT,用此命令可以把要打印的文件送到网络打印机打印出来。但是使用

NPRINT命令打印的文件内容必须是ASCII码形式,或者能用TYP

E命令显示文件内容。对不能用TYPE命令显示的文件(可执行文件除外)

,如何使用网络打印机打印呢?笔者在工作中经过实践总结出以下几点使用方

法:

一、打印TYPE命令不能显示的文件

用TYPE命令不能显示的文件,只能在不同的应用环境下发布打印命令

。具体 *** 作是:

1.注册上网后,在“>”提示符下键入捕获命令:CAPTURE;

2.进入不同的应用程序,发布不同的打印命令:

例1:在QUICK BASIC环境下要打印程序,则在FILE菜单

下,将光标移到PRINT,并回车,即可从网络打印机上打印出你所需要的

文件。当你退出QUICK BASIC环境,回到“>”时应立即键入EN

DCAP命令结束捕获。

例2:在FOXBASE环境下,若要打印数据库结构或记录时,则按以

下步骤 *** 作:

(1)打开数据库:USE数据库名

(2)打印库结构:LIST STUR TO PRINT

打印记录:LIST TO PRINT

(3)结束打印:在“>”提示符下键入命令ENDCAP结束捕获。

二、打印屏幕信息

在应用程序环境下打印屏幕信息,只要在启动应用程序之前,即在“>”

提示符下发CAPTURE命令,启动应用程序后若要打印屏幕信息,则同时

按下SHIFT和PRINT SCREEN两键即可,当退到DOS环境后

应立即发ENDCAP命令。

例如:在FOXBASE环境下打印屏幕信息有两种方法:

第一种方法:在启动FOX之前,发CAPTURE命令,启动FOX后,如果要打

印屏幕信息,则同时按下SHIFT和PRINT SCREEN即可打印信息。

第二种方法:在“·”提示符下,键入两条命令:

SET DEVICE TO PRINTER

SET PRINTER TO \\SPOOLER

键入这两条命令后,凡是选用…TO PRINT命令,均可把内容送到网络打印机

打印。若不想打印,则应发以下两条命令:

SET PRINTER TO

SET DEVICE TO SCREEN

如果要在FOX程控方式下进行报表打印,则只需将以下命令嵌入FOX程序中,即

SET DEVICE TO PRINTER

SET PRINTER TO \\SPOOLER

打印格式语句

SET PRINTER TO

SET DEVICE TO SCREEN

以上经实验已在网络环境下通过。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/sjk/9933674.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-03
下一篇2023-05-03

发表评论

登录后才能评论

评论列表(0条)

    保存