Почему эта команда New-Item работает в PowerShell, но не в скрипте PS1?

Почему эта команда New-Item работает в PowerShell, но не в скрипте PS1?

Полностью застрял и не знаю, что делать: у меня есть интерактивный скрипт Powershell с множественным выбором, который я разрабатываю для операторов, чтобы они могли сэкономить несколько минут, когда им нужно выполнить быстрые задачи на удаленных компьютерах.

Я заменил весь код для всех остальных вариантов на просто You have selected #, чтобы никого не утомлять остальной частью скрипта, но выбор 6сводит меня с ума.

Вот к чему я стремлюсь, но пока не могу продвинуться дальше первого пункта:

  • Создать новый .vncфайл
  • Добавить в файл стандартный текст протокола VNC.
  • Добавить $ComputerNameпослеHost=
  • Запустить файл

Проблема в том, что нижеприведенный код вообще не создает файл; если скопировать/вставить его напрямую в Powershell, он работает, но не запускается в скрипте! Кто-нибудь знает, почему это может быть?

$commands = {
  function Show-Menu
  {
    param (
      [string]$Title = 'My Menu'
    )
    Clear-Host
    Write-Host "================ $Title ================"

    Write-Host "1: Press '1' (Description)."
    Write-Host "2: Press '2' (Description)."
    Write-Host "3: Press '3' (Description)."
    Write-Host "4: Press '4' (Description)."
    Write-Host "5: Press '5' (Description)."
    Write-Host "6: Press '6' To start a VNC Connection."
    Write-Host "Q: Press 'Q' to quit."
  }

  Show-Menu –Title 'My Menu'
  $selection = Read-Host "Please make a selection"
  switch ($selection)
  {
    '1' {
      "You have selected 1"
      sleep -seconds 2
    } '2' {
      "You have selected 2"
      sleep -seconds 2
    } '3' {
      "You have selected 3"
      sleep -seconds 2
    } '4' {
      "You have selected 4"
      sleep -seconds 2
    } '5' {
      "You have selected 5"
      sleep -seconds 2
    } '6' {
      $ComputerName = (Read-Host "ComputerName")
      {
        New-Item -Path "C:\Windows\Temp\$ComputerName.VNC"
        Set-Content "C:\Windows\Temp\$ComputerName.VNC" '
        [connection]
        host=$ComputerName
        port=5900
        [options]
        use_encoding_1=1
        copyrect=1
        viewonly=0
        fullscreen=0
        8bit=0
        shared=1
        belldeiconify=0
        disableclipboard=0
        swapmouse=0
        fitwindow=0
        cursorshape=1
        noremotecursor=0
        preferred_encoding=7
        compresslevel=-1
        quality=6
        localcursor=1
        scale_den=1
        scale_num=1
        local_cursor_shape=1'
      }
    } 'q' {
      #Closes the script
      return
    }
  }
  .$commands

}
&$commands

решение1

Если скопировать/вставить непосредственно в Powershell, то это сработает, но не будет запущено в скрипте.

Это звучит как неподходящая политика выполнения. Вы можете запустить Get-ExecutionPolicyее, чтобы проверить. Вероятно, она возвращает Restricted.

Чтобы изменить это навсегда, запустите PowerShell с повышенными привилегиями, выполните команду Set-ExecutionPolicy RemoteSignedи подтвердите ее с помощью y.

Чтобы временно изменить это только для выполнения вашего скрипта, вы можете запустить его следующим образом:

powershell -ExecutionPolicy Bypass -File .\ScriptFile.ps1

Итак, вот как вы можете запустить свой скрипт из файла скрипта. Кроме того, есть еще одна проблема, о которой уже упоминал@jfrmilner. В вашем 6-м варианте вы определяете еще один блок скрипта с помощью дополнительных фигурных скобок:

...
} '6' {
      $ComputerName = (Read-Host "ComputerName")
      {
        # This just the definition of a scriptblock and will not be executed!
        # Instead, it will be sent to stdout.
      }
    } 'q' {
...

Само определение не будет запускать эти строки. У вас есть две возможности решить эту проблему:

  1. Опустите фигурные скобки и таким образом не определите блок скрипта. Строки будут выполнены.
  2. Добавьте к блоку сценария префикс a ., и он будет выполнен:
...
} '6' {
      $ComputerName = (Read-Host "ComputerName")
      .{
        # This is a scriptblock that will directly be executed!
      }
    } 'q' {
...

решение2

То же самое говорят @Reg Edit и @Lee-Dailey.

Мы не видим ваш экран.

Во-вторых, почему вы ожидаете...

&$commands

...это будет работать в сценарии?

$commands — это не .ps1 для выполнения, это блок скрипта в вашем скрипте.

Вы говорите, что вставляете код в консоль powershell.exe или ISE или VSCode, и он должен работать, поскольку вы загрузили код и запустили его из существующего экземпляра PowerShell, и код был прочитан в этом экземпляре.

Таким образом, если этот код не сохранен как commands.ps1, то &$commands не имеет смысла, поскольку код никогда не загружается в работающий или вызываемый экземпляр PowerShell.

Кроме того, этот блок скрипта на самом деле вообще не нужен.

Итак, попробуйте это...

# VNCCommands.ps1
function Show-Menu
{
    param 
    (
        [string]$Title = 'My Menu'
    )

    Clear-Host
    $Banner = '='*16
    "$Banner $Title $Banner"

    "1: Press '1' (Description)."
    "2: Press '2' (Description)."
    "3: Press '3' (Description)."
    "4: Press '4' (Description)."
    "5: Press '5' (Description)."
    "6: Press '6' To start a VNC Connection."
    "Q: Press 'Q' to quit."
}

Show-Menu –Title 'My Menu'
$selection = Read-Host "Please make a selection"

switch ($selection)
{
    1 
    {
        "You have selected 1"
        sleep -seconds 2
    } 
    2 
    {
        "You have selected 2"
        sleep -seconds 2
    } 
    3 
    {
        "You have selected 3"
        sleep -seconds 2
    } 
    4 
    {
        "You have selected 4"
        sleep -seconds 2
    } 
    5 
    {
        "You have selected 5"
        sleep -seconds 2
    } 
    6 
    {
        $ComputerName = Read-Host -Prompt 'Enter a computer name: '
        If (-Not (Test-Path -Path "D:\temp\$ComputerName"))
        {New-Item -Path 'D:\Temp' -Name "$ComputerName.VNC" -ItemType File -Verbose}
        Else {Write-Warning -Message "D:\temp\$ComputerName.VNC creation failed"}
    } 
    'q' {return}
}

Выполнять ---

.\VNCCommands.ps1



# Results
<#
================ My Menu ================
1: Press '1' (Description).
2: Press '2' (Description).
3: Press '3' (Description).
4: Press '4' (Description).
5: Press '5' (Description).
6: Press '6' To start a VNC Connection.
Q: Press 'Q' to quit.
Please make a selection: 6
Enter a computer name: : test
VERBOSE: Performing the operation "Create File" on target "Destination: D:\Temp\test.VNC".


    Directory: D:\Temp


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         19-Jul-20     17:14              0 test.VNC
#>

Связанный контент