Pergunta

Solution (kinda):

Acontece que esta representação com a segurança do .NET só permite o acesso em nível de aplicativo. Desde o objeto COM é no nível do sistema, o usuário representado ainda não pode instanciá-lo. Eu descobri isso clicando com o executável e selecionando "Executar como ...", o programa funcionou bem. Eu descobri que inicia o programa com acesso ao sistema (assumindo que o usuário que você está executando-o com tem essas credenciais). Agora eu estou no processo de criação de um programa externo que vai lançar este aplicativo utilizando este método.

Obrigado pelas dicas: D


Eu tenho uma instalação do Windows XP em uma máquina virtual. Faz parte do meu domínio, mas o usuário conectado é de apenas um usuário local. Obviamente, se eu tentar acessar um compartilhamento de rede que irá pedir para um usuário / senha:

text alt

O programa que eu estou testando a máquina virtual usa um objeto COM para a interface com os dados de outro programa. Se eu não fizer impersonate, eu recebo erros, porque eu não tenho as credenciais adequadas.

Eu fiz alguma pesquisa sobre o assunto e encontrou uma série de sites que tinham uma quantidade razoável de informações VB.NET. O problema que estou tendo com o código que eu escrevi é que eu posso acessar os recursos de rede, mas não posso instanciar o objeto COM.

Se eu preencher e enviar o solicitação de credenciais (acima) antes de tentar instanciar-lo, ele funciona bem. Que me leva a crer que deve haver algo que a solicitação de credenciais WinXP está fazendo que eu não sou. Abaixo está o código que estou usando para representação:

Public Sub BeginImpersonation()
    Const LOGON32_PROVIDER_DEFAULT As Integer = 0
    Const LOGON32_LOGON_INTERACTIVE As Integer = 2
    Const SecurityImpersonation As Integer = 2

    Dim win32ErrorNumber As Integer

    _tokenHandle = IntPtr.Zero
    _dupeTokenHandle = IntPtr.Zero

    If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, _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()
    _impersonating = True
End Sub

Eu também tentei enviar diferentes bandeiras para o método imitador, mas nada parece estar funcionando. Aqui estão as diferentes bandeiras que encontrei:

Enum LOGON32_LOGON
    INTERACTIVE = 2
    NETWORK = 3
    BATCH = 4
    SERVICE = 5
    UNLOCK = 7
    NETWORK_CLEARTEXT = 8
    NEW_CREDENTIALS = 9
End Enum
Enum LOGON32_PROVIDER
    [DEFAULT] = 0
    WINNT35 = 1
    WINNT40 = 2
    WINNT50 = 3
End Enum
Enum SECURITY_LEVEL
    Anonymous = 0
    Identification = 1
    Impersonation = 2
    Delegation = 3
End Enum
Foi útil?

Solução

Eu tenho que correr para isso antes, e usou dois soloution diferente - o mais fácil estava usando um aplicativo de terceiros: TqcRunas: http://www.quimeras.com/Products/products.asp que lhe permite empacotar os creentials necessários em um arquivo criptografado. No entanto é uma dor se a senha é forçado a expirar.

A outra solução que eu usei é chamar um novo processo com credenciais alternativas:

        Dim myProcessStartInfo As ProcessStartInfo = New ProcessStartInfo

    With myProcessStartInfo

        .FileName = "file path and name"

        .Domain = "domainname"
        .UserName = "username"

        'password needs to be a SerureString
        Using NewPassword As New Security.SecureString
            With NewPassword
                For Each c As Char In "password".ToCharArray
                    .AppendChar(c)
                Next c
                .MakeReadOnly()
            End With
            .Password = NewPassword.Copy
        End Using

        'UseShellExecute must be false for impersonated process
        .UseShellExecute = False

    End With

    Using Process As New System.Diagnostics.Process
        With Process
            .StartInfo = myProcessStartInfo
            .Start()
        End With
    End Using

Outras dicas

Com as definições, eu uso

LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _tokenHandle)

no meu código que está autenticando através da rede. Estou a representar um utilizador local no caixa remoto, como você é. Foi há muito tempo que eu não me lembro a razão para a utilização desses valores, no entanto.

I fazer uma coisa semelhante para mapear unidades de rede para copiar arquivos entre máquinas. Eu não escrever o código, mas é praticamente a mesma que a sua, exceto por duas coisas:

  • Depois dos retornos método personificar Eu fecho ambas as fichas utilizando a rotina CloseHandle, antes de eu sair do meu método imitador.

  • No topo do imitador a primeira coisa que acontece é uma chamada para RevertToSelf, presumivelmente para cancelar qualquer representação anterior.

Eu não sei se eles iriam fazer a diferença, mas vale a pena uma tentativa. Estas foram as declarações relevantes:

Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top