无法从Windows 7上的Windows服务启动桌面应用程序

时间:2010-10-01 10:41:17

标签: c# windows wcf service

HI,

我在Windows 7上以具有管理员权限的用户身份登录C#WCF Windows服务。 我想在服务启动后启动桌面应用程序。我发现的所有讨论都是关于Windows工作站和桌面的...我创建了一个单独的线程,设置了线程站和桌面,并尝试启动桌面应用程序。 当我使用asp.net开发服务器从VS2010启动代码时,代码有效,但如果它是从服务启动的,则没有错误,但是没有启动进程。我试图以不同的用户启动进程并尝试调用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 个答案:

答案 0 :(得分:3)

Interactive Windows Services在Windows Vista中获得了以安全为中心的改造。服务现在在隔离的“会话0”中运行,并且不能轻易地将窗口注入交互式用户会话。上面的代码将在会话0中创建GUI元素,这些元素不会显示在任何用户的桌面上,即使选中“允许服务与桌面交互”也是如此。

有关Windows服务限制的更多详细信息,请参见this technical document from Microsoft

答案 1 :(得分:1)

答案 2 :(得分:1)

自Windows Vista以来,应用程序在不同的会话中打开。因此,您看不到应用程序已打开,并且您无法与应用程序通信。这可能会有所帮助

Possible to launch a process in a user's session from a service?

阿西

答案 3 :(得分:0)

我现在正处于这个中间,我知道UltraVNC这样做,所以我会查看代码。我现在不是100%肯定答案,当我弄明白时我会更新这篇文章。

要点是你做了一个CreateProcessAsUser,然后该过程可能需要执行OpenInputDesktop然后是一个SetThreadDesktop,但是就像我无法让它工作一样。