Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

Κλήση εξωτερικής εφαρμογής με διαφορετικά user credentials (run as) προγραμματιστικά (.NET 1.1)

Μετά από αρκετή διερεύνηση, επιχειρώντας να λύσω ένα συγκεκριμένο πρόβλημα, κατέληξα σε ένα "μπούσουλα" για τον τρόπο με τον οποίο μπορεί κάποιος να καλέσει με κώδικα μέσα από μια εφαρμογή ένα εξωτερικό process (ενα executable) χρησιμοποιώντας διαφορετικά user credentials από αυτά του χρήστη που "τρέχει" την εφαρμογή (ουσιαστικά δηλαδή να μιμηθούμε το "run as.." που μας δίνει το shell των Windows).

Το θέμα αυτό έχει λόγο ύπαρξης μόνο στο .NET 1.1, μια και στο .NET 2.0 μπορεί κανείς να προσδιορίσει user credentials στο System.Diagnostics.Process.Start().

Θερμές ευχαριστίες, φυσικά, στους συναδέλφους του dotNetZone.gr (είναι αυτονόητο οτι χωρίς τη βοήθειά τους δεν θα επιζούσα):

Ο παρακάτω κώδικας λειτουργεί για χρήστη που βρίσκεται σε domain και η κλήση έχει ως εξής:

        clsSpawnProcess.CreateProcess( _
                  "myUser" _
                , "myDomain" _
                , "myPassword" _
                , "c:\myfolder\myexecutable.exe" _
                , " " + "myCommandLineArguments")

Η χρήση των υποδειγματικών strings που αναφέρονται στην κλήση, φαντάζομαι, είναι αυτονόητη. Ο κώδικας δουλεύει σε WinXP, Win2000 και Win2003.

Ακολουθεί ο κώδικας:

Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
Imports System.Runtime.InteropServices
Imports System.IO

Public Class clsSpawnProcess

    <Flags()> _
    Enum LogonFlags
        LOGON_WITH_PROFILE = &H1
        LOGON_NETCREDENTIALS_ONLY = &H2
    End Enum

    <Flags()> _
    Enum CreationFlags

        CREATE_SUSPENDED = &H4
        CREATE_NEW_CONSOLE = &H10
        CREATE_NEW_PROCESS_GROUP = &H200
        CREATE_UNICODE_ENVIRONMENT = &H400
        CREATE_SEPARATE_WOW_VDM = &H800
        CREATE_DEFAULT_ERROR_MODE = &H4000000
    End Enum

    <StructLayout(LayoutKind.Sequential)> _
    Structure ProcessInfo
        Public hProcess As IntPtr
        Public hThread As IntPtr
        Public dwProcessId As UInt32
        Public dwThreadId As UInt32
    End Structure

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    Structure StartupInfo
        Public cb As Int32
        Public reserved1 As String
        Public desktop As String
        Public title As String
        Public dwX As UInt32
        Public dwY As UInt32
        Public dwXSize As UInt32
        Public dwYSize As UInt32
        Public dwXCountChars As UInt32
        Public dwYCountChars As UInt32
        Public dwFillAttribute As UInt32
        Public dwFlags As UInt32
        Public wShowWindow As Short
        Public reserved2 As Short
        Public reserved3 As Integer
        Public hStdInput As IntPtr
        Public hStdOutput As IntPtr
        Public hStdError As IntPtr
    End Structure

    <DllImport("advapi32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True, SetLastError:=True)> _
    Public Shared Function CreateProcessWithLogonW( _
    ByVal principal As String, _
    ByVal authority As String, _
    ByVal password As String, _
    ByVal logonFlags As LogonFlags, _
    ByVal appName As String, _
    ByVal cmdLine As String, _
    ByVal creationFlags As CreationFlags, _
    ByVal environmentBlock As IntPtr, _
    ByVal currentDirectory As String, _
     ByRef startupInfo As StartupInfo, _
     ByRef processInfo As ProcessInfo) As Boolean
    End Function

    <DllImport("kernel32.dll")> _
    Public Shared Function CloseHandle(ByVal h As IntPtr) As Boolean
    End Function

    '/// -----------------------------------------------------------------------------
    '/// <summary>
    '/// This is the class entry point. A call to this method allows us to
    '/// spawn an executable using alternate user credentials.
    '/// </summary>
    '/// <param name="username">The user's username</param>
    '/// <param name="domain">The domain name</param>
    '/// <param name="password">The user's password</param>
    '/// <param name="applicationPath">The full path to the executable</param>
    '/// <param name="commandLineArgs">Any command line arguments</param>
    '/// <remarks>
    '/// It is important that command line arguments start with a space, or else
    '/// the call will not work.
    '/// </remarks>
    '/// -----------------------------------------------------------------------------
    Public Shared Sub CreateProcess( _
    ByVal username As String _
    , ByVal domain As String _
    , ByVal password As String _
    , ByVal applicationPath As String _
    , ByVal commandLineArgs As String)

        Dim si As StartupInfo = New StartupInfo
        si.cb = Marshal.SizeOf(GetType(StartupInfo))
        Dim pi As ProcessInfo = New ProcessInfo

        If (CreateProcessWithLogonW(username, domain, password, _
         LogonFlags.LOGON_NETCREDENTIALS_ONLY, _
         applicationPath, commandLineArgs, _
         0, IntPtr.Zero, Nothing, _
         si, pi)) Then
            CloseHandle(pi.hProcess)
            CloseHandle(pi.hThread)
        Else
            'TODO: throw exception here or something
            Console.WriteLine("Error code: {0}", Marshal.GetLastWin32Error())
        End If
    End Sub
End Class

 

 

 

Έχουν δημοσιευτεί Τετάρτη, 14 Δεκεμβρίου 2005 3:41 μμ από το μέλος cap
Δημοσίευση στην κατηγορία:

Ενημέρωση για Σχόλια

Αν θα θέλατε να λαμβάνετε ένα e-mail όταν γίνονται ανανεώσεις στο περιεχόμενο αυτής της δημοσίευσης, παρακαλούμε γίνετε συνδρομητής εδώ

Παραμείνετε ενήμεροι στα τελευταία σχόλια με την χρήση του αγαπημένου σας RSS Aggregator και συνδρομή στη Τροφοδοσία RSS με σχόλια

Σχόλια:

Χωρίς Σχόλια

Ποιά είναι η άποψή σας για την παραπάνω δημοσίευση;

(απαιτούμενο)
απαιτούμενο
(απαιτούμενο)
ÅéóÜãåôå ôïí êùäéêü:
CAPTCHA Image