Открыть удаленную общую папку с учетными данными - PullRequest
3 голосов
/ 26 сентября 2011

Мне нужно открыть папку на удаленном сервере с разными учетными данными в окне (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()

Ответы [ 2 ]

6 голосов
/ 28 сентября 2011

Я столкнулся с этой же проблемой на работе и смог решить ее с помощью подражания.просто добавьте новый класс со следующим:

    '*****************************************************************************************
'*****************************************************************************************
' 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()
0 голосов
/ 18 сентября 2018

Ответ - очень затянутое решение, в котором нет необходимости.Я знаю, что ответ с 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', который нужно вызывать, чтобы вы не делали свой список использования в сети огромным.Даже если вы позвоните по этому сабвуферу, вы все равно будете иметь полные права администратора на открытую c $:

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

Я искал во всем Интернете, как это сделать, и никто даже близко не подошел к этой простоте,Он делает именно то, что вы хотите, и он просто сумасшедший и не слишком затянутый, с множеством сумасшедших функций / классов, которые просто не нужны для этой простой вещи.

Надеюсь, это поможет другим, как помогло мне!:)

LilD

...