WinBatch® Technical Support Forum

Archived Boards => COM Automation and dotNet => Topic started by: stanl on November 10, 2013, 10:26:05 AM

Title: CLR and VB.net dll
Post by: stanl on November 10, 2013, 10:26:05 AM
Just thought I'd throw this out. The attached Powershell script if run under Powershell will create a 7k dll with a method to CopyToClipboard(). Big Deal - WB can already do that.
I also know that even if WB couldn't do that the following WB code would fail with a DLL Entry error
Code (WINBATCH) Select

a0="Hello World"
dllname="C:\powershell\extension.dll"
a1=DllCall(dllname, lpstr:"CopyToClipboard", lpstr:a0)
Message(a0,a1)

The point being, is there a possibility that the WB CLR interface could execute the method?
Title: Re: CLR and VB.net dll
Post by: stanl on November 11, 2013, 06:16:09 AM
I read you could use System.Reflection to call a dll method. May be overkill and the Clipboard method is trivial. But if possible it gives WB more leverage with .NET IMOH:
Title: Re: CLR and VB.net dll
Post by: stanl on November 11, 2013, 07:43:05 AM
Here is my S.W.A.G. (and I attached the dll).
Code (Winbatch) Select

ModuleName = dirscript():"extension.dll";
TypeName = "Utility";
MethodName = "CopyToClipboard";
ObjectClrOption("use","System.Net, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")
;oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )
;oAssembly = oAssembly.Load( ModuleName )
oBase =  ObjectClrNew( 'System.Reflection.MethodBase' )
oMethod = ObjectClrNew( 'System.Reflection.MethodInfo' )
oModule = ObjectClrNew( 'System.Reflection.Module', ModuleName )
oMethod.GetType(TypeName)   ;fails here, but surprised I got that close
oMethod.GetMethod(MethodName)
oMethod.Invoke("Hello World")
oMethod=0
oAssembly=0
Exit
Title: Re: CLR and VB.net dll
Post by: Deana on November 12, 2013, 10:34:12 AM
Stan,

So it appears you would like to call the CopyToClipboard method in this "extension" module. Is that correct? It appears the code is compiled as a Visual Basic DLL. I wonder if you could load it like any other assembly?

Here is what I tried:

Code (winbatch) Select
ObjectClrOption( "appbase", "c:\temp\" )
objUtility = ObjectClrNew("ClipboardAddon.Utility")
 

However that was unsuccessful.

I may need to defer to Tony's knowledge on this subject....
Title: Re: CLR and VB.net dll
Post by: td on November 12, 2013, 11:48:18 AM
For starters the 'appbase' option cannot be used to specify a specific assembly.  It is used to specify the location of all non-GAC assemblies used by the application or script in this case. 

The dll as provided does not want to load on my system even when 'appbase' is used correctly because some assembly dependencies are missing.  This problem might (or might not) be corrected by taking PowerShell out of the equation.  WinBatch is perfectly capable of compiling properly written VB code into a dotNet assembly.
Title: Re: CLR and VB.net dll
Post by: Deana on November 12, 2013, 01:23:36 PM
Okay this seems to work for me. Give this a try Stan...:

Code (winbatch) Select
ModuleName = "c:\temp\extension.dll";
objectClrOption( 'use', 'System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a') 
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )
oAssembly = oAssembly.LoadFrom( ModuleName )

objUtility = ObjectClrNew("ClipboardAddon.Utility")
objUtility.CopyToClipboard("Hello World")
Exit
Title: Re: CLR and VB.net dll
Post by: Deana on November 12, 2013, 01:41:20 PM
Here is the WinBatch code that can generate the extenstion.dll:

Code (winbatch) Select
;***************************************************************************
;**   Compile assembly library from VB source.
;**
;** Purpose:  Compile assembly from source.
;** Inputs:   VB source code
;** Outputs:  Compiled VB DLL
;** Reference:
;**       REQUIRES WinBatch 2013A or newer & File
;**       
;**
;** Developers: Deana Falk 2013.11.12
;***************************************************************************
If Version( )< '2013A'
   Pause('Notice', 'Need 2013A or Newer Version of WinBatch')
   Exit
EndIf

code = 'Imports Microsoft.VisualBasic':@lf
code = code: 'Imports System':@lf
code = code: 'Namespace ClipboardAddon':@lf
code = code: '  Public Class Utility':@lf
code = code: '    Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Integer) As Integer':@lf
code = code: '    Private Declare Function EmptyClipboard Lib "user32" () As Integer':@lf
code = code: '    Private Declare Function CloseClipboard Lib "user32" () As Integer':@lf
code = code: '    Private Declare Function SetClipboardData Lib "user32"(ByVal wFormat As Integer, ByVal hMem As Integer) As Integer':@lf
code = code: '    Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Integer, ByVal dwBytes As Integer) As Integer':@lf
code = code: '    Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Integer) As Integer':@lf
code = code: '    Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Integer) As Integer':@lf
code = code: '    Private Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Integer, ByVal lpString2 As String) As Integer':@lf
code = code: '':@lf
code = code: '    Public Shared Sub CopyToClipboard(ByVal text As String)':@lf
code = code: '      Dim result As Boolean = False':@lf
code = code: '      Dim mem As Integer = GlobalAlloc(&H42, text.Length + 1)':@lf
code = code: '      Dim lockedmem As Integer = GlobalLock(mem)':@lf
code = code: '      lstrcpy(lockedmem, text)':@lf
code = code: '      If GlobalUnlock(mem) = 0 Then':@lf
code = code: '        If OpenClipboard(0) Then':@lf
code = code: '          EmptyClipboard()':@lf
code = code: '          result = SetClipboardData(1, mem)':@lf
code = code: '          CloseClipboard()':@lf
code = code: '        End If':@lf
code = code: '      End If':@lf
code = code: '    End Sub':@lf
code = code: '  End Class':@lf
code = code: 'End Namespace'

;Add-Type -TypeDefinition $code -Language VisualBasic -OutputType Library -OutputAssembly c:\temp\extension.dll

If Version( )< '2013A'
   Pause('Notice', 'Need 2013A or Newer Version of WinBatch')
   Exit
EndIf


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Load assemblies into the WinBatch process.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; mscorlib assembly is automatically loaded by WinBatch when the CLR is loaded.
ObjectClrOption('use','System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Prompt for Input
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
assemblydll =  DirScript():'extension.dll'

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Create a class implemented by a managed assembly.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
objVB = ObjectClrNew('Microsoft.VisualBasic.VBCodeProvider')
objParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
;objParams.ReferencedAssemblies.Add( 'System.dll' )
objParams.OutputAssembly  = assemblydll
;objParams.CompilerOptions = '/optimize'
objResult = objVB.CompileAssemblyFromSource(objParams, BSTR:code)
;; Check for compiler errors.
If objResult.Errors.Count > 0
   ForEach ce In objResult.Errors
      Pause('Error', ce.ToString())
   Next
   Exit
EndIf

Exit


For complete example see:
http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/tsleft.web+WinBatch/dotNet/System_CodeDom+Compile~Dll~from~VB~Source.txt
Title: Re: CLR and VB.net dll
Post by: td on November 12, 2013, 02:06:50 PM
Quote from: Deana on November 12, 2013, 01:23:36 PM
Okay this seems to work for me. Give this a try Stan...:

Code (winbatch) Select
ModuleName = "c:\temp\extension.dll";
objectClrOption( 'use', 'System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a') 
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )
oAssembly = oAssembly.LoadFrom( ModuleName )

objUtility = ObjectClrNew("ClipboardAddon.Utility")
objUtility.CopyToClipboard("Hello World")
Exit


Actually all you need to do is
Code (winbatch) Select

ObjectClrOption( "appbase", "C:\Projects\DotNet\StansDll" )
ObjectClrOption("use", "extension")
objUtility = ObjectClrNew("ClipboardAddon.Utility")


I was getting an error because I left the .dll extension on "extension"...
Title: Re: CLR and VB.net dll
Post by: stanl on November 12, 2013, 02:24:08 PM
Thank you both. Obviously my initial interpretation was a bit off from how WB can actually handle working with VB dll's (and create them). However, this (at least to me) opens up an incredible opportunity to [once again] leverage .net stuff into WB.
Title: Re: CLR and VB.net dll
Post by: stanl on November 13, 2013, 04:09:30 AM
Everything works but one question. Deana's code called
objectClrOption( 'use', 'System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )
My laptop doesn't recognize this (Win 7 32 bit, updated .NET 4.5)
instead I use
ObjectClrOption("use","System.Net, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )

Just wondered why the difference?

P.S. and all worked with the original Powershell created dll, but happy to see WB can create as well.



Title: Re: CLR and VB.net dll
Post by: stanl on November 13, 2013, 06:32:35 AM
One final observation. I compiled the script after adding a Message() to display what was in the clipboard. Worked on my laptop and a desktop I placed the EXE on. Tried it on my work laptop (it is PGP encrypted). It worked, but before the message() was displayed I got the attached pop-up - outside the WB error-handler. Is there a way to trap for it?
Title: Re: CLR and VB.net dll
Post by: JTaylor on November 13, 2013, 06:52:08 AM
To make sure I understand....What does this do for us?   Allow us to load a DLL and then call any Methods from within it?  If so, what type of DLL's would work?

Apologies if the answer is obvious and I'm just being dense, as usual.

Jim
Title: Re: CLR and VB.net dll
Post by: Deana on November 13, 2013, 07:55:45 AM
Quote from: stanl on November 13, 2013, 06:32:35 AM
One final observation. I compiled the script after adding a Message() to display what was in the clipboard. Worked on my laptop and a desktop I placed the EXE on. Tried it on my work laptop (it is PGP encrypted). It worked, but before the message() was displayed I got the attached pop-up - outside the WB error-handler. Is there a way to trap for it?

That seems to be a dotNet related error. I Googled the error message and found these threads:

http://answers.microsoft.com/en-us/windows/forum/windows_vista-windows_install/parser-error-0xc00ce556/c8a0a7cd-a5cc-46c3-9e76-96306143d36b
http://social.msdn.microsoft.com/Forums/en-US/ab6aff56-e42e-4da2-88d1-07311116b084/configuration-parser-error?forum=whatforum
Title: Re: CLR and VB.net dll
Post by: Deana on November 13, 2013, 08:00:33 AM
Quote from: JTaylor on November 13, 2013, 06:52:08 AM
To make sure I understand....What does this do for us?   Allow us to load a DLL and then call any Methods from within it?  If so, what type of DLL's would work?

Apologies if the answer is obvious and I'm just being dense, as usual.

Jim

Basically yes. If you have a managed code assembly you can use WinBatch to access said assembly. In order to access using the CLR functions in WinBatch, it must be a "managed code assembly".

We have added three new functions give WinBatch scripts access to the Microsoft .Net Framework. WinBatch makes this possible by hosting the common language runtime (CLR) and exposing functionality for creating and accessing the members of classes, structures and enumerations of managed code assemblies (DLLs) that are part of or based on the Framework.

I found this blog that helps explain managed code assemblies: http://blogs.msdn.com/b/slessard/archive/2010/04/09/types-of-managed-code-assemblies.aspx
Title: Re: CLR and VB.net dll
Post by: JTaylor on November 13, 2013, 08:05:37 AM
Aware of the new functions and have used them, with some help, but what is does this thread demonstrate that is different?   Just the use of a DLL whereas the other things I've seen and done just call the .NET stuff directly?

Jim
Title: Re: CLR and VB.net dll
Post by: Deana on November 13, 2013, 08:09:10 AM
Quote from: JTaylor on November 13, 2013, 08:05:37 AM
Aware of the new functions and have used them, with some help, but what is does this thread demonstrate that is different?   Just the use of a DLL whereas the other things I've seen and done just call the .NET stuff directly?

Jim

It shows that you can not only create your own custom managed assembly, but it can also be called/accessed by WinBatch.
Title: Re: CLR and VB.net dll
Post by: td on November 13, 2013, 08:10:32 AM
Quote from: stanl on November 13, 2013, 04:09:30 AM
Everything works but one question. Deana's code called
objectClrOption( 'use', 'System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )
My laptop doesn't recognize this (Win 7 32 bit, updated .NET 4.5)
instead I use
ObjectClrOption("use","System.Net, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )

Just wondered why the difference?

You apparently did see my response to Deana's post.  The only assembly you need to load is your 'extension' dll.  WinBatch will pick up any dependent assemblies that 'extension' needs.

Quote
P.S. and all worked with the original Powershell created dll, but happy to see WB can create as well.

Yes we know but the point is that there is no need to introduce another dependency  like Powershell into the equation. All you need is WinBatch and the FCL.
Title: Re: CLR and VB.net dll
Post by: td on November 13, 2013, 08:27:38 AM
Quote from: stanl on November 13, 2013, 04:09:30 AM
Everything works but one question. Deana's code called
objectClrOption( 'use', 'System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )
My laptop doesn't recognize this (Win 7 32 bit, updated .NET 4.5)
instead I use
ObjectClrOption("use","System.Net, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")
oAssembly = ObjectClrNew( 'System.Reflection.Assembly' )

Just wondered why the difference?


Didn't directly answer your question in my previous post so... You don't need to load any assemblies to use the 'System.Reflection.Assembly'  class.  It is part of the mscorlib assembly which is automagically loaded when the CLR is loaded into a WinBatch process.
Title: Re: CLR and VB.net dll
Post by: JTaylor on November 13, 2013, 08:30:33 AM
Thanks.  Just wanted to make sure I understood.

Jim
Title: Re: CLR and VB.net dll
Post by: stanl on November 13, 2013, 10:46:31 AM
Quote
You apparently did see my response to Deana's post.  The only assembly you need to load is your 'extension' dll.  WinBatch will pick up any dependent assemblies that 'extension' needs.

Not sure if you meant to write 'didn't see' rather than 'did see'. But I did see it and your code worked perfectly. My question was about why the particular line

objectClrOption( 'use', 'System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')

cannot be used on my laptop, but apparently worked for Deana.

As for powershell. I used it because it was easily called from the command line. I assume the code Deana posted could be re-written as a generic load VB code from a Text file and with a couple parameters export a DLL.  Hard to call PS a dependency as it is more and more part of the OS.

moot points.  I will put your comments about appbase and the fact that reflection is loaded by default into a header file so that I don't forget the next time I venture into .NET la-la land....  :o
Title: Re: CLR and VB.net dll
Post by: td on November 13, 2013, 11:53:50 AM
Quote from: stanl on November 13, 2013, 10:46:31 AM

Not sure if you meant to write 'didn't see' rather than 'did see'. But I did see it and your code worked perfectly. My question was about why the particular line

objectClrOption( 'use', 'System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')

cannot be used on my laptop, but apparently worked for Deana.

I did mean 'didn't see' because the use of 'System.Reflection' is completely unnecessary in the case at hand.  However, after posting the response I realized that you may have been asking a question not directly related to the problem of loading your VB dotNet assembly. So I added the second post addressing the 'System.Reflection' issue by noting that you do not need a  'use' option with 'System.Reflection' because that namespace is part of the mscorlib assembly.

Quote
As for powershell. I used it because it was easily called from the command line. I assume the code Deana posted could be re-written as a generic load VB code from a Text file and with a couple parameters export a DLL.  Hard to call PS a dependency as it is more and more part of the OS.

It is still an additional dependency as far as I can tell.  There are more than a few XP machines out there that have dotNet but don't have PowserShell.  There are also more than a few newer machines build from corporate images that only have a limited subset of OS utilities and subsystems on board or available to standard users.  Avoiding dependencies is a concern that comes up often among our corporate WinBatch users.

Corporate users also have concerns about maintaining their scripts and programs.  Often when you add an additional tool to the mix you add the need for more knowledge and increase the chances of inadvertently breaking something.  So even if you know a tool is available, that fact doesn't necessarily negate the risks of adding that additional dependency.

There are certainly good reasons for adding dependencies but there are also good reasons to avoid doing so.
   
Title: Re: CLR and VB.net dll
Post by: stanl on November 13, 2013, 02:12:36 PM
Without beating the dead horse on this thread your points well taken. Currently, I do nothing in WB that is work-related, so a lot of these threads are just personal learning experiences, but I trust members of the large WB community would look at this thread with a "Hey, didn't know you could do that" and the end result is more CLR threads.

Title: Re: CLR and VB.net dll
Post by: td on November 14, 2013, 06:46:19 AM
Creating dotNet assemblies provides a quick and relatively easy way to extend WinBatch functionality, if you have a bit of fluency in one of the dotNet languages.  They allow you to create the rough equivalent of a WIL extender without having to master the WIL extender interface or C/C++.
Title: Re: CLR and VB.net dll
Post by: stanl on November 14, 2013, 07:19:32 AM
Quote from: td on November 14, 2013, 06:46:19 AM
Creating dotNet assemblies provides a quick and relatively easy way to extend WinBatch functionality, if you have a bit of fluency in one of the dotNet languages.  They allow you to create the rough equivalent of a WIL extender without having to master the WIL extender interface or C/C++.

Took the words out of my mouth.  I am looking into a SQL Server assembly.
Title: Re: CLR and VB.net dll
Post by: kdmoyers on November 15, 2013, 05:29:31 AM
So, if I'm getting this right, When I want my .Net consultant to write me a bit of magic to do something, I can tell him to make a "managed code assembly" and that should result in something I can call from Winbatch, as long as it does not require "events" or "call backs".  Is that essentially correct?
(sorry if this is dumb -- really straining the limits of my understanding here)
-Kirby
Title: Re: CLR and VB.net dll
Post by: td on November 15, 2013, 07:28:21 AM
Quote from: kdmoyers on November 15, 2013, 05:29:31 AM
So, if I'm getting this right, When I want my .Net consultant to write me a bit of magic to do something, I can tell him to make a "managed code assembly" and that should result in something I can call from Winbatch, as long as it does not require "events" or "call backs".  Is that essentially correct?
(sorry if this is dumb -- really straining the limits of my understanding here)
-Kirby

I don't think you need to mention 'managed code assembly'.  If he is producing '.Net' (the MSFT marketing name for the MSFT implementation of the Common Language Infrastructure) assemblies, it will work given the two restriction you mentioned.  Note that a .Net based assembly can be in MicroSoft Intermediate Language (MSIL) assembled Bytecode or compiled into native code using MFST's ngen tool. It doesn't matter to WinBatch.

While dotNet seems to be new to many WinBatch users for some reason, it has been around for 13 years and is used in somewhere around  one-half of all Windows based software development projects.  There are many freely available assemblies and source code all over the web for solving all manor of problem.   The MSFT's CLI based language compilers are build into the Framework Class Library so you don't even need to buy anything to produce assemblies you write yourself.
Title: Re: CLR and VB.net dll
Post by: Deana on November 15, 2013, 10:17:37 AM
Quote from: kdmoyers on November 15, 2013, 05:29:31 AM
So, if I'm getting this right, When I want my .Net consultant to write me a bit of magic to do something, I can tell him to make a "managed code assembly" and that should result in something I can call from Winbatch, as long as it does not require "events" or "call backs".  Is that essentially correct?
(sorry if this is dumb -- really straining the limits of my understanding here)
-Kirby

Yes, you hit the proverbial nail on the head.

WinBatch supports access to the Microsoft .Net Framework. WinBatch makes this possible by hosting the common language runtime (CLR) and exposing functionality for creating and accessing the members of classes, structures and enumerations of managed code assemblies (DLLs) that are part of or based on the Framework.

You may want to give the consultant this list of limitations:

dotNet Limitations in WIL

While WinBatch CLR hosting has many advantages, it has limitations that should be considered before deciding whether or not to implement a solution using Framework based assemblies. The following is a partial listing of those limitations:
Title: Re: CLR and VB.net dll
Post by: td on November 15, 2013, 01:03:11 PM
The only WinBatch dotNet limitations that are relevant to  a consultant creating an assembly are the lack of support for delegate (events) and uninstantiated  generics.  The former being the more important.