一个例子:
如果您打开并运行Visual Studio(2010),然后双击PC桌面上的misc * .cs文件,该文件将在当前运行的Visual Studio实例中打开,而不是打开VS的另一个实例
如何让我自己的C#程序模仿这种行为?
换句话说,如果我的文件类型如* .myfile与我的程序相关联,并且用户在Windows资源管理器中双击* .myfile,并且.... 我的程序已在运行 .....它应该在没有Windows启动程序的另一个实例的情况下打开文件。如果程序没有运行,那么Windows可以正常启动实例。
请注意,我的程序的多个实例是允许的 - 与Visual Studio相同。
任何建议都将不胜感激!!
答案 0 :(得分:3)
如果您查看注册表中注册的.cs文件的内容,您将看到它不是Visual Studio。对于Express版本,例如注册的应用程序是'VCSExpress.exe',工作室正在'WDExpress.exe'中运行。在高级版本中,我认为该工作室以'devenv.exe'运行。有趣的是,有两个应用程序:您的UI应用程序和一种启动器应用程序。我不知道VS是怎么做到的,但我可以想象这样:启动器通过任何类型的进程间通信与UI进行通信,例如:命名管道。 (See here)也许试试这个:
答案 1 :(得分:0)
自从我做这样的事情已经差不多20年了,但是IIRC,你做了这样的事情:
如果在创建窗口之前执行这些步骤,它应该像您想要的那样。
答案 2 :(得分:0)
我使用windows-messaging制作了一些实现这些东西的项目模板。 模板很大,包含一些其他内容(如本地化,更新,formclosing,剪贴板和文档界面,这样MDI中的操作可以很容易地转发给MDI子项)。 如果您想查看模板,请尝试this link(或this link)
部分代码:
Win32.cs:
public partial class Win32
{
//public const int WM_CLOSE = 16;
//public const int BN_CLICKED = 245;
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;
}
}
}
[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);
}
的Program.cs:
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
{
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];
}
[STAThread]
static void Main()
{
if (mutex.WaitOne(TimeSpan.Zero, true))
{
#region standaard
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#endregion
#region Culture instellen
string cult = CultureInfo.CurrentCulture.Name;
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cult);
Thread.CurrentThread.CurrentCulture = new CultureInfo(cult);
#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(600);
hwnd = MainWindowHandle;
}
if (hwnd != 0)
{
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();
}
}
}
}
}
MainFrom.cs:
[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;
}
}
一次最多可以启动15个文件,它甚至可以使用。