Code Monkey home page Code Monkey logo

explainpowershell's Introduction

Explain PowerShell

PowerShell version of explainshell.com

On ExplainShell.com, you can enter a Linux terminal oneliner, and the site will analyze it, and return snippets from the proper man-pages, in an effort to explain the oneliner. I have created a similar thing but for PowerShell here:

https://www.explainpowershell.com

If you'd like a tour of this repo, open the repo in VSCode (from here with the '.' key), and install the CodeTour extension. In the Explorer View, you will now see CodeTour all the way at the bottom left. There currently are four code tours available:

  • High level tour of the application
  • Tour of development container
  • Tour of the Azure bootstrapper
  • Tour of the help collector

Goal

I want to make it easy for anyone to find out what a certain line of PowerShell code does. I envision something like this:

mock

Azure Resources overview

  • C# Azure Function backend API that analyzes PowerShell oneliners.
  • Azure Storage that hosts Blazor Wasm pages as a static website.
  • Azure Storage Table in which all help metadata is for currently supported modules.

azure resources

Development

This repo offers a development container, with a bootstrap script to get you fully up and running.

  • Clone repo
  • MAKE SURE THAT THE FILE .devcontainer\library-scripts\azcli-debian.sh HAS 'LF' LINE ENDINGS (NOT CRLF). You can very easily convert them to LF in VSCode by opening the file, going to the statusbar in the bottom right, you will find it saying either LF or CRLF. If it says CRLF, change it to LF and save the file.
  • Open in VSCode, and accept the offer to open in development container
  • Container is built, and automatically runs the bootstrap.ps1 script which will:
    • Check permissions on your repo so dotnet works without sudo
    • Perform dotnet restore
    • Install all necessary PowerShell modules
    • Fill local Azurite Table emulator with the necessary database
    • Run all tests for you, so you know everything is working

There are multiple preconfigured launch configurations and tasks. Use the Watch run .. tasks if you want to iterate quickly without debugging (these use dotnet watch under the hood).

Please note that in the Development Container, the BlazorWasmDebugginExtension extension does not work, but it is loaded/wasm is detected. Because of this, when running the solution, you will see these two errors, which can be completely ignored: errors at run time that can be ignored

Access to local emulated db

The local emulated db lives in the Azurite container. This container is automatically started when you open the repository in a Development Container. It should be accessible through http://localhost:10002/devstoreaccount1/HelpData with for instance Azure Storage Explorer, with the default development keys. See Azurite documentation for more info. Keep in mind that the Azurite container access works with timing based auth. If the docker container clock deviates from the system clock, you cannot authenticate. On Windows, this has been a bug, that is fixed in WSL2 kernel 5.10.16.3. To see your WSL2 kernel version, use uname -r. Read more information

Deploying to Azure

Deploying to Azure is done using GitHub Actions. To set everything up, you will need to create an Azure resource group, an service principal for that group. Also you will need to save the secret for that service principal in GitHub as a secret. Lastly you need to give your resources a name. I wrote a script so you can sit back and relax while all that is being done for you. Just make sure you log on to GitHub an Azure when prompted.

./azuredeploymentbootstrapper.ps1 -SubscriptionId 12345678-91e7-42d9-bb2d-09876543321 -ResourceGroupName MyExplainPowerShell -AzureLocation westeurope

After this, go to your explainpowershell fork on GitHub. Under Actions, run the Deploy Azure Infra workflow, then the Deploy app to Azure workflow and run ./explainpowershell.helpwriter.ps1 -Force -IsProduction -ResourceGroupName $ResourceGroupName -StorageAccountName $StorageAccountName. The Url where you can reach your version of the project can be found in the Azure Portal. Under the storage account resource that was deployed, find the Static Website entry in the menu. It is the Url for Primary Endpoint. Alternatively, you can retrieve it with az:

$myStorageAccountName = ".."
(az storage account show --name $myStorageAccountName | convertfrom-json).primaryEndpoints.web

explainpowershell's People

Contributors

jawz84 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

rhvdpols

explainpowershell's Issues

Explaining DSC keywords throws exceptions on DevContainer

When runing the application in a DevContainer and sending:

configuration MyDscConfig {sdf}

This happens:

# log
[2021-06-12T19:53:44.338Z] Executing 'SyntaxAnalyzer' (Reason='This function was programmatically called via the host APIs.', Id=f5f0071b-c60e-4893-a083-0f6903777f82)
[2021-06-12T19:53:44.339Z] PowerShell code sent: configuration MyDscConfig {sdf}
Unhandled exception. System.TypeInitializationException: The type initializer for 'System.Management.Automation.Tracing.PSEtwLog' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'System.Management.Automation.Tracing.PSSysLogProvider' threw an exception.
 ---> System.DllNotFoundException: Unable to load shared library 'libpsl-native' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibpsl-native: cannot open shared object file: No such file or directory
   at System.Management.Automation.Tracing.NativeMethods.OpenLog(IntPtr ident, SysLogPriority facility)
   at System.Management.Automation.Tracing.SysLogProvider..ctor(String applicationId, PSLevel level, PSKeyword keywords, PSChannel channels)
   at System.Management.Automation.Tracing.PSSysLogProvider..cctor()
   --- End of inner exception stack trace ---
   at System.Management.Automation.Tracing.PSSysLogProvider..ctor()
   at System.Management.Automation.Tracing.PSEtwLog..cctor()
   --- End of inner exception stack trace ---
   at System.Management.Automation.Tracing.PSEtwLog.LogOperationalInformation(PSEventId id, PSOpcode opcode, PSTask task, PSKeyword keyword, Object[] args)
   at System.Management.Automation.Remoting.RemoteSessionNamedPipeServer.ProcessListeningThread(Object state)
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ThreadHelper.ThreadStart(Object obj)

localhost website hangs:
image

Works just fine on the live website:

image

There should be a high level design

The High Level Design (HLD) should describe:

microservice / modular approach, split up in roughly these components:

  • Command line analyzer (AST, alias resolver) -> azure function?
  • PSGallery Module scraper (background job) -> azure function
  • Help analyzer/cache builder (background job) -> azure function
  • Help-to-token matcher
  • Database for help (meta)information
  • frontend website

Speed up module help pipeline

Improve speed of helpwriter in the pipeline by eliminating the need for Azure PowerShell (which takes forever to load / login to from azure/login@v1)

Use Az cli instead in https://github.com/Jawz84/explainpowershell/blob/09f902583fc4df8ec655d006464ce01b6c861fdb/explainpowershell.helpcollector/helpwriter.ps1

Get storage account key
$a = az storage account keys list --resource-group powershellexplainer --account-name explainpowershell | convertfrom-json
$a | where keyname -eq key2 | select -exp value
$key2 = $a | where keyname -eq key2 | select -exp value

how to read an entity:
az storage entity show --account-name explainpowershell --table-name TestHelpData --partition-key CommandHelp --row-key it --account-key $key2

write entity:
see here: https://github.com/Azure/azure-cli-samples/blob/master/storage/tables.md

Troubles with Get-ADUser

Analyzing Get-aduser -Filter { $_.SamAccountName -like '*demo*' -and $_.PasswordNeverExpires -eq $true } throws an unhandled exception.

I know it is invalid filter syntax for Get-ADUser, it's just a demo. The real one, Get-aduser -Filter { SamAccountName -like '*demo*' -and PasswordNeverExpires -eq $true }, has other problems. Properties inside filter aren't detected, but that's ActiveDirectory-module specific syntax so it's a different issue. ๐Ÿ™‚

ParseError should be handled gracefully

ParseExceptions should be handled better, user should be notified what went wrong.

Event time 4/19/2021, 1:18:42 AM (Local time) ย 
Message Exception while executing function: SyntaxAnalyzer At line:1 char:35 + Gci *.json | %{iex (gc $_.FullName} + ~ Missing closing ')' in expression. ย 
Exception type System.Management.Automation.ParseException

current behaviour: http500 without any context
expected behaviour: a message to the user what's wrong with their oneliner

cc @1RedOne thanks!

Create 'best effort' parameter explainer

Command parameters are now largely left dangling. We want to provide some context, but first we need to figure out how to get that information from cmdlet help and store it.
Also cmdlet parameter binding is harder than it looks.

Request support for a module

You can automatically request support for a module via this issue.
Comment with ONLY the name of the module you would like to see added, and this GitHub Action will automatically try to install it from PSGallery and process it.

Note: this GitHub Action is best-effort. Feel free to create a new issue if your module was not added correctly.

Comments starting with '#.' will be ignored by the Action.

Baseclass inheritance results in Exception

Throws exception:

class Person {[int]$age ; Person($a) {$this.age = $a}}; class Child : Person {[string]$School   ;   Child([int]$a, [string]$s ) : base($a) {         $this.School = $s     } }
#log:
[2021-06-12T19:46:13.911Z] PowerShell code sent: class Person {[int]$age ; Person($a) {$this.age = $a}}; class Child : Person {[string]$School   ;   Child([int]$a, [string]$s ) : base($a) {         $this.School = $s     } }
[2021-06-12T19:46:13.934Z] error
[2021-06-12T19:46:13.934Z] explainpowershell: Object reference not set to an instance of an object.
[2021-06-12T19:46:13.936Z] Executed 'SyntaxAnalyzer' (Succeeded, Id=81cd567f-89e4-4054-a6c6-4389f5f28c51, Duration=32ms)

image

Static property is not correctly explained

Example :

$Enumerable=[System.Data.DataTableExtensions]::AsEnumerable($Dt) ; $D=[Datetime]::Now

The first instruction is, in my opinion, correctly explained.

Invoke the static method 'AsEnumerable' on class '[System.Data.DataTableExtensions]', with arguments '$Dt'.

For a static property is not the case :

Access the property 'Now' on object '[Datetime]'

instead of

Access the static property 'Now' on class '[Datetime]'

Baseclass inheritance results in Exception

Throws exception:

class Person {[int]$age ; Person($a) {$this.age = $a}}; class Child : Person {[string]$School   ;   Child([int]$a, [string]$s ) : base($a) {         $this.School = $s     } }
#log:
[2021-06-12T19:46:13.911Z] PowerShell code sent: class Person {[int]$age ; Person($a) {$this.age = $a}}; class Child : Person {[string]$School   ;   Child([int]$a, [string]$s ) : base($a) {         $this.School = $s     } }
[2021-06-12T19:46:13.934Z] error
[2021-06-12T19:46:13.934Z] explainpowershell: Object reference not set to an instance of an object.
[2021-06-12T19:46:13.936Z] Executed 'SyntaxAnalyzer' (Succeeded, Id=81cd567f-89e4-4054-a6c6-4389f5f28c51, Duration=32ms)

Generic types are not properly handled

Examples :

$names=[System.Collections.Generic.List[String]]::New()
{} -as [System.Action[String,int]] #only the operator is known not the operands
(${function:Print} -as [System.Action[String]])
[System.Action[String]]
{} -as [System.Action[String,int]]

That said, Bravo . Because Powershell code analysis is difficult

Results should be color coded

For easier readability, results should be color coded. For example:

Gci| select fullname

๐Ÿ”ดGet-ChildItem | ๐ŸSelect-Object fullname

๐Ÿ”ด [Gci help ]
๐Ÿ [ Select help]

There should be Proof of Concept versions of the various components

Proof of Concept should be built for the following parts:

  • AST code analyzer
  • PSgallery scraper (or something with a copy to storage with nuget?)
  • Helpfile analyzer / help cache builder
  • Database schema (what will I actually be needing?)
  • token-to-help matcher
  • frontend with fancy graphics (flask?)

Goals:

  • gather knowledge
  • find bottlenecks early

Parameter data from the helpscraper can be too big to fit in Azure table property

It seems there there are two problems here: one is that for some cmdlets, the parameter help is so big, it doesn't fit the 64k limit in an Azure Table storage property. This is why Import-Module -name didn't return any help (-allowclobber is not a valid param here). So that part needs some work, because it means some module help imports may have failed because the Parameter property data was too big. It appears I can compress the json before uploading, and that saves quite a bit of space. This is what I did to fix this for Import-Module. But now I have to figure out a way to fix this at scale.

The other problem (where the parameter data does not fit the schema) I have not even touched yet.

image

Originally posted by @Jawz84 in #64 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.