Wrox
Wrox

Reputation: 73

PostMessage from windows service

My issue is PostMessage windows API is not working properly as it works when running from console application.

Working code:

I have 2 application [1] is console application [2] Windows Forms application.

Requirement is I want to send message to all the running instances of application.

console application code:

class Program
{
    #region Dll Imports
    public const int HWND_BROADCAST = 0xFFFF;

    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);
    #endregion Dll Imports

    public static readonly int WM_ACTIVATEAPP = RegisterWindowMessage("CLOSE");

    static void Main(string[] args)
    {
            //we tried to create a mutex, but there's already one (createdNew = false - another app created it before)
            //so there's another instance of this application running
        Process currentProcess = Process.GetCurrentProcess();

        //get the process that has the same name as the current one but a different ID
        foreach (Process process in Process.GetProcessesByName("ClientApp1"))
        {
            if (process.Id != currentProcess.Id)
            {
                IntPtr handle = process.MainWindowHandle;

                //if the handle is non-zero then the main window is visible (but maybe somewhere in the background, that's the reason the user started a new instance)
                //so just bring the window to front
                //if (handle != IntPtr.Zero)
                    //SetForegroundWindow(handle);
                //else
                    //tough luck, can't activate the window, it's not visible and we can't get its handle
                    //so instead notify the process that it has to show it's window
                    PostMessage((IntPtr)HWND_BROADCAST, WM_ACTIVATEAPP, IntPtr.Zero, IntPtr.Zero);//this message will be sent to MainForm

                break;
            }
        }

    }
}

Windows Forms application code:

 public partial class Form1 : Form
{
    #region Dll Imports
    public const int HWND_BROADCAST = 0xFFFF;

    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

    [DllImport("user32")]
    public static extern int RegisterWindowMessage(string message);
    #endregion Dll Imports

    public static readonly int WM_ACTIVATEAPP = RegisterWindowMessage("CLOSE");

    public Form1()
    {
        InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        //someone (another process) said that we should show the window (WM_ACTIVATEAPP)
        if (m.Msg == WM_ACTIVATEAPP)
            this.Close();
    }
}

Above code is working as expected.

My issues start from here. I want to run the same code from windows service instead of console application. Need immediate guidance.

It seems when I run this code from windows service its not getting hold of the process or service runs in different account so message is not getting delivered.

Upvotes: 0

Views: 1708

Answers (1)

PepitoSh
PepitoSh

Reputation: 1836

Most probably you run your service as Local System account in session 0 and it is rather isolated for good reasons. For example you don't have access to other desktops/sessions.

You have to implement a different IPC method, e.g. pipes or memory mapped files.

Upvotes: 6

Related Questions