locked
Calling CreateProcessAsUser from Windows Service to launch windows application does not work RRS feed

  • Question

  • Hello Eric,

    Can a user account service interact with desktop?

    I have a window service which intern should launch winforms(used notepad for testing purpose) application with user account not with Local System account.I have used below code ,and ran it from window application and window service.In case windows application, it successfully launching a notepad with (logged in)user account as a owner however when I used same code with Windows Service ,it creates process and it stays in Task Manager but not displaying UI(Notepad ,in my code). Here is my code, I appreciate your help reading my code and suggest possible solution.

    I am using Windows XP machine with SP3

    IntPtr hToken = WindowsIdentity.GetCurrent().Token;
                    IntPtr hDupedToken = IntPtr.Zero;

                    ProcessUtility.PROCESS_INFORMATION pi = new ProcessUtility.PROCESS_INFORMATION();
                    try
                    {
                        ProcessUtility.SECURITY_ATTRIBUTES sa = new ProcessUtility.SECURITY_ATTRIBUTES();
                        sa.Length = Marshal.SizeOf(sa);

                        bool result = ProcessUtility.DuplicateTokenEx(
                              hToken,
                              ProcessUtility.GENERIC_ALL_ACCESS,
                              ref sa,
                              (int)ProcessUtility.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                              (int)ProcessUtility.TOKEN_TYPE.TokenPrimary,
                              ref hDupedToken
                           );

                        if (!result)
                        {
                            throw new ApplicationException("DuplicateTokenEx failed");
                        }


                        ProcessUtility.STARTUPINFO startup = new ProcessUtility.STARTUPINFO();
                        startup.cb = Marshal.SizeOf(startup);
                        startup.lpDesktop = "Winsta0\\Default";


                        result = ProcessUtility.CreateProcessAsUser(
                                             hDupedToken,
                                             @"C:\Program Files\Marathon Mobile Framework\MobileManager.exe",
                                             String.Empty,
                                             ref sa, ref sa,
                                             false, 0, IntPtr.Zero,
                                             @"C:\", ref startup, out pi
                                       );

                        if (!result)
                        {
                            int error = Marshal.GetLastWin32Error();
                            string message = String.Format("CreateProcessAsUser Error: {0}", error);
                            throw new ApplicationException(message);
                        }
                    }
                    finally
                    {

                    }
                }
                catch (Exception Ex)
                {
                    eventLog1.WriteEntry(Ex.ToString()  );
                }

     

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;

    namespace TestService
    {
        static class ProcessUtility
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct PROCESS_INFORMATION
            {
                public IntPtr hProcess;
                public IntPtr hThread;
                public Int32 dwProcessID;
                public Int32 dwThreadID;
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct SECURITY_ATTRIBUTES
            {
                public Int32 Length;
                public IntPtr lpSecurityDescriptor;
                public bool bInheritHandle;
            }

            public enum SECURITY_IMPERSONATION_LEVEL
            {
                SecurityAnonymous,
                SecurityIdentification,
                SecurityImpersonation,
                SecurityDelegation
            }

            public enum TOKEN_TYPE
            {
                TokenPrimary = 1,
                TokenImpersonation
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct STARTUPINFO
            {
                public Int32 cb;
                public string lpReserved;
                public string lpDesktop;
                public string lpTitle;
                public Int32 dwX;
                public Int32 dwY;
                public Int32 dwXSize;
                public Int32 dwXCountChars;
                public Int32 dwYCountChars;
                public Int32 dwFillAttribute;
                public Int32 dwFlags;
                public Int16 wShowWindow;
                public Int16 cbReserved2;
                public IntPtr lpReserved2;
                public IntPtr hStdInput;
                public IntPtr hStdOutput;
                public IntPtr hStdError;
            }
     


            [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern bool CreateProcessAsUser(
            IntPtr hToken,
            string lpApplicationName,
            string lpCommandLine,
            ref SECURITY_ATTRIBUTES lpProcessAttributes,
            ref SECURITY_ATTRIBUTES lpThreadAttributes,
            bool bInheritHandles,
            uint dwCreationFlags,
            IntPtr lpEnvironment,
            string lpCurrentDirectory,
            ref STARTUPINFO lpStartupInfo,
            out PROCESS_INFORMATION lpProcessInformation);

            public const int GENERIC_ALL_ACCESS = 0x10000000;

            [
               DllImport("kernel32.dll",
                  EntryPoint = "CloseHandle", SetLastError = true,
                  CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)
            ]
            public static extern bool CloseHandle(IntPtr handle);
            [
               DllImport("advapi32.dll",
                  EntryPoint = "DuplicateTokenEx")
            ]
            public static extern bool
               DuplicateTokenEx(IntPtr hExistingToken, Int32 dwDesiredAccess,
                                ref SECURITY_ATTRIBUTES lpThreadAttributes,
                                Int32 ImpersonationLevel, Int32 dwTokenType,
                                ref IntPtr phNewToken);


        }
    }

    Monday, April 19, 2010 7:26 PM

All replies

  • Launching an INTERACTIVE process to the INTERACTIVE desktop from a non Local System service can be done but the service is going to need help from an external process.  This is much easier to do if the service is running in the LocalSystem account.

    thanks

    Frank K [MSFT]

    Follow us on Twitter, www.twitter.com/WindowsSDK

    Wednesday, January 7, 2015 6:17 AM