FSharp.Management


The PowerShell type provider

Requirements:

  • .NET 4.5
  • PowerShell 3.0

This tutorial shows the use of the PowerShell type provider.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
// reference the type provider dll
#r "System.Management.Automation.dll"
#r "FSharp.Management.PowerShell.dll"

open FSharp.Management

// Let the type provider infer the signatures of available cmdlets
type PS = PowerShellProvider< "Microsoft.PowerShell.Management;Microsoft.PowerShell.Core" >

// now you have typed access to your PowerShell and you can browse it via Intellisense
PS.``Get-EventLog``(logName="Application", entryType=[|"Error"|], newest=2)
val it :
  PowerShellProvider.Types.PsCmdletResult<Choice<List<System.Diagnostics.EventLog>,
                                                 List<System.Diagnostics.EventLogEntry>,
                                                 List<string>>,
                                          List<System.Management.Automation.ErrorRecord>>
= Success
    (Choice2Of3
       [System.Diagnostics.EventLogEntry
          {Category = "(0)";
           CategoryNumber = 0s;
           Container = null;
           Data = [||];
           EntryType = Error;
           EventID = 1022;
           Index = 72795;
           InstanceId = 1022L;
           MachineName = "xxx";
           Message = ".NET Runtime version 4.0.30319.0 - Loading profiler failed during ...";
           ReplacementStrings = [|".NET Runtime version 4.0.30319.0 - Loading profiler failed during ..."|];
           Site = null;
           Source = ".NET Runtime";
           TimeGenerated = 4/8/2016 7:46:57 PM;
           TimeWritten = 4/8/2016 7:46:57 PM;
           UserName = "xxx";};
        System.Diagnostics.EventLogEntry
          {Category = "(0)";
           CategoryNumber = 0s;
           Container = null;
           Data = [||];
           EntryType = Error;
           EventID = 1022;
           Index = 72794;
           InstanceId = 1022L;
           MachineName = "xxx";
           Message = ".NET Runtime version 4.0.30319.0 - Loading profiler failed during ...";
           ReplacementStrings = [|".NET Runtime version 4.0.30319.0 - Loading profiler failed during ..."|];
           Site = null;
           Source = ".NET Runtime";
           TimeGenerated = 4/8/2016 7:46:25 PM;
           TimeWritten = 4/8/2016 7:46:25 PM;
           UserName = "xxx";}])

alt text

Manage Windows services

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
#r "System.ServiceProcess.dll"

let service =
    match PS.``Get-Service``(name=[|"Windows Search"|]) with
    | Success(services) when services.Length = 1 ->
        services.Head
    | _ -> failwith "Choice is ambiguous or service not found"
val service : ServiceProcess.ServiceController =
  System.ServiceProcess.ServiceController
    {CanPauseAndContinue = false;
     CanShutdown = true;
     CanStop = true;
     Container = null;
     DependentServices = [|System.ServiceProcess.ServiceController;
                           System.ServiceProcess.ServiceController|];
     DisplayName = "Windows Search";
     MachineName = ".";
     ServiceHandle = SafeServiceHandle;
     ServiceName = "WSearch";
     ServiceType = Win32OwnProcess;
     ServicesDependedOn = [|System.ServiceProcess.ServiceController|];
     Site = null;
     Status = Running;}

PS.``Start-Service``(inputObject=[|service|])

Working with Snapins

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
// get all registered PowerShell Snapins
PS.``Get-PSSnapin``(registered=true)
val it :
  PsCmdletResult<List<System.Management.Automation.PSSnapInInfo>,
                 List<System.Management.Automation.ErrorRecord>> =
  Success
    [WDeploySnapin3.0
       {ApplicationBase = "C:\Program Files\IIS\Microsoft Web Deploy V3\";
        AssemblyName = "Microsoft.Web.Deployment.PowerShell, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
        Description = "This is a PowerShell snap-in that contains cmdlets for managing Microsoft Web Deployment infrastructure.";
        Formats = seq [];
        IsDefault = false;
        LogPipelineExecutionDetails = false;
        ModuleName = "Microsoft.Web.Deployment.PowerShell.dll";
        Name = "WDeploySnapin3.0";
        PSVersion = 2.0;
        Types = seq [];
        Vendor = "Microsoft";
        Version = 9.0.0.0;}]

Working with Script Module files

  • The PowerShell script execution should be enable on the system, make sure the execution policy is appropriately set (Example: set-executionpolicy remotesigned Note that x86 and x64 runtimes have different execution policy settings)
  • The exported function in the module file needs to have the OutputType attribute if they return a value

This following module definition

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
function doSomething {
    [OutputType([string])]
    param (
        [string] $test
    )
    return $test
}

export-moduleMember -function doSomething

can be referenced like so

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
let [<Literal>]ModuleFile =
    __SOURCE_DIRECTORY__ + @"\..\..\tests\FSharp.Management.Tests\testModule.psm1"

type PSFileModule =  PowerShellProvider< ModuleFile >

PSFileModule.doSomething(test="testString")
val it : 
  PsCmdletResult<List<string>,List<System.Management.Automation.ErrorRecord>>
= Success ["testString"]

Parallel commands execution

  • The "CustomRunspace" method will create a separate runspace where you can execute all provided commands. The runspace is closed on disposing
1: 
2: 
use runspace = new PSFileModule.CustomRunspace()
runspace.doSomething(test="testString")

This can be used to execute commands in parallel

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
["testString1"; "testString2"; "testString3"]
    |> Seq.map (fun testString -> async {
                    use runspace = new PSFileModule.CustomRunspace()
                    runspace.doSomething(test=testString)
               })
    |> Async.Parallel
    |> Async.RunSynchronously
    |> ignore
        
namespace FSharp
namespace FSharp.Management
type PS = PowerShellProvider<...>

Full name: PowerShellProvider.PS
Multiple items
namespace FSharp.Management.PowerShellProvider

--------------------
type PowerShellProvider

Full name: FSharp.Management.PowerShellProvider


<summary>Typed representation of a PowerShell runspace</summary>
            <param name='Modules'>List of Modules that will be loaded at the start (separated by semicolon).</param>
            <param name='PSSnapIns'>List of PSSnapIn that will be added at the start (separated by semicolon).</param>
            <param name='Is64BitRequired'>Mark that 64bit runtime should be used for PowerShell</param>
val service : System.ServiceProcess.ServiceController

Full name: PowerShellProvider.service
union case PsCmdletResult.Success: 'TSuccess -> PsCmdletResult<'TSuccess,'TFailure>
val services : List<System.ServiceProcess.ServiceController>
property List.Length: int
property List.Head: System.ServiceProcess.ServiceController
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
Multiple items
type LiteralAttribute =
  inherit Attribute
  new : unit -> LiteralAttribute

Full name: Microsoft.FSharp.Core.LiteralAttribute

--------------------
new : unit -> LiteralAttribute
val ModuleFile : string

Full name: PowerShellProvider.ModuleFile
type PSFileModule = PowerShellProvider<...>

Full name: PowerShellProvider.PSFileModule
PowerShellProvider<...>.doSomething(?test: string) : PsCmdletResult<List<string>,List<System.Management.Automation.ErrorRecord>>


<summary><para></para></summary>
val runspace : PowerShellProvider<...>.CustomRunspace

Full name: PowerShellProvider.runspace
PowerShellProvider<...>.CustomRunspace.doSomething(?test: string) : PsCmdletResult<List<string>,List<System.Management.Automation.ErrorRecord>>


<summary><para></para></summary>
module Seq

from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val testString : string
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val runspace : PowerShellProvider<...>.CustomRunspace
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task -> Async<unit>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:System.Threading.CancellationToken -> 'T
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
Fork me on GitHub