Skip to content

Instantly share code, notes, and snippets.

@ImaginaryDevelopment
Last active December 14, 2016 18:04
Show Gist options
  • Save ImaginaryDevelopment/f4bc33ae75bdf29e5aad8fd4045f193d to your computer and use it in GitHub Desktop.
Save ImaginaryDevelopment/f4bc33ae75bdf29e5aad8fd4045f193d to your computer and use it in GitHub Desktop.
.net run elevated capturing output (F# FAKE build script)
#r @"packages/FAKE/tools/FakeLib.dll"
open Fake
let lprunPath = @"C:\ProgramData\LINQPad\Updates50\510\lprun.exe"
type System.String with
static member Delimit delimiter (items:string seq) =
String.Join(delimiter,items |> Array.ofSeq)
module Proc =
// ExecProcess is a thin wrapper around Process.Start
// docs at
// https://github.com/fsharp/FAKE/blob/master/src/app/FakeLib/ProcessHelper.fs#L184-L185
// https://github.com/fsharp/FAKE/blob/master/src/app/FakeLib/ProcessHelper.fs#L68-L107
let ExecProcessElevated cmd args timeOut =
ExecProcess (fun si ->
si.Verb <- "runas"
si.Arguments <- args
si.FileName <- cmd
si.UseShellExecute <- true) timeOut
// wrapper for fake built-in in case we want the entire process results, not just the exitcode
let runElevated cmd args timeOut =
let tempFilePath = System.IO.Path.GetTempFileName()
// hacky work around for not being able to capture output of an elevated process
let resultCode = ExecProcessElevated "cmd" (sprintf "/c %s %s > %s" cmd args tempFilePath) timeOut
trace "reading output results of runElevated"
let outputResults = File.ReadAllLines tempFilePath
File.Delete tempFilePath
// idiomaticisizing the result, not needed, especially for uses outside of FAKE
let processResult = ProcessResult.New resultCode (ResizeArray<_> outputResults) (ResizeArray<_>())
(String.Delimit "\r\n" outputResults)
|> trace
processResult
(* more context of me calling it, in case something special caused it to work that wasn't included above *)
Target "SetupNode" (fun _ ->
// install Choco
// fake has a run elevated, let's see if that works
//Sec.requireAdmin()
let chocoPath =
match Proc.findCmd "choco" with
| Some x -> x
| None ->
let resultCode =
ExecProcessElevated
"@powershell"
"""-NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" """
(TimeSpan.FromMinutes 3.)
resultCode
|> sprintf "choco install script returned %i"
|> trace
if resultCode <> 0 then
failwithf "Task failed"
// choco is installled, we think
// probably won't work if it was just installed, the %path% variable given to/used by a process is immutable
else
// we could be wrong, check again
match Proc.findCmd "choco" with
| Some x -> x
| None -> failwithf "choco was installed, in order for choco to be found or used, this has process has to be restarted"
// check if our hack runElevated is actually elevated, test can provide rejection or support, not proof
let hackResult = Proc.runElevated lprunPath @" ""C:\projects\LinqPad\LinqPad\LINQPad Queries\LpRun\requireAdmin.linq"" " (TimeSpan.FromSeconds 3.)
trace (sprintf "hackResult: %A" hackResult)
// choco install nodeJs
let nodePath =
let results = Proc.runElevated "echo" "hello admin" (TimeSpan.FromSeconds 3.)
trace (sprintf "%A" results)
()
)
// duplicate of the .linq file, but with syntax highlighting that github won't do in that file
module Sec =
open System.Security.Principal
let getIsAdmin() =
WindowsIdentity.GetCurrent()
|> WindowsPrincipal
|> fun wp -> wp.IsInRole(WindowsBuiltInRole.Administrator)
let requireAdmin () =
let runningAsAdmin = getIsAdmin()
if not runningAsAdmin then
failwithf "Can't alter hosts file without admin permissions"
Sec.requireAdmin()
printfn "success!"
Console.WriteLine("success! admin did not throw")
<Query Kind="FSharpProgram" />
module Sec =
open System.Security.Principal
let getIsAdmin() =
WindowsIdentity.GetCurrent()
|> WindowsPrincipal
|> fun wp -> wp.IsInRole(WindowsBuiltInRole.Administrator)
let requireAdmin () =
let runningAsAdmin = getIsAdmin()
if not runningAsAdmin then
failwithf "Can't alter hosts file without admin permissions"
Sec.requireAdmin()
printfn "success!"
Console.WriteLine("success! admin did not throw")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment