介紹:通過pdf位址先将檔案下載下傳到本地,然後調用列印機列印,最後将下載下傳的檔案删除。
環境:windows系統。(windows64位)
windows系統中安裝python3.6.2環境
資料:
O2S.Components.PDFRender4NET.dll(vs項目引用,這是在C#中調用列印機)
python3.6.2 for windows python-3.6.2-amd64-webinstall
在python環境中添加:pywin32-221.win-amd64-py3.6 和 GSPRINT檔案(python環境中執行檔案下載下傳 列印 删除)
windows環境下安裝python環境:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLyAzMwYzNxYDOx0SNxYTMwUTM1EDOyQDM5EDMy0SMzMTN0ETMvwFNwkTMwIzLcFzMzUDNxEzLcd2bsJ2Lc12bj5ycn9Gbi52YugTMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
點選程式進行安裝........
推薦安裝教程:https://baijiahao.baidu.com/s?id=1606573927720991570&wfr=spider&for=pc
配置列印環境:
首先進入cmd環境導入requests子產品
下載下傳pywin32 官網 https://sourceforge.net/projects/pywin32/
首先從C#代碼開始
界面預覽:這個很簡單,在wpf中可以寫個button按鈕事件即可
/* 由于質保書背景接口給的是pdf下載下傳位址,是以我的思路是 先下載下傳到本地然後列印,列印完成後在删除檔案
* 由于時間倉促:檔案的下載下傳及删除功能使用python來完成(這裡也可以改為C#來寫)
*
*/
try
{
// 1:檔案下載下傳
var result = PythonHelper.PdfDownload(this.model.ZhiBaoShu.DownloadUrl);
if (!result.Successed)
{
Dispatcher.Invoke(() =>
{
MessageBox.Show("pdf質保書下載下傳失敗,請聯系管理者", "列印消息", MessageBoxButton.OK, MessageBoxImage.Stop);
LogHelper.LogInfo($"檔案:【{this.model.ZhiBaoShu.DownloadUrl}】下載下傳失敗\r\n 錯誤:\r\n{result.Message}");
// 發生錯誤傳回首頁
UtilHelper.BackToMain(this, mainPage.stpBG, () => { BackToMain(); }, null);
});
}
Thread.Sleep(1000);
_savePath = result.Result.ToString();
// 2:列印下載下傳pdf檔案(python列印隻能列印一份,還有列印樣式未完善,是以還是用C#來調用列印)
result = PythonHelper.PdfPrint(_savePath, model.ZhiBaoShu.PrinterName);
// result = ph.PdfPrint(_savePath, model.ZhiBaoShu.PrinterName, (short)model.ZhiBaoShu.PrintNum);
if (!result.Successed)
{
Dispatcher.Invoke(() =>
{
MessageBox.Show("pdf質保書列印失敗,請聯系管理者", "列印消息", MessageBoxButton.OK, MessageBoxImage.Stop);
LogHelper.LogInfo($"檔案:【{result.Result.ToString()}】列印失敗\r\n 錯誤:\r\n{result.Message}");
// 發生錯誤傳回首頁
UtilHelper.BackToMain(this, mainPage.stpBG, () => { BackToMain(); }, null);
});
}
Thread.Sleep(1000);
//// 3:删除pdf檔案
//result = PythonHelper.PdfDelete(_savePath);
//if (!result.Successed)
//{
// //MessageBox.Show("pdf質保書删除失敗", "列印消息", MessageBoxButton.OK, MessageBoxImage.Stop);
// LogHelper.LogInfo($"檔案:【{this.model.ZhiBaoShu.DownloadUrl}】删除失敗\r\n 錯誤:\r\n{result.Message}");
// // 發生錯誤傳回首頁
// //UtilHelper.BackToMain(this, mainPage.stpBG, () => { BackToMain(); }, null);
// // 檔案删除失敗不代表列印失敗,是以這裡結果重置一下
// result.Successed = true;
//}
}
catch (Exception e)
{
}
pythonhelper.cs 檔案 (代碼未優化)
/// <summary>
/// 執行python檔案
/// </summary>
public static class PythonHelper
{
/// <summary>
/// 程式debug目錄檔案路徑
/// </summary>
private static string _binPath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
/// <summary>
/// 儲存本地pdf檔案名
/// </summary>
private static string _pdfName = DateTime.Now.ToString("HHmmss") + ".pdf";
/// <summary>
/// 檔案下載下傳儲存本地位址+檔案名
/// </summary>
private static string _savePath = _binPath + "file\\" + _pdfName;
/// <summary>
/// pdf下載下傳
/// </summary>
/// <param name="downloadurl">pdf下載下傳位址</param>
/// <returns>傳回儲存檔案位址</returns>
public static HandlingResult PdfDownload(string downloadurl)
{
// python檔案位址 ,待處理python檔案的路徑,本例中放在debug檔案夾下
string _pdfDownloadPy = _binPath + "python\\pdfdownload.py";
var result = new HandlingResult() { Successed = false };
try
{
// 拼接執行指令(方法傳參)
ArrayList arrayList = new ArrayList();
arrayList.Add(downloadurl);
arrayList.Add(_savePath);
foreach (var param in arrayList)//添加參數
_pdfDownloadPy += " " + param;
// 執行設定
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "python";//執行python.exe
//執行python腳本的指令
start.Arguments = _pdfDownloadPy;
//設定運作python腳本的初始目錄 這裡注意:如果你的python腳本有檔案操作,必須設定初始目錄,python腳本所在的目錄
start.WorkingDirectory = _binPath + "python\\";
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
using (Process process = Process.Start(start))
{
// 異步擷取指令行内容
process.BeginOutputReadLine();
// 為異步擷取訂閱事件
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
// 列印python腳本中的資訊
LogHelper.LogInfo(e.Data);
//MessageBox.Show(e.Data);//e.Data 就是指令行列印的最後一行資訊
});
}
result.Successed = true;
result.Result = _savePath;
}
catch (Exception e)
{
result.Successed = false;
result.Message = e.Message;
LogHelper.LogError(e);
}
return result;
}
/// <summary>
/// 删除pdf檔案
/// </summary>
/// <param name="path">本地pdf檔案全路徑</param>
public static HandlingResult PdfDelete(string path)
{
string _pdfDeletePy = _binPath + "python\\pdfdelete.py";
var result = new HandlingResult() { Successed = true };
try
{
// 拼接執行指令(方法傳參)
ArrayList arrayList = new ArrayList();
arrayList.Add(path);
foreach (var param in arrayList)//添加參數
_pdfDeletePy += " " + param;
// 執行設定
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "python";//執行python.exe
//執行python腳本的指令
start.Arguments = _pdfDeletePy;
//設定運作python腳本的初始目錄 這裡注意:如果你的python腳本有檔案操作,必須設定初始目錄,python腳本所在的目錄
start.WorkingDirectory = _binPath + "python\\";
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
using (Process process = Process.Start(start))
{
// 異步擷取指令行内容
process.BeginOutputReadLine();
// 為異步擷取訂閱事件
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
// 列印python腳本中的資訊
LogHelper.LogInfo(e.Data);
//MessageBox.Show(e.Data);//e.Data 就是指令行列印的最後一行資訊
});
}
}
catch (Exception e)
{
result.Successed = false;
result.Message = e.Message;
}
return result;
}
/// <summary>
/// 列印pdf
/// </summary>
/// <param name="printPath">檔案全路徑</param>
/// <param name="printName">列印機名稱</param>
public static HandlingResult PdfPrint(string printPath, string printName)
{
string _pdfPrint = _binPath + "python\\pdfprint.py";
var result = new HandlingResult() { Successed = true };
try
{
// 拼接執行指令(方法傳參)
ArrayList arrayList = new ArrayList();
arrayList.Add(printPath);
arrayList.Add(printName);
foreach (var param in arrayList)//添加參數
_pdfPrint += " " + param;
// 執行設定
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "python";//執行python.exe
start.Arguments = _pdfPrint;//執行python腳本的指令
//設定運作python腳本的初始目錄 這裡注意:如果你的python腳本有檔案操作,必須設定初始目錄,python腳本所在的目錄
start.WorkingDirectory = _binPath + "python\\";
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
using (Process process = Process.Start(start))
{
// 異步擷取指令行内容
process.BeginOutputReadLine();
// 為異步擷取訂閱事件
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
// 列印python腳本中的資訊
LogHelper.LogInfo(e.Data);
//MessageBox.Show(e.Data);//e.Data 就是指令行列印的最後一行資訊
});
}
}
catch (Exception e)
{
LogHelper.LogError(e);
result.Successed = false;
result.Message = e.Message;
}
return result;
}
}
第二種調用列印機方法:使用第三方O2S.Components.PDFRender4NET.dll檔案調用列印機列印pdf
/// <summary>
/// 列印pdf檔案
/// </summary>
/// <param name="pdfPath">檔案全路徑</param>
/// <param name="printName">列印機名稱</param>
/// <param name="copies">列印份數</param>
/// <returns></returns>
public HandlingResult PdfPrint(string pdfPath, string printName, short copies = 1)
{
PDFFile file =null;
var result = new HandlingResult()
{
Successed = true,
};
try
{
file = PDFFile.Open(pdfPath);
PrinterSettings settings = new PrinterSettings();
System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();
settings.PrinterName = printName; // "NPI84FFAF (HP LaserJet MFP M436)"; // 列印機名稱
settings.PrintToFile = false;
//設定紙張大小(可以不設定,取預設設定)3.90 in, 8.65 in
PaperSize ps = new PaperSize("test", 4, 9);
ps.RawKind = 9; //如果是自定義紙張,就要大于118,(A4值為9,詳細紙張類型與值的對照請看http://msdn.microsoft.com/zh-tw/library/system.drawing.printing.papersize.rawkind(v=vs.85).aspx)
O2S.Components.PDFRender4NET.Printing.PDFPrintSettings pdfPrintSettings =
new O2S.Components.PDFRender4NET.Printing.PDFPrintSettings(settings);
pdfPrintSettings.PaperSize = ps;
pdfPrintSettings.PageScaling =
O2S.Components.PDFRender4NET.Printing.PageScaling.FitToPrinterMarginsProportional;
pdfPrintSettings.PrinterSettings.Copies = copies;
file.Print(pdfPrintSettings);
}
catch (Exception e)
{
LogHelper.LogError(e);
result.Successed = false;
result.Message = e.Message;
}
finally
{
file.Dispose();
LogHelper.LogInfo($"{pdfPath}---列印成功");
}
return result;
}
以上是C#部分代碼,以下python腳本就比較簡單了。
注:其實可以隻寫一個列印方法即可,為了流程看到清楚,是以一個操作一個方法檔案。
1:根據位址下載下傳pdf檔案 pdfdownload.py
# -*- coding: utf-8 -*-
# 聲明字元編碼
# coding:utf-8
import os, sys
from requests import get
def dwnloadpfd(file_path, save_path):
'''
根據file_path位址下載下傳檔案儲存到save_path路徑中
:param file_path:下載下傳位址
:param save_path: 儲存位址
:return:True或False
'''
try:
head = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36"
}
response =get(file_path, headers=head).content
with open(save_path, 'wb') as f:
f.write(response)
print('%s--下載下傳成功'%(save_path))
return save_path
except Exception as e:
print(e)
return None
if __name__ == "__main__":
#url = ""
#dwnloadpfd(url, "musics/1.pdf")
# 接收參數
dwnloadpfd(sys.argv[1], sys.argv[2])
2:列印pdf檔案:pdfprint.py
# -*- coding: utf-8 -*-
# 聲明字元編碼
# coding:utf-8
import os, sys
import win32api
import win32print
import json
from handlingresult import handlingresult
GHOSTSCRIPT_PATH = "C:\\Program Files\\gs\\gs9.27\\bin\\gswin64.exe"
GSPRINT_PATH = "C:\\Program Files\\GSPRINT\\gsprint.exe"
def pdfprint(full_file_name, print_name=win32print.GetDefaultPrinter()):
'''
根據指定的列印機列印pdf檔案
:param full_file_name:檔案全路徑
:param print_name:列印機名稱(預設列印機)
:return:
'''
result = handlingresult()
try:
# portraint:縱向 landscape:橫向
win32api.ShellExecute(
0,
'open',
GSPRINT_PATH,
'-ghostscript "' + GHOSTSCRIPT_PATH + '" -landscape -printer "' + print_name + '" "' + full_file_name + '"',
'.',
0
)
result.Message = '%s---列印成功' % (full_file_name)
result.Result = None
result.Successed = True
except Exception as e:
result.Message = '%s---列印異常:\n %s' % (full_file_name, str(e))
result.Result = None
result.Successed = False
js = json.dumps(result, default=lambda obj: obj.__dict__, sort_keys=True, indent=4)
return js
if __name__ == "__main__":
path ="D:\\1.pdf" #"E:\\開發項目\\學習項目\\Python\\MusicDownLoad\\musics\\1.pdf"
name = "NPIE091D5 (HP LaserJet MFP M227fdw)" # win32print.GetDefaultPrinter() # "NPI84FFAF (HP LaserJet MFP M436)" #
print(pdfprint(path, name))
# len(sys.argv)
# print(sys.argv[1]) # 檔案路徑
# print(sys.argv[2:]) # 列印機名稱
# name = ' '.join(sys.argv[2:])
# print(name)
# # 列印機名稱中有可能有空格
# print(pdfprint(sys.argv[1], name))
3:列印完成後即可删除檔案 pdfdelete.py
# -*- coding: utf-8 -*-
# 聲明字元編碼
# coding:utf-8
import os, sys
def pdfdelete(full_path):
'''
根據檔案全路徑位址删除
:param full_path:檔案路徑
:return:True或False
'''
try:
if (os.path.exists(full_path)):
os.remove(full_path)
print(full_path + '---删除成功')
return True
else:
print(full_path + '---删除檔案不存在')
return False
except Exception as e:
print(str(e))
return False
if __name__ == "__main__":
pdfdelete(sys.argv[1])
補充:擷取列印機狀态
# -*- coding: utf-8 -*-
# 聲明字元編碼
# coding:utf-8
import os, sys
import win32api
import win32print
import json
from handlingresult import handlingresult
GHOSTSCRIPT_PATH = "C:\\Program Files\\gs\\gs9.27\\bin\\gswin64.exe"
GSPRINT_PATH = "C:\\Program Files\\GSPRINT\\gsprint.exe"
# 詳細參考:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/1625e9d9-29e4-48f4-b83d-3bd0fdaea787
# 對應:win32api 最上面有
PRINTER_STATUE_STR = {
"2": "列印機處于錯誤狀态",
"4096": "列印機無法列印",
"262144": "列印機沒有碳粉",
"128": "列印機處于脫機狀态",
"2097152": "列印機記憶體不足",
"524288": "列印機無法列印目前頁面",
"8": "紙張卡在列印機中",
"16": "列印機缺紙",
"64": "列印機有一個未指定的紙張問題",
"1": "列印機暫停",
"131072": "列印機墨粉不足",
"1048576": "列印機出現錯誤"
}
def printer_status_code(printer_name):
'''
根據列印機名稱擷取狀态
:param printer_name:
:return:
'''
result = handlingresult()
try:
hPrinter = win32print.OpenPrinter(printer_name)
dic = win32print.GetPrinter(hPrinter, 2)
stuta_int = dic.get('Status', 0)# 擷取狀态值
result.Result = stuta_int
stuta = PRINTER_STATUE_STR.get(str(stuta_int), None)
if stuta == None:
result.Message = '列印機狀态:%s:\n %s' % (printer_name, result.Result)
result.Successed = True
else:
result.Message = '列印機狀态:%s:\n %s' % (printer_name, stuta)
result.Successed = False
except Exception as e:
result.Message = '列印機擷取狀态異常:%s:\n %s' % (printer_name, str(e))
result.Result = None
result.Successed = False
js = json.dumps(result, default=lambda obj: obj.__dict__, sort_keys=True, indent=4)
return js
if __name__ == "__main__":
name = ' '.join(sys.argv[1:])
print(printer_status_code(printer_name=name))
# code = printer_status_code(
# "Brother Color Leg Type1 Class Driver") # Brother Color Leg Type1 Class Driver HP LaserJet MFP M436 PCL-6 NPI84FFAF (HP LaserJet MFP M436)
# print(code)
注:上面python調用列印機進行列印的份數這些設定後續有待完善。(列印份數可以循環調用列印即可)