2009-05-22 9 views
1

Il y a quelques mois, j'ai écrit une application de console VB.net pour migrer un groupe d'environ 100 imprimantes et les plus de 1800 utilisateurs qui les utilisent à partir de vieux appareils d'impression HP. un serveur d'impression mixte et des solutions d'impression directe sur IP. L'application utilise une base de données pour comparer les imprimantes installées et supprimer les anciens/non valides et remapper sur le nouveau serveur d'impression basé sur Win2K3 OU créer un port d'imprimante TCPIP et installer le pilote pour l'impression directe sur IP.VB.net 1.1 Création de port d'imprimante TCPIP avec l'API CreateProcessWithLogon

Cela fonctionnait très bien, mais les utilisateurs avaient besoin de droits d'utilisateur pour créer le port d'imprimante TCPIP. Pour le campus principal, ce n'était pas un problème, mais les petits sites distants ont besoin d'une solution qui permet à l'application d'être exécutée par des utilisateurs sans droits d'utilisateur. Ma solution était de prendre la fonction "CreatePrinterIPPort" et de la mettre dans sa propre application encapsuleur, puis l'appeler au besoin à partir de l'application principale en utilisant un compte d'administrateur local codé dur à cet effet, mais je rencontre des problèmes lors de la création de l'application createport. Si je lance l'application de manière autonome, elle crée le port sans problème, mais lorsque je l'exécute dans mon application de test pour générer le port de création à l'aide de l'API CreateProcessWithLogon, la création du port échoue avec une erreur «Accès refusé». Je suis limité à l'utilisation de. Net 1.1 car 2.0 n'est pas dans notre environnement à travers et on m'a dit qu'il ne serait pas poussé juste pour cette application.

Des pensées?

Source répertoriée ci-dessous.

app Frai:

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

Fonction dans l'application de création de port TCPIP qui fait le travail et échoue lorsque donné naissance à l'application ci-dessus.

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 

Répondre

1

que WMI ne Semblent permet pas l'accès en écriture à un compte d'emprunt d'identité, donc je me suis déplacé à l'aide de la Prnadmin.dll pour créer des ports. Cela m'oblige à vérifier que la DLL est enregistrée et à s'enregistrer si ce n'est pas le cas, mais il semble que ce soit la seule façon que je puisse trouver (et garder ma santé mentale) pour que cela soit fait.

Questions connexes