幾個月前,我編寫了一個VB.net控制檯應用程序,用於將一組約100臺以上的打印機和1800多位使用它們的用戶從一些舊的HP打印設備遷移到混合打印服務器和直接到IP打印解決方案。應用程序使用數據庫比較已安裝的打印機並刪除舊的/無效的共享並重新映射到基於Win2K3的新打印服務器,或創建TCPIP打印機端口並安裝驅動程序以直接進行IP打印。VB.net 1.1使用CreateProcessWithLogon API創建TCPIP打印機端口
它工作得很好,但用戶需要高級用戶權限才能創建TCPIP打印機端口。對於主校園來說,這不是問題,但較小的遠程站點需要一個解決方案,允許應用程序由沒有權限用戶權限的用戶運行。
我的解決方案是採用「CreatePrinterIPPort」函數並將其放入它自己的包裝應用程序中,然後根據需要使用硬編碼的本地管理員帳戶從主應用程序調用此目的,但我遇到問題生成createport應用程序時。如果我獨立運行應用程序,它將創建沒有問題的端口,但是當我在測試應用程序中運行它以使用CreateProcessWithLogon API產生createport時,端口創建失敗,並顯示「拒絕訪問」錯誤。我僅限於使用.net 1.1,因爲2.0完全不在我們的環境中,我被告知它不會被推到這個應用程序。
有什麼想法?
來源如下。
產卵應用:
Imports System.Runtime.InteropServices
Module Module1
Region "API Structures"
<StructLayout(LayoutKind.Sequential)> _
Public Structure PROCESS_INFORMATION
Dim hProcess As System.IntPtr
Dim hThread As System.IntPtr
Dim dwProcessId As Integer
Dim dwThreadId As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure STARTUPINFO
Dim cb As Integer
Dim lpReserved As System.IntPtr
Dim lpDesktop As System.IntPtr
Dim lpTitle As System.IntPtr
Dim dwX As Integer
Dim dwY As Integer
Dim dwXSize As Integer
Dim dwYSize As Integer
Dim dwXCountChars As Integer
Dim dwYCountChars As Integer
Dim dwFillAttribute As Integer
Dim dwFlags As Integer
Dim wShowWindow As Short
Dim cbReserved2 As Short
Dim lpReserved2 As System.IntPtr
Dim hStdInput As System.IntPtr
Dim hStdOutput As System.IntPtr
Dim hStdError As System.IntPtr
End Structure
End Region
Region "API Constants"
Private Const LOGON_NETCREDENTIALS_ONLY As Integer = &H2
Private Const NORMAL_PRIORITY_CLASS As Integer = &H20
Private Const CREATE_DEFAULT_ERROR_MODE As Integer = &H4000000
Private Const CREATE_NEW_CONSOLE As Integer = &H10
Private Const CREATE_NEW_PROCESS_GROUP As Integer = &H200
Private Const LOGON_WITH_PROFILE As Integer = &H1
End Region
Region "API Functions"
Private Declare Unicode Function CreateProcessWithLogon Lib "Advapi32" Alias "CreateProcessWithLogonW" _
(ByVal lpUsername As String, _
ByVal lpDomain As String, _
ByVal lpPassword As String, _
ByVal dwLogonFlags As Integer, _
ByVal lpApplicationName As String, _
ByVal lpCommandLine As String, _
ByVal dwCreationFlags As Integer, _
ByVal lpEnvironment As System.IntPtr, _
ByVal lpCurrentDirectory As System.IntPtr, _
ByRef lpStartupInfo As STARTUPINFO, _
ByRef lpProcessInfo As PROCESS_INFORMATION) As Integer
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As System.IntPtr) As Integer
End Region
Public Sub RunProgram(ByVal UserName As String, ByVal Password As String, ByVal Domain As String, ByVal Application As String, ByVal CommandLine As String)
Dim siStartup As STARTUPINFO
Dim piProcess As PROCESS_INFORMATION
Dim intReturn As Integer
If CommandLine Is Nothing OrElse CommandLine = "" Then CommandLine = String.Empty
siStartup.cb = Marshal.SizeOf(siStartup)
siStartup.dwFlags = 0
intReturn = CreateProcessWithLogon(UserName, Domain, Password, LOGON_WITH_PROFILE, Application, CommandLine, _
NORMAL_PRIORITY_CLASS Or CREATE_DEFAULT_ERROR_MODE Or CREATE_NEW_CONSOLE Or CREATE_NEW_PROCESS_GROUP, _
IntPtr.Zero, IntPtr.Zero, siStartup, piProcess)
If intReturn = 0 Then
Throw New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())
End If
CloseHandle(piProcess.hProcess)
CloseHandle(piProcess.hThread)
End Sub
Overloads Sub Main(ByVal args() As String)
Dim command As String = "C:\Program Files\Printer Server Update Utility\CreatePrinterPort.exe"
Dim arguments As String = Chr(34) & "C:\Program Files\Printer Server Update Utility\CreatePrinterPort.exe" & Chr(34) & " /I:138.90.1.3"
Dim user As String = "PrintAdmin"
Dim domain As String = System.Environment.MachineName
Dim password As String = "Pa$$word" '<---- No not really
Dim currentDirectory As String = System.IO.Directory.GetCurrentDirectory()
RunProgram(user, password, domain, command, arguments)
System.Console.WriteLine("Please press the ENTER key to close window.")
System.Console.WriteLine("")
System.Console.Read()
End Sub
End Module
功能的TCPIP端口創建應用程序,並在工作和應用催生以上時失敗。
Function CreatePrinterIPPort(ByVal strPrinterIPAddress As String, Optional ByVal Protocol As Short = 1, Optional ByVal QueueName As String = "Dummy", _ Optional ByVal ByteCount As Boolean = False) As Boolean ' Protocal 1 = RAW (Default) 2 = LPR System.Console.WriteLine("Attempting to create port at IP Address: " & strPrinterIPAddress) Dim options As New ConnectionOptions options.Impersonation = ImpersonationLevel.Impersonate Dim mpBasePath As New ManagementPath("\.\ROOT\CIMV2") Dim mpTCPIPPort As New ManagementPath("Win32_TCPIPPrinterPort") Dim msLocalMachine As New ManagementScope(mpBasePath, options) msLocalMachine.Connect() Dim mcNetworkPorts As New ManagementClass(msLocalMachine, mpTCPIPPort, New ObjectGetOptions) Dim moNewPort As ManagementObject = mcNetworkPorts.CreateInstance() moNewPort.Properties("Name").Value = "IP_" & strPrinterIPAddress moNewPort.Properties("Protocol").Value = Protocol moNewPort.Properties("HostAddress").Value = strPrinterIPAddress If Protocol = 1 Then moNewPort.Properties("PortNumber").Value = "9100" ElseIf Protocol = 2 Then moNewPort.Properties("ByteCount").Value = ByteCount moNewPort.Properties("Queue").Value = QueueName End If
Try
moNewPort.Put()
Catch ex As Exception
System.Console.WriteLine("Port creation failed.")
System.Console.WriteLine(ex.Message.ToString)
Return False
End Try
System.Console.WriteLine("Created port at IP Address: " & strPrinterIPAddress)
Return True
End Function