WPF: Setting source to Browser control prevents application from recieveing the arguments.

Anudeep Garge 1 Reputation point
2021-06-25T05:33:13.14+00:00

On setting source in WebBrowserControl , the app stops receiving arguments passed from command line.

Usage:

  1. run the exe from commandline : BrowserArgsIgnore.exe
  2. Minimize the window
  3. try passing a arguments again with BrowserArgsIgnore.exe "Testing"

Please find the code below. I have also attached zip.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace BrowserArgsIgnore
{
internal static class UnsafeNative
{
public const int WM_COPYDATA = 0x004A;

    public static string GetMessage(int message, IntPtr lParam)
    {
        if (message == UnsafeNative.WM_COPYDATA)
        {
            try
            {
                var data = Marshal.PtrToStructure<UnsafeNative.COPYDATASTRUCT>(lParam);
                var result = string.Copy(data.lpData);
                return result;
            }
            catch
            {
                return null;
            }
        }

        return null;
    }

    public static void SendMessage(IntPtr hwnd, string message)
    {
        var messageBytes = Encoding.Unicode.GetBytes(message); /* ANSII encoding */
        var data = new UnsafeNative.COPYDATASTRUCT
        {
            dwData = IntPtr.Zero,
            lpData = message,
            cbData = messageBytes.Length + 1 /* +1 because of \0 string termination */
        };

        if (UnsafeNative.SendMessage(hwnd, WM_COPYDATA, IntPtr.Zero, ref data) != 0)
            throw new Win32Exception(Marshal.GetLastWin32Error());
    }

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

    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);

    [StructLayout(LayoutKind.Sequential)]
    private struct COPYDATASTRUCT
    {
        public IntPtr dwData;
        public int cbData;

        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpData;
    }
}

}

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace BrowserArgsIgnore
{

public static class Program
{
    /// <summary>
    ///  Main
    /// </summary>
    /// <param name="args"></param>
    [STAThread]
    public static void Main(string[] args)
    {
        var proc = Process.GetCurrentProcess();
        var processName = proc.ProcessName.Replace(".vshost", "");
        var runningProcess = Process.GetProcesses()
            .FirstOrDefault(x => (x.ProcessName == processName || x.ProcessName == proc.ProcessName || x.ProcessName == proc.ProcessName + ".vshost") && x.Id != proc.Id);

        if (runningProcess == null)
        {
            var app = new App();
            var window = new MainWindow();
            MainWindow.HandleParameter(args);
            app.Run(window);
            return; // In this case we just proceed on loading the program
        }

        if (args.Length > 0)
            UnsafeNative.SendMessage(runningProcess.MainWindowHandle, string.Join(" ", args));
    }
}

<Application x:Class="BrowserArgsIgnore.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BrowserArgsIgnore">
<Application.Resources>

</Application.Resources>

</Application>

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{

}

}

<Window x:Class="BrowserArgsIgnore.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BrowserArgsIgnore"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

    <TextBlock x:Name="textBlock" Text="Try minimize the window & pass arguments from commandline" />

    <WebBrowser Grid.Row="1" Source="https://www.google.com">

    </WebBrowser>
</Grid>

</Window>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace BrowserArgsIgnore
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += (s, e) =>
{
MainWindow.WindowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
HwndSource.FromHwnd(MainWindow.WindowHandle)?.AddHook(new HwndSourceHook(HandleMessages));
};
}

    public static IntPtr WindowHandle { get; private set; }

    private static IntPtr HandleMessages(IntPtr handle, int message, IntPtr wParameter, IntPtr lParameter, ref Boolean handled)
    {
        if (handle != MainWindow.WindowHandle)
            return IntPtr.Zero;

        var data = UnsafeNative.GetMessage(message, lParameter);

        if (data != null)
        {
            if (Application.Current.MainWindow == null)
                return IntPtr.Zero;

            if (Application.Current.MainWindow.WindowState == WindowState.Minimized)
                Application.Current.MainWindow.WindowState = WindowState.Normal;

            UnsafeNative.SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);

            var args = data.Split(' ');
            HandleParameter(args);
            handled = true;
        }

        return IntPtr.Zero;
    }

    public static void HandleParameter(string[] args)
    {
        if (Application.Current?.MainWindow is MainWindow mainWindow)
        {
            if (args != null && args.Length > 0)
            {
                mainWindow.textBlock.Text = $"Article Id: {args[0]}";
            }
            else
            {
                //  mainWindow.textBlock.Text = "Trying:" + string.Join("\r\n", args);
                if (args.Length > 0)
                {
                    mainWindow.textBlock.Text = $"Article Id: {args[0]}";
                    //mainWindow.WebBrowserControl.Navigate(new Uri(link, UriKind.RelativeOrAbsolute));
                    //mainWindow.Back.IsEnabled = mainWindow.WebBrowserControl.CanGoBack;
                }

            }
        }
    }
}

}

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,670 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,234 questions
{count} votes