创建一个应用程序,对同一个 Web 应用程序具有多个视图,但使用不同的凭据?
Posted
技术标签:
【中文标题】创建一个应用程序,对同一个 Web 应用程序具有多个视图,但使用不同的凭据?【英文标题】:Create an application, with multiple view to the same Web application, but with different credentials? 【发布时间】:2012-06-26 13:26:15 【问题描述】:我希望构建一个 WPF(或 Windows 窗体,如果它可以解决问题),它可以同时显示具有不同凭据的同一网页(它是具有复杂用户操作流的 Web 应用程序的测试工具)。
到目前为止,我有一个非常简单的 WPF 应用程序:
<Window x:Class="TestTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<WebBrowser Margin="8" Source="http://theapptotest" />
<WebBrowser Margin="8" Source="http://theapptotest" Grid.Column="1" />
</Grid>
</Window>
这不是应用程序的目标布局,但可以测试我的目标是否可行。
正如预期的那样,该应用程序并排显示同一个 Web 应用程序。但是,如果我登录第一个 Web 浏览器控件,则第二个也会登录。我猜这是因为 cookie 是为当前用户共享的。
我查看了WebBrowser class documentation,但没有发现任何有用的信息。
我怎样才能达到我的目标?
是否可以将一个浏览器与其他浏览器“隔离”?
是否可以“模拟”用户控件?就像一些应用程序(主要是网络浏览器)产生不同的进程一样,我可以在不同的帐户下“产生”进程并将其显示在我的主窗口中吗?
请注意,我不必与网页交互。我只想通过更改我的应用程序的一个选项卡(每个用户一个选项卡)来切换用户。
PS:我不坚持使用 Internet Explorer 引擎,如果存在替代浏览器的解决方案,请告诉我
PS:目标应用程序使用两种身份验证机制。用户可以使用 Windows 帐户或基于自定义表单的身份验证进行身份验证。如果需要,我只能使用表单身份验证(如果我可以插入单独的 cookie 容器,则可以完成这项工作)。
[编辑] 我尝试使用其他用户凭据生成 Internet Explorer 的新实例,然后通过将其父窗口设置到我的一个 Windows 窗体主机来附加进程主窗口。然而,这是非常不可靠的(进程经常崩溃,如果任何现有的 IE 实例正在运行,则无法工作,等等。
【问题讨论】:
你确定是因为cookies吗?会话 cookie?持久性cookies?这可能会影响解决方案。例如,假设目标站点的身份验证是基于 IP 的(即使这是一个愚蠢的想法),那么解决方案会有所不同。 目标应用程序是一个asp.net应用程序(实际上是一个sharepoint应用程序)。它使用标准的 asp.net 身份验证行为(如果我没记错的话,使用一些 cookie,混合持久性和会话 cookie)。但是,我不知道当用户使用 Windows 凭据进行身份验证时这是如何表现的。我只能依靠表单身份验证,所以如果我不得不忘记 Windows 身份验证,这不会是一个问题 您是否尝试在此处描述的窗口之一中调用 ClearAuthenticationCache:blogs.msdn.com/b/ieinternals/archive/2010/04/05/…? 如何使用 webbrowser 控件发送此命令?而且,我不是它会有所帮助。如前所述,the ClearAuthenticationCache command clears ALL session cookies, Authentication, and Client Certificates for ALL sites running in the current session
。然而,有一些有趣的事情。如果运行“iexplore.exe -nomerge”,生成的 IE 将被隔离。我可以运行两个IE实例,并在两个IE中分别登录。仍然必须找到一种方法将其嵌入我的应用程序中。
【参考方案1】:
好的,在Simon Mourrier previous answer的帮助下,我终于找到了实现目标的方法。
我创建了一个自定义用户控件:
Xaml 部分:
<UserControl x:Class="WpfApplication1.AppIsolatedView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" SizeChanged="UserControl_SizeChanged"
d:DesignHeight="300" d:DesignWidth="300" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded">
<Grid>
<WindowsFormsHost Margin="12" Name="windowsFormsHost1" />
</Grid>
</UserControl>
后面有这段代码:
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
public partial class AppIsolatedView : UserControl
public AppIsolatedView()
InitializeComponent();
_panel = new System.Windows.Forms.Panel();
windowsFormsHost1.Child = _panel;
string url = "http://theapptotest";
System.Windows.Forms.Panel _panel;
Process _process;
private void UserControl_Loaded(object sender, RoutedEventArgs e)
if (IsInDesignModeStatic) return; // Avoid consumer of the control to explode when in design mode
ProcessStartInfo psi = new ProcessStartInfo("iexplore.exe", "-noframemerging -private \"" + url + "\"");
_process = Process.Start(psi);
_process.WaitForInputIdle();
Thread.Sleep(2000);
SetParent(_process.MainWindowHandle, _panel.Handle);
// remove control box
int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
// resize embedded application & refresh
ResizeEmbeddedApp();
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
if (_process != null)
_process.Refresh();
_process.Close();
private void ResizeEmbeddedApp()
if (_process == null)
return;
SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
protected override Size MeasureOverride(Size availableSize)
Size size = base.MeasureOverride(availableSize);
ResizeEmbeddedApp();
return size;
private static bool? _isInDesignMode;
/// <summary>
/// Gets a value indicating whether the control is in design mode (running in Blend
/// or Visual Studio).
/// </summary>
public static bool IsInDesignModeStatic
get
if (!_isInDesignMode.HasValue)
#if SILVERLIGHT
_isInDesignMode = DesignerProperties.IsInDesignTool;
#else
var prop = DesignerProperties.IsInDesignModeProperty;
_isInDesignMode
= (bool)DependencyPropertyDescriptor
.FromProperty(prop, typeof(FrameworkElement))
.Metadata.DefaultValue;
#endif
return _isInDesignMode.Value;
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
ResizeEmbeddedApp();
#region pinvoke stuff
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOACTIVATE = 0x0010;
private const int GWL_STYLE = -16;
private const int WS_CAPTION = 0x00C00000;
private const int WS_THICKFRAME = 0x00040000;
#endregion
我不得不作弊:
我必须在触发IExplore.exe
时添加-noframemerging
以避免内部IE 会话共享。
在启动进程后我必须睡一会儿。不知道确切原因,但 MainWindowHandle
属性在几毫秒后发生了变化(我猜 iexplore 有一个引导进程来连接到现有进程或产生一个新进程,使用新句柄或类似的东西)。李>
我仍然需要扩展用户控件以接受输入参数(url 是硬编码的),但想法就在这里。我只需要专注于应用程序本身。
【讨论】:
仍然需要一些改进...在应用程序关闭后,Internet Explorer 的实例仍然存在于任务管理器中。 哇 :-) 如果您要走这条路(如果没有其他选择,为什么不走),您可能还想查看 UI 自动化(请参阅此处的其他答案:@987654322 @) 这将允许您在外部进程中控制 IE(或任何其他应用程序)的某些部分。至少对强制它退出很有用。 如果有更好的解决方案,我会很高兴听到它:)。幸运的是,我唯一的目标是简化需要多个用户登录的复杂 Web 应用程序的测试。如果测试人员必须在会话开始时手动输入 8 个密码,我可以忍受。以上是关于创建一个应用程序,对同一个 Web 应用程序具有多个视图,但使用不同的凭据?的主要内容,如果未能解决你的问题,请参考以下文章