0

我想创建一个使用 ClickOnce 进行安装并注册文件关联的程序,并且始终只启动一个实例,这样如果再次单击该文件扩展名的文件,它将被发送到第一个(已经打开的)程序.

有人知道如何做到这一点的好代码示例吗?

请记住 ClickOnce 部分 - 因为这会改变处理 SingleInstance 位的方式。

4

5 回答 5

1

您应该使用 Mutex 来检查您的应用程序是否正在运行:

    static void Main()
    {
        bool createdNew;

        using (Mutex mutex = new Mutex(true, Application.ProductName, out createdNew))
        {
            mutex.ReleaseMutex();
            if (createdNew)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new FormMain());
            }
            else
            {
                using (Process currentProcess = Process.GetCurrentProcess())
                {
                    foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))
                    {
                        if (process.Id != currentProcess.Id)
                        {
                            User32.SetForegroundWindow(process.MainWindowHandle);
                            break;
                        }
                    }
                }
            }
        }
    }

设置前景窗口:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SetForegroundWindow(IntPtr hWnd);
于 2009-12-14T17:23:51.163 回答
1

我想这会对你有所帮助:http ://www.openwinforms.com/single_instance_application.html

于 2009-12-14T14:36:18.520 回答
0

同样的问题在这里:如何使用 Click Once 构建单实例应用程序?

试试这个: http: //northhorizo​​n.net/2010/single-instance-clickonce/

于 2010-08-31T04:32:24.540 回答
0

我制作了一个以这种方式工作的应用程序。它使用 Windows 消息进行通信。所以在第二个实例中,您只需要第一个实例中的 MainForm 的句柄。我将此句柄保存在名为 hwnd 的 ClickOnce 设置中。

using ProjectApplicationTemplate.Properties;
using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.Hosting;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace ProjectApplicationTemplate
{
    static class Program
    {
        static Mutex mutex = new Mutex(true, guid());
        static string guid()
        {
            // http://stackoverflow.com/questions/502303/how-do-i-programmatically-get-the-guid-of-an-application-in-net2-0
            Assembly assembly = Assembly.GetExecutingAssembly();
            var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
            return attribute.Value;
        }

        static int MainWindowHandle
        {
            get
            {
                Settings.Default.Reload();
                return Settings.Default.hwnd;
            }
            set
            {
                Settings sett = Settings.Default;
                sett.hwnd = value;
                sett.Save();
            }
        }
        public static string GetFileName()
        {
            ActivationArguments a = AppDomain.CurrentDomain.SetupInformation.ActivationArguments;
            // aangeklikt bestand achterhalen
            string[] args = a == null ? null : a.ActivationData;
            return args == null ? "" : args[0];
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            if (mutex.WaitOne(TimeSpan.Zero, true))
            {
                #region standaard
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                #endregion
                MainForm frm = new MainForm();
                MainWindowHandle = (int)frm.Handle;
                Application.Run(frm);
                MainWindowHandle = 0;
                mutex.ReleaseMutex();
            }
            else
            {
                int hwnd = 0;
                while (hwnd == 0)
                {
                    Thread.Sleep(5);
                    hwnd = MainWindowHandle;
                }

                Win32.CopyDataStruct cds = new Win32.CopyDataStruct();
                try
                {
                    string data = GetFileName();
                    cds.cbData = (data.Length + 1) * 2; // number of bytes
                    cds.lpData = Win32.LocalAlloc(0x40, cds.cbData); // known local-pointer in RAM
                    Marshal.Copy(data.ToCharArray(), 0, cds.lpData, data.Length); // Copy data to preserved local-pointer
                    cds.dwData = (IntPtr)1;
                    Win32.SendMessage((IntPtr)hwnd, Win32.WM_COPYDATA, IntPtr.Zero, ref cds);
                }
                finally
                {
                    cds.Dispose();
                }
            }
        }
    }
}

在你的 MainForm

using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Windows.Forms;

namespace ProjectApplicationTemplate
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            OpenFile(Program.GetFileName());
        }

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case Win32.WM_COPYDATA:
                    Win32.CopyDataStruct st = (Win32.CopyDataStruct)Marshal.PtrToStructure(m.LParam, typeof(Win32.CopyDataStruct));
                    string strData = Marshal.PtrToStringUni(st.lpData);
                    OpenFile(strData);
                    Activate();
                    break;
                default:
                    // let the base class deal with it
                    base.WndProc(ref m);
                    break;
            }
        }

        void OpenFile(string filename)
        {
            if (filename == "") return;
            if (!File.Exists(filename)) return;
            IDocument[] vensters = MdiChildren.Select(T => (IDocument)T).Where(T => T.CurrentFileName == filename).ToArray();
            if (vensters.Length == 0)
            {
                ChildForm frm = new ChildForm();
                frm.OpenFile(filename);
                frm.MdiParent = this;
                frm.Show();
            }
            else
            {
                vensters[0].Activate();
            }
        }

        private void fileMenu_DropDownOpening(object sender, EventArgs e)
        {
            IDocument active = (IDocument)ActiveMdiChild;
            if (active == null)
            {
                saveToolStripMenuItem.Enabled = false;
                saveAsToolStripMenuItem.Enabled = false;
                printToolStripMenuItem.Enabled = false;
                printSetupToolStripMenuItem.Enabled = false;
                printPreviewToolStripMenuItem.Enabled = false;
            }
            else
            {
                saveToolStripMenuItem.Enabled = active.Changed;
                saveAsToolStripMenuItem.Enabled = true;
                printToolStripMenuItem.Enabled = active.CanPrint;
                printSetupToolStripMenuItem.Enabled = active.CanPrint;
                printPreviewToolStripMenuItem.Enabled = active.CanPrint;
            }

            // fill the MRU-list

            tmiOnlangsGeopend.DropDownItems.Clear();
            string RecentFolder = Environment.GetFolderPath(Environment.SpecialFolder.Recent);
            string[] bestanden = Directory.GetFiles(RecentFolder).Where(T => T.EndsWith(".text.lnk")).ToArray();
            if (bestanden.Length == 0)
            {
                tmiOnlangsGeopend.DropDownItems.Add(new ToolStripMenuItem(Properties.Resources.NoRecent) { Enabled = false });
            }
            else
            {
                foreach (string bestand in bestanden.OrderBy(T => File.GetLastWriteTime(T)).Reverse())
                {
                    ToolStripMenuItem tmi = new ToolStripMenuItem(Path.GetFileNameWithoutExtension(bestand.Substring(0, bestand.Length - 4)));
                    tmi.Click += delegate { OpenFile(ResolveShortCut(bestand)); };
                    tmiOnlangsGeopend.DropDownItems.Add(tmi);
                }
            }
        }

        string ResolveShortCut(string shc)
        {
            // Add Reference -> COM -> Windows Script Host Object Model
            if (File.Exists(shc))
            {
                IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
                IWshRuntimeLibrary.IWshShortcut link = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(shc);
                return link.TargetPath;
            }
            else
            {
                return "";
            }
        }
    }
}

Win32.cs

using System;
using System.Runtime.InteropServices;

namespace ProjectApplicationTemplate
{
    public partial class Win32
    {
        public const int WM_COPYDATA = 0x004A;

        public struct CopyDataStruct : IDisposable
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;

            public void Dispose()
            {
                if (this.lpData != IntPtr.Zero)
                {
                    LocalFree(this.lpData);
                    this.lpData = IntPtr.Zero;
                }
            }
        }

        /// <summary>
        /// The SendMessage API
        /// </summary>
        /// <param name="hWnd">handle to the required window</param>
        /// <param name="Msg">the system/Custom message to send</param>
        /// <param name="wParam">first message parameter</param>
        /// <param name="lParam">second message parameter</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref CopyDataStruct lParam);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LocalAlloc(int flag, int size);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LocalFree(IntPtr p);

    }
}

如果有人想了解更多信息: http ://pieterjan.pro/?a=Projecten_csharp_DrawIt.php

而这个是 ac# 模板,包含大量内容: - 具有文件关联的单实例应用程序 - 本地化(在运行时也是如此) - MDI 和用于遍历用户命令的界面 - 检查更新 - 最近使用的列表

http://pieterjan.pro/Projecten/csharp/ProjectApplicationTemplate.zip

于 2016-08-16T16:22:36.977 回答
-1

你可以做类似这样的事情:

using System.Diagnostics;

    namespace Foo

    {

        class Bar

        {

            static void Main(string[] args)

            {

                Process p = Process.GetCurrentProcess();

                Process [] processSearch = Process.GetProcessesByName(p.ProcessName);

                if (processSearch.Length > 1)

                {

                    return;

                }

            }
         }
    }
于 2009-12-14T14:40:43.470 回答