我开发了一个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);
}
请让我知道我哪里错了?为什么它不适用于同一终端上的用户?
答案 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;
}
}