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:
- Rebuild it to .NET 4.8
- Delete file SharedAssemblyInfo.cs from this place - https://github.com/ArthurHub/HTML-Renderer/tree/master/Source
- Delete two two project from solution related to WPF.
- Try to start modified project.
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
2:
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
12:
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
8:
9: <TestClass()> Public Class UnitTest1
10: Friend Request As MyWebClient
11: Friend Shared Log As NLog.Logger = LogManager.GetCurrentClassLogger()
12:
13: <TestInitialize>
14: Public Sub Start()
15: Request = New MyWebClient
16: End Sub
17:
18:
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")
56:
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
66:
67: End Sub
68:
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"
20:
21: Set PdfCretor = Server.CreateObject("TDS.HTML2PDF")
22: PdfCretor.CreatePdfFile TmpFileName, Request.Form("html"), 1
23:
24: Set FS = Server.CreateObject("Scripting.FileSystemObject")
25: Set FileContent = FS.GetFile(TmpFileName)
26:
27: Response.Redirect("/temp/" & GUID & ".pdf")
28:
29:
30: Set PdfCretor = nothing
31: Set FS = nothing
32: Set FileContent = nothing
33: end if
34:
35: Function CreateGUID
36: Dim TypeLib
37: Set TypeLib = CreateObject("Scriptlet.TypeLib")
38: CreateGUID = Mid(TypeLib.Guid, 2, 36)
39: End Function
40:
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.
|