本文介绍如何在程序入口处控制运行一次EXE,再次启动只会激活并刷新已运行例程。
刷新数据通过启动参数来传递,本文启动参数传递的是一个文件路径,详看代码:
入口处:
- static class Program
- {
- /// <summary>
- /// 应用程序的主入口点。
- /// </summary>
- [STAThread]
- static void Main( string[] args )
- {
- Application.EnableVisualStyles( );
- Application.SetCompatibleTextRenderingDefault( false );
- //通过启动参数获取文件路径
- string filePath = string.Empty;
- if ( args.Length > 0 )
- {
- filePath = args[0];
- for ( int i = 1 ; i < args.Length ; i++ )
- {
- filePath += string.Format( " {0}" , args[i] );
- }
- }
- //获取当前例程
- Process instance = RunningInstance( );
- if ( instance == null ) //第一次启动
- {
- if ( string.IsNullOrEmpty( filePath ) )
- {
- Application.Run( new FrmMain( "default path.." ) );
- }
- else
- {
- Application.Run( new FrmMain( filePath ) );
- }
- }
- else //已有例程在运行,激活并传送数据
- {
- if ( !string.IsNullOrEmpty( filePath ) )
- {
- IntPtr strPtr = Marshal.StringToHGlobalAnsi( filePath );
- COPYDATASTRUCT copyData;
- copyData.dwData = 0;
- copyData.cbData = (uint)System.Text.Encoding.Default.GetByteCount(
- filePath.ToCharArray( ) , 0 , filePath.Length );
- copyData.lpData = strPtr;
- IntPtr ptr = Marshal.AllocHGlobal( (IntPtr)( Marshal.SizeOf( copyData ) ) );
- Marshal.StructureToPtr( copyData , ptr , true );
- //给主窗体发送消息,传递新文件路径
- FrmMain.SendMessage( instance.MainWindowHandle , FrmMain.WM_COPYPATH , -1 , (int)ptr );
- }
- HandleRunningInstance( instance ); //激活已运行例程
- }
- }
- /// <summary>
- /// 获取当前例程
- /// </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 )
- {
- //确保例程从EXE文件运行
- if ( Assembly.GetExecutingAssembly( ).Location.Replace( "/" , "//" ) == current.MainModule.FileName )
- {
- //返回另一个例程实例
- return process;
- }
- }
- }
- return null;
- }
- /// <summary>
- /// 激活已运行例程
- /// </summary>
- public static void HandleRunningInstance( Process instance )
- {
- //确保窗口没有被最小化或最大化
- ShowWindowAsync( instance.MainWindowHandle , WS_SHOWNORMAL );
- //设置真实例程为foreground window
- SetForegroundWindow( instance.MainWindowHandle );
- }
- [DllImport( "User32.dll" )]
- private static extern bool ShowWindowAsync( IntPtr hWnd , int cmdShow );
- [DllImport( "User32.dll" )]
- private static extern bool SetForegroundWindow( IntPtr hWnd );
- private const int WS_SHOWNORMAL = 1;
- }
- struct COPYDATASTRUCT
- {
- public uint dwData;
- public uint cbData;
- public IntPtr lpData;
- }
主窗体:
- public partial class FrmMain : Form
- {
- [System.Runtime.InteropServices.DllImport( "User32.dll " )]
- public static extern int SendMessage( IntPtr hWnd , uint Msg , int wParam , int lParam );
- public const int WM_COPYPATH = 0x004A;
- private string FILE_PATH;
- public FrmMain( string path )
- {
- InitializeComponent( );
- this.FILE_PATH = path;
- }
- protected override void WndProc( ref Message m )
- {
- switch ( m.Msg )
- {
- case WM_COPYPATH:
- COPYDATASTRUCT copyData = (COPYDATASTRUCT)Marshal.PtrToStructure(
- (IntPtr)m.LParam , typeof( COPYDATASTRUCT ) );
- string path = string.Empty;
- //接收从入口处传过来的新文件路径
- if ( copyData.lpData != IntPtr.Zero )
- {
- path = Marshal.PtrToStringAnsi( copyData.lpData , (int)copyData.cbData );
- }
- // 在这里进行界面数据的刷新
- // this.FILE_PATH = path;
- break;
- }
- base.WndProc( ref m );
- }
- }