WinForm防止程序重復運行的方法分析
本文實例講述了WinForm防止程序重復運行的方法。分享給大家供大家參考,具體如下:
需求:
1、點擊“關閉”按鈕時,程序最小化到托盤,并沒有退出,這時再次運行程序,不會重復運行,而是顯示已運行的程序;
2、支持不同目錄;
3、支持修改名稱。
代碼(不支持修改名稱,不支持不同目錄):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tool;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
namespace 計算器
{
static class Program
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// 該函數(shù)設置由不同線程產(chǎn)生的窗口的顯示狀態(tài)。
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指定窗口如何顯示。查看允許值列表,請查閱ShowWlndow函數(shù)的說明部分。</param>
/// <returns>如果函數(shù)原來可見,返回值為非零;如果函數(shù)原來被隱藏,返回值為零。</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
/// <summary>
/// 該函數(shù)將創(chuàng)建指定窗口的線程設置到前臺,并且激活該窗口。鍵盤輸入轉向該窗口,并為用戶改各種可視的記號。系統(tǒng)給創(chuàng)建前臺窗口的線程分配的權限稍高于其他線程。
/// </summary>
/// <param name="hWnd">將被激活并被調(diào)入前臺的窗口句柄。</param>
/// <returns>如果窗口設入了前臺,返回值為非零;如果窗口未被設入前臺,返回值為零。</returns>
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private const int SW_SHOWNORMAL = 1;
/// <summary>
/// 應用程序的主入口點。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Process processes = RunningInstance();
if (processes == null)
{
Application.Run(new Form1());
}
else
{
HandleRunningInstance(processes);
}
}
/// <summary>
/// 獲取正在運行的實例,沒有運行的實例返回null;
/// </summary>
public static Process RunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
foreach (Process process in processes)
{
if (process.Id != current.Id)
{
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
{
return process;
}
}
}
return null;
}
/// <summary>
/// 顯示已運行的程序。
/// </summary>
public static void HandleRunningInstance(Process instance)
{
try
{
IntPtr formHwnd = FindWindow(null, "計算器");
ShowWindow(formHwnd, SW_SHOWNORMAL); //顯示
SetForegroundWindow(formHwnd); //放到前端
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
代碼(支持修改名稱,支持不同目錄):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tool;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
namespace 計算器
{
static class Program
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// 該函數(shù)設置由不同線程產(chǎn)生的窗口的顯示狀態(tài)。
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指定窗口如何顯示。查看允許值列表,請查閱ShowWlndow函數(shù)的說明部分。</param>
/// <returns>如果函數(shù)原來可見,返回值為非零;如果函數(shù)原來被隱藏,返回值為零。</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
/// <summary>
/// 該函數(shù)將創(chuàng)建指定窗口的線程設置到前臺,并且激活該窗口。鍵盤輸入轉向該窗口,并為用戶改各種可視的記號。系統(tǒng)給創(chuàng)建前臺窗口的線程分配的權限稍高于其他線程。
/// </summary>
/// <param name="hWnd">將被激活并被調(diào)入前臺的窗口句柄。</param>
/// <returns>如果窗口設入了前臺,返回值為非零;如果窗口未被設入前臺,返回值為零。</returns>
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private const int SW_SHOWNORMAL = 1;
/// <summary>
/// 應用程序的主入口點。
/// </summary>
[STAThread]
static void Main()
{
Common.AutoRegister();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
bool createNew;
using (System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName, out createNew))
{
if (createNew)
{
FileOperator.SetValue("ProcessId", Process.GetCurrentProcess().Id.ToString()); //進程ID寫入文件
Application.Run(new Form1());
}
else
{
try
{
string strProcessId = FileOperator.GetValue("ProcessId"); //從文件中獲取進程ID
int processId = Convert.ToInt32(strProcessId);
Process process = Process.GetProcessById(processId);
HandleRunningInstance(process);
}
catch
{
FileOperator.SetValue("ProcessId", Process.GetCurrentProcess().Id.ToString()); //進程ID寫入文件
Application.Run(new Form1());
}
}
}
}
/// <summary>
/// 顯示已運行的程序。
/// </summary>
public static void HandleRunningInstance(Process instance)
{
try
{
IntPtr formHwnd = FindWindow(null, "計算器");
ShowWindow(formHwnd, SW_SHOWNORMAL); //顯示
SetForegroundWindow(formHwnd); //放到前端
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
其實,IntPtr formHwnd = FindWindow(null, "計算器"); 這段代碼是有BUG的,比如你打開一個名為“計算器”的文件夾,那么FindWindow找到的其實是這個文件夾,而不是計算器程序。我們可以在主窗體第一次顯示的時候,記下窗口句柄,代碼如下:
private void Form1_Shown(object sender, EventArgs e)
{
FileOperator.SetValue("hwnd", Process.GetCurrentProcess().MainWindowHandle.ToString());
}
然后,顯示已運行的程序時,從文件中讀取之前記錄的窗口句柄,代碼如下:
/// <summary>
/// 顯示已運行的程序
/// </summary>
public static void HandleRunningInstance(Process instance)
{
try
{
IntPtr hwnd = new IntPtr(Convert.ToInt32(FileOperator.GetValue("hwnd")));
ShowWindow(hwnd, SW_SHOWNORMAL); //顯示
SetForegroundWindow(hwnd); //放到前端
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
綜上,再整理一下,就能得到完美的解決方案。
更多關于C#相關內(nèi)容感興趣的讀者可查看本站專題:《WinForm控件用法總結》、《C#窗體操作技巧匯總》、《C#數(shù)據(jù)結構與算法教程》、《C#常見控件用法教程》、《C#面向對象程序設計入門教程》及《C#程序設計之線程使用技巧總結》
希望本文所述對大家C#程序設計有所幫助。
上一篇:C# for循環(huán)的經(jīng)典案例集錦
欄 目:C#教程
下一篇:淺談C#中的for循環(huán)與foreach循環(huán)
本文標題:WinForm防止程序重復運行的方法分析
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/5706.html
您可能感興趣的文章
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新聞效果的方法
- 01-10C#實現(xiàn)Winform中打開網(wǎng)頁頁面的方法
- 01-10winform實現(xiàn)創(chuàng)建最前端窗體的方法
- 01-10WinForm實現(xiàn)自定義右下角提示效果的方法
- 01-10.net2.0+ Winform項目實現(xiàn)彈出容器層
- 01-10winform 實現(xiàn)控制輸入法
- 01-10WinForm實現(xiàn)程序一段時間不運行自動關閉的方法
- 01-10Winform消除button按下出現(xiàn)的虛線簡單實現(xiàn)方法


閱讀排行
本欄相關
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實例總結
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 01-11ajax實現(xiàn)頁面的局部加載
- 04-02jquery與jsp,用jquery
- 01-10使用C語言求解撲克牌的順子及n個骰子


