最近需要做一个打印的功能,于是在网上找到了这么一个方法。

  [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 发送文件到打印机的更多相关文章

  1. ansible管理windows (发送文件)

    https://github.com/ansible/ansible/raw/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 环境: 服务 ...

  2. 使用Windows API发送HTTP请求

    先看一个简单的GET示例 #include <Windows.h> #include <winhttp.h> #include <stdio.h> int main ...

  3. MT4调用Windows API进行文件读写操作

    /*导入相关函数*/ #import "kernel32.dll" int CreateDirectoryW(string directoryName,int type); int ...

  4. 【转】用C#调用Windows API向指定窗口发送

    一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.InteropServices; 2.引用需要使用的方法,格式 ...

  5. 用C#调用Windows API向指定窗口发送按键消息 z

    用C#调用Windows API向指定窗口发送 一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.Interop ...

  6. 用C#调用Windows API向指定窗口发送按键消息

    一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.InteropServices; 2.引用需要使用的方法,格式 ...

  7. 用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle)完成文件拷贝程序(初级版)

    文件拷贝程序 程序类型:Console 参数:源文件名   目的文件名 要求:1.只能使用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle ...

  8. LoadLibrary文件路径及windows API相关的文件路径问题

    LoadLibrary HMODULE WINAPI LoadLibrary( _In_  LPCTSTR lpFileName ); Loads the specified module into ...

  9. 学习:Windows API核心DLL文件

    在 Windows 的系统目录中,存在着很多的动态链接库文件(DLL 文件).这些 DLL 文件中包括了 Windows API 函数可执行程序. DLL 将各函数"导出",这样应 ...

随机推荐

  1. ES 中的 POST 和 PUT 的区别

    0.什么是Restful架构 比较难说清楚,这部分大雾状态,引ruanyf 理解RESTful架构 的几句总结吧: Fielding将他对互联网软件的架构原则,定名为REST,即Representat ...

  2. 基于struts2框架文件的上传与下载

    在开发一些社交网站时,需要有允许用户上传自己本地文件的功能,则需要文件的上传下载代码. 首先考虑的是文件的储存位置,这里不考虑存在数据库,因为通过数据库查询获取十分消耗资源与时间,故需将数据存储在服务 ...

  3. IE8 frameset SESSION丢失

    IE8 使用 frameset后,子页面,脚本触发父页面js函数, 如果使用 window.parent.location.href 跳转,则session会丢失 使用 window.location ...

  4. 详谈JavaScript 匿名函数及闭包

    1.匿名函数函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种:这 ...

  5. 编程之美 set 17 拈游戏分析 (2)

    题目 有 N 块石头河两个玩家 A 和 B. A 先将石头分成若干堆, 然后按照 BABABA... 的顺序轮流取石块, 能将剩下的石头依次取光的玩家获胜. 每次取石头时, 每个玩家只能取一堆的 m( ...

  6. 开发环境eclipse for Mac 下的常用快捷键汇总(基本参照Win系,将Ctrl换为Command)

    最近迁移开发环境到Mac下,在豆瓣看到一个常用快捷键,去掉废话直接上干货 Command + O:显示大纲 Command + 1:快速修复 Command + D:删除当前行 Command + O ...

  7. IOS7开发~新UI学起(二)

    本文转载至 http://blog.csdn.net/lizhongfu2013/article/details/9133281 1.UINavigationBar: NSDictionary* at ...

  8. 通过python3学习编码

    简介 今天在写python程序的时候,遇到了编码问题,今天,我准备好好了解一下编码问题 ASCII编码 计算机是美国人发明的,最初只有不超过256字符需要编码,1字节能编码2**8个,所以ASCII编 ...

  9. LeetCode 笔记系列三 3Sum

    题目:Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all ...

  10. Spring的泛型依赖注入

    Spring 4.x 中可以为子类注入子类对应的泛型类型的成员变量的引用,(这样子类和子类对应的泛型类自动建立关系)具体说明: 泛型注入:就是Bean1和Bean2注入了泛型,并且Bean1和Bean ...