Использование Process.Start () для запуска процесса от имени другого пользователя из службы Windows

Я хотел бы периодически запускать произвольный .NET EXE под указанной учетной записью пользователя из службы Windows.

До сих пор моя служба Windows работала с логикой, чтобы решить, каков целевой процесс и когда его запускать. Целевой процесс запускается следующим образом:

  1. Служба Windows запускается с использованием учетных данных администратора.
  2. Когда приходит время, выполняется промежуточный процесс .NET с аргументами, детализирующими, какой процесс должен быть запущен (имя файла, имя пользователя, домен, пароль).
  3. Этот процесс создает новый System.Diagnostics.Process, связывает объект ProcessStartInfo, заполненный переданными ему аргументами, а затем вызывает Start () для объекта процесса.

Когда это происходит в первый раз , целевой процесс выполняется нормально, а затем нормально закрывается . Однако каждый последующий раз, как только запускается целевой процесс, он выдает ошибку «Приложение не удалось правильно инициализировать (0xc0000142)». Перезапуск службы Windows позволит процессу снова успешно запуститься (для первого выполнения).

Естественно, цель состоит в том, чтобы каждый раз успешно выполнять целевой процесс.

Относительно шага 2 выше: для запуска процесса от имени другого пользователя .NET вызывает функцию win32 CreateProcessWithLogonW. Эта функция требует дескриптор окна для входа в систему указанного пользователя. Поскольку служба Windows не работает в интерактивном режиме, она не имеет дескриптора окна. Этот промежуточный процесс решает проблему, поскольку имеет дескриптор окна, который можно передать целевому процессу.

Пожалуйста, никаких предложений по использованию psexec или планировщика задач Windows. Я принял свою судьбу в жизни, и это включает в себя решение проблемы, как указано выше.

12.12.2008 10:32:37
Пожалуйста, расскажите нам, что произошло в конце, когда у вас есть закрытие
Vinko Vrsalovic 12.12.2008 22:23:43
да - на данный момент это не решено, но я есть :) Я в отпуске до нового года.
Matt Jacobsen 17.12.2008 09:17:56
8 ОТВЕТОВ

Я не буду предлагать ни psexec, ни планировщик задач. Но вы смотрели на Судовина ?

Он выполняет почти то, что вы хотите, за исключением того, что запрашивает пароль перед выполнением процесса.

Кроме того, с открытым исходным кодом и все, вы можете увидеть, как он выполняет процессы из связанной службы снова и снова.

1
12.12.2008 11:03:52
Я просматриваю svn-репозиторий sudowin сейчас, после вашего предложения. Кажется, они полностью игнорируют Systme.Diagnostics.Process и взаимодействуют с CreateProcessAsUser вместо CreateProcessWithLogonW. Может быть, в этом-то и дело ...
Matt Jacobsen 12.12.2008 11:26:59
какое-нибудь окончательное решение с полным примером исходного кода работает над этим? используя судовин?
Kiquenet 5.07.2013 10:59:40

Просто предположение - вы используете LoadUserProfile = true с начальной информацией? CreateProcessWithLogonW не загружает куст реестра пользователей по умолчанию, если вы не указали это.

1
12.12.2008 11:50:04
Я не думал, что мне нужен реестр или действительно профиль пользователя, но я просто попробовал ваше предложение, чтобы посмотреть, будет ли оно иметь положительный эффект. К сожалению, нет .. :(
Matt Jacobsen 12.12.2008 12:56:09
Это, конечно, актуально, только если запущенные приложения должны иметь доступ к кусту пользователя.
liggett78 12.12.2008 13:15:13
Как указано выше в исходном сообщении: целевой процесс успешно выполняется ОДИН РАЗ. если он может выполняться один раз, это означает, что он имел доступ ко всем необходимым ресурсам.
Matt Jacobsen 12.12.2008 14:01:56

Вам не нужен дескриптор окна для использования CreateProcessWithLogonW, я не уверен, откуда ваша информация.

Приложению не удалось инициализировать ошибку по многим причинам, но она почти всегда связана с безопасностью или исчерпанием пользовательских ресурсов. Диагностировать это чрезвычайно сложно без большого количества информации о том, что вы запускаете, и контекста, в котором вы работаете. Но на что стоит обратить внимание: есть ли у предоставленного пользователя правильные разрешения для доступа к каталогу исполняемого файла, пользователь имеет разрешение на доступ к оконной станции и рабочему столу, на котором он запускается, имеет ли он правильные права доступа к файлам DLL, которые ему нужно загрузить при инициализации, и т. д.

0
12.12.2008 12:14:09
Это не проблема безопасности. Если бы это было так, я бы вообще не смог успешно запустить целевой процесс.
Matt Jacobsen 12.12.2008 12:46:05
Запуск целевого процесса непосредственно из службы и предоставление учетных данных пользователя всегда приводит к исключению «неверный дескриптор». Запуск промежуточного процесса без попытки изменить учетные данные, а затем запуск целевого процесса из этого промежуточного процесса решает проблему.
Matt Jacobsen 12.12.2008 12:50:28
Какой аккаунт использует ваш сервис для запуска? «Вы не можете вызвать CreateProcessWithLogonW из процесса, который выполняется под учетной записью LocalSystem» (см. функцию CreateProcessWithLogonW в MSDN)
liggett78 12.12.2008 13:26:10
Если есть проблема безопасности с Window Station или рабочим столом, процесс запустится, а затем прекратит работу при попытке инициализации user32. Придется перепроверить, когда возникнут другие ошибки безопасности.
Stephen Martin 12.12.2008 13:50:01
@ liggett78 Как уже упоминалось в оригинальном сообщении: в данный момент я работаю в качестве «администратора», а не в LocalSystem
Matt Jacobsen 12.12.2008 14:05:01

Я только что прочитал этот комментарий на MSDN ( http://msdn.microsoft.com/en-us/library/ms682431(VS.85).aspx ):

Не вызывайте пользовательские приложения с этой функцией! ChristianWimmer |
Редактировать | Показать историю, пожалуйста, подождите. Если вы собираетесь вызывать приложения пользовательского режима, которые предлагают редактирование документов и тому подобное (например, Word), все несохраненные данные будут потеряны. Это связано с тем, что обычная последовательность завершения работы не применяется к процессам, запущенным с помощью CreateProcessWithLogonW. Таким образом, запущенные приложения не получают WM_QUERYENDSESSION, WM_ENDSESSION и самое важное сообщение WM_QUIT. Таким образом, они не просят сохранить данные или очистить их вещи. Они просто уйдут без предупреждения. Эта функция не удобна для пользователя и должна использоваться с осторожностью.

Это просто "плохой пользовательский опыт". Никто не ожидает этого.

Это может объяснить то, что я наблюдал: работает с первого раза. Сбой каждый последующий раз. Это укрепляет мою веру в то, что что-то не очищается должным образом внутри

0
12.12.2008 13:48:33

Причина сбоя вызова после первого раза очень вероятна, потому что он использует дескриптор безопасности «по умолчанию» (что бы это ни было).

из MSDN :

lpProcessAttributes [in, необязательно]

Указатель на структуру SECURITY_ATTRIBUTES, которая задает дескриптор безопасности для нового объекта процесса и определяет, могут ли дочерние процессы наследовать возвращенный дескриптор процесса. Если lpProcessAttributes имеет значение NULL или lpSecurityDescriptor имеет значение NULL, процесс получает дескриптор безопасности по умолчанию и дескриптор не может быть унаследован. Дескриптор безопасности по умолчанию - дескриптор пользователя, на который ссылается параметр hToken. Этот дескриптор безопасности может не разрешить доступ для вызывающей стороны, и в этом случае процесс не может быть снова открыт после его запуска. Дескриптор процесса действителен и будет по-прежнему иметь полные права доступа.

Я предполагаю, что CreateProcessWithLogonW создает этот дескриптор безопасности по умолчанию (во всяком случае, я его не указываю).

Время начинать взаимодействие ...

1
6.01.2009 09:25:05

Вы говорите, что «Служба Windows запущена с использованием« учетных данных администратора »

Вы имеете в виду настоящую учетную запись «Администратор» или пользователя в группе «Администраторы»? Запуск службы в качестве администратора решил это для меня.

0
13.01.2009 14:56:11
Возможно, у вас есть проблема в том, что ваш администратор всегда должен входить в систему, да?
Matt Jacobsen 19.02.2009 08:50:05
РЕШЕНИЕ

Кажется, у меня есть рабочая реализация (Works On My Machine (TM)) для следующих сценариев:

Пакетный файл, сборка консоли .NET, приложение .NET Windows Forms.

Вот как:

У меня есть служба Windows, работающая от имени администратора. Я добавляю следующие политики для пользователя-администратора:

  • Войти как сервис
  • Действовать как часть операционной системы
  • Настройте квоты памяти для процесса
  • Заменить токен уровня процесса

Эти политики можно добавить, открыв Панель управления / Администрирование / Локальная политика безопасности / Назначение прав пользователя. После установки политики не вступают в силу до следующего входа в систему. Вы можете использовать другого пользователя вместо администратора, что может сделать вещи немного безопаснее :)

Теперь у моей службы Windows есть необходимые разрешения для запуска заданий от имени других пользователей. Когда необходимо запустить задание, служба выполняет отдельную сборку (сборка консоли .NET для начинающих), которая инициирует процесс для меня.

Следующий код, расположенный в службе Windows, выполняет мою сборку консоли «Starter»:

Process proc = null;
System.Diagnostics.ProcessStartInfo info;
string domain = string.IsNullOrEmpty(row.Domain) ? "." : row.Domain;
info = new ProcessStartInfo("Starter.exe");
info.Arguments = cmd + " " + domain + " " + username + " " + password + " " + args;
info.WorkingDirectory = Path.GetDirectoryName(cmd);
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
proc = System.Diagnostics.Process.Start(info);

Затем консольная сборка запускает целевой процесс с помощью вызовов взаимодействия:

class Program
{
    #region Interop

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
        public UInt32 LowPart;
        public Int32 HighPart;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID_AND_ATTRIBUTES
    {
        public LUID Luid;
        public UInt32 Attributes;
    }

    public struct TOKEN_PRIVILEGES
    {
        public UInt32 PrivilegeCount;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public LUID_AND_ATTRIBUTES[] Privileges;
    }

    enum TOKEN_INFORMATION_CLASS
    {
        TokenUser = 1,
        TokenGroups,
        TokenPrivileges,
        TokenOwner,
        TokenPrimaryGroup,
        TokenDefaultDacl,
        TokenSource,
        TokenType,
        TokenImpersonationLevel,
        TokenStatistics,
        TokenRestrictedSids,
        TokenSessionId,
        TokenGroupsAndPrivileges,
        TokenSessionReference,
        TokenSandBoxInert,
        TokenAuditPolicy,
        TokenOrigin,
        TokenElevationType,
        TokenLinkedToken,
        TokenElevation,
        TokenHasRestrictions,
        TokenAccessInformation,
        TokenVirtualizationAllowed,
        TokenVirtualizationEnabled,
        TokenIntegrityLevel,
        TokenUIAccess,
        TokenMandatoryPolicy,
        TokenLogonSid,
        MaxTokenInfoClass
    }

    [Flags]
    enum CreationFlags : uint
    {
        CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
        CREATE_DEFAULT_ERROR_MODE = 0x04000000,
        CREATE_NEW_CONSOLE = 0x00000010,
        CREATE_NEW_PROCESS_GROUP = 0x00000200,
        CREATE_NO_WINDOW = 0x08000000,
        CREATE_PROTECTED_PROCESS = 0x00040000,
        CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
        CREATE_SEPARATE_WOW_VDM = 0x00001000,
        CREATE_SUSPENDED = 0x00000004,
        CREATE_UNICODE_ENVIRONMENT = 0x00000400,
        DEBUG_ONLY_THIS_PROCESS = 0x00000002,
        DEBUG_PROCESS = 0x00000001,
        DETACHED_PROCESS = 0x00000008,
        EXTENDED_STARTUPINFO_PRESENT = 0x00080000
    }

    public enum TOKEN_TYPE
    {
        TokenPrimary = 1,
        TokenImpersonation
    }

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

    [Flags]
    enum LogonFlags
    {
        LOGON_NETCREDENTIALS_ONLY = 2,
        LOGON_WITH_PROFILE = 1
    }

    enum LOGON_TYPE
    {
        LOGON32_LOGON_INTERACTIVE = 2,
        LOGON32_LOGON_NETWORK,
        LOGON32_LOGON_BATCH,
        LOGON32_LOGON_SERVICE,
        LOGON32_LOGON_UNLOCK = 7,
        LOGON32_LOGON_NETWORK_CLEARTEXT,
        LOGON32_LOGON_NEW_CREDENTIALS
    }

    enum LOGON_PROVIDER
    {
        LOGON32_PROVIDER_DEFAULT,
        LOGON32_PROVIDER_WINNT35,
        LOGON32_PROVIDER_WINNT40,
        LOGON32_PROVIDER_WINNT50
    }

    #region _SECURITY_ATTRIBUTES
    //typedef struct _SECURITY_ATTRIBUTES {  
    //    DWORD nLength;  
    //    LPVOID lpSecurityDescriptor;  
    //    BOOL bInheritHandle;
    //} SECURITY_ATTRIBUTES,  *PSECURITY_ATTRIBUTES,  *LPSECURITY_ATTRIBUTES;
    #endregion
    struct SECURITY_ATTRIBUTES
    {
        public uint Length;
        public IntPtr SecurityDescriptor;
        public bool InheritHandle;
    }

    [Flags] enum SECURITY_INFORMATION : uint
    {
        OWNER_SECURITY_INFORMATION        = 0x00000001,
        GROUP_SECURITY_INFORMATION        = 0x00000002,
        DACL_SECURITY_INFORMATION         = 0x00000004,
        SACL_SECURITY_INFORMATION         = 0x00000008,
        UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
        UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
        PROTECTED_SACL_SECURITY_INFORMATION   = 0x40000000,
        PROTECTED_DACL_SECURITY_INFORMATION   = 0x80000000
    }

    #region _SECURITY_DESCRIPTOR
    //typedef struct _SECURITY_DESCRIPTOR {
    //  UCHAR  Revision;
    //  UCHAR  Sbz1;
    //  SECURITY_DESCRIPTOR_CONTROL  Control;
    //  PSID  Owner;
    //  PSID  Group;
    //  PACL  Sacl;
    //  PACL  Dacl;
    //} SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
    #endregion
    [StructLayoutAttribute(LayoutKind.Sequential)]
    struct SECURITY_DESCRIPTOR
    {
        public byte revision;
        public byte size;
        public short control; // public SECURITY_DESCRIPTOR_CONTROL control;
        public IntPtr owner;
        public IntPtr group;
        public IntPtr sacl;
        public IntPtr dacl;
    }

    #region _STARTUPINFO
    //typedef struct _STARTUPINFO {  
    //    DWORD cb;  
    //    LPTSTR lpReserved;  
    //    LPTSTR lpDesktop;  
    //    LPTSTR lpTitle;  
    //    DWORD dwX;  
    //    DWORD dwY;  
    //    DWORD dwXSize;  
    //    DWORD dwYSize;  
    //    DWORD dwXCountChars;  
    //    DWORD dwYCountChars;  
    //    DWORD dwFillAttribute;  
    //    DWORD dwFlags;  
    //    WORD wShowWindow;  
    //    WORD cbReserved2;  
    //    LPBYTE lpReserved2;  
    //    HANDLE hStdInput;  
    //    HANDLE hStdOutput;  
    //    HANDLE hStdError; 
    //} STARTUPINFO,  *LPSTARTUPINFO;
    #endregion
    struct STARTUPINFO
    {
        public uint cb;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string Reserved;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string Desktop;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string Title;
        public uint X;
        public uint Y;
        public uint XSize;
        public uint YSize;
        public uint XCountChars;
        public uint YCountChars;
        public uint FillAttribute;
        public uint Flags;
        public ushort ShowWindow;
        public ushort Reserverd2;
        public byte bReserverd2;
        public IntPtr StdInput;
        public IntPtr StdOutput;
        public IntPtr StdError;
    }

    #region _PROCESS_INFORMATION
    //typedef struct _PROCESS_INFORMATION {  
    //  HANDLE hProcess;  
    //  HANDLE hThread;  
    //  DWORD dwProcessId;  
    //  DWORD dwThreadId; } 
    //  PROCESS_INFORMATION,  *LPPROCESS_INFORMATION;
    #endregion
    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr Process;
        public IntPtr Thread;
        public uint ProcessId;
        public uint ThreadId;
    }

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool InitializeSecurityDescriptor(IntPtr pSecurityDescriptor, uint dwRevision);
    const uint SECURITY_DESCRIPTOR_REVISION = 1;

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool SetSecurityDescriptorDacl(ref SECURITY_DESCRIPTOR sd, bool daclPresent, IntPtr dacl, bool daclDefaulted);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    extern static bool DuplicateTokenEx(
        IntPtr hExistingToken,
        uint dwDesiredAccess,
        ref SECURITY_ATTRIBUTES lpTokenAttributes,
        SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
        TOKEN_TYPE TokenType,
        out IntPtr phNewToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken
        );

    #region GetTokenInformation
    //BOOL WINAPI GetTokenInformation(
    //  __in       HANDLE TokenHandle,
    //  __in       TOKEN_INFORMATION_CLASS TokenInformationClass,
    //  __out_opt  LPVOID TokenInformation,
    //  __in       DWORD TokenInformationLength,
    //  __out      PDWORD ReturnLength
    //);
    #endregion
    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool GetTokenInformation(
        IntPtr TokenHandle,
        TOKEN_INFORMATION_CLASS TokenInformationClass,
        IntPtr TokenInformation,
        int TokenInformationLength,
        out int ReturnLength
        );


    #region CreateProcessAsUser
    //        BOOL WINAPI CreateProcessAsUser(
    //  __in_opt     HANDLE hToken,
    //  __in_opt     LPCTSTR lpApplicationName,
    //  __inout_opt  LPTSTR lpCommandLine,
    //  __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
    //  __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
    //  __in         BOOL bInheritHandles,
    //  __in         DWORD dwCreationFlags,
    //  __in_opt     LPVOID lpEnvironment,
    //  __in_opt     LPCTSTR lpCurrentDirectory,
    //  __in         LPSTARTUPINFO lpStartupInfo,
    //  __out        LPPROCESS_INFORMATION lpProcessInformation);
    #endregion
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    static extern bool CreateProcessAsUser(
        IntPtr Token, 
        [MarshalAs(UnmanagedType.LPTStr)] string ApplicationName,
        [MarshalAs(UnmanagedType.LPTStr)] string CommandLine,
        ref SECURITY_ATTRIBUTES ProcessAttributes, 
        ref SECURITY_ATTRIBUTES ThreadAttributes, 
        bool InheritHandles,
        uint CreationFlags, 
        IntPtr Environment, 
        [MarshalAs(UnmanagedType.LPTStr)] string CurrentDirectory, 
        ref STARTUPINFO StartupInfo, 
        out PROCESS_INFORMATION ProcessInformation);

    #region CloseHandle
    //BOOL WINAPI CloseHandle(
    //      __in          HANDLE hObject
    //        );
    #endregion
    [DllImport("Kernel32.dll")]
    extern static int CloseHandle(IntPtr handle);

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

    [DllImport("advapi32.dll", SetLastError = true)]
    internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct TokPriv1Luid
    {
        public int Count;
        public long Luid;
        public int Attr;
    }

    //static internal const int TOKEN_QUERY = 0x00000008;
    internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
    //static internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

    internal const int TOKEN_QUERY = 0x00000008;
    internal const int TOKEN_DUPLICATE = 0x0002;
    internal const int TOKEN_ASSIGN_PRIMARY = 0x0001;

    #endregion

    [STAThread]
    static void Main(string[] args)
    {
        string username, domain, password, applicationName;
        username = args[2];
        domain = args[1];
        password = args[3];
        applicationName = @args[0];

        IntPtr token = IntPtr.Zero;
        IntPtr primaryToken = IntPtr.Zero;
        try
        {
            bool result = false;

            result = LogonUser(username, domain, password, (int)LOGON_TYPE.LOGON32_LOGON_NETWORK, (int)LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out token);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
            }

            string commandLine = null;

            #region security attributes
            SECURITY_ATTRIBUTES processAttributes = new SECURITY_ATTRIBUTES();

            SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
            IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd));
            Marshal.StructureToPtr(sd, ptr, false);
            InitializeSecurityDescriptor(ptr, SECURITY_DESCRIPTOR_REVISION);
            sd = (SECURITY_DESCRIPTOR)Marshal.PtrToStructure(ptr, typeof(SECURITY_DESCRIPTOR));

            result = SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
            }

            primaryToken = new IntPtr();
            result = DuplicateTokenEx(token, 0, ref processAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out primaryToken);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
            }
            processAttributes.SecurityDescriptor = ptr;
            processAttributes.Length = (uint)Marshal.SizeOf(sd);
            processAttributes.InheritHandle = true;
            #endregion

            SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES();
            threadAttributes.SecurityDescriptor = IntPtr.Zero;
            threadAttributes.Length = 0;
            threadAttributes.InheritHandle = false;

            bool inheritHandles = true;
            //CreationFlags creationFlags = CreationFlags.CREATE_DEFAULT_ERROR_MODE;
            IntPtr environment = IntPtr.Zero;
            string currentDirectory = currdir;

            STARTUPINFO startupInfo = new STARTUPINFO();
            startupInfo.Desktop = "";

            PROCESS_INFORMATION processInformation;

            result = CreateProcessAsUser(primaryToken, applicationName, commandLine, ref processAttributes, ref threadAttributes, inheritHandles, 16, environment, currentDirectory, ref startupInfo, out processInformation);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
                File.
  
23
19.02.2009 08:47:40
Не уверен, что безопасность является проблемой, но NULL-DACL, как правило, очень плохая идея с точки зрения безопасности. Прочитайте раздел замечаний SetSecurityDescriptorDacl: msdn.microsoft.com/en-us/library/windows/desktop/…
Andreas Magnusson 23.04.2012 08:34:04
Боже мой, это действительно сработало. Я боролся с этим больше недели, сдавался и возвращался, гуглял снова и снова. Это было единственное, что позволило мне запускать произвольные процессы, выдавая себя за других пользователей из оконной службы, из оконной службы, работающей как локальная система, локальная служба или сетевая служба
Mike Mooney 14.11.2013 14:13:02
Требуется ли промежуточный процесс «Стартер»? Я не сразу понимаю, почему это будет.
Mark 24.11.2016 19:01:02
Какое первоначальное намерение или идея стояли за промежуточным «стартовым» процессом? Почему вы включили его как часть рабочего процесса? Это скрывает какую-то проблему, с которой вы столкнулись?
Ryan 18.05.2018 02:10:03
@ Райан, это было давным-давно, но, оглядываясь на код выше, я думаю, что это связано с тем, что я не хотел / не мог вызвать LogonUser из сервиса.
Matt Jacobsen 19.06.2018 09:03:03

У меня были похожие проблемы, когда я пытался запустить бинарный файл PhantomJS с глаголом «runas» в службе Windows. Теперь я решил проблему, используя следующую процедуру:

  • Имитировать пользователя
  • Начать процесс (без интерфейса)
  • Выдавать себя за

Вы можете использовать Имитатор-Класс для подражания. Также важно установить следующие свойства в ProcessStartInfo, чтобы приложение не пыталось получить доступ к пользовательскому интерфейсу Windows:

var processStartInfo = new ProcessStartInfo()
{
    FileName = $@"{assemblyFolder}\PhantomJS\phantomjs.exe",
    Arguments = $"--webdriver={port}",
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    RedirectStandardInput = true,
    UseShellExecute = false,
    CreateNoWindow = true,
    ErrorDialog = false,
    WindowStyle = ProcessWindowStyle.Hidden
};
0
28.04.2017 12:09:29