2013-08-05 123 views
1

我開發了一個Windows應用程序,它安裝在客戶端的大約15臺機器上。我在應用程序中創建了自我更新功能。自我更新功能只是主應用程序中的小型控制檯應用程序。將消息從一個應用程序發送到同一終端中的另一個應用程序

當主應用程序啓動時,它將其版本(從配置文件)與數據庫(存儲最新版本的表)進行比較。如果兩個版本都不同,則執行控制檯應用程序並停止主應用程序。

控制檯應用程序關閉主應用程序的所有實例,並從中心位置選擇主應用程序的最新文件並更新應用程序。

問題是,當控制檯應用程序關閉主應用程序的所有實例時,用戶應該會收到一條通知消息,指出「應用程序將關閉以進行更新等等......」。

我做了這個,並找到發送消息函數發送消息到其他進程。發送消息對同一臺機器上的多個實例工作良好。所有實例在關閉之前都會顯示消息。

但是,當2個或更多用戶在同一終端/服務器上使用應用程序時,它不能在終端上運行。應用程序關閉時不向用戶發送任何通知消息。在終端上,每個用戶使用其用戶名和密碼登錄,並且可以獨立工作。

* 下面是我的代碼實現:*

**Console application that sends the messgae** 

private const int RF_TESTMESSAGE = 0xA123; 

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public static extern int SendMessage(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int Msg, IntPtr wParam, IntPtr lParam); 

var processFinder = new ManagementObjectSearcher(string.Format("Select * from Win32_Process where Name='{0}.exe'", processName)); 
    var processes = processFinder.Get(); 
    if (processes.Count == 0) 
    { 
     return true; 
    } 
    else 
    { 
     foreach (ManagementObject managementObject in processes) 
     { 
      var n = Convert.ToString(managementObject["Name"]); 
      var pId = Convert.ToInt32(managementObject["ProcessId"]); 
      var process = Process.GetProcessById(pId); 

      process.StartInfo.UseShellExecute = false; 

      if (currentUserOnly) //current user 
      { 
       var processOwnerInfo = new object[2]; 
       managementObject.InvokeMethod("GetOwner", processOwnerInfo); 
       var processOwner = (string)processOwnerInfo[0]; 
       var net = (string)processOwnerInfo[1]; 
       if (!string.IsNullOrEmpty(net)) 
        processOwner = string.Format("{0}\\{1}", net, processOwner); 



       if (string.CompareOrdinal(processOwner, userName) == 0) 
       { 
        SendMessage(process.MainWindowHandle, RF_TESTMESSAGE, IntPtr.Zero, IntPtr.Zero); 
        System.Threading.Thread.Sleep(5000); 
       } 

       if (process.HasExited == false) // if application has not closed 
       { 

        //Process is still running. 
        //Test to see if the process is hung up. 
        if (process.Responding) // if user interface of process is still responding 
        { 
         // Process was responding; close the main window. 
         process.CloseMainWindow(); 


         if (process.HasExited == false) // if application is still running then close kill the process 
         { 
          process.Kill(); 

         } 
        } 
        else 
        { 
         // Process was not responding; force the process to close. 
         process.Kill(); 

        } 
       } 

       process.WaitForExit(5000); 

       UpdateSoftware = process.HasExited; 
       process.Close(); 
      } 
     } 

    } 

是臨危消息

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public static extern int SendMessage(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int Msg, IntPtr wParam, IntPtr lParam); 

protected override void WndProc(ref Message message) 
{ 
    //filter the RF_TESTMESSAGE 
    if (message.Msg == RF_TESTMESSAGE) 
    { 
     //display that we recieved the message, of course we could do 
     //something else more important here. 

     MessageBox.Show("Your application will be closed becuase new update is available. Please start the application after some time."); 
    } 
    //be sure to pass along all messages to the base also 
    base.WndProc(ref message); 
} 

請讓我知道我錯了,主要用途?爲什麼它不適用於同一終端上的用戶?

+2

針對不同用戶的窗口在不同的會議,你不能會話之間發送窗口消息。 –

+0

那麼有沒有其他出路發送消息? –

+0

任何跨會話信令技術往往會有點片面或要求機器上的(至少一個)用戶是管理員 - 是這種情況,還是用戶帳戶只是普通的用戶帳戶? –

回答

0

經過這麼多天,我找到了解決方案。通過使用Cassia .NET庫,我們可以發送消息到跨會話。這裏是鏈接庫http://code.google.com/p/cassia

private static readonly ITerminalServicesManager _manager = new TerminalServicesManager(); 
using (ITerminalServer server = GetServerFromName("local")) 
      { 
       server.Open(); 

       int i = 0; 
       foreach (ITerminalServicesSession session in server.GetSessions()) 
       { 
        IEnumerable<ITerminalServicesProcess> processes = session.GetProcesses(); 

        foreach (ITerminalServicesProcess p in processes) 
        { 
         if (p.ProcessName == "Your Process Name.exe") 
         { 
          Console.WriteLine(String.Format("Process Name: {0} Process ID: {1} Session ID: {2}", p.ProcessName, p.ProcessId, p.SessionId)); 
          if (i == 0) 
          { 
           session.MessageBox("Your application will be stopped for new updates", "Application Update", RemoteMessageBoxIcon.Warning); 
           i = 1; 
          } 
          p.Kill(); 
         } 
        } 

        i = 0; 
       } 
      } 
相關問題