(MVC) MVC (2022)

How to create and testing COM-object of ancient ASP web-sites - list of tools and description of all workflow.

I still expand, evolving and develop ancient ASP web-sites. I still have a lot of order to this job. Usually there are only one way to adding new function to ancient ASP web-sites - create COM-object. In this page I try to describe whole this process step-by-step.

I will create sophisticated COM-object with reference to other external library. This COM-object will creating PDF file from HTML, more details about that project see in page PDF creator COM-object based on TheArtOfDev.HtmlRenderer.PdfSharp..

So, firstly, I download this project and make 3 step:

Prepare strong name assemblies used as reference of COM-object.

Next step is absolutely important, need to create strong name assembly.

This is simple step, need only sign assembly, but trouble with this sign will be huge. In this time I firstly made mistake with sing and deploy my COM-component without strong name. In foreground you can see Assembly with strong name (ended to PublicKeyToken=17c660a72cb52832), in background assembly without strong name.

Assembly without strong name can be working successfully on developer computer, but in server you will see error similar to this.

Tools for checking assemblies.

There are two cool tools, first is modern Dependency Walker https://github.com/lucasg/Dependencies (and link to it IlDasm). And of course, you need on server NETFX-4.8-Tools, usually server have no this package, you need to download it https://sourceforge.net/projects/netfx-4-8-tools/.

Cool alternatives for modern Dependency Walker is JustDecompile https://www.telerik.com/products/decompiler.aspx.

Create COM-object functions and pack COM-object to special tags.

I have a couple of description for this case, for example post about 5 years ago COM-component for classic ASP

Firstly we can create Interface with this tags

   7:  <Runtime.InteropServices.ComVisible(True)>
   8:  <Runtime.InteropServices.Guid("864f3ae4-7c66-11ed-9649-5254008de3b3")>
   9:  <Runtime.InteropServices.InterfaceType(Runtime.InteropServices.ComInterfaceType.InterfaceIsDual)>

Next step is implementation, with another GUID.

   7:  <Runtime.InteropServices.ComVisible(True)>
   8:  <Runtime.InteropServices.Guid("37191c45-7c66-11ed-9649-5254008de3b3")>
   9:  <Runtime.InteropServices.ClassInterface(Runtime.InteropServices.ClassInterfaceType.AutoDispatch)>
  10:  <Runtime.InteropServices.ProgId("TDS.HTML2PDF")>

Next step is sign assembly of your COM-object.

That's it for creating COM-object.

Registration of COM-object.

Main command for register and unregister COM-object is:

>C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm /codebase your.dll
>C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm /u your.dll

Pay attention that DLL for COM-object must be sign.

OleViewDotNet - main tool for checking registration and working with COM-object.

This is next main tool to whole working process with COM-object https://github.com/tyranid/oleviewdotnet.

If something going wrong with COM-object, this is first diagnostic tool. we always see error in this tool.

Add referenced assembly to GAC.

Next step is add referenced assembly to GAC.

>C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\gacutil -i your.dll

Four way to test COM-object locally.

First way is simple try to create instance of your COM-object.

Next step is simple check all your function as class, of course this step you can make after you complete your functions of COM-object. Main point of this step is that test platform now working with .NET CORE, but we need test platform we need exactly with .NET Framework. Because a lot of assemblies (for example System.Drawing) is different in .NET CORE and .NET Framework.

And than you can ordinary test, in my case this is read file and creating PDF from HTML. As you can see, all working fine.

This is my test.

   1:  Imports System.Net
   3:  Public Class MyWebClient
   4:      Inherits WebClient
   5:      Protected Overloads Function GetWebRequest(URL As Uri) As WebRequest
   6:          Dim WebRequest = MyBase.GetWebRequest(URL)
   7:          Debug.WriteLine(WebRequest.RequestUri)
   8:          WebRequest.ContentType = "text/html"
   9:          WebRequest.Timeout = Integer.MaxValue
  10:          Return WebRequest
  11:      End Function
  13:  End Class

   1:  Imports System.Net
   2:  Imports System.Security.Policy
   3:  Imports System.Text
   4:  Imports Microsoft.VisualStudio.TestTools.UnitTesting
   5:  Imports Microsoft.VisualStudio.TestTools.UnitTesting.Logging
   6:  Imports NLog
   7:  Imports TDSprint2
   9:  <TestClass()> Public Class UnitTest1
  10:      Friend Request As MyWebClient
  11:      Friend Shared Log As NLog.Logger = LogManager.GetCurrentClassLogger()
  13:      <TestInitialize>
  14:      Public Sub Start()
  15:          Request = New MyWebClient
  16:      End Sub
  19:      <TestMethod()>
  20:      <DataRow("https://www.codeproject.com/")>
  21:      Public Sub TestClass(URL As String)
  22:          Try
  23:              Dim Response = Request.DownloadString(URL)
  24:              Log.Info(Response)
  25:              Dim TmpDir As String = System.IO.Path.GetTempPath
  26:              Dim TmpFile As String = IO.Path.Combine(TmpDir, Replace(Replace(Replace(Replace(Replace(URL, "/", "-"), "&", "-"), "?", "-"), "https:", ""), "http:", ""))
  27:              IO.File.WriteAllText(TmpFile & ".html", Response)
  28:              'Dim Ret1 = Process.Start("C:\Program Files\Mozilla Firefox\firefox.exe", TmpFile & ".html")
  29:              Dim X As New HTML2PDF
  30:              X.CreatePdfFile(TmpFile & ".pdf", Response, PageSize.A0)
  31:              Dim Ret2 = Process.Start("C:\Program Files\Mozilla Firefox\firefox.exe", TmpFile & ".pdf")
  32:          Catch ex As WebException
  33:              Dim Resp As String = ""
  34:              Dim Stream = ex.Response?.GetResponseStream()
  35:              If Stream IsNot Nothing Then
  36:                  Dim Sr = New IO.StreamReader(Stream)
  37:                  Resp = Sr.ReadToEnd
  38:              End If
  39:              Log.Info(Resp & vbCrLf & ex.Message)
  40:          End Try
  41:      End Sub

Next test is more complex and sophisticated. This is perform the same class as COM-object. As you can see, all working fine.

Pay attention how to call COM-object, this is my code.

  43:      <DataRow("https://www.codeproject.com/")>
  44:      <TestMethod()>
  45:      Public Sub TestCOM(URL As String)
  46:          Try
  47:              Dim Response = Request.DownloadString(URL)
  48:              Dim TmpDir As String = System.IO.Path.GetTempPath
  49:              Dim TmpFile As String = IO.Path.Combine(TmpDir, Replace(Replace(Replace(Replace(Replace(URL, "/", "-"), "&", "-"), "?", "-"), "https:", ""), "http:", ""))
  50:              IO.File.WriteAllText(TmpFile & ".html", Response)
  51:              '
  52:              Dim ComObjType = Type.GetTypeFromProgID("TDS.HTML2PDF")
  53:              Dim X As IHTML2PDF = Activator.CreateInstance(ComObjType)
  54:              X.CreatePdfFile(TmpFile & ".pdf", Response, PageSize.A0)
  55:              Dim Ret2 = Process.Start("C:\Program Files\Mozilla Firefox\firefox.exe", TmpFile & ".pdf")
  57:          Catch ex As WebException
  58:              Dim Resp As String = ""
  59:              Dim Stream = ex.Response?.GetResponseStream()
  60:              If Stream IsNot Nothing Then
  61:                  Dim Sr = New IO.StreamReader(Stream)
  62:                  Resp = Sr.ReadToEnd
  63:              End If
  64:              Log.Info(Resp & vbCrLf & ex.Message)
  65:          End Try
  67:      End Sub
  69:  End Class

And this is final and most sophisticated and complex test as possible.

   1:  <%@ Language=VBScript%>
   2:  <!DOCTYPE html>
   3:  <html>
   4:  <body>
   5:  <form name='TDS' method='post' ID="test1" action="/TSTPDF1.asp">
   6:  <a href="#">Test PDF component.</a> <br><br>
   7:  Set HTML.<br>
   8:  <textarea type="text" name="html" style="width: 500px;"><html><body><h1>Test PDF component</h1><img src='https://app.tariffdatasystems.com/Media/Images/header_left_side.gif'></body></html></textarea>
   9:  <br>
  10:  <br>
  11:  <br>
  12:  <input type="submit" value="Submit">
  13:  </form>
  14:  <%
  15:  If Request.Form.Count>0 then
  16:  Dim PdfCretor, TmpDir, FS, FileContent, GUID
  17:  TmpDir = Server.MapPath("temp")
  18:  GUID = CreateGUID()
  19:  TmpFileName = TmpDir & "\" & GUID & ".pdf"
  21:  Set PdfCretor = Server.CreateObject("TDS.HTML2PDF")
  22:  PdfCretor.CreatePdfFile TmpFileName, Request.Form("html"), 1 
  24:  Set FS = Server.CreateObject("Scripting.FileSystemObject")
  25:  Set FileContent = FS.GetFile(TmpFileName)
  27:  Response.Redirect("/temp/" & GUID & ".pdf")
  30:  Set PdfCretor = nothing
  31:  Set FS = nothing
  32:  Set FileContent = nothing
  33:  end if
  35:  Function CreateGUID
  36:    Dim TypeLib
  37:    Set TypeLib = CreateObject("Scriptlet.TypeLib")
  38:    CreateGUID = Mid(TypeLib.Guid, 2, 36)
  39:  End Function
  41:  %>
  42:  </body>
  43:  </html>

Its working fine too!

We going to finist line and we are ready to deploy component to server.

Copy COM-object to server.

What main point to copy COM-object to server? Of course, your will updated your COM-object on server many times. Pay attention, that library of COM-object still busy, despite you unregister COM-object.

And your DLL at common can be busy by your test of other program, to check who used DLL, you can use this opportunity of Windows.

Finally check COM-object on remote server.

Finally check your COM-object you can by the same way as in local computer, but pay attention to tune pool of IIS. For example this flag set my COM-object not-workable.

And of course, usually ancient ASP site need to strong debugging. Look to this page for read more about debugging Remote debugging.

Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
Link to this page: http://www.vb-net.com/Com-Object/Index.htm