2010-10-01 4 views
5

HI,Windows, Windows hizmetinden masaüstü uygulaması başlatılamıyor 7

Ben Windows 7 C# WCF Windows hizmet yönetici haklarına sahip kullanıcı olarak oturum var. Servis başlatıldıktan sonra masaüstü uygulamasını başlatmaya çalışıyorum. Bulduğum tüm tartışmalar pencere istasyonları ve masaüstleri hakkında ... Ayrı bir iş parçacığı oluşturdum, iş istasyonu ve masaüstünü ayarladım ve masaüstü uygulamasını başlatmaya çalıştım. Kod, asp200 geliştirme sunucusunu kullanarak VS2010'dan başladığımda çalışır ancak hizmetten başlatılmışsa hata yoktur, ancak işlem başlatılmamıştır. İşlemi farklı kullanıcı olarak başlatmayı denedim ve CreateProcessWithLogonW çağrısını denedim (startInfo.lpDesktop ayarını "winsta0 \ default"; daha önce). Her iki durumda da processId döndüm ancak masaüstü uygulamasını göremiyorum. Birisi nerede hata olduğunu görmeme yardım edebilir mi? Bu Perhapse

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

tam kaynak kod örneği bu konuda çalışma ile herhangi bir nihai çözüm yardımcı olabilir? – Kiquenet

cevap

1
+0

Thx, Bunu okuduğumda, "Hizmetin masaüstüyle etkileşime girmesine izin ver" onay kutusunu işaretlemeyi denedim, hizmet çalıştıran kullanıcıyı değiştir ..., Belirli bir kullanıcı için onay kutusuna izin verilmiyorsa, ayarlamaya çalıştım. el ile kayıt defterinde ancak sonuçsuz ... – Jovan

+0

Bu bildirime daha çok atıfta bulundum: "Önemli Hizmetler, Windows Vista ile doğrudan bir kullanıcıyla etkileşimde bulunamaz. Bu nedenle, Etkileşimli Hizmet Kullanarak başlıklı bölümde belirtilen teknikler kullanılmamalıdır. yeni kodda. " - Görünüşe bakılırsa, bir hizmetin doğrudan Windows Vista'dan başlayarak kullanıcıyla etkileşime girmesi artık mümkün değil (Bu, Vista, 7 ve Server 2008'i tahmin ediyorum!). Hata ayıklayıcıda çalışıyor çünkü hata ayıklayıcı gerçek bir hizmet değil! –

+0

evet, o kısımdan korktum. Bu farklı tasarım denemek zorunda anlamına gelir. Çok teşekkürler. – Jovan

4

Etkileşimli Windows Hizmetleri Windows Vista'daki güvenlik merkezli makyaj aldı. Hizmetler artık yalıtılmış "Oturum 0" da çalışır ve kolayca etkileşimli kullanıcı oturumlarına pencereleri enjekte edemez. Yukarıdaki kodunuz, "Hizmetin masaüstüyle etkileşime girmesine izin ver" işaretli olsa bile, herhangi bir kullanıcının masaüstünde gösterilmeyen Oturum 0'da GUI öğeleri oluşturacaktır.

Windows Services kısıtlamaları hakkında daha fazla bilgi this technical document from Microsoft numaralı telefondan alınabilir.

0

Şu an bunun ortasındayım, UltraVNC'nin bunu yapabildiğini biliyorum, bu yüzden bu koda bakıyorum. Bu andaki cevaptan% 100 emin değilim, anladığımda bu yazıyı güncelleyeceğim.

Özgün bir CreateProcessAsUser gerçekleştirdiğinizde, işlem daha sonra bir SetThreadDesktop OpenInputDesktop yapmak zorunda olabilir, ancak henüz işe alamıyorum gibi. Windows Vista'dan beri uygulama farklı bir oturumda açılır.