2

我开发了一个 Windows 应用程序,它安装在客户端的大约 15 台机器上。我在应用程序中创建了自我更新功能。自我更新功能只是主应用程序中的小型控制台应用程序。

当主应用程序启动时,它会将其版本(来自配置文件)与数据库(存储最新版本的表)进行比较。如果两个版本不同,则执行控制台应用程序并停止主应用程序。

控制台应用程序关闭主应用程序的所有实例,并从中心位置选择主应用程序的最新文件并更新应用程序。

问题是当控制台应用程序关闭主应用程序的所有实例时,用户应该收到一条通知消息“应用程序将被关闭以进行更新等等等等”。

我为此做了 rnd 并找到了将消息发送到其他进程的发送消息功能。发送消息适用于同一台机器上的多个实例。所有实例在关闭之前都会显示消息。

但是当 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);
}

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

4

1 回答 1

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;
                }
            }
于 2013-08-20T09:06:52.117 回答