Last active
December 14, 2016 18:04
-
-
Save ImaginaryDevelopment/f4bc33ae75bdf29e5aad8fd4045f193d to your computer and use it in GitHub Desktop.
.net run elevated capturing output (F# FAKE build script)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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) | |
() | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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