将消息从一个应用程序发送到同一终端中的另一个应用程序

时间:2013-08-05 07:02:52

标签: .net winforms

我开发了一个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);
}

请让我知道我哪里错了?为什么它不适用于同一终端上的用户?

1 个答案:

答案 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;
                }
            }