如何确定Adobe PDF打印机的“Ne”端口?

如何检测打印机所在的端口(Ne01:,Ne02:,Ne99:等)?

BigCorp的计算机(WinXP)安装了Adobe Acrobat(版本7.0 Pro),它提供了一个名为“Adobe PDF”的虚拟打印机。 如果在录制宏的同时将Excel(2003)工作簿打印为pdf,则打印机的全名为“Nexx上的Adobe PDF:”,其中xx是两位数….根据您尝试使用的计算机而不同

我已经使用Excel.Interop编写了一个C#控制台应用程序(我强烈反对其他任何人开始这条路走向地狱),这会打开一系列电子表格。 它在每个中运行一个宏,保存,打印为pdf,然后将pdf移动到共享驱动器上的报告文件夹。

我面临的问题是,每次安装Acrobat似乎都会为PDF打印机选择一个随机端口号…我无法弄清楚如何获得它。

到目前为止,我已经尝试过像这样使用Win32_Printer类

var searcher = new ManagementObjectSearcher( @"SELECT * FROM Win32_Printer" ); foreach ( ManagementObject printer in searcher.Get() ) { if ( Regex.IsMatch( printer["Name"].ToString(), @"(adobe|pdf)", RegexOptions.IgnoreCase ) ) { //printer["Name"]; => "Adobe PDF" //printer["PortName"] => "my documents/*.pdf" foreach ( PropertyData pd in printer.Properties ) { Console.WriteLine(string.Format("{0}, {1}", pd.Name, pd.Value)); } break; } } 

我也在System.Drawing.Printing类中探讨过。 PrinterSettings.InstalledPrinters将为您提供打印机“Adobe PDF”的名称,但我无法弄清楚如何获取端口信息。

如果我只将“Adobe PDF”传递给excel interop PrintOut()方法,它有时会工作,有时会因“文档无法打印”而失败……我无法弄清楚原因。

如果我使用适当的x值传递硬编码的“Nexx上的Adobe PDF:”,它每次都有效

如果我尝试所有可能的变化,Excel可以帮助打印到默认打印机。 我没有更改默认打印机的选项(安全策略限制)

有人能指出我正确拉动打印机端口的代码吗?

这就是我最终做的事情

 using Microsoft.Win32; ... var devices = Registry.CurrentUser.OpenSubKey( @"Software\Microsoft\Windows NT\CurrentVersion\Devices" ); //Read-accessible even when using a locked-down account string printerName = "Adobe PDF"; try { foreach ( string name in devices.GetValueNames() ) { if ( Regex.IsMatch( name, printerName, RegexOptions.IgnoreCase ) ) { var value = (String)devices.GetValue( name ); var port = Regex.Match( value, @"(Ne\d+:)", RegexOptions.IgnoreCase ).Value; return printerName + " on " + port; } } } catch { throw; } 

上次我使用Acrobat时,它总是习惯在LPT1上安装自己:从而避免了这个问题。 但我认为你必须在注册表中徘徊, HKCU\Software\Microsoft\Windows NT\CurrentVersion\Devices有它们。

正如您发现的那样,您必须查询注册表,这是我在[VBA]中使用的方式,这是我从Chip Pearson的Excel网站获得的 :

 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' modListPrinters ' By Chip Pearson, chip@cpearson.com www.cpearson.com ' Created 22-Sept-2012 ' This provides a function named GetPrinterFullNames that ' returns a String array, each element of which is the name ' of a printer installed on the machine. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const HKEY_CURRENT_USER As Long = &H80000001 Private Const HKCU = HKEY_CURRENT_USER Private Const KEY_QUERY_VALUE = &H1& Private Const ERROR_NO_MORE_ITEMS = 259& Private Const ERROR_MORE_DATA = 234 Private Const REG_SZ = 1 Private Declare Function RegOpenKeyEx Lib "advapi32" _ Alias "RegOpenKeyExA" ( _ ByVal hKey As Long, _ ByVal lpSubKey As String, _ ByVal ulOptions As Long, _ ByVal samDesired As Long, _ phkResult As Long) As Long Private Declare Function RegEnumValue Lib "ADVAPI32.DLL" _ Alias "RegEnumValueA" ( _ ByVal hKey As Long, _ ByVal dwIndex As Long, _ ByVal lpValueName As String, _ lpcbValueName As Long, _ ByVal lpReserved As Long, _ lpType As Long, _ lpData As Byte, _ lpcbData As Long) As Long Private Declare Function RegCloseKey Lib "ADVAPI32.DLL" ( _ ByVal hKey As Long) As Long Public Function GetPrinterFullNames() As String() ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' GetPrinterFullNames ' By Chip Pearson, chip@cpearson.com, www.cpearson.com ' Returns an array of printer names, where each printer name ' is the device name followed by the port name. The value can ' be used to assign a printer to the ActivePrinter property of ' the Application object. Note that setting the ActivePrinter ' changes the default printer for Excel but does not change ' the Windows default printer. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Dim Printers() As String ' array of names to be returned Dim PNdx As Long ' index into Printers() Dim hKey As Long ' registry key handle Dim Res As Long ' result of API calls Dim Ndx As Long ' index for RegEnumValue Dim ValueName As String ' name of each value in the printer key Dim ValueNameLen As Long ' length of ValueName Dim DataType As Long ' registry value data type Dim ValueValue() As Byte ' byte array of registry value value Dim ValueValueS As String ' ValueValue converted to String Dim CommaPos As Long ' position of comma character in ValueValue Dim ColonPos As Long ' position of colon character in ValueValue Dim M As Long ' string index ' registry key in HCKU listing printers Const PRINTER_KEY = "Software\Microsoft\Windows NT\CurrentVersion\Devices" PNdx = 0 Ndx = 0 ' assume printer name is less than 256 characters ValueName = String$(256, Chr(0)) ValueNameLen = 255 ' assume the port name is less than 1000 characters ReDim ValueValue(0 To 999) ' assume there are less than 1000 printers installed ReDim Printers(1 To 1000) ' open the key whose values enumerate installed printers Res = RegOpenKeyEx(HKCU, PRINTER_KEY, 0&, _ KEY_QUERY_VALUE, hKey) ' start enumeration loop of printers Res = RegEnumValue(hKey, Ndx, ValueName, _ ValueNameLen, 0&, DataType, ValueValue(0), 1000) ' loop until all values have been enumerated Do Until Res = ERROR_NO_MORE_ITEMS M = InStr(1, ValueName, Chr(0)) If M > 1 Then ' clean up the ValueName ValueName = Left(ValueName, M - 1) End If ' find position of a comma and colon in the port name CommaPos = InStr(1, ValueValue, ",") ColonPos = InStr(1, ValueValue, ":") ' ValueValue byte array to ValueValueS string On Error Resume Next ValueValueS = Mid(ValueValue, CommaPos + 1, ColonPos - CommaPos) On Error GoTo 0 ' next slot in Printers PNdx = PNdx + 1 Printers(PNdx) = ValueName & " on " & ValueValueS ' reset some variables ValueName = String(255, Chr(0)) ValueNameLen = 255 ReDim ValueValue(0 To 999) ValueValueS = vbNullString ' tell RegEnumValue to get the next registry value Ndx = Ndx + 1 ' get the next printer Res = RegEnumValue(hKey, Ndx, ValueName, ValueNameLen, _ 0&, DataType, ValueValue(0), 1000) ' test for error If (Res <> 0) And (Res <> ERROR_MORE_DATA) Then Exit Do End If Loop ' shrink Printers down to used size ReDim Preserve Printers(1 To PNdx) Res = RegCloseKey(hKey) ' Return the result array GetPrinterFullNames = Printers End Function 

然后我使用此函数来获取PDF打印机名称:

 Public Function FindPDFPrinter() As String 'this function finds the exact printer name for the Adobe PDF printer Dim Printers() As String Dim N As Integer FindPDFPrinter = "" Printers = GetPrinterFullNames() For N = LBound(Printers) To UBound(Printers) If InStr(1, Printers(N), "PDF") Then FindPDFPrinter = Printers(N) End If Next N End Function 

然后,将Application.ActivePrinter设置为该String。

如果你真的只需要端口,你可以把它拉出字符串的末尾。