Не удается запустить настольное приложение из службы Windows в Windows 7 - PullRequest
5 голосов
/ 01 октября 2010

HI,

У меня есть служба Windows C # WCF в Windows 7, вошедшая в систему как пользователь с правами администратора.Я пытаюсь запустить настольное приложение после запуска службы.Все обсуждения, которые я нашел, касаются оконных станций и рабочих столов ... Я создал отдельный поток, настроил потоковую станцию ​​и рабочий стол и попытался запустить настольное приложение.Код работает, когда я запускаю его с VS2010, используя сервер разработки asp.net, но если он был запущен из сервиса, ошибок нет, но процесс не был запущен.Я пытался запустить процесс от имени другого пользователя и пытался вызвать CreateProcessWithLogonW (с установкой startInfo.lpDesktop на «winsta0 \ default»; ранее).В обоих случаях я возвратил processId, но не вижу настольного приложения.Может кто-нибудь помочь мне увидеть, где ошибка?

public class ExternalProcess
{
    const int READ_CONTROL = 0x20000;
    const int WRITE_DAC = 0x40000;
    const int DESKTOP_WRITEOBJECTS = 0x80;
    const int DESKTOP_READOBJECTS = 0x1;

    private Process extProcess;
    private string sFilePath = "";

    [DllImport("user32.dll")]
    private static extern bool SetThreadDesktop(IntPtr hDesktop);
    [DllImport("user32.dll")]
    static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags,bool fInherit, uint dwDesiredAccess);
    [DllImport("user32.dll")]
    private static extern IntPtr GetProcessWindowStation();
    [DllImport("user32.dll")]
    private static extern IntPtr OpenWindowStation(string lpszWinSta, bool fInherit, ACCESS_MASK dwDesiredAccess);
    [DllImport("user32.dll")]
    private static extern IntPtr SetProcessWindowStation(IntPtr hWinsta);

    public bool StartProcess(string filePath)
    {
        sFilePath = filePath;
        Thread t = new Thread(new ThreadStart(Thread_StartProcess));
        t.Start();

        return true;
    }

    private void Thread_StartProcess()
    {
        IntPtr hwinstaSave;
        IntPtr hwinsta, hwinsta2;
        IntPtr hdesk;

        hwinstaSave = GetProcessWindowStation();
            System.Console.WriteLine("GetProcessWindowStation Lasterror= " + Marshal.GetLastWin32Error().ToString());
            System.Console.WriteLine("GetProcessWindowStation hwinstaSave= " + hwinstaSave.ToString());
        //hwinsta = OpenWindowStation("winsta0", false, ACCESS_MASK.GENERIC_EXECUTE | ACCESS_MASK.DESKTOP_CREATEWINDOW | ACCESS_MASK.DESKTOP_CREATEMENU | ACCESS_MASK.DESKTOP_SWITCHDESKTOP | ACCESS_MASK.DESKTOP_WRITEOBJECTS);
        hwinsta = OpenWindowStation("winsta0", false, ACCESS_MASK.WINSTA_ALL_ACCESS); // when call from windows service OpenWindowStation returns 0
            System.Console.WriteLine("OpenWindowStation lasterror = " + Marshal.GetLastWin32Error().ToString());
            System.Console.WriteLine("OpenWindowStation hwinsta= " + hwinsta.ToString());
        hwinsta2 = SetProcessWindowStation(hwinsta);
            System.Console.WriteLine("SetProcessWindowStation lasterror = " + Marshal.GetLastWin32Error().ToString());
            System.Console.WriteLine("SetProcessWindowStation hwinsta2= " + hwinsta2.ToString());
        hdesk = OpenDesktop("default", 0, true, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS);
            System.Console.WriteLine("OpenDesktop lasterror = " + Marshal.GetLastWin32Error().ToString());
            System.Console.WriteLine("OpenDesktop hdesk= " + hdesk.ToString());
        bool Success = SetThreadDesktop(hdesk);
            System.Console.WriteLine("SetThreadDesktop lasterror = " + Marshal.GetLastWin32Error().ToString());
            System.Console.WriteLine("SetThreadDesktop Success= " + Success.ToString());

        try
        {
            extProcess = new Process();

            extProcess.StartInfo.FileName = sFilePath;
            extProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

            if (extProcess.Start())
                System.Console.WriteLine("Process started ");
            else
                System.Console.WriteLine("Not started!");
        }
        catch (Win32Exception e)
        {
            System.Console.WriteLine("Start {0} failed. Error: " + e.Message);
        }
    }

}

Ответы [ 4 ]

3 голосов
/ 04 ноября 2010

Интерактивные службы Windows получили безопасность в Windows Vista. Сервисы теперь работают в изолированном «сеансе 0» и не могут легко внедрить окна в интерактивные сеансы пользователя. Приведенный выше код создаст элементы графического интерфейса в сеансе 0, которые не отображаются на рабочем столе любого пользователя, даже если установлен флажок «Разрешить службе взаимодействовать с рабочим столом».

Подробнее об ограничениях служб Windows см. В этом техническом документе от Microsoft .

1 голос
/ 01 января 2015

Приложение открывается в другой сессии, начиная с Windows Vista. Следовательно, вы не видите приложение открытым и не можете связаться с приложением. Это может помочь

Можно ли запустить процесс в сеансе пользователя из службы?

Асим

1 голос
/ 01 октября 2010

Разобраться в этом поможет: http://msdn.microsoft.com/en-us/library/ms683502%28VS.85%29.aspx

НТН

Mario

0 голосов
/ 27 августа 2011

Я сейчас нахожусь в центре этого, я знаю, что UltraVNC делает это, поэтому я посмотрю на код. Я не уверен на 100% в данный момент, когда я это выясню, я обновлю этот пост.

Суть в том, что вы создаете CreateProcessAsUser, тогда процесс, возможно, должен будет сделать OpenInputDesktop, а затем SetThreadDesktop, но я пока не могу заставить его работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...