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();
        }
    }

以上就是所有代碼了,調用就很簡單了,方法以下:spa

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("文件已成功發送至打印隊列!","提示信息");
            }
        }
相關文章
相關標籤/搜索