DotNetBrowser uses ConfuserEx to protect its assemblies. The code protected by this solution conflicts with SmartAssembly.


During the attempt to create the SmartAssembly project with the assembly which references DotNetBrowser you can see the following error: 'Non-negative number required. Parameter name: count'.


To avoid this error you need to create the wrapping library which will interact with DotNetBrowser. Then you can reference this wrapper to the assembly that should be obfuscated. The wrapping library should not reference DotNetBrowser library directly. Instead of this, the wrapper should use the reflection.


First of all, you need to create the library which will contain single interface. This interface describes which actions you need to perform with the browser:


public interface IBrowserProxy : IDisposable
{
    string GetWebPageHtml(string url);
}


Next, you need to create the assembly which will implement this interface. This assembly will reference the DotNetBrowser library and the library with the previously declared interface:


public class BrowserProxy : IBrowserProxy
{
    private Browser browser;
    private ManualResetEvent pageLoadEvent;

    public BrowserProxy()
    {
        browser = BrowserFactory.Create();
        browser.FinishLoadingFrameEvent += (sender, args) =>
        {
            if (args.IsMainFrame)
            {
                pageLoadEvent.Set();
            }
        };
        pageLoadEvent = new ManualResetEvent(false);
    }

    public string GetWebPageHtml(string url)
    {
        pageLoadEvent.Reset();
        browser.LoadURL(url);
        pageLoadEvent.WaitOne();
        return browser.GetHTML();
    }

    public void Dispose()
    {
        browser.Dispose();
    }
}


In the target application, you need to reference the interfaces library and then dynamically load the implementation of the IBrowserProxy interface:


class Program
{
    static void Main(string[] args)
    {
        //Load library with the implementation
        IBrowserProxy proxy = GetProxyFromAssembly("DotNetBrowserProxy.dll");

        //Use proxy interface
        string githubHtml = proxy.GetWebPageHtml("github.com");
        Console.WriteLine(githubHtml);

        proxy.Dispose();

        Console.ReadKey();
    }

    static IBrowserProxy GetProxyFromAssembly(string assemblyFileName)
    {
        if (File.Exists(assemblyFileName))
        {
            //Load assembly from file
            Assembly proxyAssembly = Assembly.LoadFrom(assemblyFileName);
            //Get the implementation type of the IBrowserProxy interface
            Type browserProxyType = proxyAssembly.GetTypes()
                .FirstOrDefault(type => type.IsClass && type.GetInterface("IBrowserProxy") != null);

            if (browserProxyType != null)
            {
                //Instantiate and return the implementation type
                IBrowserProxy proxy = (IBrowserProxy) Activator.CreateInstance(browserProxyType);
                return proxy;
            }
        }

        return null;
    }
}


There are few notes regarding the usage:

  • All compiled libraries and DotNetBrowser libraries should be located in the same directory
  • You need to obfuscate the proxy library and the target library
  • You should NOT obfuscate the implementation library (which references DotNetBrowser)


Also, you can find the sample Visual Studio solution attached to this article.