国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#編程中設置程序只可被運行一次的方法

2020-01-24 01:22:50
字體:
來源:轉載
供稿:網友

防止程序運行多個實例的方法有多種,如:通過使用互斥量和進程名等.而我想要實現的是:在程序運行多個實例時激活的是第一個實例,使其獲得焦點,并在前端顯示.

主要用到兩個API 函數:

ShowWindowAsync 該函數設置由不同線程產生的窗口的顯示狀態。
SetForegroundWindow 該函數將創建指定窗口的線程設置到前臺,并且激活該窗口。鍵盤輸入轉向該窗口,并為用戶改各種可視的記號。系統給創建前臺窗口的線程分配的權限稍高于其他線程。
代碼如下:
引用以下命名空間:

using System.Runtime.InteropServices;using System.Diagnostics;using System.Reflection;//***************************************************** static class Program  {    /// <summary>    /// 該函數設置由不同線程產生的窗口的顯示狀態。    /// </summary>    /// <param name="hWnd">窗口句柄</param>    /// <param name="cmdShow">指定窗口如何顯示。查看允許值列表,請查閱ShowWlndow函數的說明部分。</param>    /// <returns>如果函數原來可見,返回值為非零;如果函數原來被隱藏,返回值為零。</returns>    [DllImport("User32.dll")]    private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);    /// <summary>    /// 該函數將創建指定窗口的線程設置到前臺,并且激活該窗口。鍵盤輸入轉向該窗口,并為用戶改各種可視的記號。系統給創建前臺窗口的線程分配的權限稍高于其他線程。    /// </summary>    /// <param name="hWnd">將被激活并被調入前臺的窗口句柄。</param>    /// <returns>如果窗口設入了前臺,返回值為非零;如果窗口未被設入前臺,返回值為零。</returns>    [DllImport("User32.dll")]    private static extern bool SetForegroundWindow(IntPtr hWnd);    private const int WS_SHOWNORMAL = 1;    /// <summary>    /// 應用程序的主入口點。    /// </summary>    [STAThread]    static void Main()    {      Application.EnableVisualStyles();      Application.SetCompatibleTextRenderingDefault(false);      Process instance = RunningInstance();      if (instance == null)      {        Form1 frm = new Form1();        Application.Run(new Form1());      }      else      {        HandleRunningInstance(instance);      }    }    /// <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("/", "http://") == current.MainModule.FileName)          {            return process;          }        }      }      return null;    }    /// <summary>    /// 顯示已運行的程序。    /// </summary>    public static void HandleRunningInstance(Process instance)    {      ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL); //顯示,可以注釋掉      SetForegroundWindow(instance.MainWindowHandle);      //放到前端    }  }

實現讓程序只能打開一個實例(其他方法)

//=====創建互斥體法:=====bool blnIsRunning;Mutex mutexApp = new Mutex(false, Assembly.GetExecutingAssembly().FullName, out  blnIsRunning);if (!blnIsRunning){  MessageBox.Show("程序已經運行!", "提示",  MessageBoxButtons.OK, MessageBoxIcon.Exclamation);  return;}  //保證同時只有一個客戶端在運行  System.Threading.Mutex mutexMyapplication = new System.Threading.Mutex(false, "OnePorcess.exe");if (!mutexMyapplication.WaitOne(100, false)){  MessageBox.Show("程序" + Application.ProductName + "已經運行!", Application.ProductName,  MessageBoxButtons.OK, MessageBoxIcon.Error);  return;}//=====判斷進程法:(修改程序名字后依然能執行)=====Process current = Process.GetCurrentProcess();Process[] processes = Process.GetProcessesByName(current.ProcessName);foreach (Process process in processes){  if (process.Id != current.Id)  {    if (process.MainModule.FileName    == current.MainModule.FileName)    {      MessageBox.Show("程序已經運行!", Application.ProductName,      MessageBoxButtons.OK, MessageBoxIcon.Exclamation);      return;    }  }}

實現程序自重啟
程序運行過程中,不能有多個實例運行,并且需要程序自己可以重啟(重新運行),所以代碼如果下代碼:

static void Main() {   bool createNew;   using (System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName, out createNew))   {     if (createNew)     {       Application.EnableVisualStyles();       Application.SetCompatibleTextRenderingDefault(false);       Application.Run(new Form1());     }     else     {       MessageBox.Show("Only one instance of this application is allowed!");     }   } }Boolean createdNew; //返回是否賦予了使用線程的互斥體初始所屬權System.Threading.Mutex instance = new System.Threading.Mutex(true, "MutexName", out createdNew); //同步基元變量if (createdNew) //賦予了線程初始所屬權,也就是首次使用互斥體{Application.Run(new Form1()); /s/這句是系統自動寫的instance.ReleaseMutex();}else{MessageBox.Show("已經啟動了一個程序,請先退出!","系統提示",MessageBoxButtons.OK,MessageBoxIcon.Error);Application.Exit();}

用以上代碼實現了禁止多重啟動的功能。
同時程序關閉重啟是通過下面的代碼實現的:

Process.Start(Process.GetCurrentProcess().ProcessName + ".exe");Application.Exit();

這時就出現一個問題,程序自動關閉重啟的時候就會提示已經啟動了一個程序了。
請問應該怎么解決?
關閉之后過一會兒再啟動是沒問題的。
但是現在自動關閉,自動重啟有的時候能成功,有的時候就被禁止多重啟動的那個截住了。
那就必須手動重新啟動了。
比如,點【重新啟動】按鈕的時候執行以下代碼:

Process.Start(Process.GetCurrentProcess().ProcessName + ".exe");Application.Exit();

這時它是先啟動一個新的Process然后才退出當前程序。
這時就會在Program.cs里遇到禁止多重啟動的那段代碼。就不能自動啟動了。
解決方案:
解決方法一:
一般程序:
因為進程還沒有中止,還占在內存中所以才會報錯.
出現這種原因的情況可能是:使用多線程,其中的線程沒有執行結束,也沒有被置為后臺線程,所以雖然應用程序關閉,但進程仍駐留在內存中.
可以使用Application.ExitThread();中止進程中的所有線程.
也可以在進程執行中獲得進程的ID,然后通過Process.GetProcessById()獲得這個進程,然后將它Kill掉,再啟動新的進程.

解決方法二:
要不就在用戶點[重新啟動]時,把mutex先釋放掉?可能需要把那個mutex變量做成一個global,這樣你在兩個地方都能訪問到。然后在程序退出時(Application.Run下面那一句),檢查一下如果mutex已經被釋放了,就不要再釋放了。

解決方法三:
或者就在點[重新啟動]時再設另外一個不同的信號量,當第二個程序重入時如果看到這個信號量說明是自動重啟的情況,就不報錯而直接正常往下走了。這個信號量可以在第一個程序[重新啟動]那里執行完后再釋放,不過應該也可以在整個程序退出時檢查一下如果存在就釋放。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武夷山市| 桐梓县| 上饶市| 年辖:市辖区| 翁源县| 疏附县| 青田县| 利津县| 江西省| 察哈| 麟游县| 色达县| 郧西县| 宁乡县| 长葛市| 沛县| 陵川县| 靖边县| 乐陵市| 太保市| 大足县| 明水县| 罗甸县| 根河市| 武陟县| 长沙县| 金堂县| 珠海市| 晋宁县| 临澧县| 阳山县| 班戈县| 广宁县| 平阳县| 江都市| 土默特左旗| 双城市| 揭东县| 天镇县| 浦北县| 乌海市|