Here ya go - tested it just a minute ago. Use like this:
ProcessAsUser.Launch("c:\YourApp.exe", "-Your -commands")
Imports System.Runtime.InteropServices
Module modProcessAsUser
<structlayout(layoutkind.sequential)> _
Private Structure STARTUPINFO
Public cb As Int32
Public lpReserved As String
Public lpDesktop As String
Public lpTitle As String
Public dwX As Int32
Public dwY As Int32
Public dwXSize As Int32
Public dwYSize As Int32
Public dwXCountChars As Int32
Public dwYCountChars As Int32
Public dwFillAttribute As Int32
Public dwFlags As Int32
Public wShowWindow As Short
Public cbReserved2 As Short
Public lpReserved2 As IntPtr
Public hStdInput As IntPtr
Public hStdOutput As IntPtr
Public hStdError As IntPtr
End Structure
<structlayout(layoutkind.sequential)> _
Friend Structure PROCESS_INFORMATION
Public hProcess As IntPtr
Public hThread As IntPtr
Public dwProcessId As Int32
Public dwThreadId As Int32
End Structure
<structlayout(layoutkind.sequential)> _
Friend Structure SECURITY_ATTRIBUTES
Public nLength As Int32
Public lpSecurityDescriptor As IntPtr
Public bInheritHandle As Boolean
End Structure
Public Enum SECURITY_IMPERSONATION_LEVEL
SecurityAnonymous
SecurityIdentification
SecurityImpersonation
SecurityDelegation
End Enum
Public Enum TOKEN_TYPE
TokenPrimary = 1
TokenImpersonation
End Enum
Private Declare Auto Function CreateProcessAsUser Lib "advapi32" ( _
ByVal hToken As IntPtr, _
ByVal strApplicationName As String, _
ByVal strCommandLine As String, _
ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _
ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
ByVal bInheritHandles As Boolean, _
ByVal dwCreationFlags As Integer, _
ByVal lpEnvironment As IntPtr, _
ByVal lpCurrentDriectory As String, _
ByRef lpStartupInfo As STARTUPINFO, _
ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean
Declare Function DuplicateTokenEx Lib "advapi32.dll" (ByVal hExistingToken As IntPtr, _
ByVal dwDesiredAccess As System.UInt32, ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
ByVal ImpersonationLevel As Int32, ByVal dwTokenType As Int32, ByRef phNewToken As IntPtr) As Boolean
Declare Function CreateEnvironmentBlock Lib "userenv.dll" (ByRef lpEnvironment As IntPtr, _
ByVal hToken As IntPtr, ByVal bInherit As Boolean) As Boolean
Public Class ProcessAsUser
Private Const SE_FILE_OBJECT = 1&
Private Const OWNER_SECURITY_INFORMATION = &H1
Private Const NAME_SIZE = 64
Private Const SID_SIZE = 32
Private Const STARTF_USESHOWWINDOW As Integer = &H1&
Private Const STARTF_FORCEONFEEDBACK = &H40
Private Const SW_SHOW = 5
Private Const CREATE_UNICODE_ENVIRONMENT As Long = &H400&
Private Const TOKEN_DUPLICATE = &H2
Private Const TOKEN_ASSIGN_PRIMARY = &H1
Private Const TOKEN_QUERY = &H8
Private Declare Function OpenProcessToken Lib "advapi32.dll" ( _
ByVal ProcessHandle As IntPtr, _
ByVal DesiredAccess As Integer, _
ByRef TokenHandle As IntPtr) As Boolean
Declare Function DestroyEnvironmentBlock Lib "userenv.dll" (ByVal lpEnvironment As IntPtr) As Boolean
Private Shared Function LaunchProcessAsUser(ByVal cmdLine As String, ByVal token As IntPtr, ByVal envBlock As IntPtr, Optional cmds As String = "") As Boolean
Dim result As Boolean = False
Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
Dim saProcess As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
Dim saThread As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
saProcess.nLength = Runtime.InteropServices.Marshal.SizeOf(saProcess)
saThread.nLength = Runtime.InteropServices.Marshal.SizeOf(saThread)
Dim si As STARTUPINFO = New STARTUPINFO
si.cb = Runtime.InteropServices.Marshal.SizeOf(si)
si.lpDesktop = Nothing
si.wShowWindow = 1
si.dwFlags = STARTF_USESHOWWINDOW Or STARTF_FORCEONFEEDBACK
si.wShowWindow = SW_SHOW
result = CreateProcessAsUser(token, cmdLine, " " & cmds, saProcess, saThread, False, CREATE_UNICODE_ENVIRONMENT, envBlock, Nothing, si, pi)
If result = False Then
Dim iError As Integer = Runtime.InteropServices.Marshal.GetLastWin32Error
Dim message As String = String.Format("CreateProcessAsUser Error: {0}", iError)
Debug.WriteLine(message)
End If
Return result
End Function
Private Shared Function GetPrimaryToken(ByVal processId As Integer) As IntPtr
Dim token As IntPtr = IntPtr.Zero
Dim primaryToken As IntPtr = IntPtr.Zero
Dim retVal As Boolean = False
Dim p As Process = Nothing
Try
p = Process.GetProcessById(processId)
Catch generatedExceptionVariable0 As ArgumentException
Dim details As String = String.Format("ProcessID {0} Not Available", processId)
Debug.WriteLine(details)
Return primaryToken
End Try
retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, token)
If retVal = True Then
Dim sa As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
sa.nLength = Runtime.InteropServices.Marshal.SizeOf(sa)
retVal = DuplicateTokenEx(token, TOKEN_ASSIGN_PRIMARY Or TOKEN_DUPLICATE Or TOKEN_QUERY, sa, CType(SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Integer), CType(TOKEN_TYPE.TokenPrimary, Integer), primaryToken)
If retVal = False Then
Dim message As String = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error)
Debug.WriteLine(message)
End If
Else
Dim message As String = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error)
Debug.WriteLine(message)
End If
Return primaryToken
End Function
Private Shared Function GetEnvironmentBlock(ByVal token As IntPtr) As IntPtr
Dim envBlock As IntPtr = IntPtr.Zero
Dim retVal As Boolean = CreateEnvironmentBlock(envBlock, token, False)
If retVal = False Then
Dim message As String = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error)
Debug.WriteLine(message)
End If
Return envBlock
End Function
Public Shared Function Launch(ByVal appCmdLine As String, Optional cmds As String = "", Optional ByVal processName As String = "explorer") As Boolean
Dim ret As Boolean = False
Dim ps As Process() = Process.GetProcessesByName(processName)
Dim processId As Integer = -1
If ps.Length > 0 Then
processId = ps(0).Id
End If
If processId > 1 Then
Dim token As IntPtr = GetPrimaryToken(processId)
If Not (token.Equals(IntPtr.Zero)) Then
Dim envBlock As IntPtr = GetEnvironmentBlock(token)
ret = LaunchProcessAsUser(appCmdLine, token, envBlock, cmds)
If Not (envBlock.Equals(IntPtr.Zero)) Then
DestroyEnvironmentBlock(envBlock)
End If
End If
End If
Return ret
End Function
End Class
End Module
Hope this helps.
- Pete