C# 使用 Windows API 发送文件到打印机
最近需要做一个打印的功能,于是在网上找到了这么一个方法。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pDataType;
} public class PrintCode
{
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd); [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di); [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten); /// <summary>
/// 该方法把非托管内存中的字节数组发送到打印机的打印队列
/// </summary>
/// <param name="szPrinterName">打印机名称</param>
/// <param name="pBytes">非托管内存指针</param>
/// <param name="dwCount">字节数</param>
/// <returns>成功返回true,失败时为false</returns>
public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
{
Int32 dwError = , dwWritten = ;
IntPtr hPrinter = new IntPtr();
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; di.pDocName = "My C#.NET RAW Document";
di.pDataType = "RAW"; try
{
// 打开打印机
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
// 启动文档打印
if (StartDocPrinter(hPrinter, , di))
{
// 开始打印
if (StartPagePrinter(hPrinter))
{
// 向打印机输出字节
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
}
}
catch (Win32Exception ex)
{
WriteLog(ex.Message);
bSuccess = false;
}
return bSuccess;
} /// <summary>
/// 发送文件到打印机方法
/// </summary>
/// <param name="szPrinterName">打印机名称</param>
/// <param name="szFileName">打印文件的路径</param>
/// <returns></returns>
public static bool SendFileToPrinter(string szPrinterName, string szFileName)
{
bool bSuccess = false;
try
{
// 打开文件
FileStream fs = new FileStream(szFileName, FileMode.Open); // 将文件内容读作二进制
BinaryReader br = new BinaryReader(fs); // 定义字节数组
Byte[] bytes = new Byte[fs.Length]; // 非托管指针
IntPtr pUnmanagedBytes = new IntPtr(); int nLength; nLength = Convert.ToInt32(fs.Length); // 读取文件内容到字节数组
bytes = br.ReadBytes(nLength); // 为这些字节分配一些非托管内存
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength); // 将托管字节数组复制到非托管内存指针
Marshal.Copy(bytes, , pUnmanagedBytes, nLength); // 将非托管字节发送到打印机
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength); // 释放先前分配的非托管内存
Marshal.FreeCoTaskMem(pUnmanagedBytes); fs.Close();
fs.Dispose();
}
catch (Win32Exception ex)
{
WriteLog(ex.Message);
bSuccess = false;
}
return bSuccess;
} /// <summary>
/// 将字符串发送到打印机方法
/// </summary>
/// <param name="szPrinterName">打印机名称</param>
/// <param name="szString">打印的字符串</param>
/// <returns></returns>
public static bool SendStringToPrinter(string szPrinterName, string szString)
{
bool flag = false;
try
{
IntPtr pBytes;
Int32 dwCount; // 获取字符串长度
dwCount = szString.Length; // 将字符串复制到非托管 COM 任务分配的内存非托管内存块,并转换为 ANSI 文本
pBytes = Marshal.StringToCoTaskMemAnsi(szString); // 将已转换的 ANSI 字符串发送到打印机
flag = SendBytesToPrinter(szPrinterName, pBytes, dwCount); // 释放先前分配的非托管内存
Marshal.FreeCoTaskMem(pBytes);
}
catch (Win32Exception ex)
{
WriteLog(ex.Message);
flag = false;
}
return flag;
} /// <summary>
/// 写入日志方法
/// </summary>
/// <param name="msg">记录信息</param>
public static void WriteLog(string msg)
{
string str = string.Empty;
string path = AppDomain.CurrentDomain.BaseDirectory + "log\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt"; FileStream filestream = new FileStream(path, FileMode.OpenOrCreate); str += "************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "************\r\n";
str += msg;
str += "************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "************\r\n"; FileStream fs = new FileStream(path, FileMode.Append);
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);
sw.WriteLine(str); sw.Flush(); sw.Close();
sw.Dispose(); fs.Close();
fs.Dispose();
}
}
以上就是全部代码了,调用就很简单了,方法如下:
private void Print_Click(object sender, EventArgs e)
{
//打印文件的路径,该方法获取到的文件路径在应用程序 bin\Debug\ 目录下,所以 ../../ 向上两级目录
string fileName = AppDomain.CurrentDomain.BaseDirectory + @"../../File/demo.txt"; if (PrintCode.SendFileToPrinter("PrinterName", fileName))
{
MessageBox.Show("文件已成功发送至打印队列!","提示信息");
}
}
C# 使用 Windows API 发送文件到打印机的更多相关文章
- ansible管理windows (发送文件)
https://github.com/ansible/ansible/raw/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 环境: 服务 ...
- 使用Windows API发送HTTP请求
先看一个简单的GET示例 #include <Windows.h> #include <winhttp.h> #include <stdio.h> int main ...
- MT4调用Windows API进行文件读写操作
/*导入相关函数*/ #import "kernel32.dll" int CreateDirectoryW(string directoryName,int type); int ...
- 【转】用C#调用Windows API向指定窗口发送
一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.InteropServices; 2.引用需要使用的方法,格式 ...
- 用C#调用Windows API向指定窗口发送按键消息 z
用C#调用Windows API向指定窗口发送 一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.Interop ...
- 用C#调用Windows API向指定窗口发送按键消息
一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.InteropServices; 2.引用需要使用的方法,格式 ...
- 用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle)完成文件拷贝程序(初级版)
文件拷贝程序 程序类型:Console 参数:源文件名 目的文件名 要求:1.只能使用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle ...
- LoadLibrary文件路径及windows API相关的文件路径问题
LoadLibrary HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName ); Loads the specified module into ...
- 学习:Windows API核心DLL文件
在 Windows 的系统目录中,存在着很多的动态链接库文件(DLL 文件).这些 DLL 文件中包括了 Windows API 函数可执行程序. DLL 将各函数"导出",这样应 ...
随机推荐
- php -- each()、list()
1.each的用法 先看API:array each ( array &$array ) api里是这么描述的:each — 返回数组中当前的键/值对并将数组指针向前移动一步 我们先来看看返回 ...
- install phalcon on mac with XAMPP
首先使用brew安装对应版本的phalcon,参考https://docs.phalconphp.com/en/latest/reference/tutorial.html 安装好后会有 phalco ...
- JavaScript的parseint()函数
定义和用法 parseInt() 函数可解析一个字符串,并返回一个整数. 语法 parseInt(string, radix) 参数 描述 string 必选项.要转换为数字的字符串. radix 可 ...
- UNMET PEER DEPENDENCY @angular/common@2.3.1
install of angular-cli results in unmeet peer dependencies. OSX 10.11.6node v6.9.1npm v3.10.8 [sudo] ...
- Angular 组件与模板 - 属性指令
指令概览 在 Angular 中有三种类型的指令: 组件 — 拥有模板的指令 结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令 属性型指令 — 改变元素.组件或其它指令的外观和行为 ...
- 复习及总结--.Net线程篇(4)
这里要说的就是多线程的锁的问题了 锁:作用在于实现线程间的同步问题,最典型的是售票问题 1,InterLocked 提供的都是静态方法,用来同步对多个共享变量的访问,包括以原子方式递增,递减,比较和替 ...
- ProcessBuilder执行本地命令
/**关键技术剖析 * 用本命令名和命令的参数选项构造ProcessBuilder对象,它的start方法执行命令,启动一个进程,返回一个Process对象 * ProcessBuilder的envi ...
- String、StringBuffer与StringBuilder区别
1.三者在执行速度方面的比较:StringBuilder > StringBuffer > String 2.String <(StringBuffer,StringBuild ...
- 折腾deeplin系统
1.双系统失败记录 多系统启动问题 先安装完deepin,发现再安装windows怎么都起不起来,哪怕他们已经安装在不同的盘 (体现再Windows7通过ghost位于另外一个盘,但就是没有启动项) ...
- centos7上开启路由转发
CentOS7 开启路由转发 2018-03-27 09:18:14 1.临时开启,(写入内存,在内存中开启) echo "1" > /proc/sys/net/ipv4 ...