interactive icon indicating copy to clipboard operation
interactive copied to clipboard

Out-Gridview in .NET (PowerShell) kernel fails

Open claudio-salvio opened this issue 4 years ago • 12 comments

Hello

Describe the bug

When I try to use Out-Gridview in a code cell of a notebook with .NET (PowerShell) kernel it fails.

Is there any way to use Out-Gridview in a code cell when the notebook kernel is .NET (PowerShell)? I use Out-GridView a lot as a selection tool when the kernel is PowerShell and would like to be able to do it also with .NET (PowerShell). Not being able to do it is something that stops me from adopting the latter.

The problem exists in Azure Data Studio, Jupyter Notebook and VSCode. For more info see: Notebook, Out-Gridview in .NET (PowerShell) kernel fails #17105

In case it is not currently possible, will you be able to advise me where to make the request?

Regards

Please complete the following:

Which version of .NET Interactive are you using? (In a notebook, run the #!about magic command. ): 1.0.255902+b0afbdc47dec91e62b0c5cb587a0f2c24242eca8

  • OS
    • [ ] Windows 11
    • [x] Windows 10
    • [x] Windows Server 2022
    • [ ] macOS
    • [ ] Linux (Please specify distro)
    • [ ] iOS
    • [ ] Android
  • Browser
    • [ ] Chrome
    • [ ] Edge
    • [ ] Firefox
    • [ ] Safari
  • Frontend
    • [x] Jupyter Notebook
    • [ ] Jupyter Lab
    • [ ] nteract
    • [x] Visual Studio Code
    • [ ] Visual Studio Code Insiders
    • [ ] Visual Studio
    • [x] Other (please specify) Azure Data Studio

Screenshots

md5=6d18b72a66c0a13874e22c99f616353c

claudio-salvio avatar Nov 26 '21 16:11 claudio-salvio

Out-GridView launches an external window so it won't work but give this should:

$processes = Get-Process
$processes | Select Name, Id | Out-Default

jonsequitur avatar Mar 22 '22 17:03 jonsequitur

Hello @jonsequitur

Apologies for not having detected your response earlier, being an issue of November 2021 I had already resigned myself to the fact that it would remain unsolved.

Unfortunately your suggestion does not work for me.

As I mentioned initially, I want to use Out-GridView as a selection tool inside a PowerShell (.Net Interactive) cell within a notebook. No offense intended, I ask you to please re-read my initial post.

It seems to me that as it works now ".Net Interactive" is not very interactive. In fact the PowerShell (Jupyter kernel) does allow you to use Out-GridView in the way I want.

Can you think of a way in which I can achieve the interactivity that Out-GridView provides in other contexts when used with the -OutputMode parameter as Single or Multiple ?

An example of what I want to do is:

$processes = Get-Process
$processesToStop = $processes = $processes | Out-GridView -OutputMode Multiple  #Here I select the processes to kill
$processesToStop | Stop-Process

Best regards, Claudio Salvio

claudio-salvio avatar Apr 21 '22 20:04 claudio-salvio

@daxian-dbw Any insights here?

In fact the PowerShell (Jupyter kernel) does allow you to use Out-GridView in the way I want.

@claudio-salvio Can you point me to this kernel and/or provide an example of what the experience looks like when it works as you would like?

jonsequitur avatar Apr 22 '22 01:04 jonsequitur

@jonsequitur

Thank you for your prompt reply.

In September 2021, I started the search for a solution to this issue in the Azure Data Studio forum with the issue Notebook, Out-Gridview in .NET (PowerShell) kernel fails #17105 .

Based on the discussion there, I considered the problem to be related to Dotnet Interactive and registered this issue here in November 2021.

Attached is more info regarding the issue obtained using Azure Data Studio (ADS).

In ADS, with the PowerShell kernel (Jupyter Python based) the cell runs normally. The Out-GridView window appears, I can select rows and the $processesToStop variable is assigned with the selected processes. image

In ADS, with the PowerShell kernel (.NET Interactive) the cell execution gives an error when running: "Out-GridView: Exception has been thrown by the target of an invocation.". The Out-GridView window does not appear and -as expected in this case- $processesToStop is set to null since no selection has been made. image

In Visual Studio Code, with the PowerShell kernel (.NET Interactive) something different happens: the cell keeps running endlessly and the Stop button does not work to stop the execution. To interrupt it, it is necessary to close the VSCode window. image

Let me know if you need any other information.

Best regards, Claudio Salvio

claudio-salvio avatar Apr 22 '22 02:04 claudio-salvio

I'm afraid Out-GridView won't work in .NET Interactive because it depends on WPF. For PowerShell Core, When building package for Windows, we use Microsoft.NET.Sdk.WindowsDesktop instead of Microsoft.NET.Sdk to include the WPF components, and that's why Out-GridView works in PowerShell Core on Windows. .NET Interactive doesn't have WPF components included, so it won't work. Also, WPF application requires STA thread apartment.

For the PowerShell kernel (Jupyter Python based), it actually has a fully fledged Windows PowerShell process running behind the scene, and that's why Out-GridView works there.

daxian-dbw avatar Apr 22 '22 18:04 daxian-dbw

Thanks, Dongbo! Is there an alternative approach you can think of that would work for this? Is there a module that could be loaded at runtime that might enable this?

jonsequitur avatar Apr 22 '22 20:04 jonsequitur

Hello @daxian-dbw

Regarding your comment:

"I'm afraid Out-GridView won't work in .NET Interactive because it depends on WPF. For PowerShell Core, When building package for Windows, we use Microsoft.NET.Sdk.WindowsDesktop instead of Microsoft.NET.Sdk to include the WPF components, and that's why Out-GridView works in PowerShell Core on Windows."

it would seem that the most obvious solution is for .Net Interactive to also use Microsoft.NET.Sdk.WindowsDesktop. Is there any obstacle for that to happen?

I consider that in "literate programming" it is very necessary to have interaction mechanisms such as the one offered by Out-GridView.

In my personal case, since a couple of years ago, I work with notebooks almost every day. Because of the way I use them, I usually need to select items from lists and other types of tasks that involve real interactivity.

I raised an issue regarding Out-GridView because it is by far the most necessary for me in this aspect but I understand that this problem is not limited to this function. It also affects other very useful and interactive features such as Show-Command.

As the support for notebooks with PowerShell .NET Interactive kernel was improved I was trying to adopt it but the lack of interactivity is a big obstacle.

Can you think of any other alternative to enjoy the required functionality?

Regards Claudio Salvio

claudio-salvio avatar Apr 22 '22 21:04 claudio-salvio

I agree that this kind of interactivity is important. We'd like to support it in a way that's truly cross-platform so that notebooks can be shared across operating systems as well as in browser-based online editors like CodeSpaces, so the Windows-specific implementation is the main reason this implementation isn't supported.

We're very open to proposals.

jonsequitur avatar Apr 22 '22 21:04 jonsequitur

Is there an alternative approach you can think of that would work for this? Is there a module that could be loaded at runtime that might enable this?

No such module exists today, but potentially it may be possible to have a module (or a nuget package?) that contains all the necessary WPF assemblies. It would also require running in STA though.

daxian-dbw avatar Apr 23 '22 00:04 daxian-dbw

@daxian-dbw, @jonsequitur

No such module exists today, but potentially it may be possible to have a module (or a nuget package?) that contains all the necessary WPF assemblies.

It seems to me that it would be a very positive thing if we could have a solution in the short term, even if it is specific to Windows, until a multiplatform solution is generated.

The faithful users of Windows (in my case user of Microsoft products since MSDOS 3.x) sometimes we feel that this initiative of your company by the multiplatformity hurts us because there are cases in which it is leveled down using the logic this is multiplatform or nothing.

I find the goal of cross-platform laudable as long as it does not mean that the many millions of Windows users lose functionality that can be achieved with relative ease in our operating system.

Hopefully in this case we can move forward with something Windows-specific (as with Out-GridView in PowerShell 7.x) until the platform-independent solution is available.

It would also require running in STA though.

Honestly I am not concerned in the least for the type of work being done in these cases.

Best regards, Claudio Salvio

claudio-salvio avatar Apr 26 '22 02:04 claudio-salvio

@jonsequitur, @daxian-dbw

I had forgotten to mention another very useful command to perform authentications when using notebooks that also does not work in the PowerShell (.Net Interactive) kernel but it does in the PowerShell kernel (Python based): Get-Credential. How can I replace its use in the current state of the PowerShell (.Net Interactive) kernel ? I mean replace it without doing questionable practices like putting passwords in environment variables.

I think it is pertinent to mention that I am a user of the Secret Management module and I use it whenever I can.

Claudio Salvio

claudio-salvio avatar Apr 27 '22 12:04 claudio-salvio

Get-Credential command was changed in PowerShell Core to not use the pop-up windows, but instead provides the console experience: image

In .NET Interactive Jupyter Notebook, it works as the follows:

image

daxian-dbw avatar Apr 29 '22 16:04 daxian-dbw

This would be a tough choice - I love the multi-language ability here, especially with SQL and variable sharing but out-gridview is a vital selector tool...

Is there a way to load WPF dlls in the same way one loads other windows system dlls in powershell? The requirement to run such notebooks on widows is not a limitation in our environment.

housten avatar Feb 21 '23 15:02 housten

You can load a DLL in a C# or F# shell using #r:

#r "/path/to/assembly.dll"

jonsequitur avatar Feb 21 '23 16:02 jonsequitur

But would dlls loaded in c# be available in powershell? Since the are in different kernels It doesn't seem likely unless you can instantiate an object, share it to powershell and use it from there? And then how much work to get an out-gridview like functionality?

It would be a pain to switch languages to get user input.

On Tue, 21 Feb 2023, 17:56 Jon Sequeira, @.***> wrote:

You can load a DLL in a C# or F# shell using #r:

#r "/path/to/assembly.dll"

— Reply to this email directly, view it on GitHub https://github.com/dotnet/interactive/issues/1792#issuecomment-1438808637, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADRXBSBPVFLI3BSMCUZRRWTWYTXVNANCNFSM5I266TJQ . You are receiving this because you commented.Message ID: @.***>

housten avatar Feb 21 '23 19:02 housten

I misunderstood. You don't need to switch languages here, and the assembly loaded into C# will not be available in PowerShell.

Loading WPF assemblies in PowerShell might work. I'm not sure. Assuming it does, just be aware that the solution won't work with remote subkernels or on non-Windows machines.

jonsequitur avatar Feb 21 '23 20:02 jonsequitur

I was trying to recreate out-gridview functionality but can't get loading of a wpf assembly to work in polyglot. The code below works in the powershell ISE but nothing appears to happen in the notebook.

[void][System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework')
function Out-Grid ($properties, $context_menu_items)
{
    $dataGrid = New-Object -TypeName System.Windows.Controls.DataGrid -Property @{
        IsReadOnly = $true
        AutoGenerateColumns = $true
    }

    $dataGrid.ItemsSource = @($input)
    $grid = New-Object System.Windows.Controls.Grid
    $grid.Children.Add($dataGrid) | Out-Null
    $window = New-Object System.Windows.Window -Property @{ Content = $grid }
    $window.ShowDialog() | Out-Null
    $dataGrid.SelectedItem    
}

dir | Out-Grid

housten avatar Feb 23 '23 09:02 housten

As I mentioned in https://github.com/dotnet/interactive/issues/1792#issuecomment-1107058569, running WPF requires the thread is in the STA thread apartment, and it will fail otherwise. However, the .NET Interactive is running in MTA I believe.

daxian-dbw avatar Feb 23 '23 18:02 daxian-dbw

I was just experimenting a little with running this in a new thread in a notebook and setting the apartment state. It looks like there are some missing dependencies that might be specific to my machine. I'm not familiar enough with Out-GridView to know. I'm not sure if it's useful but here's what I did:

using System.Threading;
using Microsoft.DotNet.Interactive;
using Microsoft.DotNet.Interactive.Commands;

var newThread = new Thread(new ThreadStart(ThreadMethod));

newThread.SetApartmentState(ApartmentState.STA);

newThread.Start();
newThread.Join();

static void ThreadMethod()
{
    Console.WriteLine("ThreadMethod starting");

    var powershellCode = """
    [void][System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework')
    function Out-Grid ($properties, $context_menu_items)
    {
        $dataGrid = New-Object -TypeName System.Windows.Controls.DataGrid -Property @{
            IsReadOnly = $true
            AutoGenerateColumns = $true
        }

        $dataGrid.ItemsSource = @($input)
        $grid = New-Object System.Windows.Controls.Grid
        $grid.Children.Add($dataGrid) | Out-Null
        $window = New-Object System.Windows.Window -Property @{ Content = $grid }
        $window.ShowDialog() | Out-Null
        $dataGrid.SelectedItem    
    }

    dir | Out-Grid
    """;


    try
    {
        var result = Kernel.Root.FindKernelByName("pwsh").SendAsync(new SubmitCode(powershellCode)).GetAwaiter().GetResult();

        result.Display();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

Here's the result I saw when I ran it:

image

jonsequitur avatar Feb 23 '23 18:02 jonsequitur