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 = 0, dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            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, 1, 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(0);

                int nLength;

                nLength = Convert.ToInt32(fs.Length);

                // 读取文件内容到字节数组
                bytes = br.ReadBytes(nLength);

                // 为这些字节分配一些非托管内存
                pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);

                // 将托管字节数组复制到非托管内存指针
                Marshal.Copy(bytes, 0, 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("文件已成功发送至打印队列!","提示信息");
            }
        }
时间: 2024-07-29 02:27:52

C# 使用 Windows API 发送文件到打印机的相关文章

Windows API——SHFileOperation——文件操作

1 int SHFileOperation( LPSHFILEOPSTRUCT lpFileOp); 如果执行成功返回0. typedef struct _SHFILEOPSTRUCT { HWND hwnd; //指向发送消息的窗口 UINT wFunc; //执行的操作 LPCTSTR pFrom; //源文件名 LPCTSTR pTo; //目标文件名 FILEOP_FLAGS fFlags; //操作与确认标识 BOOL fAnyOperationsAborted; //操作是否终止 L

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

一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.InteropServices; 2.引用需要使用的方法,格式:[DllImport("DLL文件")]方法的声明; [DllImport("user32.dll")]private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("

使用windows API函数获取目录下所有文件名---目录下文件的扫描和处理

直接上代码 // test_max.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <windows.h> #include <Shlwapi.h> #include <iostream> #include <string> #include <vector> #pragma comment(lib,"shlwapi.lib") //注意放置的位置

VBS调用windows api函数(postmessage)实现后台发送按键脚本

'=========================================================================='' VBScript Source File -- Created with SAPIEN Technologies PrimalScript 4.0'' NAME: '' AUTHOR: Microsoft , Microsoft' DATE : 2014/8/10'' COMMENT: ''===================定义变量,注册

Windows API 大全

常用Windows API1. API之网络函数WNetAddConnection 创建同一个网络资源的永久性连接WNetAddConnection2 创建同一个网络资源的连接WNetAddConnection3 创建同一个网络资源的连接WNetCancelConnection 结束一个网络连接WNetCancelConnection2 结束一个网络连接WNetCloseEnum 结束一次枚举操作WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接WNetDis

WINDOWS API 函数(超长,值得学习)

一.隐藏和显示光标 函数: int ShowCursor ( BOOL bShow );  参数 bshow,为布尔型,bShow的值为False时隐藏光标,为True时显示光标:该函数的返回值为整型,为鼠标隐藏或显示的指数器:返回值大于等于0时显示光标,否则隐藏鼠标:如果安装了鼠标初值为0. 二.交换鼠标左右键和恢复 函数:BOOL SwapMouseButton ( BOOL fSwap );  参数 fSwap,为布尔型,TRUE表示交换鼠标左右键,FALSE表示恢复系统默认左右手习惯:返

简要的Windows API函数大全

1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同一个网络资源的连接 WNetCancelConnection 结束一个网络连接 WNetCancelConnection2 结束一个网络连接 WNetCloseEnum 结束一次枚举操作 WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接 WNetDisconne

Windows API参考大全新编

书名:新编Windows API参考大全 作者:本书编写组 页数:981页 开数:16开 字数:2392千字 出版日期:2000年4月第二次印刷 出版社:电子工业出版社 书号:ISBN 7-5053-5777-8 定价:98.00元 内容简介 作为Microsoft 32位平台的应用程序编程接口,Win32 API是从事Windows应用程序开发所必备的.本书首先对Win32 API函数做完整的概述:然后收录五大类函数:窗口管理.图形设备接口.系统服务.国际特性以及网络服务:在附录部分,讲解如何

WINDOWS API函数说明

Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同一个网络资源的连接 WNetCancelConnection 结束一个网络连接 WNetCancelConnection2 结束一个网络连接 WNetCloseEnum 结束一次枚举操作 WNetConnectionDialog 启动一个