2

異なる資格情報を持つ同じWebページを同時に表示できるWPF(または問題を解決できる場合はWindowsフォーム)をtpで構築したいと思います(複雑なユーザーアクションフローを持つ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ブラウザコントロールにログインすると、2番目のWebブラウザコントロールにもログインします。クッキーが現在のユーザーと共有されているためだと思います。

WebBrowserクラスのドキュメントをチェックインしましたが、有用なものは何も見つかりませんでした。

どうすれば目標を達成できますか?

1つのWebブラウザを他のWebブラウザから「分離」することは可能ですか?

ユーザーコントロールを「偽装」することは可能ですか?一部のアプリケーション(主にWebブラウザー)がさまざまなプロセスを生成しているように、別のアカウントでプロセスを「生成」してメインウィンドウに表示できますか?

Webページを操作する必要がないことに注意してください。アプリケーションのタブを変更することでユーザーを切り替えたいだけです(ユーザーごとに1つのタブ)。

PS:私はInternet Explorerエンジンに固執していません。代替ブラウザで解決策が存在する場合は、私に知らせてください

PS:ターゲットアプリケーションは2つの認証メカニズムを使用します。ユーザーは、Windowsアカウント、またはカスタムフォームベースの認証で認証できます。必要に応じて、フォーム認証のみを使用できます(プラグインできる場合は、別のCookieコンテナーがその役割を果たします)。

[編集]他のユーザーの資格情報を使用してInternetExplorerの新しいインスタンスを生成し、その親をWindowsフォームホストの1つに設定して、プロセスのメインウィンドウをアタッチしようとしました。ただし、これは非常に信頼性が低くなります(プロセスがクラッシュすることが多く、IEの既存のインスタンスが実行されていると機能しないなど)。

4

1 に答える 1

2

わかりました、 Simon Mourrierの以前の回答の助けを借りて、最終的に目標を達成する方法を見つけました。

カスタム ユーザー コントロールを作成しました。

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
        }
}

私は少しカンニングする必要があります:

  • 内部 IE セッション共有を避けるために、起動-noframemerging時に追加する必要があります。IExplore.exe
  • プロセスを起動した後、少し眠る必要があります。正確な理由はわかりませんが、MainWindowHandle数ミリ秒後にプロパティが変更されます (iexplore には、既存のプロセスに接続するか、新しいハンドルを使用して新しいプロセスを生成するなどのブートストラップ プロセスがあると思います)。

入力パラメーターを受け入れるようにユーザー コントロールを拡張する必要がありますが (URL はハードコードされています)、アイデアはここにあります。アプリ自体に集中するしかありません。

于 2012-06-28T11:01:04.220 に答える