DOT NET Interface Library v2: Unterschied zwischen den Versionen
K (Spelling fixes.) |
K |
||
Zeile 12: | Zeile 12: | ||
Before any communication can take place between expecco and any dotNet object, the .NET side of the bridge has to be started, and a communication path to be setup. |
Before any communication can take place between expecco and any dotNet object, the .NET side of the bridge has to be started, and a communication path to be setup. |
||
All of the bridges classes are in the < |
All of the bridges classes are in the <code>DOTNET</code> namespace; the main interface class is <code>DotNet</code>, in this namespace: |
||
< |
<code><pre> |
||
dotNetHandle := DOTNET::DotNet newWithServer. |
dotNetHandle := DOTNET::DotNet newWithServer. |
||
</ |
</pre></code> |
||
or (in JavaScript): |
or (in JavaScript): |
||
< |
<code><pre> |
||
dotNetHandle = DOTNET::DotNet.newWithServer(); |
dotNetHandle = DOTNET::DotNet.newWithServer(); |
||
</ |
</pre></code> |
||
This starts the .NET-side of the bridge (the executable named "DotNetBridge.Server.exe"), |
This starts the .NET-side of the bridge (the executable named "DotNetBridge.Server.exe"), |
||
Zeile 26: | Zeile 26: | ||
When finished, release the bridge with: |
When finished, release the bridge with: |
||
< |
<code><pre> |
||
dotNetHandle.close(); |
dotNetHandle.close(); |
||
</ |
</pre></code> |
||
which shuts down the connection and terminates the executable. |
which shuts down the connection and terminates the executable. |
||
=== Loading Assemblies === |
=== Loading Assemblies === |
||
Using the "loadLibrary"-function, well-known assemblies can be loaded: |
Using the "loadLibrary"-function, well-known assemblies can be loaded: |
||
< |
<code><pre> |
||
dotNetHandle.loadLibrary("System.Windows.Forms"); |
dotNetHandle.loadLibrary("System.Windows.Forms"); |
||
</ |
</pre></code> |
||
or: |
or: |
||
< |
<code><pre> |
||
dotNetHandle.loadLibrary("user32.dll"); |
dotNetHandle.loadLibrary("user32.dll"); |
||
</ |
</pre></code> |
||
Arbitrary files which contain assemblies are loaded with: |
Arbitrary files which contain assemblies are loaded with: |
||
< |
<code><pre> |
||
dotNetHandle.loadFile(pathToDLL); |
dotNetHandle.loadFile(pathToDLL); |
||
</ |
</pre></code> |
||
or: |
or: |
||
< |
<code><pre> |
||
dotNetHandle.loadExtension(pathToDLL); |
dotNetHandle.loadExtension(pathToDLL); |
||
</ |
</pre></code> |
||
the former loads an assembly from the machine running the bridge server (DotNetBridge.Server.exe), the latter loads it from the machine running expecco. |
the former loads an assembly from the machine running the bridge server (DotNetBridge.Server.exe), the latter loads it from the machine running expecco. |
||
<b>loadExtension</b> also makes loaded assemblies available to dynamically compiled VB/C# compilation units. |
<b>loadExtension</b> also makes loaded assemblies available to dynamically compiled VB/C# compilation units. |
||
Zeile 57: | Zeile 57: | ||
These messages can be chained, to access a hierarchy of namespaces. |
These messages can be chained, to access a hierarchy of namespaces. |
||
For example: |
For example: |
||
< |
<code><pre> |
||
dotNetHandle.System.Reflection.Assembly.LoadFile("c:\foo\bar\myAssembly.dll"); |
dotNetHandle.System.Reflection.Assembly.LoadFile("c:\foo\bar\myAssembly.dll"); |
||
</ |
</pre></code> |
||
=== Instantiating a Class === |
=== Instantiating a Class === |
||
Object instances are created via the "new"-message, sent to a global: |
Object instances are created via the "new"-message, sent to a global: |
||
< |
<code><pre> |
||
b = dotNetHandle.Button.new(); |
b = dotNetHandle.Button.new(); |
||
f = dotNetHandle.Form.new(); |
f = dotNetHandle.Form.new(); |
||
</ |
</pre></code> |
||
once instantiated, any message can be sent transparently to such an .NET object, as if it was an expecco object: |
once instantiated, any message can be sent transparently to such an .NET object, as if it was an expecco object: |
||
< |
<code><pre> |
||
b.text("Hello World"); |
b.text("Hello World"); |
||
f.controls.add(b); |
f.controls.add(b); |
||
f.showDialog(); |
f.showDialog(); |
||
</ |
</pre></code> |
||
=== Callbacks === |
=== Callbacks === |
||
Zeile 81: | Zeile 81: | ||
Here is a complete example for creating a .NET form with a callback into expecco. This code could be put into an EB (Elementary Block) of an expecco activity diagram: |
Here is a complete example for creating a .NET form with a callback into expecco. This code could be put into an EB (Elementary Block) of an expecco activity diagram: |
||
< |
<code><pre> |
||
var dotNet, form, button; |
var dotNet, form, button; |
||
// called when the .NET button is clicked |
// called when the .NET button is clicked |
||
function callBack() { |
function callBack() { |
||
dotNet.MessageBox.show("Hello from expecco"); |
dotNet.MessageBox.show("Hello from expecco"); |
||
}; |
}; |
||
dotNet = DOTNET::DotNet.newWithServer(); |
dotNet = DOTNET::DotNet.newWithServer(); |
||
dotNet.loadLibrary("System.Windows.Forms"); |
dotNet.loadLibrary("System.Windows.Forms"); |
||
button = dotNet.Button.new(); |
button = dotNet.Button.new(); |
||
button.text("Hello"); |
button.text("Hello"); |
||
button.click.add( callBack ); |
button.click.add( callBack ); |
||
form = dotNet.Form.new(); |
form = dotNet.Form.new(); |
||
button.dock( dotNet.DockStyle.fill ); |
button.dock( dotNet.DockStyle.fill ); |
||
form.controls.add( button ); |
form.controls.add( button ); |
||
form.showDialog(); |
form.showDialog(); |
||
dotNet.close(); |
dotNet.close(); |
||
</ |
</pre></code> |
||
=== Remote Dynamic Code Injection === |
=== Remote Dynamic Code Injection === |
||
Zeile 110: | Zeile 110: | ||
C#: |
C#: |
||
< |
<code><pre> |
||
typeCode := ' |
typeCode := ' |
||
using System; |
using System; |
||
Zeile 127: | Zeile 127: | ||
typeObject := dotnet getDotNetType:'SomeNamespace.SomeClass' fromCSharpSource:typeCode. |
typeObject := dotnet getDotNetType:'SomeNamespace.SomeClass' fromCSharpSource:typeCode. |
||
typeObject ConsoleWrite:'Hello, World!'. |
typeObject ConsoleWrite:'Hello, World!'. |
||
</ |
</pre></code> |
||
VB: |
VB: |
||
< |
<code><pre> |
||
moduleCode := ' |
moduleCode := ' |
||
Zeile 145: | Zeile 145: | ||
moduleObject := dotnet getDotNetType:'SomeNamespace.SomeModule' fromVBSource:moduleCode. |
moduleObject := dotnet getDotNetType:'SomeNamespace.SomeModule' fromVBSource:moduleCode. |
||
moduleObject ConsoleWrite:'Hello, World!'. |
moduleObject ConsoleWrite:'Hello, World!'. |
||
</ |
</pre></code> |
||
=== Calling ActiveX/COM Objects=== |
=== Calling ActiveX/COM Objects=== |
||
Zeile 157: | Zeile 157: | ||
In this shell, you can e.g. execute |
In this shell, you can e.g. execute |
||
tlbimp c:\windows\system32\wshom.ocx |
tlbimp c:\windows\system32\wshom.ocx |
||
which will create a file called IWshRuntimeLibrary.dll for the Windows Script Host Runtime Library in the current directory. This can then be used to automate the Windows Script Host Runtime Library Object. |
which will create a file called IWshRuntimeLibrary.dll for the Windows Script Host Runtime Library in the current directory. This can then be used to automate the Windows Script Host Runtime Library Object. |
||
Zeile 163: | Zeile 163: | ||
Here an example how to use this in code: |
Here an example how to use this in code: |
||
< |
<code><pre> |
||
|dotNet shell buttonPressed| |
|dotNet shell buttonPressed| |
||
dotNet := DotNet singletonInstance. |
dotNet := DotNet singletonInstance. |
||
Zeile 171: | Zeile 171: | ||
shell := dotNet WshShellClass new. |
shell := dotNet WshShellClass new. |
||
buttonPressed := shell popup:'Hello from Micha' secToWait:15 title:'.NET Bridge Com Demo' type:0. |
buttonPressed := shell popup:'Hello from Micha' secToWait:15 title:'.NET Bridge Com Demo' type:0. |
||
buttonPressed inspect |
buttonPressed inspect |
||
⚫ | |||
⚫ | |||
Version vom 11. Juni 2017, 11:40 Uhr
Inhaltsverzeichnis
Overview[Bearbeiten]
The .NET Interface Library (".NET Bridge") contains a mechanism to access Microsoft .NET (CLR) objects of a local or remote .NET application (a so-called .NET bridge), and an API for elementary blocks and a library of blocks to interact with these objects.
Programmatic Interface[Bearbeiten]
Access to .NET objects, classes and programs is done via a framework called "dotNET-Bridge". This framework implements transparent forwarding of expecco messages (virtual function calls) from either Smalltalk or JavaScript code to .NET objects as existent in a local or remote .NET virtual machine. Also, return values, callBacks and exception information are passed back from the .NET program to expecco. A proxy-object mechanism which catches all function calls, wraps the arguments and sends a datagram to the other bridge side is used for this to be almost completely transparent to the Smalltalk/JavaScript code inside expecco.
In addition to existing blocks of the .NET Interface Library, programmatic access to dotNET objects is sometimes useful or required. So the following information is useful if you want to write your own elementary .NET-blocks, or if you have to enhance the existing library by adding application-specific interface blocks.
Initializing / Releasing the Bridge[Bearbeiten]
Before any communication can take place between expecco and any dotNet object, the .NET side of the bridge has to be started, and a communication path to be setup.
All of the bridges classes are in the DOTNET
namespace; the main interface class is DotNet
, in this namespace:
dotNetHandle := DOTNET::DotNet newWithServer.
or (in JavaScript):
dotNetHandle = DOTNET::DotNet.newWithServer();
This starts the .NET-side of the bridge (the executable named "DotNetBridge.Server.exe"), and waits for a connection request from this program.
When finished, release the bridge with:
dotNetHandle.close();
which shuts down the connection and terminates the executable.
Loading Assemblies[Bearbeiten]
Using the "loadLibrary"-function, well-known assemblies can be loaded:
dotNetHandle.loadLibrary("System.Windows.Forms");
or:
dotNetHandle.loadLibrary("user32.dll");
Arbitrary files which contain assemblies are loaded with:
dotNetHandle.loadFile(pathToDLL);
or:
dotNetHandle.loadExtension(pathToDLL);
the former loads an assembly from the machine running the bridge server (DotNetBridge.Server.exe), the latter loads it from the machine running expecco. loadExtension also makes loaded assemblies available to dynamically compiled VB/C# compilation units.
Accessing Globals[Bearbeiten]
Globals, nameSpaces and members of a namespace are accessed using message sends to the dotNet handle, where the message name is the name of the global, namespace or interface. These messages can be chained, to access a hierarchy of namespaces. For example:
dotNetHandle.System.Reflection.Assembly.LoadFile("c:\foo\bar\myAssembly.dll");
Instantiating a Class[Bearbeiten]
Object instances are created via the "new"-message, sent to a global:
b = dotNetHandle.Button.new();
f = dotNetHandle.Form.new();
once instantiated, any message can be sent transparently to such an .NET object, as if it was an expecco object:
b.text("Hello World");
f.controls.add(b);
f.showDialog();
Callbacks[Bearbeiten]
Callbacks from .NET back into expecco are implemented via Smalltalk blocks (JavaScript anonymous functions). The bridge automatically installs an appropriate callback, whenever a block/function is given to a .NET component as a callback or hook.
Here is a complete example for creating a .NET form with a callback into expecco. This code could be put into an EB (Elementary Block) of an expecco activity diagram:
var dotNet, form, button;
// called when the .NET button is clicked
function callBack() {
dotNet.MessageBox.show("Hello from expecco");
};
dotNet = DOTNET::DotNet.newWithServer();
dotNet.loadLibrary("System.Windows.Forms");
button = dotNet.Button.new();
button.text("Hello");
button.click.add( callBack );
form = dotNet.Form.new();
button.dock( dotNet.DockStyle.fill );
form.controls.add( button );
form.showDialog();
dotNet.close();
Remote Dynamic Code Injection[Bearbeiten]
C# and VB code can be dynamically loaded and compiled:
C#:
typeCode := '
using System;
namespace SomeNamespace
{
class SomeClass
{
public static void ConsoleWrite(string text)
{
Console.Write(text)
}
}
}
'.
typeObject := dotnet getDotNetType:'SomeNamespace.SomeClass' fromCSharpSource:typeCode.
typeObject ConsoleWrite:'Hello, World!'.
VB:
moduleCode := '
Imports System
Namespace SomeNamespace
Public Module SomeModule
Sub ConsoleWrite(ByVal text As String)
Console.WriteLine (text)
End Sub
End Module
End Namespace
'.
moduleObject := dotnet getDotNetType:'SomeNamespace.SomeModule' fromVBSource:moduleCode.
moduleObject ConsoleWrite:'Hello, World!'.
Calling ActiveX/COM Objects[Bearbeiten]
It's possible to make calls to ActiveX/COM Objects through the bridge.
To do this, you need to create a dotNet Assembly with the types from a .tlb or .ocx file.
This can be done with the tlbimp utility which is part of VisualStudio (reachable through the VS Dev CMD Shell...)
In this shell, you can e.g. execute
tlbimp c:\windows\system32\wshom.ocx
which will create a file called IWshRuntimeLibrary.dll for the Windows Script Host Runtime Library in the current directory. This can then be used to automate the Windows Script Host Runtime Library Object.
Here an example how to use this in code:
|dotNet shell buttonPressed|
dotNet := DotNet singletonInstance.
dotNet loadFile:'C:\Temp\IWshRuntimeLibrary.dll'.
shell := dotNet WshShellClass new.
buttonPressed := shell popup:'Hello from Micha' secToWait:15 title:'.NET Bridge Com Demo' type:0.
buttonPressed inspect
to be continued
See Also[Bearbeiten]
The Java Interface Plugin & Library, which implements a likewise interface for Java applications/libraries.
Back to Plugins
Back to Online Documentation.