关于wpf WebBrowser传递参数的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于wpf WebBrowser传递参数的问题相关的知识,希望对你有一定的参考价值。

如果一个WPF ,右边是一个WebBrowser,我左边选中关键词,就给右边的WebBrowser的uri赋值,地址是我本地自定义的一个html页面,并且我还需要把关键词传过去,

但是这样写报错了,

传参的标识符问号被当成了非法字符,去掉问号和后面的参数就能够成功运行了,我想问是不是WPF的WebBrowser不支持这样传参,还有我应该怎样实现这个需求,把关键词成功传到html页面

有一个变通方法,通过WebBrowser的InvokeScript方法来传递参数到html页面。 参考技术A 那么上面这段路径可否直接用浏览器打开呢?感觉你有点混淆了概念了,要带参数访问网页必须是网页在运行状态,也就是最好用IIS发布后。而上面这个路径只是一堆磁盘上的文件,还不能被访问。

WPF WebBrowser Memory Leak 问题及临时解决方法

首先介绍一下内存泄漏(Memory Leak)的概念,内存泄露是指程序中已动态分配的堆内存由于某种原因未释放或者无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

最近在使用WPF WebBrowser时,就遇到了Memory Leak的问题。

在主窗体上通过一个按钮点击事件加载包含有WebBrowser控件的窗体,使用这个WebBrowser来浏览网页,然后调用WebBrowser的Dispose()方法,然后调用GC.Collect(),最后关闭当前包含有WebBrowser控件的窗体。

通过下面的代码和步骤来还原这个问题。

MainWindow.xaml

    <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
        <Button Content="Launch Browser Window" x:Name="btnLaunchNewWindow" Margin="5,0,5,0" Click="btnLaunchNewWindow_Click" />
        <Button Content="Force Garbage Collection" x:Name="btnForceGarbageCollection"  Click="btnForceGarbageCollection_Click" />
        <Button Content="Quit" x:Name="btnQuit" Click="btnQuit_Click" />
    </StackPanel>
        private void btnLaunchNewWindow_Click(object sender, RoutedEventArgs e)
        {
            new BrowserWindow().Show();
        }

        private void btnForceGarbageCollection_Click(object sender, RoutedEventArgs e)
        {
            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();
            System.GC.Collect();
        }

        private void btnQuit_Click(object sender, RoutedEventArgs e)
        {
            Environment.Exit(0);
        }

BrowserWindow.xaml

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal">
            <Label Content="URL:" />
            <TextBox x:Name="txtURL" Width="400" />
        </StackPanel>

        <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,10">
            <Button Content="1. Go/Navigate" x:Name="btnGo"  Click="btnGo_Click" />
            <Button Content="2. Dispose"  x:Name="btnClose"  Click="btnClose_Click" Margin="10,0" />
            <Button Content="3. Force Garbage Collection"  x:Name="btnForceGarbageCollection"  Click="btnForceGarbageCollection_Click" />
            <Button Content="4. Close Window"  x:Name="closeWindow" Click="closeWindow_Click"  Margin="10,0" />
        </StackPanel>

        <WebBrowser Grid.Row="2" x:Name="webBrowser" />
    </Grid>
        private void btnGo_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                webBrowser.Navigate(new Uri(txtURL.Text));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Exception: " + ex.Message);
            }
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            webBrowser.Dispose();
        }

        private void btnForceGarbageCollection_Click(object sender, RoutedEventArgs e)
        {
            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();
            System.GC.Collect();
        }

        private void closeWindow_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

问题重现步骤:
Step1: 启动程序
Step2: “Launch Browser Window”
Step3: 在地址栏输入 http://www.msn.com (其他网址也可以)
Step4: 点击“1. Go/Navigate” button,
Step5: 当网页加载成功后,点击 “2. Dispose”
Step6: 点击 ”3. Force Garbage Collection”
Step7: 点击“4. Close Window”

重复Step2--Step7 20-25次。

多次测试后的结果如下:
在Step1程序启动后,内存占用在20M左右(不同的机器会有一些差别),

重复Step2--Step7 20-25次之后,程序的内存在130M左右,并且长时间等待不释放。

很不幸运的遇到一个内存泄露的问题。

和大多数WPF控件不一样,WebBrowser控件继承自HwndHost,使用的是非托管的资源,所以对WebBrowser进行Dispose()操作并不管用。

第一种解决方法:

早前使用过WinForm的WebBrowser控件,不存在内存泄露的问题,所以决定使用WinForm的WebBrowser代替WPF的。关于如何在WPF中承载WinForm控件,请参考https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/walkthrough-hosting-a-windows-forms-control-in-wpf

第二种解决方法:
依然使用WPF WebBrowser,但是将第二个页面(BrowserWindow.xaml)单独成一个exe。通过主程序去调用,这样当网页浏览完毕后,关闭WebBrowser所在exe,它所关联的内存全部被释放掉了。如果两个程序之间需要通信或者交换数据,可以选用WCF/命名管道等方式。

参考链接:
https://stackoverflow.com/questions/2069314/memory-leak-when-using-wpf-webbrowser-control-in-multiple-windows
https://stackoverflow.com/questions/8302933/how-to-get-around-the-memory-leak-in-the-net-webbrowser-control

以上是关于关于wpf WebBrowser传递参数的问题的主要内容,如果未能解决你的问题,请参考以下文章

解决使用webbrowser请求url时数据传递丢失问题

传递给命令 WPF 的多个参数 [重复]

WPF 利用Process.Start()方法启动指定路径下的exe文件并传递参数接收参数

WPF在单击复选框时传递多个参数

将命令行参数从 VB 传递到 C# WPF 应用程序

关于使用Webbrowser打开PPT的问题