程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#編程中設置法式只可被運轉一次的辦法

C#編程中設置法式只可被運轉一次的辦法

編輯:C#入門知識

C#編程中設置法式只可被運轉一次的辦法。本站提示廣大學習愛好者:(C#編程中設置法式只可被運轉一次的辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是C#編程中設置法式只可被運轉一次的辦法正文


避免法式運轉多個實例的辦法有多種,如:經由過程應用互斥量和過程名等.而我想要完成的是:在法式運轉多個實例時激活的是第一個實例,使其取得核心,並在前端顯示.

重要用到兩個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.WordStr("/", "\\") == 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曾經被釋放了,就不要再釋放了。

處理辦法三:
或許就在點[從新啟動]時再設別的一個分歧的旌旗燈號量,當第二個法式重入時假如看到這個旌旗燈號量解釋是主動重啟的情形,就不報錯而直接正常往下走了。這個旌旗燈號量可以在第一個法式[從新啟動]那邊履行完後再釋放,不外應當也能夠在全部法式加入時檢討一下假如存在就釋放。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved