2009-05-22 143 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是否已经注册并注册,如果不是的话,但看起来这是我能找到(并保持理智)来完成的唯一途径。