System.Windows.Forms.Clipboard via ClearScript into JavaScript in C#
Tags: csharp, clearscript, clipboard
Published: 2019-10-25 08:46:33

It's been an interesting week. One of the successes this week was working out how to connect to `System.Windows.Forms` and use the clipboard without having to add `System.Windows.Forms` to the project. 

This really only has meaning within the context of [ClearScript](https://github.com/microsoft/ClearScript), but if you want, you can drop by [Lychen](https://github.com/axtens/Lychen) or [LychenBASIC](https://github.com/axtens/LychenBASIC) where the code is implemented. 

Both Lychen and LychenBASIC have an `attach` function. This enables one to attach an assembly to the running instance of whatever language you're running on through ClearScript. Attach is exposed to the language engine using
```csharp
            v8.Script.attach = (Action<string, string>)Attach;
``` 
for Lychen and 
```csharp
            vbscriptEngine
                .Script
                .Attach = (Action<string, string>)Attach;
```
for LychenBASIC and is coded as follows:
```csharp
        private static void Attach(string dllPath, string name = "")
        {
            var htc = new HostTypeCollection();
            try
            {
                //var assem = System.Reflection.Assembly.LoadFrom(dllPath);
                var assem = Assembly.Load(AssemblyName.GetAssemblyName(dllPath));
                htc.AddAssembly(assem);
                if (name.Length == 0)
                {
                    name = assem.FullName.Split(',')[0];
                }
                v8.AddHostObject(name, htc);
                Console.WriteLine($"Attached {dllPath} as {name}");

            }
            catch (ReflectionTypeLoadException rtle)
            {
                foreach (var item in rtle.LoaderExceptions)
                {
                    Console.WriteLine(item.Message);
                    logger.Error(item.Message);
                }
            }
            catch (FileNotFoundException fnfe)
            {
                Console.WriteLine(fnfe.Message);
                logger.Error(fnfe.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                logger.Error(e.Message);
            }
        }
```
the `logger` is an NLog (currently only used in Lychen).

You may remember me grumbling about oddities with `Assembly.LoadFrom`. Well now we use `Assembly.Load(AssemblyName.GetAssemblyName(dllPath))` and avoid those problems.

So I currently have a folder on my hard disk containing the nuget package for System.Windows.Forms. I downloaded the package using NuGet as follows:
```
C:\Packages\SystemWindowsFormsPackages>nuget install System.Windows.Forms
Feeds used:
  https://api.nuget.org/v3/index.json
  C:\Users\bugma\.dotnet\NuGetFallbackFolder
  C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\

Installing package 'System.Windows.Forms' to 'C:\Packages\SystemWindowsFormsPackages'.
  GET https://api.nuget.org/v3/registration4-gz-semver2/system.windows.forms/index.json
  OK https://api.nuget.org/v3/registration4-gz-semver2/system.windows.forms/index.json 1200ms


Attempting to gather dependency information for package 'System.Windows.Forms.4.0.0' with respect to project 'C:\Packages\SystemWindowsFormsPackages', targeting 'Any,Version=v0.0'
Gathering dependency information took 27.68 ms
Attempting to resolve dependencies for package 'System.Windows.Forms.4.0.0' with DependencyBehavior 'Lowest'
Resolving dependency information took 0 ms
Resolving actions to install package 'System.Windows.Forms.4.0.0'
Resolved actions to install package 'System.Windows.Forms.4.0.0'
Retrieving package 'System.Windows.Forms 4.0.0' from 'nuget.org'.
  GET https://api.nuget.org/v3-flatcontainer/system.windows.forms/4.0.0/system.windows.forms.4.0.0.nupkg
  OK https://api.nuget.org/v3-flatcontainer/system.windows.forms/4.0.0/system.windows.forms.4.0.0.nupkg 965ms
Installing System.Windows.Forms 4.0.0.
Adding package 'System.Windows.Forms.4.0.0' to folder 'C:\Packages\SystemWindowsFormsPackages'
Added package 'System.Windows.Forms.4.0.0' to folder 'C:\Packages\SystemWindowsFormsPackages'
Successfully installed 'System.Windows.Forms 4.0.0' to C:\Packages\SystemWindowsFormsPackages
Executing nuget actions took 2.74 sec

C:\Packages\SystemWindowsFormsPackages>dir /s/b
C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0
C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0\.signature.p7s
C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0\lib
C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0\System.Windows.Forms.4.0.0.0.nupkg
C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0\lib\System.Windows.Forms.dll
```
Now to the demo of `System.Windows.Forms.Clipboard.SetText`:
```
C:\>lb /REPL
LychenBASIC: attach "C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0\lib\System.Windows.Forms.dll", "SWFC"
Attached C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0\lib\System.Windows.Forms.dll as SWFC
LychenBASIC: print SWFC
Microsoft.ClearScript.HostTypeCollection
LychenBASIC: print SWFC.System
Microsoft.ClearScript.PropertyBag
LychenBASIC: print SWFC.System.Windows
Microsoft.ClearScript.PropertyBag
LychenBASIC: print SWFC.System.Windows.Forms
Microsoft.ClearScript.PropertyBag
LychenBASIC: print SWFC.System.Windows.Forms.Clipboard
HostType:Clipboard
LychenBASIC: print SWFC.System.Windows.Forms.Clipboard.SetText
HostMethod:SetText
LychenBASIC: print SWFC.System.Windows.Forms.Clipboard.SetText("hello world")
Microsoft.ClearScript.VoidResult
LychenBASIC: hello world
``` 
"hello world" appears after a right-mousebutton click.

And in Lychen (sans all the otherwise useless prints)
```
C:\>Lychen.exe
Lychen> attach("C:\\Packages\\SystemWindowsFormsPackages\\System.Windows.Forms.4.0.0.0\\lib\\System.Windows.Forms.dll", "SWFC")
Attached C:\Packages\SystemWindowsFormsPackages\System.Windows.Forms.4.0.0.0\lib\System.Windows.Forms.dll as SWFC
Lychen> print(SWFC.System.Windows.Forms.Clipboard.SetText("goodbye world"))
Microsoft.ClearScript.VoidResult
Lychen> goodbye world
```
"goodbye world" appearing on right-mouseclick.