ho fatto qualche progetto-modello che implementa questa roba, utilizzando Windows-messaging. Il modello è enorme e contiene alcune altre cose (come la localizzazione, gli aggiornamenti, formclosing, appunti e un'interfaccia per i documenti, in questo modo le azioni nella MDI possono essere facilmente inoltrate ai figli MDI). Se si desidera visualizzare il modello, provare this link (o this link)
Parte del codice:
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;
}
}
Funziona anche quando si lanciano fino a 15 file contemporaneamente.
Hai provato a verificare i processi attualmente in esecuzione nel sistema e se il tuo programma è già in esecuzione forse gli passa qualche informazione? Per chiarire, lo fai all'inizio del tuo programma prima di mostrare un'interfaccia utente e se c'è un'istanza basta passarci le informazioni e chiudere la nuova istanza –
@Jafar Kofahi - Grazie per la risposta. Sulla base del tuo commento, sembra che una seconda istanza del programma dovrebbe iniziare brevemente, controllare se il file può essere passato a un'altra istanza in esecuzione, quindi passare il file e spegnere se trovato. Ci ho pensato, ma il programma è abbastanza grande. Suppongo che stavo cercando un modo per dire a Windows di non avviare un'altra istanza, quindi ottenere una notifica in qualche modo se l'utente ha fatto doppio clic sul file associato. – user1689175
In genere questo viene implementato utilizzando [applicazioni a singola istanza] (http://stackoverflow.com/questions/424368/opening-a-known-file-type-into-running-stance-of-custom-app-net), che non è quello che vuoi Dai un'occhiata a questo - [Qual è il metodo più semplice per la comunicazione tra processi tra processi 2 C#?] (Http://stackoverflow.com/questions/528652/what-is-the-simplest-method-of-inter-process- comunicazione-tra-2-c-sharp-pro). – Neolisk