CreateProcessasuser — AccessViolationError

Я пытаюсь запустить приложение лотка графического интерфейса из службы Windows (LocalSystem) с помощью createProcessasUser - вот так:

    public static System.Diagnostics.Process StartProcessInSession(int sessionID, String commandLine)
    {
        IntPtr userToken;
        if (WTSQueryUserToken(sessionID, out userToken))
        {
            //note that WTSQueryUserToken only works when in context of local system account with SE_TCB_NAME
            IntPtr lpEnvironment;
            if (CreateEnvironmentBlock(out lpEnvironment, userToken, false))
            {
                StartupInfo si = new StartupInfo();
                si.cb = Marshal.SizeOf(si);
                si.lpDesktop = "winsta0\\default";
                si.dwFlags = STARTF.STARTF_USESHOWWINDOW;
                si.wShowWindow = ShowWindow.SW_SHOW;
                ProcessInformation pi;
                if (CreateProcessAsUser(userToken, null, new StringBuilder(commandLine), IntPtr.Zero, IntPtr.Zero, false, CreationFlags.CREATE_NEW_CONSOLE | CreationFlags.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref si, out pi))
                {
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);
                    //context.Undo();
                    try
                    {
                        return System.Diagnostics.Process.GetProcessById(pi.dwProcessId);
                    }
                    catch (ArgumentException e)
                    {
                        //The process ID couldn't be found - which is what always happens because it has closed
                        return null;
                    }
                }
                else
                {
                    int err = Marshal.GetLastWin32Error();
                    throw new System.ComponentModel.Win32Exception(err, "Could not create process.\nWin32 error: " + err.ToString());
                }
            }
            else
            {
                int err = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(err, "Could not create environment block.\nWin32 error: " + err.ToString());
            }
        }
        else
        {
            int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            if (err == 1008) return null; //There is no token
            throw new System.ComponentModel.Win32Exception(err, "Could not get the user token from session " + sessionID.ToString() + " - Error: " + err.ToString());
        }
    }

Я использую функцию так:

   protected override void OnStart(string[] args)
    {   
       _agentProcess = StartProcessInSession(WTSGetActiveConsoleSessionId(), "Some_correct_path");  
    }

Это действительно работало какое-то время, но в одном из моих запусков оно внезапно перестало работать... выдавая следующую ошибку при выполнении команды CreateProccessAsUser (не могу углубиться)

{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}

Я понятия не имею, почему это происходит или даже как отлаживать это дальше, во всяком случае, есть идеи ?? потому что это не имеет для меня никакого смысла.

Создать процесс как определение пользователя:

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, [In] StringBuilder lpCommandLine, IntPtr /*to a SecurityAttributes struct or null*/ lpProcessAttributes, IntPtr /*to a SecurityAttributes struct or null*/ lpThreadAttributes, bool bInheritHandles, CreationFlags creationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation);

Спасибо


person Menyh    schedule 09.01.2012    source источник
comment
Является ли lpEnvironment допустимым указателем? И userToken действительный HANDLE?   -  person Ben Voigt    schedule 09.01.2012
comment
Как вы определили CreateProcessAsUser?   -  person David Heffernan    schedule 09.01.2012
comment
Оба значения устанавливаются, как мне узнать, действителен ли дескриптор?   -  person Menyh    schedule 10.01.2012
comment
@Menyh: Основные: не 0, не -1, а кратное четырем. Кроме того, вы можете использовать Process Monitor для получения списка допустимых дескрипторов для приложения.   -  person Ben Voigt    schedule 10.01.2012


Ответы (1)


Является ли ваш тип ProcessInformation типом значения (структурой) или ссылочным типом (классом)?

Покажите его определение и объявление p/invoke для CreateProcessAsUser.

Кстати, вся эта GetLastWin32Error проверка выполняется за вас с помощью p/invoke, если вы используете правильные атрибуты.

person Ben Voigt    schedule 09.01.2012
comment
[StructLayout(LayoutKind.Sequential)] internal struct ProcessInformation { #region Data Members (4) public int dwProcessId; общедоступный интервал dwThreadId; общедоступный IntPtr hProcess; общедоступный IntPtr hThread; #endregion Члены данных } - person Menyh; 10.01.2012