We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now


Need help in studying this c# class

Medium Priority
Last Modified: 2012-06-27
hi, i got this class from the web. i think it enables a program to execute external application using windows Administrator(or others) account. but as a beginner, its too much for me to grasp. i need to know how to use this class?
basically i want to execute a program as administrator, and let it run without waiting for it to exit.

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security.Principal;
using System.Text;

/// UserSpecificProcess extends the standard Process object to
/// create new processes under a different user than the calling parent process.
/// Also, the standard output of the child process redirected back to the parent process.
/// This is class is designed to operate inside an ASP.NET web application.
/// The assumption is that the calling thread is operating with an impersonated security token.
/// The this class will change the imperonated security token to a primary token,
/// and call CreateProcessAsUser.
/// A System.Diagnostics.Process object will be returned with appropriate properties set.
/// To use this function, the following security priviliges need to be set for the ASPNET account
/// using the local security policy MMC snap-in. CreateProcessAsUser requirement.
/// "Replace a process level token"/SE_ASSIGNPRIMARYTOKEN_NAME/SeAssignPrimaryTokenPrivilege
/// "Adjust memory quotas for a process"/SE_INCREASE_QUOTA_NAME/SeIncreaseQuotaPrivilege
/// This class was designed for .NET 1.1 for operating systems W2k an higher.
/// Any other features or platform support can be implemented by using the .NET reflector and
/// investigating the Process class.
public class UserSpecificProcess : Process
    public class CreateProcessStartupInfo
        public int cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public int dwX;
        public int dwY;
        public int dwXSize;
        public int dwYSize;
        public int dwXCountChars;
        public int dwYCountChars;
        public int dwFillAttribute;
        public int dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
        public CreateProcessStartupInfo()
            this.cb = Marshal.SizeOf(typeof(CreateProcessStartupInfo));
            this.lpReserved = null;
            this.lpDesktop = null;
            this.lpTitle = null;
            this.dwX = 0;
            this.dwY = 0;
            this.dwXSize = 0;
            this.dwYSize = 0;
            this.dwXCountChars = 0;
            this.dwYCountChars = 0;
            this.dwFillAttribute = 0;
            this.dwFlags = 0;
            this.wShowWindow = 0;
            this.cbReserved2 = 0;
            this.lpReserved2 = IntPtr.Zero;
            this.hStdInput = IntPtr.Zero;
            this.hStdOutput = IntPtr.Zero;
            this.hStdError = IntPtr.Zero;

    public class CreateProcessProcessInformation
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
        public CreateProcessProcessInformation()
            this.hProcess = IntPtr.Zero;
            this.hThread = IntPtr.Zero;
            this.dwProcessId = 0;
            this.dwThreadId = 0;

    public class SecurityAttributes
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
        public SecurityAttributes()
            this.nLength = Marshal.SizeOf(typeof(SecurityAttributes));

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern bool CloseHandle(HandleRef handle);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CreateProcess([MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName, StringBuilder lpCommandLine, SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory, CreateProcessStartupInfo lpStartupInfo, CreateProcessProcessInformation lpProcessInformation);

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool CreateProcessAsUserW(IntPtr token, [MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName, [MarshalAs(UnmanagedType.LPTStr)] string lpCommandLine, SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory, CreateProcessStartupInfo lpStartupInfo, CreateProcessProcessInformation lpProcessInformation);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr GetStdHandle(int whichHandle);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, SecurityAttributes lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, HandleRef hTemplateFile);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CreateNamedPipe(string name, int openMode, int pipeMode, int maxInstances, int outBufSize, int inBufSize, int timeout, SecurityAttributes lpPipeAttributes);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetConsoleOutputCP();

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool DuplicateTokenEx(HandleRef hToken, int access, SecurityAttributes tokenAttributes, int impersonationLevel, int tokenType, ref IntPtr hNewToken);

    const int GENERIC_ALL = 0x10000000;


    // WinNT.h TOKEN TYPE
    const int TOKEN_PRIMARY = 1;

    // WinBase.h
    const int STD_INPUT_HANDLE = -10;
    const int STD_ERROR_HANDLE = -12;

    // WinBase.h STARTUPINFO
    const int STARTF_USESTDHANDLES = 0x100;

    // Microsoft.Win23.NativeMethods
    static IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
    public static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);

    /// Starts the process with the security token of the calling thread.
    /// If the security token has a token type of TokenImpersonation,
    /// the token will be duplicated to a primary token before calling
    /// CreateProcessAsUser.
    /// The process to start.
    public void StartAsUser()

    /// Starts the process with the given security token.
    /// If the security token has a token type of TokenImpersonation,
    /// the token will be duplicated to a primary token before calling
    /// CreateProcessAsUser.
    public void StartAsUser(IntPtr userToken)
        if (StartInfo.UseShellExecute)
            throw new InvalidOperationException("can't call this with shell execute");

        // just assume that the securityToken is of TokenImpersonation and create a primary.
        IntPtr primayUserToken = CreatePrimaryToken(userToken);

        CreateProcessStartupInfo startupInfo = new CreateProcessStartupInfo();
        CreateProcessProcessInformation processInformation = new CreateProcessProcessInformation();

        IntPtr stdinHandle;
        IntPtr stdoutReadHandle;
        IntPtr stdoutWriteHandle = IntPtr.Zero;
        IntPtr stderrHandle;
            stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
            MyCreatePipe(out stdoutReadHandle, out stdoutWriteHandle, false);
            stderrHandle = GetStdHandle(STD_ERROR_HANDLE);

            //assign handles to startup info
            startupInfo.dwFlags = STARTF_USESTDHANDLES;
            startupInfo.hStdInput = stdinHandle;
            startupInfo.hStdOutput = stdoutWriteHandle;
            startupInfo.hStdError = stderrHandle;

            string commandLine = GetCommandLine();
            int creationFlags = 0;
            IntPtr environment = IntPtr.Zero;
            string workingDirectory = GetWorkingDirectory();

            // create the process or fail trying.
            if (!CreateProcessAsUserW(
                throw new Win32Exception();
            // close thread handle
            if (processInformation.hThread != INVALID_HANDLE_VALUE)
                CloseHandle(new HandleRef(this, processInformation.hThread));

            // close client stdout handle
            CloseHandle(new HandleRef(this, stdoutWriteHandle));

        // get reader for standard output from the child
        Encoding encoding = Encoding.GetEncoding(GetConsoleOutputCP());
        StreamReader standardOutput = new StreamReader(new FileStream(stdoutReadHandle, FileAccess.Read, true, 0x1000, true), encoding);

        // set this on the object accordingly.
        BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance,
        null, this, new object[] { standardOutput });

        // scream if a process wasn't started instead of returning false.
        if (processInformation.hProcess == IntPtr.Zero)
            throw new Exception("failed to create process");

        // configure the properties of the Process object correctly
        BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
        null, this, new object[] { processInformation.hProcess });
        BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
        null, this, new object[] { processInformation.dwProcessId });

    /// Creates a primayToken out of an existing token.
    private IntPtr CreatePrimaryToken(IntPtr userToken)
        SecurityAttributes securityAttributes = new SecurityAttributes();
        IntPtr primaryUserToken = IntPtr.Zero;
        if (!DuplicateTokenEx(new HandleRef(this, userToken), GENERIC_ALL, securityAttributes, SECURITY_IMPERSONATION, TOKEN_PRIMARY, ref primaryUserToken))
            throw new Win32Exception();
        return primaryUserToken;

    /// Gets the appropriate commandLine from the process.
    private string GetCommandLine()
        StringBuilder builder1 = new StringBuilder();
        string text1 = StartInfo.FileName.Trim();
        string text2 = StartInfo.Arguments;
        bool flag1 = text1.StartsWith("\"") && text1.EndsWith("\"");
        if (!flag1)
        if (!flag1)
        if ((text2 != null) && (text2.Length > 0))
            builder1.Append(" ");
        return builder1.ToString();

    /// Gets the working directory or returns null if an empty string was found.
    private string GetWorkingDirectory()
        return (StartInfo.WorkingDirectory != string.Empty) ? StartInfo.WorkingDirectory : null;

    /// A clone of Process.CreatePipe. This is only implemented because reflection with
    /// out parameters are a pain.
    /// Note: This is only finished for w2k and higher machines.
    /// Specifies whether the parent will be performing the writes.
    public static void MyCreatePipe(out IntPtr parentHandle, out IntPtr childHandle, bool parentInputs)
        string pipename = @"\\.\pipe\Global\" + Guid.NewGuid().ToString();

        SecurityAttributes attributes2 = new SecurityAttributes();
        attributes2.bInheritHandle = false;

        parentHandle = CreateNamedPipe(pipename, 0x40000003, 0, 0xff, 0x1000, 0x1000, 0, attributes2);
        if (parentHandle == INVALID_HANDLE_VALUE)
            throw new Win32Exception();

        SecurityAttributes attributes3 = new SecurityAttributes();
        attributes3.bInheritHandle = true;
        int num1 = 0x40000000;
        if (parentInputs)
            num1 = -2147483648;
        childHandle = CreateFile(pipename, num1, 3, attributes3, 3, 0x40000080, NullHandleRef);
        if (childHandle == INVALID_HANDLE_VALUE)
            throw new Win32Exception();
Watch Question

Explaining whole code is bit difficult but I may help you a bit

using System;
using syntax in C# is Imports keyword in Vb.Net

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] this is the way in C# to use Windows Api
In vb.net you can use it in the following manner

<DllImport("KERNEL32.DLL", EntryPoint:="GetSystemDirectoryW", _
       SetLastError:=True, CharSet:=CharSet.Unicode, _
       ExactSpelling:=True, _
       CallingConvention:=CallingConvention.StdCall)> _
       Public Shared Function GetSystemDirectory(ByVal Buffer _
         As StringBuilder, ByVal Size As Integer) As Long
        ' Leave function empty - DLLImport attribute
        ' forces calls to GetSystemDirectory to
        ' be forwarded to GetSystemDirectory in KERNEL32.DLL
    End Function

Variable declaration in C#
SecurityAttributes attributes2 = new SecurityAttributes();
in vb.Net u can use it in following manner
Dim attributes2 as new SecurityAttributes();

In last but not least, why dont you make this code as C# assembly and
use this assembly in VB.net directly by calling methods

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Sorry i forget to mention , try this one also http://www.kamalpatel.net/ConvertCSharp2VB.aspx
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.