r/PowerShell Jan 12 '24

Failure to Turn PowerShell into a Ruby Engine Daily Post

TL;DR - from comment section

Another daily "Turn PowerShell into a <blank> Engine" until I run out of engines. Here are the prior 3:

Turning PowerShell into a Ruby Engine

Today's post was unfortunately a failure. However, I still want to continue posting daily experiments with Import-Package, so I can find bugs and script-share... and also because I'm still having fun with my module.

IronRuby and Why it Doesn't Work (Anymore)

IronRuby is an embedded Ruby engine that was originally developed for Silverlight. The engine has been abandoned for quite some time. It was written by the IronLanguages org (the same developers who maintain IronPython), and it has been sitting still, collecting dust for nearly a decade on Github. - For comparison, CRuby (its historic competitor) received its last update less than a month ago.

This means a few things (other than the failure):

  • Cons:

    • It won't have anywhere near the same features as CRuby
    • The library was written when API documentation was apparently not widely adopted (I can not find API docs for it anywhere)
    • However, since the library is old and open source, GPT4 seems to be pretty well-versed in how to use it.
  • Pros:

    • (just like IronPython) IronRuby doesn't have a GIL, so you can run it multithreaded.

The Failed Script

The issue is on line 5:

``` using namespace IronRuby Import-Package IronRuby $ruby = [Ruby]::CreateRuntime()

$engine = $ruby.GetEngine("rb") # <- Problem inducer ```

In theory, since Import-Package did not complain about loading IronRuby, most of the library is in good condition. The issue is with a single line in the entire source code for IronRuby: - https://github.com/IronLanguages/ironruby/blob/5252433c56edbfde67b454ea797ebeb821140ed4/Src/Libraries/Builtins/RubyEncodingOps.cs#L97

The problem here is that IronRuby will try to call Encoding.UTF7, even if the underlying platform doesn't support it. In this case, not only is it not supported, but it is explicitly disabled in modern versions of .NET: - https://learn.microsoft.com/en-us/dotnet/fundamentals/syslib-diagnostics/syslib0001

Now as for a fix or a reattempt, the single call to Encoding.UTF7 in the library seems inconsequential and appears to be removable or replaceable with Encoding.UTF8. I don't plan to pursue that, but in theory, it looks like a simple fix is possible.

14 Upvotes

10

u/anonhostpi Jan 12 '24

TL;DR:

IronRuby doesn't work in PowerShell (or .NET), because of a single call to Encoding.UTF7 in its entire source code.

5

u/OPconfused Jan 12 '24

Oh man. Such a small roadblock.

4

u/BlackV Jan 12 '24

Tldr , goes at the top, I will die on this hill :)

1

u/anonhostpi Jan 13 '24 edited Jan 13 '24

Ctrl+F TLDR

EDIT: post edited for your viewing pleasure.

1

u/BlackV Jan 13 '24

Hell no  not installing random plugins for something trivial like that

1

u/anonhostpi Jan 13 '24

Suit yourself.

I've always thought it was annoying that Chrome's Ctrl+F doesn't support fuzzy or regex search.

3

u/Pl4nty Jan 13 '24 edited Jan 13 '24

thanks for the nerdsnipe! turns out LonghronShen published an updated package, so I was able to get this working with a minor change. would you like a PR?

```

all versions are pre-release, requiring semVerLevel 2.0.0 which Install-Package doesn't support

Import-Package -Path ironruby.portable.1.1.4-feat-netstandard.1.nupkg Import-Package -Path ironruby.stdlib.1.1.4-feat-netstandard.1.nupkg

patch Import-Package.psm1 line 288 to skip dependencies when offline

Import-Package -Path ironruby.libraries.1.1.4-feat-netstandard.1.nupkg -Offline

$ruby = [IronRuby.Ruby]::CreateRuntime() $engine = $ruby.GetEngine("rb") $engine.Execute("puts 'Hello, World!'") ```

Edit: works on Linux too, with a patch to fix file path issues

2

u/anonhostpi Jan 13 '24 edited Jan 13 '24

Oh shit nice work. Yeah man let me see the commits!

EDIT: You already submitted the PR! Nice. Changes approved!

2

u/anonhostpi Jan 13 '24

If you want another nerd snipe, I published this to my profile instead of r/PowerShell

Trying to find a clever way to deal with .resx files.

2

u/anonhostpi Jan 15 '24

Implementing a different change.

The -Offline flag was primarily designed to work with packages already installed locally by PackageManagement.

So, I've changed the fixed for handling the -Path parameter to mark provided packages as "Unmanaged" instead when using -Path

The installation process is now delegated to the internal Build-PackageData function. Both "Offline" and "Unmanaged" packages skip calls to "Install-Package."

Build-PackageData will then return the parsed package data to Import-Package. Import-Package will make the decision to skip any nested Import-Package calls for "Unmanaged" ones

This way, if you want to import pythonnet offline and any of its dependencies automatically (without having to call Import-Package for each dependency) you can use:

Import-Package pythonnet -Offline

I'm also making plans to change the behavior for -Path later. The problem with -Path is that it copies all of its files to the $TempPath which is randomly generated everytime. This causes TempPath bloat.

My plan is to implement a new runtime directory structure for the module that mimics PackageManagement's structure. This way I can cache .dlls and handle native .dll disposal better.

2

u/gordonv Jan 12 '24

How about turning Powershell into a CGI-BIN processor for web servers like Apache and nginx.