【问题标题】:Open remote shared folder with credentials使用凭据打开远程共享文件夹
【发布时间】:2011-11-25 11:15:30
【问题描述】:

我需要在一个窗口中使用不同的凭据打开远程服务器上的文件夹 (explorer.exe)。

我设法在没有凭据(我的凭据)的情况下执行此操作,但是当我使用另一个用户名和另一个密码而不是我的用户名和密码时,它会打开一个输入用户名和密码的提示,并显示“访问被拒绝”。

在远程桌面的访问日志中,它说我尝试使用自己的用户名进行连接,而不是我输入的其他用户名。所以,这个过程显然是行不通的。

但是,我不知道为什么。我的代码如下:

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"

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

command.Start()

【问题讨论】:

    标签: vb.net shared explorer


    【解决方案1】:

    我在工作中遇到了同样的问题,并且能够通过模仿解决它。只需添加一个具有以下内容的新类:

        '*****************************************************************************************
    '*****************************************************************************************
    ' 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
    

    这将允许您在会话中模拟指定用户。因此,您可以将代码更改为:

    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()
    

    【讨论】:

    • 我相信它是因为即使您为进程提供了正确的凭据,它也只是将使用凭据的进程。问题是您的会话将使用您的凭据,模拟将在开始和结束模拟之间的代码块中模拟同一用户。
    【解决方案2】:

    给出的答案是一个非常冗长的解决方案,这是不必要的。我知道答案来自 2011 年,但您需要做的只是以下几点:

    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
    

    然后这个函数来实际打开C$共享:

    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
    

    这里是 'Close_Remote_Connection' 子程序,需要调用它,以免您的网络使用列表变得非常庞大。即使你调用这个 sub,你仍然对你打开的 c$ 拥有完全的管理员权限:

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

    我在整个互联网上寻找如何做到这一点,但没有人能接近这种简单性。它完全符合您的要求,并且非常简单,并且没有冗长的各种疯狂的函数/类,这些函数/类只是完成这个简单的事情所不需要的。

    希望它能帮助像它帮助我一样的人! :)

    LilD

    【讨论】:

    • 您应该包含isPingable 代码以使您的解决方案完整。
    猜你喜欢
    • 2011-09-14
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 2018-12-11
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    相关资源
    最近更新 更多