Ouvrir des pages web dans une application WPF avec CefSharp : serveur proxy et interaction JavaScript

Cet article décrit comment intégrer un navigateur web dans une application WPF (développée avec Visual Studio 2010 et C#) à l'aide de CefSharp, afin d'ouvrir des pages web tout en respectant deux contraintes :

  • L'ordinateur ne doit pouvoir accéder à Internet qu'à travers un serveur proxy spécifique (via le réseau local), et uniquement pour cette application.
  • Le code JavaScript de la page web doit pouvoir appeler des méthodes du code C# (passage de données dans les deux sens).

CefSharp est un composant .NET qui fournit un navigateur Chrome embarqué utilisable dans les applications WPF ou WinForms.

  1. Configuration de l'environnement et installation des packages NuGet

Si vous avez besoin d'une solution simple pour afficher une page web existante, vous pouvez vous référer à d'autres tutoriels. Ici, nous allons au‑delà en intégrant également des interactions JavaScript ⇔ C# et un proxy.

Le gestionnaire de packages NuGet est nécessaire pour charger CefSharp et ses dépendances. Après installation (par exemple NuGet.Tools pour VS2010), ouvrez votre projet dans Visual Studio.

Créez un nouveau projet WPF (par exemple NavigateurEmbarque). Dans le menu Outils, sélectionnez Gestionnaire de packages NuGetGérer les packages NuGet pour la solution. Recherchez en ligne CefSharp.Wpf et CefSharp.Common et installez‑les. (Pour WinForms, remplacez par CefSharp.WinForms). L'installation peut prendre un certain temps. Le dossier packages apparaîtra à la racine du projet.

  1. Configuration du proxy et initialisation du navigateur

Dans le code de la fenêtre principale (MainWindow.xaml et MainWindow.xaml.cs), nous ajoutons une zone de texte pour l'URL et un bouton de navigation. L'essentiel est de configurer le proxy avant d'initialiser CefSharp.

<!-- MainWindow.xaml -->
<Window x:Class="NavigateurEmbarque.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Navigateur Embarqué" Height="350" Width="800"
        WindowStartupLocation="CenterScreen" Loaded="Window_Loaded">
    <Grid>
        <DockPanel>
            <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
                <TextBlock Text="Adresse web :" Margin="5"/>
                <TextBox x:Name="txtAdresse" Width="350" Margin="5"/>
                <Button Content="Ouvrir" Margin="5" Click="OnOuvrirClick" IsDefault="True"/>
            </StackPanel>
            <Grid x:Name="GrillePrincipale">
            </Grid>
        </DockPanel>
    </Grid>
</Window>

// MainWindow.xaml.cs
using System;
using System.Windows;
using CefSharp;

namespace NavigateurEmbarque
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // URL par défaut
            txtAdresse.Text = "http://www.example.com/";

            // Configuration du proxy
            var config = new CefSettings();
            config.CefCommandLineArgs.Add("--proxy-server", "http://192.168.1.100:3128");

            // Initialisation unique de CefSharp
            Cef.Initialize(config, true, false);
        }

        private void OnOuvrirClick(object sender, RoutedEventArgs e)
        {
            string url = txtAdresse.Text;
            if (!string.IsNullOrWhiteSpace(url))
            {
                var page = new PageAfficheur(url);
                GrillePrincipale.Children.Insert(0, page);
            }
        }
    }
}

Remarque importante : La méthode Cef.Initialize ne doit être appelée qu'une seule fois. Placez‑la dans le constructeur de l'application ou dans l'événement Startup du fichier App.xaml.cs. De plus, avant la fermeture de l'application, appelez Cef.Shutdown() pour éviter que le processus reste en arrière‑plan.

  1. Contrôle utilisateur pour l'affichage de la page web et l'interaction JavaScript

Créez un nouveau contrôle utilisateur PageAfficheur.xaml contenant un masque de chargement et un conteneur pour le navigateur.

<!-- PageAfficheur.xaml -->
<UserControl x:Class="NavigateurEmbarque.PageAfficheur"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Name="ctrlPage">
    <Grid x:Name="GrilleConteneur">
        <local:MasqueChargement x:Name="masqueAttente"/>
    </Grid>
</UserControl>

// PageAfficheur.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using CefSharp;
using CefSharp.Wpf;

namespace NavigateurEmbarque
{
    public partial class PageAfficheur : UserControl
    {
        public PageAfficheur(string url)
        {
            InitializeComponent();

            var navigateur = new ChromiumWebBrowser();
            // Enregistrement d'un objet accessible depuis JavaScript
            navigateur.RegisterJsObject("pont", new ObjetRappelPourJs());

            navigateur.Loaded += (s, e) =>
            {
                masqueAttente.Visibility = Visibility.Collapsed;
            };

            GrilleConteneur.Children.Insert(0, navigateur);
            navigateur.Address = url;
        }
    }

    // Classe exposée au JavaScript
    public class ObjetRappelPourJs
    {
        public string envoyerMessage(string message)
        {
            // Exemple : retourner un message à la page web
            return "Message reçu depuis C# : " + message;
        }
    }
}

Notez que l'interface IRequestHandler n'est pas implémentée ici car l'interaction JavaScript ne nécessite pas de gestionnaire de requêtes. Si vous avez besoin de gérer l'authentification proxy, implémentez‑le.

  1. Interaction avec une page web JavaScript

Créez un fichier HTML test.html (placez‑le dans le dossier de sortie, par exemple bin\Debug) :

<html>
<head><title>Page de test</title></head>
<body>
    <h1>Interaction CefSharp</h1>
    <button onclick="lancerAppel()">Tester</button>
    <p id="resultat"></p>
    <script type="text/javascript">
        function lancerAppel() {
            var reponse = pont.envoyerMessage("123");
            document.getElementById("resultat").innerText = reponse;
        }
    </script>
</body>
</html>

Pour charger cette page locale, modifiez l'URL par défaut dans MainWindow_Loaded :

string chemin = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
chemin = chemin.Replace("NavigateurEmbarque.vshost.exe", "test.html");
txtAdresse.Text = chemin;

  1. Masque de chargement

Le contrôle MasqueChargement affiche simplement un texte pendant le chargement. Créez MasqueChargement.xaml :

<UserControl x:Class="NavigateurEmbarque.MasqueChargement"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid Opacity="0.85">
        <TextBlock Text="Chargement de la page..." 
                   VerticalAlignment="Center" HorizontalAlignment="Center"/>
    </Grid>
</UserControl>

Le code‑behind est vide, seul le constructeur appelle InitializeComponent().

  1. Problèmes courants et résoultion

  • Erreur « Impossible de charger CefSharp.Core.dll » : installez le runtime Visual C++ 2013 (vcredist_x86.exe pour 32 bits, vcredist_x64.exe pour 64 bits).
  • Dans les propriétés du projet, ciblez la plateforme x86 (ou x64 selon l'architecture de votre système).
  • Si la compilation échoue, ouvrez le Gestionnaire de configurations (clic droit sur la solution → Propriétés → Configuration) et créez la plateforme x86. Vous devrez peut‑être supprimer une plateforme existante et la recréer.
  • Après changement de plateforme, vérifiez le chemin de sortie dans les propriétés du projet : il doit être bin\Debug (et non bin\x86\Debug).
  • Shutdown : ajoutez un gestionnaire d'arrêt de l'application qui appelle Cef.Shutdown() pour éviter que le processus reste en mémoire.

Étiquettes: CefSharp WPF .NET Proxy JavaScript interop

Publié le 26 juin à 02h09