UPD: added MCVE.
This is an educational task. I have to use SendMessage() function:
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd,
uint wMsg, UIntPtr wParam, IntPtr lParam);
I have to make two different applications with GUI communicationg by messages. After getting message like "start" 1 app have to start sendinding message "Ask value" to 2 app each 5 seconds. And 2 app send to 1 app message "Send value" with some data.
1 app is WinForms program:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Oven_Monitor
{
public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentProcessId();
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam);
private uint askMessageID = RegisterWindowMessage("Ask value");
private uint dataMessageID = RegisterWindowMessage("Send value");
private uint registerMessageID = RegisterWindowMessage("Register sensor");
public Form1() {
InitializeComponent();
this.Text = "Really rare title";
}
public void checkSensors() {
while (true) {
SendMessage(secondAppHWnd, askMessageID, (UIntPtr)0, (IntPtr)0);
System.Threading.Thread.Sleep(500);
}
}
private IntPtr secondAppHWnd;
protected override void WndProc(ref Message m) {
if (m.Msg == registerMessageID) {
secondAppHWnd = m.LParam;
Thread tr = new Thread(checkSensors);
tr.Start();
} else if (m.Msg == dataMessageID) {
//do some stuff
}
base.WndProc(ref m);
}
}
}
2 app is console project, but it requires System.Windows.Forms referens:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace HeatSensor
{
class Program
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
static void Main(string[] args)
{
IntPtr mainAppHandle = FindWindow(null, "Really rare title");
while (mainAppHandle == IntPtr.Zero)
{
Console.ReadKey();
mainAppHandle = FindWindow(null, "Really rare title");
}
HiddenForm form = new HiddenForm(mainAppHandle);
while (true) //it's actually not infinit
{
//do some stuff
}
}
}
}
And hidden form class:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace HeatSensor
{
public partial class HiddenForm : Form
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
static private IntPtr mainAppHandle;
public HiddenForm(IntPtr mainAppHWnd)
{
InitializeComponent();
mainAppHandle = mainAppHWnd;
string title = System.DateTime.Now.ToLongDateString();
title += System.DateTime.Now.ToLongTimeString();
title += System.DateTime.Now.Ticks.ToString();
this.Text = title;
this.CreateHandle();
int currentWindowHandle = (int)FindWindow(null, title);
SendMessage(mainAppHandle, RegisterWindowMessage("Register sensor"),
(UIntPtr)0, currentWindowHandle);
}
private uint askMessageID = RegisterWindowMessage("Ask value");
private uint dataMessageID = RegisterWindowMessage("Send value");
private uint registerMessageID = RegisterWindowMessage("Register sensor");
protected override void WndProc(ref Message m)
{
if (m.Msg == askMessageID)
{
SendMessage(mainAppHandle, dataMessageID, (UIntPtr)1, (IntPtr)1);
}
base.WndProc(ref m);
}
}
}
For some reason this programs act strange. Almost everytime 2 app don't getting sended "Ask value" message, sometimes checkSensors() send 1-3 messages and stop.
What is wrong?
Both HWnd is correct.
Update: I tried to check error here:
public void checkSensors() {
while (true) {
SendMessage(secondAppHWnd, askMessageID, (UIntPtr)0, (IntPtr)0);
int error = Marshal.GetLastWin32Error();
System.Threading.Thread.Sleep(500);
}
}
And see. As SendMessage was performed, this thread was blocked (what means, SendMessage was not copleted. After i closed 2 app, thread was unblocked and i got 164 error (ERROR_MAX_THRDS_REACHED: No more threads can be created in the system.). What it's supposed to mean?
Also, added:
protected override void WndProc(ref Message m)
{
//here is all message checks
int erro2r = Marshal.GetLastWin32Error();
if (erro2r != 0) {
int j; //stop to debug here
}
base.WndProc(ref m);
}
And it just constantly return 1400 ERROR_INVALID_WINDOW_HANDLE (i don't send any messages at that moment).
So it looks totaly unclear to me.
update 2: If i call it from WndProc(), everything works:
SendMessage(secondAppHWnd, askMessageID, (UIntPtr)0, (IntPtr)0);
But i need to send this message from different thread each 5 seconds.
So, it finally works if both programs is WinForms projects. I can just run console window from 2 app and hide main window.
Related
I'm currently trying to inject a library into a program I made(for learning purpose, it's just curiosity). I think I managed to do it, but it seems the code i did is laking of entry point maybe ?
this is the code I wrote :
I used visual studio code to generate a kind of hello-world dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace InjectDll
{
public class Inject
{
[DllImport("kernel32")]
static extern bool AllocConsole();
public Inject()
{
AllocConsole();
Console.WriteLine("blablabla");
}
public string test()
{
AllocConsole();
return "dll is injected";
}
}
}
I then made a basic program I where wanted to test my injection =>
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace basicProgram
{
class Program
{
static void Main(string[] args)
{
while(true){
Thread.Sleep(1000);
Console.WriteLine("Hello world");
}
}
}
}
So now I have my dll and the program i wanted to try my injection.I just had to write the injector, and this is what I did =>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace injectorTest.Inject
{
public enum DllInjectionResult
{
DllNotFound,
GameProcessNotFound,
InjectionFailed,
Success
}
class Injector
{
static readonly IntPtr INTPTR_ZERO = (IntPtr)0;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
//[DllImport("InjectDll.dll", CallingConvention = CallingConvention.StdCall)]
private const string DLL_NAME = "hello.dll";
private Process myProcess;
private string myPath;
public Injector()
{
}
public Injector(Process myProcess)
{
this.myProcess = myProcess;
this.myPath = Path.GetDirectoryName(myProcess.MainModule.FileName);
}
private void checkDll()
{
if (!File.Exists(myPath + #"\hello.dll")) {
}
}
public DllInjectionResult inject()
{
if (!File.Exists(myPath + "\\hello.dll"))
{
return DllInjectionResult.DllNotFound;
}
Console.WriteLine("process id : " + myProcess.Id);
if (myProcess == null)
{
return DllInjectionResult.GameProcessNotFound;
}
if (!startInject((uint)myProcess.Id, myPath + "\\hello.dll"))
{
return DllInjectionResult.InjectionFailed;
}
return DllInjectionResult.Success;
}
private bool startInject(uint processId, string dllPath)
{
IntPtr handleProcess = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, processId);
if (handleProcess == INTPTR_ZERO)
{
return false;
}
IntPtr lpAddress = VirtualAllocEx(handleProcess, (IntPtr)null, (IntPtr)dllPath.Length, (0x1000 | 0x2000), 0X40);
Console.WriteLine("lpaddr: " + lpAddress);
if (lpAddress == INTPTR_ZERO)
{
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(dllPath);
if (WriteProcessMemory(handleProcess, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
if (lpLLAddress == INTPTR_ZERO)
{
return false;
}
var remoteThread = CreateRemoteThread(handleProcess, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null);
if (remoteThread == INTPTR_ZERO)
{
return false;
}
CloseHandle(handleProcess);
return true;
}
}
}
It doesn't seems to fail i can see via ida (watching the helloworld program i tried to inject) that LoadLibraryW is trigered when I launch my injector (I then can see the path of the dll injected but it doesn't seems to trigger smthg.
It seems like I missing something (like an entry point in my dll maybe ?).
A normal C/C++ DLL will have a DllMain which gets executed when LoadLibrary is called which then passes through to a switch statement, normally we put our code inside the DLL_PROCESS_ATTACH case which will get executed on injection.
This equivalent doesn't exist in C#/CLR but you can do something tricky to make the same effect by using static constructors.
Make a class and initialize an object of that class, this will in turn call the static constructor. Something like this:
class someClass
{
//Static constructor
static someClass()
{
Console.WriteLine("injected");
}
}
I am trying to receive messages from QCollector as explained in the QCollector Data Interface developer guide. The process consists of registering predefined messages, finding the QCollector server window, and exchanging data through the registered messages.
My WndProc callback receives lost of messages, but none of those are recognized as one of the registered messages. I'm passing my Form's this.Handle in the request, but I'm unsure if this is correct.
What am I doing wrong?
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HistDataManager
{
public partial class Form1 : Form
{
[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string sClass, string sWindow);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam);
int nWinHandle = FindWindow("QCDataInterfaceWndClass", null);
uint wm_QCollectorClientDataRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_DATA_REQUEST");
uint wm_QCollectorClientPortfolioListRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_PORTFOLIO_LIST_REQUEST");
uint wm_QCollectorPortfolioListRequestComplete = RegisterWindowMessage("QCOLLECTOR_PORTFOLIO_LIST_REQUEST_COMPLETE ");
public void TestQC()
{
SendMessage(new IntPtr(nWinHandle), wm_QCollectorClientPortfolioListRequest, UIntPtr.Zero, this.Handle);
}
protected override void WndProc(ref Message m)
{
Console.WriteLine(m.HWnd + "," + m.Msg + "," + m.LParam + "," + m.WParam);
base.WndProc(ref m);
if (m.Msg == wm_QCollectorClientPortfolioListRequest || m.Msg == wm_QCollectorPortfolioListRequestComplete)
{
Console.WriteLine("Message from specified application found!");
}
}
}
}
EDIT 1:
Just to be sure that I have the basics working in c# I created a second version of this app and got them to talk to each other. This works, so I know my handles and message structures are correct.
BUT I never get a response from qCollector. Does anyone have experience of using this in any other language perhaps? I suspect qCollector was written in c++.
I dont know if it is fine in .Net but i would like to suggest you to call all the functions in either constructor or in init() function.
Suggested Design
int nWinHandle=0;
uint wm_QCollectorClientDataRequest=0;
uint wm_QCollectorClientPortfolioListRequest=0;
uint wm_QCollectorPortfolioListRequestComplete=0;
void init()
{
nWinHandle = FindWindow("QCDataInterfaceWndClass", null);
wm_QCollectorClientDataRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_DATA_REQUEST");
wm_QCollectorClientPortfolioListRequest = RegisterWindowMessage("QCOLLECTOR_CLIENT_PORTFOLIO_LIST_REQUEST");
wm_QCollectorPortfolioListRequestComplete = RegisterWindowMessage("QCOLLECTOR_PORTFOLIO_LIST_REQUEST_COMPLETE ");
}
As beginner lesson I want to port this tutorial http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/ to a Windows Form Application.
This should show a user what keys are pressed inside a label called 'lblMessage'.
I have separeted the code now into two pieces.
Form1.cs
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public GlobalKeyHook hook = new GlobalKeyHook();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Origin
// _hookID = SetHook(_proc);
hook._hookID = hook.SetHook(_proc);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Origin
// UnhookWindowsHookEx(_hookID);
hook.UnhookWindowsEx(_hookID);
}
}
}
GlobalKeyHook.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
namespace WindowsFormsApplication3
{
class GlobalKeyHook : Form
{
#region DLLs
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
#region Fields and delegation
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
public static IntPtr _hookID = IntPtr.Zero;
public delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
#endregion
public GlobalKeyHook()
{
IntPtr hookID = _hookID;
LowLevelKeyboardProc proc = _proc;
}
static Form form = new Form();
#region Methods
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
form.Text = vkCode.ToString();
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
public static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
#endregion
}
}
But I am not able to use the public static IntPtr _hookID, the method SetHook() or the DLL UnhookWindowsHookEx in the Form1 class. Is it not possible to use this "types" from another class?
Not sure this will solve all your problems but may help you avoid a few of them down the line.
If this is .net 4.0 or higher your SetWindowsHookEX() call will likely return 0 (it failed) because .net no longer emulates a native module for managed dlls. To fix this you can add a DllImport for LoadLibrary() like this:
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
Then somewhere before you call SetWindowsHookEX() do this:
IntPtr hinstDLL = UnsafeMethods.LoadLibrary("user32.dll");
and call SetWindowsHookEX() like this:
SetWindowsHookEx(WH_KEYBOARD_LL, proc,
hinstDLL, 0);
Basically SetWindowsHookEX() needs a valid module handle which it verifies but never actually uses it. the reason to load user32 is that since you are p/invoking functions from it you def have it.
Also, in your constructor just set it to IntPtr.Zero. No need make _hookID if you always are setting it to IntPtr.Zero. It is also worth noting that if the computer you are running this on has less than win7sp1 using IntPtr.Zero won't work (99% sure at least.)
I would strongly suggest you check out This set of hooks They have a decent implementation of a hook library that you can easily extend however you want.
You need to set your GlobalKeyHook class to public class GlobalKeyHook.
I'm using the Sopcast activex plugin (sopocx.ocx) in one of my C# applications.
I would like to retrieve the player status ("Buffering the channel", "Playing the channel", "Channel Offline...") and the buffering percentage. Both of these informationss are displayed on the player (I tried to post a picture but I don't have enough reputation yet).
The problem is the Sopcast activex plugin doesn't provide any methods in order to retrieve these informations.
Does someone has any idea on how this could be done??
GetWindowText results in an empty string...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
private void testToolStripMenuItem_Click(object sender, EventArgs e)
{
IntPtr hwnd = sopcast.Handle;
StringBuilder lpString = new StringBuilder(256);
GetWindowText(hwnd, lpString, 256);
MessageBox.Show(lpString.ToString());
}
private void playToolStripMenuItem_Click(object sender, EventArgs e)
{
sopcast.SetSopAddress("sop://broker.sopcast.com:3912/123456789");
sopcast.SetChannelName("Channel");
sopcast.Play();
}
}
}
You can identify Id control and get text with api windows
here a code sample (replace notepad by your application name) the most important for you is to get from your application a way to get ID control of your ocx window
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Security;
namespace Application
{
public class Program
{
public static void Main ( )
{
IntPtr hwnd = UnsafeNativeMethods.FindWindow("Notepad", null);
StringBuilder stringBuilder = new StringBuilder(256);
UnsafeNativeMethods.GetWindowText(hwnd, stringBuilder, stringBuilder.Capacity);
Console.WriteLine(stringBuilder.ToString());
}
}
[SuppressUnmanagedCodeSecurity]
internal static class UnsafeNativeMethods
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern int GetWindowText ( IntPtr hWnd, [Out] StringBuilder lpString, int nMaxCount );
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr FindWindow ( string lpClassName, string lpWindowName );
}
}
I download sopcast and try to get status using spy++:
As you see, caption is status not the channel...
so you can not get it easier
the handle you have catched is for the whole control
Sopcast draws the status text using DrawText (i found out using API Monitor http://www.rohitab.com/apimonitor). So there is no way of getting the text using conventional GetWindowText function or similar. I was able to obtain the text by hooking DrawText function. For .NET EasyHook will enable you to do this.
My scenario:
I have a winforms app that hosts the activex control and i want to obtain the status text.
public class hooklocal : EasyHook.IEntryPoint
{
[DllImport("user32.dll")]
static extern int DrawText(IntPtr hDC, string lpString, int nCount, IntPtr lpRect, uint uFormat);
[UnmanagedFunctionPointer(CallingConvention.StdCall,CharSet = CharSet.Auto,SetLastError = true)]
delegate int DDrawText(IntPtr hDC, string lpString, int nCount, IntPtr lpRect, uint uFormat);
int DrawTextH(IntPtr hDC, string lpString, int nCount, IntPtr lpRect, uint uFormat)
{
//lpString contains the status text
return DrawText(hDC, lpString, nCount, lpRect, uFormat);
}
public hooklocal()
{
try
{
var CreateHook = LocalHook.Create(
LocalHook.GetProcAddress("user32.dll", "DrawTextW"),
new DDrawText(DrawTextH),
this);
CreateHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
}
catch (Exception ExtInfo)
{
Debugger.Break();
}
}
}
To use, instantiate hooklocal class in a new thread at program startup.
EasyHook download
https://easyhook.github.io/downloads.html
I have an WPF application called app1 which has a windows named window1. When the user clicks the close button of window1, the app does not close but the window1 hides (this.hide()).
I want to check if another instance of the application is already running when it is started; if so, I want to show the already running instance and terminate the new one.
How can I do that?
I know how to check the process and how to close the current app but I don't know how to show a window from another WPF process which is running...
In my App startup event I do this :
private void Application_Startup(object sender, StartupEventArgs e)
{
if(Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1)
{
Application.Current.Shutdown(0);
}
}
A typical approach to this is to use a Mutex. This allows you to prevent a second instance from being started (or rather, detect it within the second instance of the application).
At that point, you can notify the original application instance to "show" itself. Here is a good article describing the entire process in detail (though using Windows Forms).
For a WPF application, you'll need to put this logic in the Application's startup logic, and add an HwndSourceHook to process the windows message in your WPF window which you want to have show.
I found how to do the work!
My problem solved with "Reed Copsey" help and with Windows SendMessage API.
for doing this thing I wrote these codes in my window1.xaml.cs file :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Interop;
namespace app1
{
public partial class window1: Window
{
public window1()
{
InitializeComponent();
}
private void window1_Loaded(object sender, RoutedEventArgs e)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
System.Windows.Forms.Message m = System.Windows.Forms.Message.Create(hwnd, msg, wParam, lParam);
if (m.Msg == WM_COPYDATA)
{
// Get the COPYDATASTRUCT struct from lParam.
COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
// If the size matches
if (cds.cbData == Marshal.SizeOf(typeof(MyStruct)))
{
// Marshal the data from the unmanaged memory block to a
// MyStruct managed struct.
MyStruct myStruct = (MyStruct)Marshal.PtrToStructure(cds.lpData,
typeof(MyStruct));
// Display the MyStruct data members.
if (myStruct.Message == "Show Up")
{
this.Show();
}
}
}
return IntPtr.Zero;
}
internal const int WM_COPYDATA = 0x004A;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct MyStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Message;
}
[StructLayout(LayoutKind.Sequential)]
internal struct COPYDATASTRUCT
{
public IntPtr dwData; // Specifies data to be passed
public int cbData; // Specifies the data size in bytes
public IntPtr lpData; // Pointer to data to be passed
}
}
}
And I wrote these codes in my App.xaml.cs :
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Windows.Threading;
using System.Runtime.InteropServices;
using System.Security;
namespace app1
{
public partial class App : Application
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct MyStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Message;
}
internal const int WM_COPYDATA = 0x004A;
[StructLayout(LayoutKind.Sequential)]
internal struct COPYDATASTRUCT
{
public IntPtr dwData; // Specifies data to be passed
public int cbData; // Specifies the data size in bytes
public IntPtr lpData; // Pointer to data to be passed
}
[SuppressUnmanagedCodeSecurity]
internal class NativeMethod
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
IntPtr wParam, ref COPYDATASTRUCT lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}
private void Application_Startup(object sender, StartupEventArgs e)
{
if (System.Diagnostics.Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Count() > 1)
{
IntPtr hTargetWnd = NativeMethod.FindWindow(null, "window1");
if (hTargetWnd == IntPtr.Zero)
{
return;
}
MyStruct myStruct;
myStruct.Message = "Show Up";
int myStructSize = Marshal.SizeOf(myStruct);
IntPtr pMyStruct = Marshal.AllocHGlobal(myStructSize);
try
{
Marshal.StructureToPtr(myStruct, pMyStruct, true);
COPYDATASTRUCT cds = new COPYDATASTRUCT();
cds.cbData = myStructSize;
cds.lpData = pMyStruct;
NativeMethod.SendMessage(hTargetWnd, WM_COPYDATA, new IntPtr() , ref cds);
int result = Marshal.GetLastWin32Error();
if (result != 0)
{
}
}
finally
{
Marshal.FreeHGlobal(pMyStruct);
}
Application.Current.Shutdown(0);
}
}
}
}
And that's it. :D