Share This!

Sunday, July 28, 2013

Executing an Unmanaged (COM) DLL from an ASP.NET web page.

 I had a regular old DLL that needed to accept parameters, and spit out a string as an answer.  It is a 64 bit DLL running on a 64 bit server under .NET Framework 4.5.

Here is a quick tutorial on how I got it to work.

First, I had to add this to my main <Configuration> section of my web.config


 <system.codedom>
  <compilers>
   <compiler
     language="c#;cs;csharp"
     extension=".cs"
     compilerOptions="/unsafe"
     type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </compilers>
 </system.codedom>



The /unsafe option is the big thing we needed here, as any call from managed code (.NET is all managed code) to unmanaged code, is considered unsafe.

Next, the dll must be wrapped in its own class.  So add a class to your web site.  Mine looks like this.
using System;
using System.Runtime.InteropServices;

namespace CodeGenerator
{

 internal class NativeMethods
 {
  [DllImport("kernel32.dll", SetLastError = true)]
  public static extern IntPtr LoadLibrary(string dllToLoad);

  [DllImport("kernel32.dll", SetLastError = true)]
  public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

  [DllImport("kernel32.dll")]
  public static extern bool FreeLibrary(IntPtr hModule);
 }

 public class unlocker
 {
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  private delegate IntPtr CreateCode2A(
   int level,
   string name,
   string encrypt_template,
   UInt32 hardwareID,
   UInt16 otherinfo1,
   UInt16 otherinfo2,
   UInt16 otherinfo3,
   UInt16 otherinfo4,
   UInt16 otherinfo5
   );


  public static unsafe string CreateUnlockingCode(string regname, string encrypt_template, string HardwareID, string pathtoDLL)
  {
   string unlockingcode = "";
   string sfp = HardwareID.Remove(4, 1);
   UInt32 lfingerprint = Convert.ToUInt32(sfp, 16);

   IntPtr pDll = NativeMethods.LoadLibrary(pathtoDLL);  //attempt to load the library
   int err1 = Marshal.GetLastWin32Error();
   try
   {
    IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "CreateCode2A");
    int err2 = Marshal.GetLastWin32Error();
    CreateCode2A createCode2 = (CreateCode2A)Marshal.GetDelegateForFunctionPointer(
      pAddressOfFunctionToCall,
      typeof(CreateCode2A));

    if (err1 == 0 && err2 == 0)
    {
     IntPtr unlockingcodeptr = createCode2(1, regname, encrypt_template, lfingerprint, 0, 0, 0, 0, 0);
     unlockingcode = Marshal.PtrToStringAnsi(unlockingcodeptr);
    }
    else
    {
     unlockingcode = string.Format("Error Codes: {0} and {1}", err1, err2);
    }
   }
   finally
   {
    bool result = NativeMethods.FreeLibrary(pDll);
   }
   return unlockingcode.ToString();
  }

 }
}

Now all we need is to call our CreateUnlockingCode function from the main page, which calls the DLL function, and marshals the result back to a C# string for us.


unlockingcode = CodeGenerator.unlocker.CreateUnlockingCode(regname, encrypt_template, fingerprint, pathtoDLL);

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Sunday, July 7, 2013

DLL HELL

I have a 64 bit COM DLL that generates unlocking codes for a client.  I cannot edit this DLL.  It works SOMETIMES.

[DllImport(@"codegen64.dll")]
 public static extern string CreateCode2(
  int level,
  string name,
  string encrypt_template,
  Int64 hardwareID,
  int otherinfo1,
  int otherinfo2,
  int otherinfo3,
  int otherinfo4,
  int otherinfo5
  );
 
There is the page global DLLImport function... and when I try to use it...

try
  {
    unlockingcode = CreateCode2(1, regname, encrypt_template, lfp, 0, 0, 0, 0, 0);
  }
  catch (Exception ex)
  {
    unlockingcode = "";
  }

I get this pop-up dialog on my IIS server...
[Window Title]
Visual Studio Just-In-Time Debugger

[Main Instruction]
An unhandled win32 exception occurred in w3wp.exe [11016].

The Just-In-Time debugger was launched without necessary security permissions. To debug this process, the Just-In-Time debugger must be run as an Administrator. Would you like to debug this process?

[^] Hide process details  [Yes, debug w3wp.exe] [No, cancel debugging]

[Expanded Information]
Process Name: w3wp.exe
User Name: NETWORK SERVICE

Trying to invoke the debugger gives...


NOTE: I have enclosed the call to the DLL in a TRY block and it still fails, killing my WHOLE WEBSITE.
There MUST be a way to load, use, and unload a single DLL in a web page SAFELY, so that I don't get these HORIBLE crashes.

I have a feeling that the DLL is failing to unload, as it seems to work once, then fail until I restart the app pool and web site.
BUT I don't really know because I CANT DEBUG THE PROBLEM.
Sorry for the yelling, but this is like the ninth time I have told the client this is fixed, only to have it recur EVERY TIME a client orders from the web site!
Oh, it should be noted that I have NEVER installed Visual Studio on this web server.
Also, it's IIS8
.NET framework 4
Windows Server Essentials 2012....

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Saturday, July 6, 2013

Quick Question about Speech Recognition

***From my Android Galaxy 2 with ZERO Training***
How come my android phone can understand everything that I say, yet windows 7 voice recognition can't get it after hours of training?


***From Windows (after many hours training)***
Up to my android phone can understand everything that I say, At 107 voice recognition can't get it after hours of training?

***I typed the rest.***
It seems to me that Microsoft should scrap the whole speech recognition project and just buy whatever Android did.   Because clearly they have failed.

To all my subscriber (yes there's only one), Use Windows Speech Recognition to comment below.

Contact Us

Name

Email *

Message *