WPF: Setting source to Browser control prevents application from recieveing the arguments.
On setting source in WebBrowserControl , the app stops receiving arguments passed from command line.
Usage:
- run the exe from commandline : BrowserArgsIgnore.exe
- Minimize the window
- 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;
}
}
}
}
}
}