Hej Här är ett exempel på ett program som gör det. Stort tack till MS, du är en grym klippa....SendMessage
Är det nån som kan ge mig ett bra exempel på hur man kan skicka en sträng från en applikation till en annan med hjälp av SendMessage. Det jag skulle vilja göra är att skicka vidare en commandline till en redan startad applikation?
Alltså:
1, hur skickar jag?
2, hur tar jag emot?Sv: SendMessage
<code>
// singleinstance.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
struct COPYDATASTRUCT
{
public IntPtr dwData;
public uint cbData;
public IntPtr lpData;
}
class MyForm : Form
{
public MyForm(string fileName)
{
Text = "My App";
OpenFile( fileName );
}
internal void OpenFile(string fileName)
{
// öppna filen här
MessageBox.Show( "Öppnar " + fileName );
}
protected override void WndProc(ref Message m)
{
if ( m.Msg == (int)MyApp.WM_COPYDATA ) {
COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam( typeof(COPYDATASTRUCT) );
if ( cds.dwData == MyApp.MSG_OPENFILE ) {
string fileName = Marshal.PtrToStringUni( cds.lpData );
Debug.Assert( 2 * (1 + fileName.Length) == cds.cbData );
OpenFile( fileName );
}
}
base.WndProc( ref m );
}
}
class MyApp
{
internal const uint WM_COPYDATA = 0x4A;
internal static readonly IntPtr MSG_OPENFILE = (IntPtr)1; // valfritt värde
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[STAThread]
static void Main(string[] args)
{
if ( args.Length == 0 )
return;
Process[] existing = Process.GetProcessesByName( "singleinstance" );
Process me = Process.GetCurrentProcess();
Process other = null;
foreach ( Process p in existing )
if ( p.Id != me.Id && p.MainWindowHandle != IntPtr.Zero ) {
other = p;
break;
}
if ( other != null ) {
COPYDATASTRUCT cds;
cds.dwData = MSG_OPENFILE;
IntPtr p = Marshal.StringToHGlobalUni( args[0] );
cds.lpData = p;
cds.cbData = (uint)(2 * (args[0].Length + 1));
SendMessage( other.MainWindowHandle, WM_COPYDATA, IntPtr.Zero, ref cds );
SetForegroundWindow( other.MainWindowHandle );
Marshal.FreeHGlobal( p );
return;
}
Application.Run( new MyForm( args[0] ) );
}
}
</code>
Tyvärr är Process klassen rätt slö, och Process.GetProcessesByName() kan förlänga starttiden märkbart, så du kan ju fundera på att använda något annat sätt för att indikera att en instans av programmet redan körs, t.ex. en global mutex.
MSSv: SendMessage
Har försökt ändra lite så att det skall passa. Har även försökt lägga till en Mutex med identifieraren som blir pathen där .exe:n ligger, så man kan starta flera instanser av samma exe, så länge det inte är samma... (kollar iofs bara att det om man kör in med argument)
<code>
static void Main(string[] args)
{
string m_UniqueIdentifier = Application.ExecutablePath.Replace("\\", "_");
System.Threading.Mutex m_Mutex = new System.Threading.Mutex(false, m_UniqueIdentifier);
//Process me = Process.GetCurrentProcess();
if ( args.Length == 0 )
{
Application.Run(new Form1());
}
else
{
if(m_Mutex.WaitOne(1,true))
{
//first instance
Application.Run(new Form1(args[0]));
}
else //another process is running
{
string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
Process[] existing = Process.GetProcessesByName(assemblyName );
Process me = Process.GetCurrentProcess();
Process other = null;
foreach ( Process p in existing )
if ( p.Id != me.Id && p.MainWindowHandle != IntPtr.Zero )
{
other = p;
break;
}
if ( other != null )
{
COPYDATASTRUCT cds;
cds.dwData = MSG_OPENFILE;
IntPtr p = Marshal.StringToHGlobalUni( args[0] );
cds.lpData = p;
cds.cbData = (uint)(2 * (args[0].Length + 1));
SendMessage( other.MainWindowHandle, WM_COPYDATA, IntPtr.Zero, ref cds );
SetForegroundWindow( other.MainWindowHandle );
Marshal.FreeHGlobal( p );
return;
}
}
}
}
</code>
Jag vet inte om det finns några smartare sätt att på tag WindowHandle för det andra fönstret, men kom fram till att jag inte kunde använda FindWindow eftersom jag tillåter flera fönster... annars hade ju det varit ett alternativ. Jag är grymt nöjd med detta iallafall. Tack igen MS