VB.Net Run As Administrator (impersonate a user) 2008

VB.Net Impersonate a specified User in code

VB.Net 2008 Run as Administrator

I had some trouble finding a method that worked the way I wanted, and finally found this lovely little class – can’t remember where I originally got it from but it’s definitely worth sharing…

NOTE: If you just want to start a process (run a program) as another user it may be easier to use the little snippet of code at the end of this article instead.

I prefer executable files to scripts, and require low privilege users to be able to run sections of the code/script with elevated privileges but without IT intervention – this does the job nicely. Whapped it into exes/scripts that required elevated privileges and now my most menial of users can run them with no Admin intervention 😉

Just add a new vb class to your project and save it as RunAs_Impersonator – then copy the code below over the entire RunAs_Impersonator page. In case of problems on pasting, you can click here for the .TXT RunAs_Impersonator.txt, or here for the zipped class file RunAs_Impersonator.vb. You may need to add references to the Imports…

Once in your project, any sections of code that require running with elevated privileges are preceeded by:

Dim imp As New RunAs_Impersonator ‘(somewhere in your declarations)

imp.ImpersonateStart(‘YourDomain’, ‘UserName’, ‘UserPassword’)

– – – Code to run with elevated privileges – – –

To run as a local account rather than a Domain User use ‘.’ (full stop) for the Domain.

Recently migrated 500 users, PCs, and 60 Servers to our new owners domain at short notice (1 week) – a most entertaining and quite educational experience… Didn’t go too badly considering – managed to keep both main Call Centres and payment processing running throughout so a success in my book – I’ll be posting about a few of the VB.Net tweaks I needed to get things working properly again.

RunAs_Impersonator code is below:

Imports System
Imports System.Runtime.InteropServices
Imports System.Security.Principal
Imports System.Security.Permissions
Imports Microsoft.VisualBasic
<Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode:=True), _
Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="FullTrust")>

Public Class RunAs_Impersonator
#Region "Private Variables and Enum Constants"
Private tokenHandle As New IntPtr(0)
Private dupeTokenHandle As New IntPtr(0)
Private impersonatedUser As WindowsImpersonationContext
#End Region
#Region "Properties"

#End Region
#Region "Public Methods"
Public Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
Public Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _

ByRef DuplicateTokenHandle As IntPtr) As Boolean
' Test harness.
' If you incorporate this code into a DLL, be sure to demand FullTrust.
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _

Public Sub ImpersonateStart(ByVal Domain As String, ByVal userName As String, ByVal Password As String)
tokenHandle = IntPtr.Zero
' Call LogonUser to obtain a handle to an access token.
Dim returnValue As Boolean = LogonUser(userName, Domain, Password, 2, 0, tokenHandle)
'check if logon successful

If returnValue = False Then
Dim ret As Integer = Marshal.GetLastWin32Error()
Console.WriteLine("LogonUser failed with error code : {0}", ret)
Throw New System.ComponentModel.Win32Exception(ret)
Exit Sub

End If
'Logon succeeded
' Use the token handle returned by LogonUser.
Dim newId As New WindowsIdentity(tokenHandle)
impersonatedUser = newId.Impersonate()
Catch ex As Exception

Throw ex
Exit Sub
End Try

End Sub
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
Public Sub ImpersonateStop()
' Stop impersonating the user.

' Free the tokens.
If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then
End If

End Sub
#End Region
#Region "Private Methods"
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
<DllImport("kernel32.dll")> _
Public 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
#End Region
End Class

Start Process as different user

If you just want to run a program or start a process as a different user, this can be accomplished easily as follows (using IE as an example). The first 3 lines should be on one line, if you know what I mean.

You should be OK copying and pasting the below code, or click here for the .TXT version.

The password string requires converting to a System.Security.SecureString() – hence the loop on the password string that passes each character.

‘**** Start IE as Admin ***********
Dim p As New ProcessStartInfo(My.Computer.FileSystem.SpecialDirectories.ProgramFiles + "\Internet Explorer\IEXPLORE.EXE")
p.UseShellExecute = False
p.Domain = "Domain"
p.UserName = "Username"
p.Password = New System.Security.SecureString()
For Each c As Char In "Password"
p.Arguments = ("http://www.google.com")
‘**** End Start IE as Admin ***********

  1. Pingback: Tales from the IT side » VB.Net easily Change/Modify NTFS File/Directory Security 2008

  2. This works great !
    For beginning users it’s great that you write what to do exactly.
    (create al class, call it bla bla, etc)

  3. This works great for elevating calls where I access the C$ shares of workstations and remote registry calls. However, it is not working for any sort of remote WMI calls I am trying to make. It reverts back to using the security context of the user who launched the .exe vs. using the impersonation account. I am using VB.Net and Visual Studio 2010.

    Has anyone else also experienced this? If so, did you find a solution?

  4. Does this work on Windows 7 ? I added the class, then made myself Administrator and started Notepad with the protected ‘hosts’ file, modified it and could not save it back. Code:
    Dim AdminPass As String = InputBox(“Please type the Administrator Password”, “Need Admin PW”)
    Dim imp As New RunAs_Impersonator
    imp.ImpersonateStart(Environment.MachineName, “Administrator”, AdminPass)
    Dim p As Process = Process.Start(“Notepad”, “C:\Windows\System32\drivers\etc\hosts”)
    MessageBox.Show(“Clear this box when finished with Notepad”)

    • I’ll struggle to find a Win 7 PC to try it on quickly, and not used this routine for a while so will need to revisit and check.

      Try using “.” as Domain Name (parameter 1) instead of environment.machinename.?

Leave a Reply

Your email address will not be published. Required fields are marked *