Open remote shared folder with credentials

前端 未结 2 1824
生来不讨喜
生来不讨喜 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
    
    
      <System.Runtime.InteropServices.DllImport("kernel32.dll")> _
      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()
    
    0 讨论(0)
  • 2021-01-20 06:55

    The answer given is a very long-winded solution that is unnecessary. I know the answer is from 2011, but all you need to do is the following:

    Public Sub Open_Remote_Connection(ByVal strComputer As String, ByVal strUsername As String, ByVal strPassword As String)
        Try
            Dim procInfo As New ProcessStartInfo
            procInfo.FileName = "net"
            procInfo.Arguments = "use \\" & strComputer & "\c$ /USER:" & strUsername & " " & strPassword
            procInfo.WindowStyle = ProcessWindowStyle.Hidden
            procInfo.CreateNoWindow = True
    
            Dim proc As New Process
            proc.StartInfo = procInfo
            proc.Start()
            proc.WaitForExit(15000)
        Catch ex As Exception
            MsgBox("Open_Remote_Connection" & vbCrLf & vbCrLf & ex.Message, 4096, "Error")
        End Try
    End Sub
    

    and then this function to actually open the C$ share:

    Private Sub OpenCDriveofPC(ByVal compName As String)
        Try
            If isPingable(compName) Then
                Open_Remote_Connection(compName, strUserName, strPassword)
                Process.Start("explorer.exe", "\\" & compName & "\c$")
            End If
        Catch ex As Exception
            MsgBox("OpenCDriveofPC" & vbCrLf & vbCrLf & ex.message, 4096, "Error")
        Finally
            Close_Remote_Connection("net use \\" & compName & "\c$ /delete /yes")
        End Try
    

    And here is the 'Close_Remote_Connection' sub, which needs to be called so that you don't make your net use list get crazy huge. Even if you call this sub, you will still have full admin rights to the c$ you open:

    Public Sub Close_Remote_Connection(ByVal device As String)
        Shell("cmd.exe /c " & device, vbHidden)
    End Sub
    

    I looked all over the Internet for how to do this and no one came even close to this simplicity. It does exactly what you want and is crazy simple and not long-winded with all sorts of crazy functions/classes that just are not needed to do this simple thing.

    Hope it helps others like it helped me! :)

    LilD

    0 讨论(0)
提交回复
热议问题