Click here to Skip to main content
16,016,712 members
Articles / Programming Languages / C#
Article

RunAs Class

Rate me:
Please Sign up or sign in to vote.
4.74/5 (27 votes)
14 Feb 20054 min read 333.6K   8.4K   69   71
Class that wraps CreateProcessWithLogonW as well as a simple control that makes use of the RunAs class.

Sample Image - RunAs.jpg

Introduction

There are three projects in this solution: RunAs, UseRunAsControl, and ProcessToStart. RunAs is the focus of this solution; it contains the class that wraps CreateProcessWithLogonW. UseRunAsControl defines and makes use of a simple control implementing the RunAs class and is meant to test and show its functionality. ProcessToStart is simply a form that shows the domain and username of the user whose syntax it is running under. This is merely there to start with the UseRunAsControl to demonstrate its functionality.

Demo

To see the solution in action, grab a second set of credentials (make some dummy ones on your local machine, perhaps). Run UseRunAsControl.exe and provide the credentials. Click on "Command..." and browse to ProcessToStart.exe. Click on "Run Command". Provided the credentials are correct, you will see a MessageBox containing the process ID of the new process. ProcessToStart will display the username that it is running as. If the credentials that UseRunAsControl.exe is running under has enough privileges, when you close ProcessToStart, you will see another MessageBox notifying you that the process has ended. If the user does not have privileges to the new process, you will see a MessageBox notifying you of this, and when ProcessToStart.exe exits, you will not receive any notice.

Class Usage

Using the RunAs class is simple. Add a reference to the assembly and include the namespace VastAbyss. There is an overloaded static method named StartProcess in the class. This simple overload provides standard functionality that starts the executable as the user and loads the profile. A word of caution with using this method is that if the command line is C:\Program Files\Some Directory\Some.exe, if a Program.exe exists in C:\, it will be started and this may be seen as a security flaw. It is due to the way that CreateProcessWithLogonW parses and searches the command line (space-delimited). To avoid this, surround the command line in quotes. All of the overloads return a Process. If the process failed to start, it will be null and a Win32Exception will be thrown. Below is a sample of the simple usage:

C#
string username = "SomeUser";
string domain = "SomeDomain";
string password = "I'll never tell!";
string commandline = "\"C:\\Program Files\\Some Directory\\Some.exe\"";

// Resulting string is
//  "C:\Program Files\Some Directory\Some.exe"
// with the quotes included.
try
{
  Process proc = RunAs.StartProcess(username, domain, password,
                                                  commandline);
  try
  {
    proc.EnableRaisingEvents = true;
    proc.Exited += new EventHandler(processExited);
  }
  catch
  {
    //The process started but you don't have access to it.
  }
}
catch (Win32Exception w32e)
{
  // The process didn't start.
}

To avoid the security risk of using command line, use one of the other overloads of StartProcess() to provide the executable in appname instead of command line (command line must be used to provide parameters to the executable if needed; i.e., c:\myapp.exe /q /t). These overloads provide many more options for creating the new process. Enums are provided for supplying the values of the flags. Additional overloads can easily be added to provide full control over creating the new process. The struct definition for StartUpInfo is public and can be used with the last overload to provide the maximum amount of control.

I have added a default constructor to the RunAs class. This constructor initializes the properties to the following values: UserName (System.Environment.UserName), Domain (System.Environment.UserDomainName), Password (empty string ""), ApplicationName (CurrentProcess.StartInfo.FileName), LogonFlagsInstance (LogonFlags.WithProfile), CommandLine (System.Environment.CommandLine), CreationFlagsInstance (CreationFlags.NewConsole), CurrentDirectory (System.Environment.CurrentDirectory), Environment (IntPtr.Zero), ProcessInfo (new ProcessInformation instance), StartupInfo (new StartUpInfo instance with the following values set: cb is set to the size of the new instance, dwFlags is set to StartUpInfoFlags.UseCountChars, dwYCountChars is set to 50, lpTitle is set to CurrentProcess.MainWindowTitle). After initialization, these values can be changed and the non-static method StartProcess can be called.

Control Usage

I will leave the below code included although the focus of this project is to implement the RunAs class and not this control. This control merely serves as an example of how the RunAs class can be used. I removed the RunAsControl from the RunAs project and placed it in the UseRunAsControl project.

The RunAsControl can be quickly added to a Windows Form and the four events wired up. That's all there is to it. Below is an example usage:

C#
RunAsControl m_runAsCtl = new RunAsControl();
m_runAsCtl.ProcessStarted += new ProcessStartedEventHandler(m_pStarted);
m_runAsCtl.ProcessFailed += new ProcessFailedEventHandler(m_pFailed);
m_runAsCtl.ProcessEnded += new ProcessEndedEventHandler(m_pEnded);
m_runAsCtl.ProcessAccessFailed +=
    new ProcessAccessFailedEventHandler(m_pAccessFailed);

Comment Disclaimer

I referred to the MSDN documentation for the CreateProcessWithLogonW, PROCESS_INFORMATION, STARTUPINFO, etc... functions, structs, and constants. Most of the comments in the source code are either direct quotes from this documentation or adaptations of information from that documentation.

Thanks

I would like to thank those who provided feedback to this project. I have incorporated the suggestions and fixed the bugs that I found. I hope that this makes the project better, but if there are still things that you think are wrong with it, I welcome more constructive criticism.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: No access to new process Pin
Dewey Vozel12-Feb-05 11:28
Dewey Vozel12-Feb-05 11:28 
GeneralImprove your code ... Pin
GProssliner9-Sep-04 2:44
GProssliner9-Sep-04 2:44 
GeneralRe: Improve your code ... Pin
Dewey Vozel9-Sep-04 3:49
Dewey Vozel9-Sep-04 3:49 
GeneralRe: Improve your code ... Pin
rramirezg17-Sep-04 6:43
rramirezg17-Sep-04 6:43 
GeneralRe: Improve your code ... Pin
GProssliner19-Sep-04 0:31
GProssliner19-Sep-04 0:31 
GeneralRe: Improve your code ... Pin
rramirezg30-Sep-04 11:48
rramirezg30-Sep-04 11:48 
GeneralRe: Improve your code ... Pin
GProssliner2-Oct-04 10:28
GProssliner2-Oct-04 10:28 
GeneralRe: I did the work 4 u... Pin
chriha23-Nov-04 7:33
chriha23-Nov-04 7:33 
Hello out there

I took all the input above and tried to create such an adjusted class. Unfortunately I failed on a known but unsolved compiler error in C# (Use of possibly unassigned field) and didn't find a workaround for some time and as the company I work for anyway programs in VB, I just took the freedom to switch to VB... (no please, keep this rotten tomatoes in the box, ah, no! NOOOO!)

Here's the code:

<pre>
Imports System
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.Security.Principal
Imports System.Security.Permissions
Imports System.Diagnostics
Imports System.ComponentModel

<Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode:=True)>

''<summary>Runs a command with other credentials</summary>
''<author><name>Dewey Vozel</name><email>***beep***</email></author>
''<author><alias>Phyl</alias><name>Günter Prossliner</name><email>***beep***</email></author>
''<author><name>Christoph Hafner</name><email>***beep***</email></author>
<SecurityPermission(SecurityAction.Demand, ControlPrincipal:=True)> _
Public Class RunAs

'Private Fields
Private Shared _DefaultLogonFlag As LogonFlag = LogonFlag.WithProfile
Private Shared _DefaultCreationFlag As CreationFlag = CreationFlag.Default
Private Shared _DefaultPriority As PriorityFlag = PriorityFlag.NormalPriority

'Constructors

Private Sub New()
End Sub

'Public Properties

Public Shared Property DefaultLogonFlag() As LogonFlag
Get
Return _DefaultLogonFlag
End Get
Set(ByVal Value As LogonFlag)
If (Value = LogonFlag.Undefined) Then Throw New ArgumentException("You cannot specify 'Undefined'!")
_DefaultLogonFlag = Value
End Set
End Property

Public Shared Property DefaultCreationFlag() As CreationFlag
Get
Return _DefaultCreationFlag
End Get
Set(ByVal Value As CreationFlag)
If (Value = CreationFlag.Undefined) Then Throw New ArgumentException("You cannot specify 'Undefined'!")
_DefaultCreationFlag = Value
End Set
End Property

Public Shared Property DefaultPriority() As PriorityFlag
Get
Return _DefaultPriority
End Get
Set(ByVal Value As PriorityFlag)
If (Value = PriorityFlag.Undefined) Then Throw New ArgumentException("You cannot specify 'Undefined'!")
_DefaultPriority = Value
End Set
End Property

'Public Methods

''<summary>Executes a commandline statement with "cmd.exe".</summary>
''<returns>Returns a Process object, NULL (if the process terminated faster than I could reference it) or throws a Win32Exception.</returns>
Public Overloads Shared Function ExecuteCommandWithCmd(ByVal aUserName As String, ByVal aPassword As String, ByVal aCommand As String) As Process
Dim myCommand As New StringBuilder
myCommand.Append(Environment.SystemDirectory)
myCommand.Append("\cmd.exe /C ")
myCommand.Append(aCommand)
Return PrivateCreateProcess(aUserName, Nothing, aPassword, myCommand.ToString, LogonFlag.Undefined, Nothing, CreationFlag.Undefined, PriorityFlag.Undefined, Nothing, Nothing, Nothing)
End Function

''<summary>Executes a commandline statement with "command.com".</summary>
''<returns>Returns a Process object, NULL (if the process terminated faster than I could reference it) or throws a Win32Exception.</returns>
Public Overloads Shared Function ExecuteCommandWithCommandCom(ByVal aUserName As String, ByVal aPassword As String, ByVal aCommand As String) As Process
Dim myCommand As New StringBuilder
myCommand.Append(Environment.SystemDirectory)
myCommand.Append("\command.com /C ")
myCommand.Append(aCommand)
Return PrivateCreateProcess(aUserName, Nothing, aPassword, myCommand.ToString, LogonFlag.Undefined, Nothing, CreationFlag.Undefined, PriorityFlag.Undefined, Nothing, Nothing, Nothing)
End Function

''<summary>Creates a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.</summary>
Public Overloads Shared Function CreateProcess(ByVal aUserName As String, ByVal aPassword As String, ByVal aCommand As String) As Process
Return PrivateCreateProcess(aUserName, Nothing, aPassword, aCommand, LogonFlag.Undefined, Nothing, CreationFlag.Undefined, PriorityFlag.Undefined, Nothing, Nothing, Nothing)
End Function

''<summary>Creates a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.</summary>
Public Overloads Shared Function CreateProcess(ByVal aUserName As String, ByVal aDomainName As String, ByVal aPassword As String, ByVal aCommand As String) As Process
Return PrivateCreateProcess(aUserName, aDomainName, aPassword, aCommand, LogonFlag.Undefined, Nothing, CreationFlag.Undefined, PriorityFlag.Undefined, Nothing, Nothing, Nothing)
End Function

''<summary>Creates a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.</summary>
Public Overloads Shared Function CreateProcess(ByVal aUserName As String, ByVal aDomainName As String, ByVal aPassword As String, ByVal anApplication As String, ByVal parameters As String) As Process
Return PrivateCreateProcess(aUserName, aDomainName, aPassword, parameters, LogonFlag.Undefined, anApplication, CreationFlag.Undefined, PriorityFlag.Undefined, Nothing, Nothing, Nothing)
End Function

''<summary>Creates a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.</summary>
Public Overloads Shared Function CreateProcess(ByVal aUserName As String, ByVal aDomainName As String, ByVal aPassword As String, ByVal aCommand As String, ByVal aLogonFlag As LogonFlag, ByVal anApplication As String, ByVal aCreationFlag As CreationFlag, ByVal aPriority As PriorityFlag, ByVal anEnvironment As IntPtr, ByVal aCurrentDirectory As String) As Process
Return PrivateCreateProcess(aUserName, aDomainName, aPassword, aCommand, aLogonFlag, anApplication, aCreationFlag, aPriority, anEnvironment, aCurrentDirectory, Nothing)
End Function

''<summary>Creates a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.</summary>
''<remarks>This method is untested.</remarks>
''<param name="aUserName">This is the name of the user account to log on to. If you use the UPN format, user@domain, the Domain parameter must be NULL. The user account must have the Log On Locally permission on the local computer.</param>
''<param name="aDomainName">Specifies the name of the domain or server whose account database contains the user account. If this parameter is NULL, the user name must be specified in UPN format.</param>
''<param name="aPassword">Specifies the clear-text password for the user account.</param>
''<param name="aCommand">Specifies the command line to execute. The maximum length of this string is 32,000 characters. The commandline parameter can be NULL. In that case, the function uses the string pointed to by appname as the command line. If the file name does not contain an extension, .exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory path, the system searches for the executable file.</param>
''<param name="aLogonFlags">Logon option. This parameter can be zero or one value from the LogonFlags enum.</param>
''<param name="anApplication">Specifies the module to execute. The specified module can be a Windows-based application. It can be some other type of module (for example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer. The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. If the file name does not contain an extension, .exe is assumed. Therefore, if the file name extension is .com, this parameter must include the .com extension. The appname parameter can be NULL. In that case, the module name must be the first white space-delimited token in the commandline string. If the executable module is a 16-bit application, appname should be NULL, and the string pointed to by commandline should specify the executable module as well as its arguments.</param>
''<param name="aCreatingFlag">Controls how the process is created</param>
''<param name="aPriorityFlag">Controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads.</param>
''<param name="anEnvironment"></param>
''<param name="aCurrentDirectory">Specifies the full path to the current directory for the process. The string can also specify a UNC path. If this parameter is NULL, the new process will have the same current drive and directory as the calling process.</param>
''<param name="aStartUpInfo">Specifies the window station, desktop, standard handles, and appearance of the main window for the new process.</param>
''<returns>Returns a Process object, NULL (if the process terminated faster than I could reference it) or throws a Win32Exception.</returns>
Public Overloads Shared Function CreateProcess(ByVal aUserName As String, ByVal aDomainName As String, ByVal aPassword As String, ByVal aCommand As String, ByVal aLogonFlag As LogonFlag, ByVal anApplication As String, ByVal aCreationFlag As CreationFlag, ByVal aPriority As PriorityFlag, ByVal anEnvironment As IntPtr, ByVal aCurrentDirectory As String, ByRef aStartUpInfo As StartUpInfo) As Process
Return PrivateCreateProcess(aUserName, aDomainName, aPassword, aCommand, aLogonFlag, anApplication, aCreationFlag, aPriority, anEnvironment, aCurrentDirectory, aStartUpInfo)
End Function

'Imported Interface

''<summary>The CreateProcessWithLogonW function creates a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.</summary>
<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function CreateProcessWithLogonW(ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As String, ByVal dwLogonFlags As Int32, ByVal applicationName As String, ByVal commandLine As StringBuilder, ByVal creationFlags As Int32, ByVal environment As IntPtr, ByVal currentDirectory As String, ByRef sui As StartUpInfo, ByRef processInfo As ProcessInformation) As Boolean
End Function

''+++++++ here weiterfahren +++++++
'<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
'Private Shared Function CreatePipe(ByRef phReadPipe As Long, ByRef phWritePipe As Long, ByRef lpPipeAttributes As Security_Attributes, ByVal nSize As Long) As Long

'End Function

<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function CloseHandle(ByVal aHandle As IntPtr) As Boolean
End Function

'Private Methods

''<summary>Creates a new process and its primary thread. The new process then runs the specified executable file in the security context of the specified credentials (user, domain, and password). It can optionally load the user profile for the specified user.</summary>
''<remarks>This method is untested.</remarks>
''<param name="aUserName">This is the name of the user account to log on to. If you use the UPN format, user@domain, the Domain parameter must be NULL. The user account must have the Log On Locally permission on the local computer.</param>
''<param name="aDomainName">Specifies the name of the domain or server whose account database contains the user account. If this parameter is NULL, the user name must be specified in UPN format.</param>
''<param name="aPassword">Specifies the clear-text password for the user account.</param>
''<param name="aCommand">Specifies the command line to execute. The maximum length of this string is 32,000 characters. The commandline parameter can be NULL. In that case, the function uses the string pointed to by appname as the command line. If the file name does not contain an extension, .exe is appended. Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory path, the system searches for the executable file.</param>
''<param name="aLogonFlags">Logon option. This parameter can be zero or one value from the LogonFlags enum.</param>
''<param name="anApplication">Specifies the module to execute. The specified module can be a Windows-based application. It can be some other type of module (for example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer. The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. If the file name does not contain an extension, .exe is assumed. Therefore, if the file name extension is .com, this parameter must include the .com extension. The appname parameter can be NULL. In that case, the module name must be the first white space-delimited token in the commandline string. If the executable module is a 16-bit application, appname should be NULL, and the string pointed to by commandline should specify the executable module as well as its arguments.</param>
''<param name="aCreatingFlag">Controls how the process is created</param>
''<param name="aPriorityFlag">Controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads.</param>
''<param name="anEnvironment"></param>
''<param name="aCurrentDirectory">Specifies the full path to the current directory for the process. The string can also specify a UNC path. If this parameter is NULL, the new process will have the same current drive and directory as the calling process.</param>
''<param name="aStartUpInfo">Specifies the window station, desktop, standard handles, and appearance of the main window for the new process.</param>
''<returns>Returns a Process object, nothing (if the process terminated faster than I could reference it) or throws a Win32Exception.</returns>
Private Overloads Shared Function PrivateCreateProcess(ByVal aUserName As String, ByVal aDomainName As String, ByVal aPassword As String, ByVal aCommand As String, ByVal aLogonFlag As LogonFlag, ByVal anApplication As String, ByVal aCreationFlag As CreationFlag, ByVal aPriority As PriorityFlag, ByVal anEnvironment As IntPtr, ByVal aCurrentDirectory As String, ByVal aStartUpInfo As Object) As Process
'Initialize variables
Dim myProcessInfo As New ProcessInformation
Dim myLogonFlag As Integer = CInt(IIf(aLogonFlag = LogonFlag.Undefined, DefaultLogonFlag, aLogonFlag))
Dim myCreationFlag As Integer = CInt(IIf(aCreationFlag = CreationFlag.Undefined, DefaultCreationFlag, aCreationFlag)) _
Or CInt(IIf(aPriority = PriorityFlag.Undefined, DefaultPriority, aPriority))
Dim myCommandLine As New StringBuilder(aCommand) 'nothing results in String.Empty
'Initialize StartUpInfo object
Dim myStartUpInfo As StartUpInfo
If (aStartUpInfo Is Nothing) Then
myStartUpInfo = New StartUpInfo
myStartUpInfo.cb = Marshal.SizeOf(myStartUpInfo)
myStartUpInfo.lpReserved = Nothing
myStartUpInfo.lpDesktop = Nothing
myStartUpInfo.lpTitle = Nothing
myStartUpInfo.dwX = 0
myStartUpInfo.dwY = 0
myStartUpInfo.dwXSize = 0
myStartUpInfo.dwYSize = 0
myStartUpInfo.dwXCountChars = 255
myStartUpInfo.dwYCountChars = 800
myStartUpInfo.dwFillAttribute = 0
myStartUpInfo.dwFlags = 0
myStartUpInfo.wShowWindow = 0
myStartUpInfo.cbReserved2 = 0
myStartUpInfo.lpReserved2 = Nothing
myStartUpInfo.hStdInput = Nothing
myStartUpInfo.hStdOutput = Nothing
myStartUpInfo.hStdError = Nothing
Else
myStartUpInfo = CType(aStartUpInfo, StartUpInfo)
End If
'Adjust login name / domain name
Dim myIndex As Integer
If (aDomainName Is Nothing) OrElse (aDomainName = String.Empty) Then
'Extract domain from a login like "microsoft\BGates"
myIndex = aUserName.IndexOf("\"c)
If (myIndex > -1) Then
aDomainName = aUserName.Substring(0, myIndex)
aUserName = aUserName.Substring(myIndex + 1)
Else
'Extract domain from a login like "BGates@microsoft.com"
myIndex = aUserName.IndexOf("@"c)
If (myIndex > -1) Then
aUserName = aUserName.Substring(0, myIndex)
aDomainName = aUserName.Substring(myIndex + 1)
myIndex = aDomainName.IndexOf("."c)
If (myIndex > -1) Then
aDomainName = aDomainName.Substring(0, myIndex)
End If
End If
'Take the domain where the current user is logged on
aDomainName = Environment.UserDomainName()
End If
Else
'Remove the domain from the user name if they are the same
myIndex = aUserName.IndexOf(aDomainName & "\"c)
If (myIndex = 0) Then
aUserName = aUserName.Substring(aDomainName.Length + 1)
Else
myIndex = aUserName.IndexOf("@"c & aDomainName)
If (myIndex > -1) Then
aUserName = aUserName.Substring(0, myIndex)
End If
End If
End If
'Create process
Try
Dim Okay As Boolean = CreateProcessWithLogonW(aUserName, aDomainName, aPassword, myLogonFlag, anApplication, myCommandLine, myCreationFlag, anEnvironment, aCurrentDirectory, myStartUpInfo, myProcessInfo)
If (Okay) Then
Dim myProcess As Process = Nothing
Try
'Watch out: The process may be already terminated and not accessible anymore!
myProcess = Process.GetProcessById(myProcessInfo.dwProcessId)
Catch
End Try
Return myProcess
End If
Finally
PrivateCloseHandle(myProcessInfo.hProcess)
PrivateCloseHandle(myProcessInfo.hThread)
End Try
'Throw exception if not successful
Throw New Win32Exception
End Function

Private Shared Sub PrivateCloseHandle(ByVal aHandle As IntPtr)
Try
CloseHandle(aHandle)
Catch
End Try
End Sub

'**********************************************************************
' Inner Classes / Structures / Enums
'**********************************************************************

''<summary>The STARTUPINFO structure is used with the CreateProcess, CreateProcessAsUser, and CreateProcessWithLogonW functions to specify the window station, desktop, standard handles, and appearance of the main window for the new process.</summary>
<StructLayout(LayoutKind.Sequential)> _
Public Structure StartUpInfo
''<summary>Size of the structure, in bytes.</summary>
Public cb As Int32
''<summary>Reserved. Set this member to NULL before passing the structure to CreateProcess.</summary>
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpReserved As String
''<summary>Pointer to a null-terminated string that specifies either the name of the desktop, or the name of both the desktop and window station for this process. A backslash in the string indicates that the string includes both the desktop and window station names.</summary>
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpDesktop As String
''<summary>For console processes, this is the title displayed in the title bar if a new console window is created. If NULL, the name of the executable file is used as the window title instead. This parameter must be NULL for GUI or console processes that do not create a new console window.</summary>
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpTitle As String
''<summary>The x offset of the upper left corner of a window if a new window is created, in pixels.</summary>
Public dwX As Int32
''<summary>The y offset of the upper left corner of a window if a new window is created, in pixels.</summary>
Public dwY As Int32
''<summary>The width of the window if a new window is created, in pixels.</summary>
Public dwXSize As Int32
''<summary>The height of the window if a new window is created, in pixels.</summary>
Public dwYSize As Int32
''<summary>If a new console window is created in a console process, this member specifies the screen buffer width, in character columns.</summary>
Public dwXCountChars As Int32
''<summary>If a new console window is created in a console process, this member specifies the screen buffer height, in character rows.</summary>
Public dwYCountChars As Int32
''<summary>The initial text and background colors if a new console window is created in a console application.</summary>
Public dwFillAttribute As Int32
''<summary>Bit field that determines whether certain StartUpInfo members are used when the process creates a window.</summary>
Public dwFlags As Int32
''<summary>This member can be any of the SW_ constants defined in Winuser.h.</summary>
Public wShowWindow As Int16
''<summary>Reserved for use by the C Runtime must be zero.</summary>
Public cbReserved2 As Int16
''<summary>Reserved for use by the C Runtime must be null.</summary>
Public lpReserved2 As IntPtr
''<summary>A handle to be used as the standard input handle for the process.</summary>
Public hStdInput As IntPtr
''<summary>A handle to be used as the standard output handle for the process.</summary>
Public hStdOutput As IntPtr
''<summary>A handle to be used as the standard error handle for the process.</summary>
Public hStdError As IntPtr
End Structure

''<summary>
''The ProcessInformation structure is filled in by either the CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, or CreateProcessWithTokenW function with information about the newly created process and its primary thread.
''</summary>
<StructLayout(LayoutKind.Sequential)> _
Public Structure ProcessInformation
''<summary>Handle to the newly created process. The handle is used to specify the process in all functions that perform operations on the process object.</summary>
Public hProcess As IntPtr
''<summary>Handle to the primary thread of the newly created process. The handle is used to specify the thread in all functions that perform operations on the thread object.</summary>
Public hThread As IntPtr
''<summary>Value that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated.</summary>
Public dwProcessId As Int32
''<summary>Value that can be used to identify a thread. The value is valid from the time the thread is created until the time the thread is terminated.</summary>
Public dwThreadId As Int32
End Structure

''<summary>
''The initial text and background colors if a new console window is created in a console application.
''</summary>
<Flags()> _
Public Enum FillAttributes
''<summary>Background color is intensified.</summary>
BackgroundIntensity = 128
''<summary>Background color contains red.</summary>
BackgroundRed = 64
''<summary>Background color contains green.</summary>
BackgroundGreen = 32
''<summary>Background color contains blue.</summary>
BackgroundBlue = 16
''<summary>Text color is intensified.</summary>
ForegroundIntensity = 8
''<summary>Text color contains red.</summary>
ForegroundRed = 4
''<summary>Text color contains green.</summary>
ForegroundGreen = 2
''<summary>Text color contains blue.</summary>
ForegroundBlue = 1
End Enum

''<summary>Logon option.</summary>
Public Enum LogonFlag As Short
''<summary>Internally used to choose the application default</summary>
Undefined = -1
''<summary>Don't know but is valid according to the comments</summary>
[Default] = 0
''<summary>Log on, then load the user's profile in the HKEY_USERS registry key. The function returns after the profile has been loaded. Loading the profile can be time-consuming, so it is best to use this value only if you must access the information in the HKEY_CURRENT_USER registry key.</summary>
WithProfile = 1
''<summary>Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials.</summary>
NetworkCredentialsOnly = 2
End Enum

''<summary>Controls how the process is created. The DefaultErrorMode, NewConsole, and NewProcessGroup flags are enabled by default— even if you do not set the flag, the system will function as if it were set.</summary>
Public Enum CreationFlag As Integer
''<summary>Internally used to choose the application default</summary>
Undefined = -1
''<summary>Don't know but might be valid Wink | ;-) </summary>
[Default] = 0
''<summary>The primary thread of the new process is created in a suspended state, and does not run until the ResumeThread function is called.</summary>
Suspended = &H4
''<summary>The new process has a new console, instead of inheriting the parent's console.</summary>
NewConsole = &H10
''<summary>The new process is the root process of a new process group.</summary>
NewProcessGroup = &H200
''<summary>This flag is only valid starting a 16-bit Windows-based application. If set, the new process runs in a private Virtual DOS Machine (VDM). By default, all 16-bit Windows-based applications run in a single, shared VDM.</summary>
SeperateWOWVDM = &H800
''<summary>Indicates the format of the lpEnvironment parameter. If this flag is set, the environment block pointed to by lpEnvironment uses Unicode characters.</summary>
UnicodeEnvironment = &H400
''<summary>The new process does not inherit the error mode of the calling process.</summary>
DefaultErrorMode = &H4000000
End Enum

''<summary>Controls the new process's priority class, which is used to determine the scheduling priorities of the process's threads.</summary>
Public Enum PriorityFlag As Integer
''<summary>Internally used to choose the application default</summary>
Undefined = -1
''<summary>Process with no special scheduling needs.</summary>
NormalPriority = &H20
''<summary>Process whose threads run only when the system is idle and are preempted by the threads of any process running in a higher priority class. An example is a screen saver. The idle priority class is inherited by child processes.</summary>
IdlePriority = &H40
''<summary>Process that performs time-critical tasks that must be executed immediately for it to run correctly. The threads of a high-priority class process preempt the threads of normal or idle priority class processes.</summary>
HighPriority = &H80
''<summary>Process that has the highest possible priority. The threads of a real-time priority class process preempt the threads of all other processes including operating system processes performing important tasks.</summary>
RealTimePriority = &H100
''<summary>Process that has priority above idle but below normal processes.</summary>
BelowNormalPriority = &H4000
''<summary>Process that has priority above normal but below high processes.</summary>
AboveNormalPriority = &H8000
End Enum

''<summary>Determines whether certain StartUpInfo members are used when the process creates a window.</summary>
<Flags()> _
Public Enum StartUpInfoFlags As Integer
''<summary>If this value is not specified, the wShowWindow member is ignored.</summary>
UseShowWindow = &H1
''<summary>If this value is not specified, the dwXSize and dwYSize members are ignored.</summary>
UseSize = &H2
''<summary>If this value is not specified, the dwX and dwY members are ignored.</summary>
UsePosition = &H4
''<summary>If this value is not specified, the dwXCountChars and dwYCountChars members are ignored.</summary>
UseCountChars = &H8
''<summary>If this value is not specified, the dwFillAttribute member is ignored.</summary>
UseFillAttribute = &H10
''<summary>Indicates that the process should be run in full-screen mode, rather than in windowed mode.</summary>
RunFullScreen = &H20
''<summary>Indicates that the cursor is in feedback mode after CreateProcess is called. The system turns the feedback cursor off after the first call to GetMessage.</summary>
ForceOnFeedback = &H40
''<summary>Indicates that the feedback cursor is forced off while the process is starting. The Normal Select cursor is displayed.</summary>
ForceOffFeedback = &H80
''<summary>Sets the standard input, standard output, and standard error handles for the process to the handles specified in the hStdInput, hStdOutput, and hStdError members of the StartUpInfo structure. If this value is not specified, the hStdInput, hStdOutput and hStdError members of the STARTUPINFO structure are ignored.</summary>
UseStandardHandles = &H100
''<summary>When this flag is specified, the hStdInput member is to be used as the hotkey value instead of the standard-input pipe.</summary>
UseHotKey = &H200
''<summary>When this flag is specified, the StartUpInfo's hStdOutput member is used to specify a handle to a monitor, on which to start the new process. This monitor handle can be obtained by any of the multiple-monitor display functions (i.e. EnumDisplayMonitors, MonitorFromPoint, MonitorFromWindow, etc...).</summary>
UseMonitor = &H400
''<summary>Use the HICON specified in the hStdOutput member (incompatible with UseMonitor).</summary>
UseIcon = &H400
''<summary>Program was started through a shortcut. The lpTitle contains the shortcut path.</summary>
TitleShortcut = &H800
''<summary>The process starts with normal priority. After the first call to GetMessage, the priority is lowered to idle.</summary>
Screensaver = &H8000000
End Enum

End Class
</pre>


The code is not yet tested but I think it's enough for today and now it's your turn to distribute again to the comunity Wink | ;-) .
(Of course if I gonna find some bugs when testing, I gonna post it here again).

Greetings

Christoph Hafner
Inserto AG
GeneralRe: I did the work 4 u... Pin
Dewey Vozel23-Nov-04 7:41
Dewey Vozel23-Nov-04 7:41 
GeneralRe: I did the work 4 u... Pin
GProssliner23-Nov-04 10:09
GProssliner23-Nov-04 10:09 
GeneralRe: I did the work 4 u... Pin
chriha23-Nov-04 20:23
chriha23-Nov-04 20:23 
GeneralRe: I did the work 4 u... Pin
chriha23-Nov-04 20:40
chriha23-Nov-04 20:40 
GeneralRe: Improve your code ... Pin
Dewey Vozel12-Feb-05 11:29
Dewey Vozel12-Feb-05 11:29 
QuestionHow to run under ASP.NET? Pin
GJoy30-Aug-04 9:26
GJoy30-Aug-04 9:26 
AnswerRe: How to run under ASP.NET? Pin
Dewey Vozel30-Aug-04 9:36
Dewey Vozel30-Aug-04 9:36 
GeneralRe: How to run under ASP.NET? Pin
GJoy30-Aug-04 10:02
GJoy30-Aug-04 10:02 
GeneralRe: How to run under ASP.NET? Pin
clepape29-Nov-04 23:07
clepape29-Nov-04 23:07 
GeneralRe: How to run under ASP.NET? Pin
Dewey Vozel11-Feb-05 12:06
Dewey Vozel11-Feb-05 12:06 
GeneralHide Window Pin
rodrigo diniz16-Aug-04 10:11
rodrigo diniz16-Aug-04 10:11 
GeneralRe: Hide Window Pin
Dewey Vozel16-Aug-04 10:39
Dewey Vozel16-Aug-04 10:39 
GeneralRe: Hide Window Pin
rodrigo diniz17-Aug-04 2:14
rodrigo diniz17-Aug-04 2:14 
GeneralRe: Hide Window Pin
JOHN115-Sep-04 23:08
JOHN115-Sep-04 23:08 
GeneralRe: Hide Window Pin
rramirezg17-Sep-04 12:19
rramirezg17-Sep-04 12:19 
GeneralRe: Hide Window Pin
Dewey Vozel12-Feb-05 11:30
Dewey Vozel12-Feb-05 11:30 
GeneralCongrats with your first article Pin
Jonas Follesø1-Jun-04 2:31
Jonas Follesø1-Jun-04 2:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.