Подтвердить что ты не робот

Как запустить программу EXE из службы Windows с помощью С#?

Как я могу запустить программу EXE из службы Windows с помощью С#?

Это мой код:

System.Diagnostics.Process.Start(@"E:\PROJECT XL\INI SQLLOADER\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2\bin\Debug\ConsoleApplication2.exe");

Когда я запускаю эту службу, приложение не запускается.
Что не так с моим кодом?

4b9b3361

Ответ 1

Это никогда не будет работать, по крайней мере, не под Windows Vista или более поздней версией. Основная проблема заключается в том, что вы пытаетесь выполнить это из службы Windows, а не в стандартном приложении Windows. Код, который вы показали, отлично работает в приложении Windows Forms, WPF или Console, но он вообще не работает в службе Windows.

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

Дополнительная информация доступна в ответах на эти связанные вопросы:

Лучшее решение вашей проблемы, как вы, вероятно, уже выяснили, состоит в том, чтобы создать стандартное приложение Windows вместо службы. Они предназначены для работы конкретного пользователя и связаны с этим рабочим столом пользователя. Таким образом, вы можете запускать дополнительные приложения, когда захотите, используя код, который вы уже указали.

Другое возможное решение, предполагая, что ваше консольное приложение не требует интерфейса или вывода любого типа, заключается в том, чтобы проинструктировать процесс не создавать окно. Это не позволит Windows блокировать создание вашего процесса, поскольку он больше не будет запрашивать создание окна консоли. Вы можете найти соответствующий код в этом ответе на соответствующий вопрос.

Ответ 2

Я пробовал эту статью Code Project, он отлично работает для меня. Я тоже использовал код. статья превосходна в объяснении с снимком экрана.

Я добавляю необходимое объяснение этому сценарию

Вы только что загрузили свой компьютер и собираетесь войти в систему. При входе в систему система назначает вам уникальный идентификатор сеанса. В Windows Vista первому пользователю, который должен войти на компьютер, присваивается идентификатор сеанса 1 ОС. Следующему пользователю для входа в систему будет присвоен идентификатор сеанса 2. И так далее и т.д. Вы можете просмотреть идентификатор сеанса, назначенный каждому зарегистрированному пользователю на вкладке "Пользователи" в диспетчере задач.    введите описание изображения здесь

Но ваша служба Windows подпадает под идентификатор сеанса 0. Этот сеанс изолирован от других сеансов. Это в конечном итоге не позволяет службе Windows вызывать приложение, запущенное под пользовательским сеансом, например 1 или 2.

Чтобы вызвать приложение из службы Windows, вам необходимо скопировать элемент управления из winlogon.exe, который действует как текущий зарегистрированный пользователь, как показано ниже на снимке экрана. введите описание изображения здесь

Важные коды

// obtain the process id of the winlogon process that 
// is running within the currently active session
Process[] processes = Process.GetProcessesByName("winlogon");
foreach (Process p in processes)
{
    if ((uint)p.SessionId == dwSessionId)
    {
        winlogonPid = (uint)p.Id;
    }
}

// obtain a handle to the winlogon process
hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);

// obtain a handle to the access token of the winlogon process
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken))
{
    CloseHandle(hProcess);
    return false;
}

// Security attibute structure used in DuplicateTokenEx and   CreateProcessAsUser
// I would prefer to not have to use a security attribute variable and to just 
// simply pass null and inherit (by default) the security attributes
// of the existing token. However, in C# structures are value types and   therefore
// cannot be assigned the null value.
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);

// copy the access token of the winlogon process; 
// the newly created token will be a primary token
if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, 
    (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, 
    (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
    {
      CloseHandle(hProcess);
      CloseHandle(hPToken);
      return false;
    }

 STARTUPINFO si = new STARTUPINFO();
 si.cb = (int)Marshal.SizeOf(si);

// interactive window station parameter; basically this indicates 
// that the process created can display a GUI on the desktop
si.lpDesktop = @"winsta0\default";

// flags that specify the priority and creation method of the process
int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

// create a new process in the current User logon session
 bool result = CreateProcessAsUser(hUserTokenDup,  // client access token
                            null,             // file to execute
                            applicationName,  // command line
                            ref sa,           // pointer to process    SECURITY_ATTRIBUTES
                            ref sa,           // pointer to thread SECURITY_ATTRIBUTES
                            false,            // handles are not inheritable
                            dwCreationFlags,  // creation flags
                            IntPtr.Zero,      // pointer to new environment block 
                            null,             // name of current directory 
                            ref si,           // pointer to STARTUPINFO structure
                            out procInfo      // receives information about new process
                            );

Ответ 3

Сначала мы создадим службу Windows, которая работает под Системная учетная запись. Эта служба будет нести ответственность за интерактивный процесс в текущем активном сеансе пользователей. Эта вновь созданный процесс отобразит пользовательский интерфейс и будет работать с полным админом прав. Когда первый пользователь входит в систему на компьютере, эта служба будет запускаться и запускаться в Session0; однако процесс, который эта служба будет появляться на рабочем столе текущего вошел в систему. Мы будем ссылаться на эту службу как на LoaderService.

Затем процесс winlogon.exe отвечает за управление входом пользователя и процедуры выхода из системы. Мы знаем, что каждый Пользователь, который подключается к компьютер будет иметь уникальный идентификатор сеанса и соответствующий winlogon.exe, связанный с их сеансом. Теперь мы упомянули выше, LoaderService работает под учетной записью системы. Мы также что каждый процесс winlogon.exe на компьютере работает под Системная учетная запись. Поскольку учетная запись системы является владельцем обоих процессы LoaderService и winlogon.exe, наш LoaderService может копировать токен доступа (и идентификатор сеанса) процесса winlogon.exe а затем вызовите функцию API Win32 CreateProcessAsUser для запуска перейдите в текущий активный сеанс зарегистрированного пользователя. поскольку идентификатор сеанса, расположенный в токене доступа скопированного Процесс winlogon.exe больше 0, мы можем запустить интерактивный используя этот токен.

Попробуйте это. Подчинение Vista UAC в 32-битных и 64-битных архитектурах

Ответ 4

Вы можете успешно выполнить .exe из службы Windows в Windows XP. Я сделал это сам в прошлом.

Вам нужно убедиться, что вы проверили параметр "Разрешить взаимодействие с рабочим столом" в свойствах службы Windows. Если это не сделано, оно не будет выполнено.

Мне нужно проверить Windows 7 или Vista, так как для этих версий требуются дополнительные привилегии безопасности, поэтому может возникнуть ошибка, но я уверен, что это может быть достигнуто прямо или косвенно. Для XP я уверен, что сделал это сам.

Ответ 5

Я думаю, что вы копируете .exe в другое место. Возможно, это проблема. Когда вы копируете exe, вы не копируете его зависимости.

Итак, что вы можете сделать, поместите все зависимые dll в GAC, чтобы любой .net exe мог получить к нему доступ.

Иначе, не копируйте exe в новое место. Просто создайте переменную окружения и вызовите exe в свой С#. Поскольку путь определяется в переменных среды, exe может быть доступен вашей программой С#.

Update:

раньше у меня была какая-то одна проблема в моем проекте С#.net 3.5, в котором я пытался запустить .exe файл из кода С#.net, и что exe был не чем иным, как другим exe проекта (где я добавил несколько вспомогательных dll для моей функциональности) и те методы dll, которые я использовал в своем приложении exe. Наконец, я решил это, создав это приложение как отдельный проект для того же решения, и добавил этот проект в мой проект развертывания. В соответствии с этим сценарием я ответил: "Если его не то, что он хочет, то мне очень жаль.

Ответ 6

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

например, рассмотрим, что мы хотим запланировать задачу, которая будет выполняться через пять секунд:

using (var ts = new TaskService())
        {

            var t = ts.Execute("notepad.exe")
                .Once()
                .Starting(DateTime.Now.AddSeconds(5))
                .AsTask("myTask");

        }

notepad.exe будет исполнен через пять секунд.

для получения дополнительной информации и дополнительной информации перейдите на wiki

если вы знаете, какой класс и метод в этой сборке вам нужен, вы можете вызвать его так:

        Assembly assembly = Assembly.LoadFrom("yourApp.exe");
        Type[] types = assembly.GetTypes();
        foreach (Type t in types)
        {
            if (t.Name == "YourClass")
            {
                MethodInfo method = t.GetMethod("YourMethod",
                BindingFlags.Public | BindingFlags.Instance);
                if (method != null)
                {
                    ParameterInfo[] parameters = method.GetParameters();
                    object classInstance = Activator.CreateInstance(t, null);

                    var result = method.Invoke(classInstance, parameters.Length == 0 ? null : parameters);

                    break;
                }
            }

        }

Ответ 7

System.Diagnostics.Process.Start( "Имя Exe" );