Jump to content

How to register and use a .Net COM object


sohfeyr
 Share

Recommended Posts

This seems to be a recurring topic of interest, so I thought I'd share this COM object I wrote in VB .Net, called "ImgTool". It has functions that capture all or part of the screen directly to a variety of image file formats. (Yes, I know there are easier ways to do that - at least to bitmap - but I just wanted to give a non-trivial example.)

To compile the attached source, you will need the .NET Framework 2.0 SDK or Visual Studio 2005.

To run the following code, you just need the attached DLL file, which source is in the Zip.

You'll notice that this only uses properties and methods; COM events (like for ObjEvent()) seem to take a little something extra I'm still working on, and at any rate were not needed for this sample. My main point in posting this was to show which attributes to use and how to register .Net types for COM interop. The .snk file in the source is needed to generate the type library, and is obtained using sn.exe.

If $CmdLine[0]=0 Then
    Local $path=FileOpenDialog("Select a .NET assembly to register",@ScriptDir,"DLL files (*.dll)",1) 
    If @error=1 Then Exit
    ;MsgBox(0, "Net DLL Registration", 
    RegisterDotNetComponent($path)  ;) 
Else
    RegisterDotNetComponent($CmdLine[1])
EndIf

Dim $com = ObjCreate("ImgTool.ImgConverter")
$com.Test()
$com.ScreenShot("screen","c:\screen.jpg")
; Regexp: (?<mode>LT(?<m>RB|WH))\((?<L>\d+),(?<T>\d+),(?<W>\d+),(?<H>\d+)\)
$com.ScreenShot("LTWH(50,50,100,200)","c:\ltwh.jpg") ; ArgumentException - check the RegEx
MsgBox(0,1,$com.GetLastError())
$com=0

Func RegisterDotNetComponent($path)
    Local $text
    Local $regasm = "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe"
    Local $regasmparams = ' "' & $path & '" /tlb'
    Local $gacutil= "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe"
    Local $gacutilparams = ' -i "' & $path & '"' 
    $text = GetOutput("RegAsm", $regasm, $regasmparams) ;~ regasm "$path" /tlb
    $text &= @CRLF & @CRLF 
    $text &= GetOutput("GACUtil", $gacutil, $gacutilparams) ;~ gacutil -i "$path"
    ConsoleWrite($text)
    Return $text
EndFunc

Func GetOutput($name, $path, $params)
    If StringLeft($params,1) <> " " Then $params = " " & $params 
    Local $pid = Run($path & $params, "", @SW_HIDE, 7) ;~ regasm "$path" /tlb
    Local $out = StdoutRead($pid)
    Local $strout = $name & ":" & @CRLF & $out
    While $out
        $out = StdoutRead($pid)
        $strout = $strout & @CRLF & $out
    WEnd
    Return $strout
EndFunc

Edit: uploaded second zip file with the dll and tlb files

ImgConv.zip

ImgTool_dll.zip

Edited by sohfeyr
Link to comment
Share on other sites

Anything that relates to COM I am in favour of !!

Keep up the good work

Thanks ptrex! That really does mean a lot coming from you, and I'm glad you approve.

I'm hoping that others will get interested and also post their projects or samples along these lines. I'm also considering eventually building a tutorial. I know a lot of people don't like .Net that much, but I get the feeling it is going to be around for the next few years, and getting increasingly common. If AutoIt can easily interact with .Net components and features, less development will have to be done to AutoIt itself to stay as widely useful as it is now.

For those looking for ideas, these would all make really good projects:

  • Using ObjEvent() with .Net events
  • Creating a static object that can be accessed by multiple scripts / programs at the same time (yes, this is possible!)
  • Create a COM wrapper for an AutoIt script using ConsoleWrite, StdInRead, etc. and use it in another kind of program. (Hint: use the System.Diagnostics.Process object)
  • Use that COM wrapper to transparently run an AutoIt script as a Word, Excel or PowerPoint macro like it was an ActiveX object.
  • Use a COM wrapper for an AutoIt script running as a service to treat that script like a library
  • Create a decorator object around a native .Net class and expose it's functionality to AutoIt. Suggestions include Drawing.Bitmap, System.Diagnostics.Trace and System.Diagnostics.TraceListener, System.IO.Ports.SerialPort, System.IO.FileSystemWatcher, and System.IO.Compression.GZipStream . (It is *insane* how many posts I see in the Help forum that could be answered with wrappers and decorators around these objects.)
  • Try Microsoft.CSharp.CSharpCodeProvider.CreateCompiler().CompileAssemblyFromSource() - talk about powerful? Write and compile dynamic .Net applications with AutoIt logic via a COM object! (Also available in Microsoft.VisualBasic flavor)
If all that doesn't give people ideas, then they have a serious lack of imagination. :) If anyone else can think of more, by all means post them. Potential is every bit as importent as actualization, and sooner of later it might actually get made! Edited by sohfeyr
Link to comment
Share on other sites

Great work. I will have to try this out for my .Net debugger. I would like to replace the standard installer package.

“Give a man a script; you have helped him for today. Teach a man to script; and you will not have to hear him whine for help.”AutoIt4UE - Custom AutoIt toolbar and wordfile for UltraEdit/UEStudio users.AutoIt Graphical Debugger - A graphical debugger for AutoIt.SimMetrics COM Wrapper - Calculate string similarity.

Link to comment
Share on other sites

  • 2 weeks later...
Link to comment
Share on other sites

How did that work out for you?

I got the registration working for one of my other, simpler projects. It was the strong name that I was stuck on previously (not knowing it was required). Since I added it, registration appears to work. I am using the principals to finish the complete NSIS installation script.

Thanks

“Give a man a script; you have helped him for today. Teach a man to script; and you will not have to hear him whine for help.”AutoIt4UE - Custom AutoIt toolbar and wordfile for UltraEdit/UEStudio users.AutoIt Graphical Debugger - A graphical debugger for AutoIt.SimMetrics COM Wrapper - Calculate string similarity.

Link to comment
Share on other sites

  • 2 months later...
  • 2 months later...

I have been using this and came across this issue when using this on different computers. Different computers have difference versions of .net installed and they may be in a unique directory. So I recommend including this function. It returns the directory that the most recent version of .net framework is installed.

Func _GetDotNetInstalledDir()
    Local $DotNetDir = RegRead("HKLM\Software\Microsoft\.NetFramework","InstallRoot")
    If $DotNetDir = "" Then Return "" ;.net is not installed
    Local $version = ""
    For $i =1 To 10
        If StringRegExp(RegEnumKey("HKLM\Software\Microsoft\.NetFramework\policy",$i),"v(1.1)|v(2.0)") Then
            $version = $i
            If @error <> 0 Then ExitLoop
        EndIf
    Next
    Local $versionNum = RegEnumKey("HKLM\Software\Microsoft\.NetFramework\policy",$version)
    $version = RegEnumVal("HKLM\Software\Microsoft\.NetFramework\policy\" & $versionNum,1 )
    Return $DotNetDir & $versionNum & "." & $version
EndFunc

On my machine it returned "C:\WINNT\Microsoft.NET\Framework\v2.0.50727", which was different from the example you posted. I also recommend adding a "UnRegisterDotNetComponent($path)" function to unregister the DLL as well.

btw, I really love this COM stuff thank you, its awesome!

www.itoady.com

A* (A-star) Searching Algorithm - A.I. Artificial Intelligence bot path finding

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...