Why do I have to create a separate task to run a process here?

0

I have a console application which tries to create a process this way:

public static void Main(string[] args)
{
    const string path = @"C:\Windows\system32\notepad.exe";
    const string param = "";

    Task.Factory.StartNew(() =>
                          {
                              Process pp = CreateProcessAsUser(path, param);
                              pp.WaitForExit();
                          }, 
                          TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning);

    Console.ReadLine();
}

If I run it CSRSS.exe shows a window with an error message: "The application was unable to start correctly (0xc0000142)". If I change this to the following code everything works fine:

   Task.Factory.StartNew(() =>
                         {
                             Task task = Task.Factory.StartNew(() =>
                                                               {
                                                                   Process pp = CreateProcessAsUser(path, param);
                                                                   pp.WaitForExit();
                                                               });
                              task.Wait();
                          }, 
                          TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning);

Do you have any ideas why?

Here is the code for CreateProcessAsUser:

public static Process CreateProcessAsUser(string filename, string args)
{
    IntPtr hToken = WindowsIdentity.GetCurrent().Token;
    IntPtr hDupedToken = IntPtr.Zero;

    ProcessInformation pi = new ProcessInformation();
    SecurityAttributes sa = new SecurityAttributes();
    sa.Length = Marshal.SizeOf(sa);

    DuplicateTokenEx(hToken, 
                     genericAllAccess, 
                     ref sa, 
                     (int)SecurityImpersonationLevel.SecurityIdentification, 
                     (int)TokenType.TokenPrimary, 
                     ref hDupedToken);

    STARTUPINFO si = new STARTUPINFO();
    si.cb = Marshal.SizeOf(si);
    si.lpDesktop = string.Empty;

    string path = Path.GetFullPath(filename);

    using (WindowsIdentity.Impersonate(IntPtr.Zero))
    {
        CreateProcessAsUser(hDupedToken, 
                            path, 
                            string.Format("\"{0}\" {1}", filename.Replace("\"", "\"\""), args), 
                            ref sa, 
                            ref sa, 
                            false, 
                            0, 
                            IntPtr.Zero, 
                            @".\", 
                            ref si, 
                            ref pi);
    }

    return Process.GetProcessById(pi.dwProcessID);
}

[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
private static extern bool CreateProcessAsUser(...)
c#
multithreading
winapi
asked on Stack Overflow Mar 6, 2014 by Qué Padre • edited Mar 14, 2014 by Markus Safar

1 Answer

1

I slapped this together to try and reproduce your error but it works fine with both calls.

answered on Stack Overflow Mar 12, 2014 by Unglückspilz • edited Mar 12, 2014 by Unglückspilz

User contributions licensed under CC BY-SA 3.0