我會問和回答我自己的問題。我本來以爲需要創建一個空打印機並不是一件難得的事情,但是我花了太多時間在搜索工作的解決方案之前使用google搜索和拼湊一些小部分。我發現很多關於通過Windows GUI創建一個空打印機的答案,但是關於以編程方式執行它的信息相對稀缺且分散。希望我的回答或更好的建議可以爲其他一些可憐的shmo節省一些時間。如何以編程方式爲Windows創建空打印機?
-1
A
回答
1
這個「爲我工作」。我想有一個更優雅的方法來實現這一點,我希望有任何改進/糾正代碼的建議,但是我無法找到一個簡潔完整的答案來解釋我認爲相對普遍的需求。我有一個相當具體的要求,很顯然這個代碼可以概括,也可加入適當的錯誤處理等
//pd is a PrintDocument. used like:
PrintController printController = new StandardPrintController();
pd.PrintController = printController;
NullPrinter np = new NullPrinter();
if (!np.NullPortExists())
{
np.CreateNullPort();
}
if (!np.NullPrinterExists())
{
np.CreateNullPrinter();
}
pd.PrinterSettings.PrinterName = "NUL_PRINTER";
/*********************************************/
using System;
using System.Management; // This must also be added as a reference
using System.Drawing.Printing;
using System.Runtime.InteropServices;
namespace YourFavoriteNamespace
{
//
// This helper class has methods to determine whether a 'Nul Printer' exists,
// and to create a null port and null printer if it does not.
//
public class NullPrinter
{
// Printer port management via Windows GUI (Windows 7, probably same in other versions):
//
// Go to printers & devices
// Select any printer
// Click on Print server properties
// Select Ports tab
// Add or remove (local) port
// To remove a local port, if "in use", stop and restart the print spooler service.
// It seems that the most recently used port will be "in use" until the system restarts,
// or until another port is used.
// A port may also be added when adding a printer.
// Valid names for a Null port appear to be NUL, NULL, NUL: - all case insensitive.
public bool NullPortExists()
{
for (int i = 0; i < PrinterSettings.InstalledPrinters.Count; i++)
{
string printerName = PrinterSettings.InstalledPrinters[i];
string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '%{0}'", printerName);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection coll = searcher.Get();
foreach (ManagementObject printer in coll)
{
string pName = printer["PortName"].ToString();
if (pName.Equals("NULL", StringComparison.InvariantCultureIgnoreCase) ||
pName.Equals("NUL", StringComparison.InvariantCultureIgnoreCase) ||
pName.Equals("NUL:", StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
}
return false;
}
// The application that uses this requires a printer specifically named "NUL_PRINTER"
public bool NullPrinterExists()
{
for (int i = 0; i < PrinterSettings.InstalledPrinters.Count; i++)
{
if (PrinterSettings.InstalledPrinters[i] == "NUL_PRINTER")
{
return true;
}
}
return false;
}
public bool CreateNullPort()
{
return Winspool.AddLocalPort("NUL") == 0 ? true : false;
}
public void CreateNullPrinter()
{
Winspool.AddPrinter("NUL_PRINTER");
}
}
/*********************************************************/
//
// This Winspool class was mostly borrowed and adapted
// from several different people's blog posts,
// the links to which I have lost.
// Thank you, whoever you are.
//
public static class Winspool
{
[StructLayout(LayoutKind.Sequential)]
private class PRINTER_DEFAULTS
{
public string pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[DllImport("winspool.drv", CharSet = CharSet.Auto)]
static extern IntPtr AddPrinter(string pName, uint Level, [In] ref PRINTER_INFO_2 pPrinter);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct PRINTER_INFO_2
{
public string pServerName,
pPrinterName,
pShareName,
pPortName,
pDriverName,
pComment,
pLocation;
public IntPtr pDevMode;
public string pSepFile,
pPrintProcessor,
pDatatype,
pParameters;
public IntPtr pSecurityDescriptor;
public uint Attributes,
Priority,
DefaultPriority,
StartTime,
UntilTime,
Status,
cJobs,
AveragePPM;
}
[DllImport("winspool.drv", EntryPoint = "XcvDataW", SetLastError = true)]
private static extern bool XcvData(
IntPtr hXcv,
[MarshalAs(UnmanagedType.LPWStr)] string pszDataName,
IntPtr pInputData,
uint cbInputData,
IntPtr pOutputData,
uint cbOutputData,
out uint pcbOutputNeeded,
out uint pwdStatus);
[DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true)]
private static extern int OpenPrinter(
string pPrinterName,
ref IntPtr phPrinter,
PRINTER_DEFAULTS pDefault);
[DllImport("winspool.drv", EntryPoint = "ClosePrinter")]
private static extern int ClosePrinter(IntPtr hPrinter);
public static int AddLocalPort(string portName)
{
PRINTER_DEFAULTS def = new PRINTER_DEFAULTS();
def.pDatatype = null;
def.pDevMode = IntPtr.Zero;
def.DesiredAccess = 1; //Server Access Administer
IntPtr hPrinter = IntPtr.Zero;
int n = OpenPrinter(",XcvMonitor Local Port", ref hPrinter, def);
if (n == 0)
return Marshal.GetLastWin32Error();
if (!portName.EndsWith("\0"))
portName += "\0"; // Must be a null terminated string
// Must get the size in bytes. .NET strings are formed by 2-byte characters
uint size = (uint)(portName.Length * 2);
// Alloc memory in HGlobal to set the portName
IntPtr portPtr = Marshal.AllocHGlobal((int)size);
Marshal.Copy(portName.ToCharArray(), 0, portPtr, portName.Length);
uint NotUsedByUs;
uint xcvResult;
XcvData(hPrinter, "AddPort", portPtr, size, IntPtr.Zero, 0, out NotUsedByUs, out xcvResult);
ClosePrinter(hPrinter);
Marshal.FreeHGlobal(portPtr);
return (int)xcvResult;
}
public static void AddPrinter(string PrinterName)
{
IntPtr mystrptr = new IntPtr(0);
IntPtr mysend2;
PRINTER_INFO_2 pi = new PRINTER_INFO_2();
pi.pServerName = "";
pi.pPrinterName = PrinterName;
pi.pShareName = "NUL";
pi.pPortName = "NUL";
pi.pDriverName = "Generic/Text Only";
pi.pComment = "No Comment";
pi.pLocation = "Local";
pi.pDevMode = mystrptr;
pi.pSepFile = "";
pi.pPrintProcessor = "WinPrint";
pi.pDatatype = "RAW";
pi.pParameters = "";
pi.pSecurityDescriptor = mystrptr;
mysend2 = AddPrinter(null,2, ref pi);
}
}
}
相關問題
- 1. 如何以編程方式創建打印機的快捷方式?
- 2. 以編程方式將打印機設置爲繞過Windows假脫機程序
- 3. 以編程方式打印PDF文件 - 指定打印機
- 4. 以編程方式打印到虛擬打印機(XPS)
- 5. 如何以編程方式設置打印機屬性?
- 6. 如何以編程方式創建UIScrollview
- 7. 如何以編程方式創建UIViewController?
- 8. 如何以編程方式創建UIButton
- 9. 如何以編程方式創建NSTextField?
- 10. 如何以編程方式創建Tabbar
- 11. 如何以編程方式創建ProgressBar?
- 12. 如何以編程方式創建CustomCell?
- 13. 如何以編程方式創建NSPopover
- 14. 如何以編程方式創建GPO?
- 15. 如何以編程方式創建NSFetchedPropertyDescription?
- 16. 如何以編程方式創建UIScrollView?
- 17. 如何以編程方式創建TextView?
- 18. 如何以編程方式創建NSSearchField?
- 19. 如何使用Windows用戶權限爲PDF打印創建打印機?
- 20. 創建「打印機」以PDF格式打印到SQL數據庫
- 21. 如何在Windows Phone 7中以編程方式創建ListBox.Itemtemplate,datatemplate
- 22. Silverlight:以編程方式打印XPS
- 23. 以編程方式打印文檔
- 24. 以編程方式打印excel文件
- 25. 以編程方式打印ActiveReports頁面
- 26. 以編程方式打印HTML文檔
- 27. 以編程方式打印FixedDocument
- 28. 以編程方式爲NSStatusBar.systemStatusBar創建NSMenu
- 29. 如何以編程方式創建空的Visual C++項目?
雖然這是完全可以接受的要求,在這裏回答你自己的問題,這個問題你*問*必須滿足與其他問題相同的質量標準。這不是。請[編輯]清楚解釋您嘗試解決的問題,並提出明確提出的問題,然後您發佈的答案即可解決。 –
我的歉意。我認爲標題本身清楚地表明瞭這個問題。也許我太接近它看不到它了?給我一些具體的批評,我會盡我所能來改進它。 – mickeyf
刪除問題的所有內容並添加爲什麼需要創建「空白打印機」的原因。目前帖子只包含「搜索很多」和「我很棒」的文字,沒有明確的理由爲什麼會這樣做。 (你的問題很可能是在形式上的話題)。 –