2010-10-01 128 views
5

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

我有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); 
     } 
    } 

} 
+0

完整的源代码示例工作任何有关它的最终解决方案? – Kiquenet 2013-07-11 11:37:37

回答

1

Perhapse这有助于:http://msdn.microsoft.com/en-us/library/ms683502%28VS.85%29.aspx

心连心

马里奥

+0

Thx,我已经读过,试图检查服务中的“允许服务与桌面交互”复选框,更改运行服务的用户...,对于特定用户,不允许使用复选框,我尝试设置它在注册表中手动,但没有结果... – Jovan 2010-10-01 11:20:03

+0

我更多的是指这个声明:“重要服务不能直接与Windows Vista的用户交互,因此,不应使用标题为”使用交互式服务“一节中提到的技术在新的代码中。“ - 似乎从Windows Vista开始直接从服务器与用户进行交互(这意味着,Vista,7和Server 2008,我猜!)不再是可能的。它在调试器中工作,因为调试器不是真正的服务! – 2010-10-01 11:55:56

+0

好的,我很害怕那部分。这意味着必须尝试不同的设计。非常感谢。 – Jovan 2010-10-01 12:02:30

4

互动Windows服务在Windows Vista中收到一个以安全为中心的改造。服务现在运行在孤立的“会话0”中,并且不能将窗口轻松注入到交互式用户会话中。上面的代码将在会话0中创建GUI元素,即使在选中“允许服务与桌面交互”的情况下,它们也不会显示在任何用户的桌面上。

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

0

我现在正处在这个权利当中,我知道UltraVNC这样做,所以我会看看代码。我现在不是100%肯定答案,当我知道我会更新这篇文章。

的要点是你做了一个CreateProcessAsUser,然后该过程可能必须做OpenInputDesktop,然后是一个SetThreadDesktop,但是像我无法让它工作。

相关问题