1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > WinForm 关于任务栏图标进程结束后图标无法自动清除的问题!

WinForm 关于任务栏图标进程结束后图标无法自动清除的问题!

时间:2020-06-01 15:02:44

相关推荐

WinForm 关于任务栏图标进程结束后图标无法自动清除的问题!

最近在做一个项目,有2个进程,A进程需要定时把B进程强行kill掉,然后再启动,当时这样会有一个问题,就是强行kill掉的进程在任务栏的托盘图标不会自动消失,必须用鼠标经过那个位置才会消失。这样就导致事件久了,任务栏出现一大堆图标,非常影响形象。

后来网上看到一个方法,说是通过进程间的通讯,就是由A发送通知给B,告诉B应该要退出程序了,然后由B自己来结束进程,这样任务栏的图标才会正常的消失。废话少说,直接看代码吧:

对于A进程来说,需要先找到B进程的句柄,然后才能给它发送通知,代码如下:

/// <summary>/// 根据端口号结束某个进程/// </summary>/// <param name="port">端口号,如:7012 </param>/// <returns></returns>private void KillPortProcess(int port){ int pid = 0;try{IntPtr hwnd = FindWindow(null, port.ToString());int ihWnd = (int)hwnd;GetWindowThreadProcessId(hwnd, out pid);var p = Process.GetProcessById(pid);if (p != null){if (p.ProcessName == "MySvr"){//强制杀掉进程(这种模式不能自动销毁任务栏图标)//p.Kill(); //利用发送消息方式,通知进程自杀(这种模式可以自动销毁任务栏图标)byte[] sarr = System.Text.Encoding.Default.GetBytes("SelfKill");int len = sarr.Length;COPYDATASTRUCT cds;cds.dwData = (IntPtr)Convert.ToInt16("1");//可以是任意值 cds.cbData = len + 1;//指定lpData内存区域的字节数 cds.lpData = "SelfKill";//发送给目标窗口所在进程的数据int iflag = SendMessage(ihWnd, WM_COPYDATA, 0, ref cds); }}}catch (Exception e){ } }

我这个函数是根据进程的窗体标题来查找的,因为我的标题都是一个固定的端口号,所以按这种方式来做,当然也可以根据进程名称来做,在这里就不举例了。

这里用到了Windows的API函数: SendMessage , 要引用这个函数,必须事先做以下的声明才能使用:

消息结构体:

public struct COPYDATASTRUCT{public IntPtr dwData;public int cbData;[MarshalAs(UnmanagedType.LPStr)]public string lpData;}

声明要引用的API函数:

[DllImport("User32.dll", EntryPoint = "FindWindow")]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);[DllImport("user32", EntryPoint = "GetWindowThreadProcessId")]public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int pid);[DllImport("User32.dll", EntryPoint = "SendMessage")]private static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);const int WM_COPYDATA = 0x004A;

-------------------------------------------------------------------------------------------------------------------------------------------------------

那么对于B进程来说,需要做的事情就是接收A进程发来的消息,根据消费的内容来做出对应的动作,

只要重载DefWndProc 函数即可实现消息的接收处理,代码如下:

/// <summary>/// 消息接受处理函数/// </summary>/// <param name="m"></param>protected override void DefWndProc(ref Message m){switch (m.Msg){case WM_COPYDATA: COPYDATASTRUCT cds = new COPYDATASTRUCT(); Type t = cds.GetType(); cds = (COPYDATASTRUCT)m.GetLParam(t); string strResult = cds.dwData.ToString() + ":" + cds.lpData;AppendText(strResult);//强制退出if (strResult == "1:SelfKill"){Thread.Sleep(1000);this.mainNotifyIcon.Dispose();Application.Exit();}break; default: base.DefWndProc(ref m); break; }}

在B进程退出前,只要把 NotifyIcon.Dispose() , 那么任务栏托盘图标就会自动消失了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。