VB.net 1.1使用CreateProcessWithLogon API创建TCPIP打印机端口

时间:2009-05-22 21:39:17

标签: vb.net privileges

几个月前,我写了一个VB.net控制台应用程序,将一组约100多台打印机和1800多个用户从一些旧的HP打印设备迁移到混合打印服务器和直接打印到IP打印解决方案。该应用程序使用数据库比较已安装的打印机并删除旧/无效共享并重新映射到新的基于Win2K3的打印服务器或创建TCPIP打印机端口并安装驱动程序以进行直接IP打印。

它工作得很好,但用户需要高级用户权限才能创建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

<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

在TCPIP端口创建应用程序中执行工作的功能,并在上面的应用程序中生成时失败。

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

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

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

1 个答案:

答案 0 :(得分:1)

似乎WMI不允许对模拟帐户进行写访问,因此我继续使用prnadmin.dll创建端口。这要求我检查dll是否已注册并注册,如果不是,但似乎这是我能找到的唯一方法(并保持理智)。