Open remote shared folder with credentials

前端 未结 2 1825
生来不讨喜
生来不讨喜 2021-01-20 06:16

I need to open a folder on a remote server with different credentials in a window (explorer.exe).

I managed to do it with no credentials (my credentials), but when I

2条回答
  •  终归单人心
    2021-01-20 06:45

    I ran into this same problem at work and was able to solve it with impersonation. just add a new class with the following:

        '*****************************************************************************************
    '*****************************************************************************************
    ' Contents: AliasAccount Class
    '
    ' This Class is a template class that provides all the functionality to impersonate a user
    ' over a designated instance.
    '*****************************************************************************************
    '*****************************************************************************************
    
    
    Public Class AliasAccount
      Private _username, _password, _domainname As String
    
      Private _tokenHandle As New IntPtr(0)
      Private _dupeTokenHandle As New IntPtr(0)
      Private _impersonatedUser As System.Security.Principal.WindowsImpersonationContext
    
    
      Public Sub New(ByVal username As String, ByVal password As String)
        Dim nameparts() As String = username.Split("\")
        If nameparts.Length > 1 Then
          _domainname = nameparts(0)
          _username = nameparts(1)
        Else
          _username = username
        End If
        _password = password
      End Sub
    
      Public Sub New(ByVal username As String, ByVal password As String, ByVal domainname As String)
        _username = username
        _password = password
        _domainname = domainname
      End Sub
    
    
      Public Sub BeginImpersonation()
        'Const LOGON32_PROVIDER_DEFAULT As Integer = 0
        'Const LOGON32_LOGON_INTERACTIVE As Integer = 2
        Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9
        Const LOGON32_PROVIDER_WINNT50 As Integer = 3
        Const SecurityImpersonation As Integer = 2
    
        Dim win32ErrorNumber As Integer
    
        _tokenHandle = IntPtr.Zero
        _dupeTokenHandle = IntPtr.Zero
    
        If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _tokenHandle) Then
          win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
          Throw New ImpersonationException(win32ErrorNumber, GetErrorMessage(win32ErrorNumber), _username, _domainname)
        End If
    
        If Not DuplicateToken(_tokenHandle, SecurityImpersonation, _dupeTokenHandle) Then
          win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
    
          CloseHandle(_tokenHandle)
          Throw New ImpersonationException(win32ErrorNumber, "Unable to duplicate token!", _username, _domainname)
        End If
    
        Dim newId As New System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
        _impersonatedUser = newId.Impersonate()
      End Sub
    
    
      Public Sub EndImpersonation()
        If Not _impersonatedUser Is Nothing Then
          _impersonatedUser.Undo()
          _impersonatedUser = Nothing
    
          If Not System.IntPtr.op_Equality(_tokenHandle, IntPtr.Zero) Then
            CloseHandle(_tokenHandle)
          End If
          If Not System.IntPtr.op_Equality(_dupeTokenHandle, IntPtr.Zero) Then
            CloseHandle(_dupeTokenHandle)
          End If
        End If
      End Sub
    
    
      Public ReadOnly Property username() As String
        Get
          Return _username
        End Get
      End Property
    
      Public ReadOnly Property domainname() As String
        Get
          Return _domainname
        End Get
      End Property
    
    
      Public ReadOnly Property currentWindowsUsername() As String
        Get
          Return System.Security.Principal.WindowsIdentity.GetCurrent().Name
        End Get
      End Property
    
    
    #Region "Exception Class"
      Public Class ImpersonationException
        Inherits System.Exception
    
        Public ReadOnly win32ErrorNumber As Integer
    
        Public Sub New(ByVal win32ErrorNumber As Integer, ByVal msg As String, ByVal username As String, ByVal domainname As String)
          MyBase.New(String.Format("Impersonation of {1}\{0} failed! [{2}] {3}", username, domainname, win32ErrorNumber, msg))
          Me.win32ErrorNumber = win32ErrorNumber
        End Sub
      End Class
    #End Region
    
    
    #Region "External Declarations and Helpers"
      Private Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As [String], _
              ByVal lpszDomain As [String], ByVal lpszPassword As [String], _
              ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, _
              ByRef phToken As IntPtr) As Boolean
    
    
      Private Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
                  ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
                  ByRef DuplicateTokenHandle As IntPtr) As Boolean
    
    
      Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
    
    
       _
      Private Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _
              ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _
              ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer
      End Function
    
    
      Private Function GetErrorMessage(ByVal errorCode As Integer) As String
        Dim FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
        Dim FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
        Dim FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000
    
        Dim messageSize As Integer = 255
        Dim lpMsgBuf As String = ""
        Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS
    
        Dim ptrlpSource As IntPtr = IntPtr.Zero
        Dim prtArguments As IntPtr = IntPtr.Zero
    
        Dim retVal As Integer = FormatMessage(dwFlags, ptrlpSource, errorCode, 0, lpMsgBuf, messageSize, prtArguments)
        If 0 = retVal Then
          Throw New System.Exception("Failed to format message for error code " + errorCode.ToString() + ". ")
        End If
    
        Return lpMsgBuf
      End Function
    
    #End Region
    
    End Class
    

    This will allow you to impersonate a designated user for a session. so you would than change your code to:

    Dim domain, username, passwordStr, remoteServerName As String    
    Dim password As New Security.SecureString    
    Dim command As New Process  
    
    domain = "domain.com"    
    username = "username"    
    passwordStr = "password"    
    remoteServerName = "serverName"
    Dim impersonator As New AliasAccount(username, password)
    
    For Each c As Char In passwordStr.ToCharArray        
      password.AppendChar(c)    
    Next
    
    
    command.StartInfo.FileName = "explorer.exe"    
    command.StartInfo.Arguments = "\\" & serverName & "\admin$\Temp"        
    
    command.StartInfo.UserName = username    
    command.StartInfo.Password = password    
    command.StartInfo.Domain = domain    
    command.StartInfo.Verb = "open"    
    command.StartInfo.UseShellExecute = False 
    
      impersonator.BeginImpersonation()
    command.Start() 
      impersonator.EndImpersonation()
    

提交回复
热议问题