您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > C/C++/C#

C# 使用 Windows API 发送文件到打印机

时间:2022-01-04 10:05:52  来源:  作者:中年农码工

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

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") + "************rn";
            str += msg;
            str += "************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "************rn";

            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();
        }
    }
C# 使用 Windows API 发送文件到打印机

 

以上就是全部代码了,调用就很简单了,方法如下:

C# 使用 Windows API 发送文件到打印机

 

private void Print_Click(object sender, EventArgs e)
        {
            //打印文件的路径,该方法获取到的文件路径在应用程序 binDebug 目录下,所以 ../../ 向上两级目录
            string fileName = AppDomain.CurrentDomain.BaseDirectory + @"../../File/demo.txt";

            if (PrintCode.SendFileToPrinter("PrinterName", fileName))
            {
                MessageBox.Show("文件已成功发送至打印队列!","提示信息");
            }
        }


Tags:C#   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
最近需要做一个打印的功能,于是在网上找到了这么一个方法。   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class DOCINFOA { [M...【详细内容】
2022-01-04  Tags: C#  点击:(0)  评论:(0)  加入收藏
最近有个需求需要定时清理服务器上所有的缓存。本来以为很简单的调用一下 MemoryCache.Clear 方法就完事了。谁知道 MemoryCache 类以及 IMemoryCache 扩展方法都没有 Clear...【详细内容】
2021-12-30  Tags: C#  点击:(8)  评论:(0)  加入收藏
一、简介很多时候我们都需要用到一些验证的方法,有时候需要用正则表达式校验数据时,往往需要到网上找很久,结果找到的还不是很符合自己想要的。所以我把自己整理的校验帮助类分...【详细内容】
2021-12-27  Tags: C#  点击:(9)  评论:(0)  加入收藏
读取SQLite数据库,就是读取一个路径\\192.168.100.**\position\db.sqlite下的文件<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/...【详细内容】
2021-12-16  Tags: C#  点击:(25)  评论:(0)  加入收藏
一文看懂"async"和“await”关键词是如何简化了C#中多线程的开发过程当我们使用需要长时间运行的方法(即,用于读取大文件或从网络下载大量资源)时,在同步的应用程序中,应用程序本...【详细内容】
2021-12-01  Tags: C#  点击:(26)  评论:(0)  加入收藏
OpenCV(Open Source Computer Vision Library)是一个(开源免费)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android、ios等操作系统上,它轻量级而且高效---由一系列...【详细内容】
2021-11-11  Tags: C#  点击:(56)  评论:(0)  加入收藏
在进行C#接口开发时经常需要将数据集转换成json返回,下面介绍一种将DataTable数据转换成实体类,然后再转换成json的方法。一、创建全病案类/// <summary> /// 全病案 //...【详细内容】
2021-11-04  Tags: C#  点击:(49)  评论:(0)  加入收藏
C# 获取网络路径文件大小信息的方法private void button1_Click(object sender, EventArgs e){label2.Text= GetInfo(textBox1.Text);}private string GetInfo(string URL){...【详细内容】
2021-10-29  Tags: C#  点击:(58)  评论:(0)  加入收藏
现如今二维码广泛应用,已经成为了生活中不可或缺的东西;所以我们日常的开发中,也少不了对二维码的生成或者解析。此文讲述一下使用C# 生成和解析二维码 实现功能:将字符串生成二...【详细内容】
2021-10-21  Tags: C#  点击:(66)  评论:(0)  加入收藏
最开始接触.net大概是2003年,当时用的还是framework1.1,那是CAM项目,使用.net主要是利用RemotingService做分布式开发,我当时做其中的一个子系统,因为之前一直都是C++开发,对C#一...【详细内容】
2021-08-17  Tags: C#  点击:(108)  评论:(0)  加入收藏
▌简易百科推荐
最近需要做一个打印的功能,于是在网上找到了这么一个方法。   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class DOCINFOA { [M...【详细内容】
2022-01-04  中年农码工    Tags:C#   点击:(0)  评论:(0)  加入收藏
最近有个需求需要定时清理服务器上所有的缓存。本来以为很简单的调用一下 MemoryCache.Clear 方法就完事了。谁知道 MemoryCache 类以及 IMemoryCache 扩展方法都没有 Clear...【详细内容】
2021-12-30  开发软件  博客园  Tags:C#   点击:(8)  评论:(0)  加入收藏
一、简介很多时候我们都需要用到一些验证的方法,有时候需要用正则表达式校验数据时,往往需要到网上找很久,结果找到的还不是很符合自己想要的。所以我把自己整理的校验帮助类分...【详细内容】
2021-12-27  中年农码工    Tags:C#   点击:(9)  评论:(0)  加入收藏
引言在学习C语言或者其他编程语言的时候,我们编写的一个程序代码,基本都是在屏幕上打印出 hello world ,开始步入编程世(深)界(坑)的。C 语言版本的 hello world 代码:#include <std...【详细内容】
2021-12-21  一起学嵌入式    Tags:C 语言   点击:(16)  评论:(0)  加入收藏
读取SQLite数据库,就是读取一个路径\\192.168.100.**\position\db.sqlite下的文件<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/...【详细内容】
2021-12-16  今朝我的奋斗    Tags:c#   点击:(25)  评论:(0)  加入收藏
什么是shellshell是c语言编写的程序,它在用户和操作系统之间架起了一座桥梁,用户可以通过这个桥梁访问操作系统内核服务。 它既是一种命令语言,同时也是一种程序设计语言,你可以...【详细内容】
2021-12-16  梦回故里归来    Tags:shell脚本   点击:(19)  评论:(0)  加入收藏
一、编程语言1.根据熟悉的语言,谈谈两种语言的区别?主要浅谈下C/C++和PHP语言的区别:1)PHP弱类型语言,一种脚本语言,对数据的类型不要求过多,较多的应用于Web应用开发,现在好多互...【详细内容】
2021-12-15  linux上的码农    Tags:c/c++   点击:(20)  评论:(0)  加入收藏
1.字符串数组+初始化char s1[]="array"; //字符数组char s2[6]="array"; //数组长度=字符串长度+1,因为字符串末尾会自动添&lsquo;\0&lsquo;printf("%s,%c\n",s1,s2[2]);...【详细内容】
2021-12-08  灯-灯灯    Tags:C语言   点击:(48)  评论:(0)  加入收藏
函数调用约定(Calling Convention),是一个重要的基础概念,用来规定调用者和被调用者是如何传递参数的,既调用者如何将参数按照什么样的规范传递给被调用者。在参数传递中,有两个很...【详细内容】
2021-11-30  小智雅汇    Tags:函数   点击:(25)  评论:(0)  加入收藏
一、问题提出问题:把m个苹果放入n个盘子中,允许有的盘子为空,共有多少种方法?注:5,1,1和1 5 1属同一种方法m,n均小于10二、算法分析设f(m,n) 为m个苹果,n个盘子的放法数目,则先对...【详细内容】
2021-11-17  C语言编程    Tags:C语言   点击:(54)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条