2009-05-22 200 views
1

幾個月前,我編寫了一個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 

回答

1

似乎WMI不允許一個模擬的帳戶寫權限,所以我已經轉移到使用prnadmin.dll來創建端口。這要求我檢查一下dll是否已經註冊並註冊,如果不是的話,但看起來這是我能找到(並保持理智)來完成的唯一途徑。