Skip to content

Hosting powershell sessions inside golang not using exec enabling bi directional communication

License

Notifications You must be signed in to change notification settings

rooneysh/go-powershell

 
 

Repository files navigation

Build Status Go Report Card gopherbadger GoDoc GitHub commits since latest release (branch)

Goal

The goal of this project is to enable you to quickly write golang code and interact with windows via powershell and not use exec. Because powershell is a powerful scripting language you will sometimes want to call back into golang. This is also enabled by this project. Also due to sometimes wanting to host .net and powershell giving you an easy way to wrap .net modules and functions and objects, this project also enables that.

Features:

  1. Call from golang to powershell
  2. Call from powershell to golang (via special Send-HostCommand commandlet)
  3. Easy logging - Trap host output in powershell and call custom logging routines in golang
  4. Uses syscall - so do not need to use cGo

Status

It works

  1. call scripts / cmdlets
  2. reuse variables between calls / invocation
  3. Call from golang to powershell
  4. Call from powershell back to golang (via special Send-HostCommand commandlet)
  5. trap host output in powershell and call custom logging routines in golang
  6. has automated tests
  7. Docs - if you missed the badge above go to https://godoc.org/github.com/KnicKnic/go-powershell/pkg/powershell

This project is not api stable, however I believe it will be simple if you do use the current api to migrate to any future changes.

TODO:

  • add some code for easy back and forth json serialization of complex objects
  • more examples / tests
  • example / helper classes around exception
  • a doc overview
  • plumb through callback handler for each specific logging type (verbose, debug, warning, ...)
  • support for default loggers, like glog or log (in separate package)

Usage

package main

import (
	"fmt"
	"github.com/KnicKnic/go-powershell/pkg/powershell"
)

func main() {
	// create a runspace (where you run your powershell statements in)
	runspace := powershell.CreateRunspaceSimple()
	// auto cleanup your runspace
	defer runspace.Close()

	// gets whatever environment variable we request
	//     wrapping $args[0] inside $() so powershell understands [0] associated with $args
	getEnvironmentVariable := `$environVariable = get-childitem "env:\$($args[0])";`

	// Execute the statement
	// false - says to not execute the statement in a temporary child scope
	//     meaning that the variables will be available to future invocations
	// nil - means we didn't name any arguments
	// "OS" - after first 3 parameters comes the unnamed arguments which we reference via $args[index]
	results1 := runspace.ExecScript(getEnvironmentVariable, false, nil, "OS")
	//not deferring close as we do not need the results
	results1.Close()

	returnEnvironmentInfo := `"emitting your $($environVariable.Name) is $($environVariable.Value)"`
	// true - we are choosing the create in a temporary child scope, the parent scope variables are still accessible to us
	//     we could however choose to specify false and be in the same scope
	results2 := runspace.ExecScript(returnEnvironmentInfo, false, nil)
	// auto cleanup all results returned
	defer results2.Close()

	// print the string result of the first object from the last statement (which happens to already be a string)
	fmt.Println(results2.Objects[0].ToString())

	// Output: emitting your OS is Windows_NT
}

Dependencies

This project has a dependency on native-powershell. This is a c++/cli project that enables interacting with powershell through a C DLL interface.

Using native-powershell

  1. Simply fetch the dependencies, go get -d . and then make sure to build, go build
  2. Copy the precompiled psh_host.dll into your location so it can be found when running the app
    1. cmd - copy %GOPATH%\src\github.com\KnicKnic\go-powershell\bin\psh_host.dll .
    2. powershell - copy "$($env:GOPATH)\src\github.com\KnicKnic\go-powershell\bin\psh_host.dll" .
  3. I ended up checking in the psh_host.dll and host.h (to make things easy)
    1. I could not find a better way to go about this and still have things be easy.

Docs

https://grokbase.com/t/gg/golang-nuts/154m672a6t/go-nuts-linking-cgo-with-visual-studio-x64-release-libraries-on-windows

About

Hosting powershell sessions inside golang not using exec enabling bi directional communication

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 89.5%
  • C 7.8%
  • PowerShell 2.7%