Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
The following code has been tested on Windows 2003 SP2. The calling user account must have 'Assign Primary Token' and 'Increase Quota' permissions to properly execute CreateProcessAsUser; see MS KB285879.
Public Function RunProc(ByVal CMD As String, ByVal ARG As String) As String Dim er As Int16 Dim exitCode As System.UInt32 = Convert.ToUInt32(123) Dim saThreadAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES saThreadAttributes.nLength = Marshal.SizeOf(saThreadAttributes) Dim impToken As System.IntPtr = IntPtr.Zero Dim priToken As System.IntPtr = IntPtr.Zero If LogonUser("DomainUser", "Domain", "Passwd", LogonType.LOGON32_LOGON_INTERACTIVE, _ LogonProvider.LOGON32_PROVIDER_DEFAULT, impToken) Then If DuplicateTokenEx(impToken, &H2000000, Nothing, SecurityImpersonationLevel.SecurityDelegation, TOKEN_TYPE.TokenPrimary, priToken) Then Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION Dim si As STARTUPINFO = New STARTUPINFO si.cb = Marshal.SizeOf(si) si.lpDesktop = IntPtr.Zero Dim saProcessAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES saProcessAttributes.nLength = Marshal.SizeOf(saProcessAttributes) If Not CreateProcessAsUser(priToken, CMD, CMD & " " & ARG, saProcessAttributes, _ saThreadAttributes, False, 0, IntPtr.Zero, "c:\", si, pi) Then er = Marshal.GetLastWin32Error RunProc = ("err runas " & er) Else WaitForSingleObject(pi.hProcess, Infinite) GetExitCodeProcess(pi.hProcess, exitCode) End If CloseHandle(priToken) CloseHandle(impToken) CloseHandle(pi.hProcess) CloseHandle(pi.hThread) End If End If End Function