N
N
NewDevLab2020-05-11 19:59:28
PowerShell
NewDevLab, 2020-05-11 19:59:28

How to make execution not as a string, but as a block?

Now everything works like this:

Functions

function Test-IsAdmin() {
  return ( [Security.Principal.WindowsPrincipal] ([Security.Principal.WindowsIdentity]::GetCurrent())
    ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
Set-Alias IsAdmin Test-IsAdmin

function Invoke-CommandExt() {
  param (
    [Alias("Command")] [parameter(Mandatory=$true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()]
      [string[]] $cmd,
    [Alias("Wait")] [parameter(Mandatory=$false)]
      [bool] $isWait = $true,
    [Alias("VerbRunAs")] [parameter(Mandatory=$false)]
      [bool] $isVerbRunAs = $false,
    [Alias("Pause")] [parameter(Mandatory=$false)]
      [bool] $isPause = $false,
    [Alias("Echo")] [parameter(Mandatory=$false)]
      [bool] $isEcho = $false
  )
  BEGIN {
    [System.Collections.ArrayList] $listCmds = new-object System.Collections.ArrayList
  }
  PROCESS {
    [void] $listCmds.AddRange($cmd)
  }
  END {

    [string] $cmds = [string]::Join([Environment]::NewLine, $listCmds.ToArray())
    # Эхо команды на экран
    if ($isEcho) {
      Write-Host "*** Echo Start ***"
      Write-Host $cmds.ToString() -ForegroundColor Gray
      Write-Host "*** Echo End ***"
    }
    #Write-Host "Wait = $isWait, VerbRunAs = $isVerbRunAs, IsAdmin = $(Test-IsAdmin)"	

    # Расширяем команду до ожидания нажатия после выполнения
    [string] $cmdExt = if ($isPause) {
        #$cmd = "& {$Command; pause}"
        #While ([Console]::ReadKey(`$true).Key -notin @([ConsoleKey]::Enter, [ConsoleKey]::Escape)) {};
        "& {$cmds
          Write-Host `"Нажмите [AnyKey] для продолжения…`" -ForegroundColor Gray; [Console]::ReadKey(`$true);}"
        #Write-Host $cmdExt -ForegroundColor Gray
      } else {
        "& {$cmds}"
      }
    [string] $cmdExtWithoutPause = "& {$cmds}"

    # Выполняем команду
    if ($isWait) {
      # Ждём завершения выполнения команды
      if ($isVerbRunAs) {
        # Проверка необходимости повышения привилегий
        if (IsAdmin) {
          Invoke-Expression $cmdExtWithoutPause # не учитываем $isPause
        } else {
          $bytes = [System.Text.Encoding]::Unicode.GetBytes($cmdExt)
          [array] $argumentList = @("-NoProfile", "-ExecutionPolicy Bypass", "-encodedCommand", [Convert]::ToBase64String($bytes))
          Start-Process -FilePath "PowerShell" -argumentlist $argumentList -Wait -Verb runAs
        }
      } else {
        Invoke-Expression $cmdExtWithoutPause # не учитываем $isPause
      }
    } else {
      # Не ждём завершения выполнения команды, всегда новая консоль
      $bytes = [System.Text.Encoding]::Unicode.GetBytes($cmdExt)
      [array] $argumentList = @("-NoProfile", "-ExecutionPolicy Bypass", "-encodedCommand", [Convert]::ToBase64String($bytes))
      if ($isVerbRunAs) {
        Start-Process -FilePath "PowerShell" -argumentlist $argumentList -Verb runAs
      } else {
        Start-Process -FilePath "PowerShell" -argumentlist $argumentList
      }
    }

  }
}



and called like this:
".`"$(Join-Path $PathToBinFolderTap "tapinstall.exe")`" install '$(Join-Path $PathToBinFolderTap "OemVista.inf")' tap0901" |
    <#Shell.Invoke.#>Invoke-CommandExt -Wait $true -VerbRunAs $true -Pause $true -Echo $false

I would like to get rid of extra quotes / screens when calling and write not a string but code.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
MaxKozlov, 2020-05-11
@MaxKozlov

Well, no one bothers to call scriptblocks and construct them exactly like scriptblocks

$myscriptblock = { mysupercommand $args }
& $myscriptblock $myparams

you can even pass parameters
$scriptblock = { param($fg,$bg, $text) Write-Host -Foreground $fg -Background $bg $text }
& $scriptblock yellow blue text

Moreover, when constructing them, you don’t even need to fool around with using
PS> $text = 'first'
PS> $sb = { "my Text - $text" }
PS> & $sb
my Text - first
PS> $text = 'second'
PS> &$sb
my Text - second

with a strong desire to make a multitool, you can pile something like this
function Invoke-MyTool {
param(
[ValidateSet('ping','write')]
[parameter()]
[string]$cmd,
 [parameter(mandatory=$false,  position=1, ValueFromRemainingArguments=$true)]$args
)
)
$config = @{
ping = { ping },
'write' = { param($text, $fg, $bg)  write-host $text -fore $fg -back $bg }
}
& $config[$cmd] $args
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question