Note: Advice in this article is only necesary for DotNetBrowser 1.
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:
C#
public interface IBrowserProxy : IDisposable { string GetWebPageHtml(string url); }
VB.NET
Public Interface IBrowserProxy Inherits IDisposable Function GetWebPageHtml(url As String) As String End Interface
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:
C#
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(); } }
VB.NET
Public Class BrowserProxy Implements IBrowserProxy Dim ReadOnly browser As Browser Dim ReadOnly pageLoadEvent As ManualResetEvent Public Sub New() browser = BrowserFactory.Create() AddHandler browser.FinishLoadingFrameEvent, Sub(sender, e) If (e.IsMainFrame) Then pageLoadEvent.Set() End If End Sub pageLoadEvent = new ManualResetEvent(false) End Sub Public Function GetWebPageHtml(url As String) As String Implements IBrowserProxy.GetWebPageHtml pageLoadEvent.Reset() browser.LoadURL(url) pageLoadEvent.WaitOne() return browser.GetHTML() End Function Public Sub Dispose() Implements IDisposable.Dispose browser.Dispose() End Sub End Class
In the target application, you need to reference the interfaces library and then dynamically load the implementation of the IBrowserProxy interface:
C#
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; } }
VB.NET
Module Module1 Sub Main() Dim proxy As IBrowserProxy = GetProxyFromAssembly("../../../DotNetBrowserProxy/bin/Debug/DotNetBrowserProxy.dll") Dim githubHtml As String = proxy.GetWebPageHtml("github.com") Console.WriteLine(githubHtml) proxy.Dispose() Console.ReadKey() End Sub Private Function GetProxyFromAssembly(assemblyFileName As String) As IBrowserProxy If File.Exists(assemblyFileName) Then Dim proxyAssembly As Assembly = Assembly.LoadFrom(assemblyFileName) Dim browserProxyType As Type = proxyAssembly.GetTypes().FirstOrDefault( Function(type) type.IsClass AndAlso type.GetInterface("IBrowserProxy") IsNot Nothing) If browserProxyType IsNot Nothing Then Dim proxy = CType(Activator.CreateInstance(browserProxyType), IBrowserProxy) Return proxy End If End If Return Nothing End Function End Module
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 C# and VB.NET sample Visual Studio solutions attached to this article.