Нет вывода с базовой функцией PowerShell - PullRequest
0 голосов
/ 01 октября 2018

Прошло уже много времени с тех пор, как я только начал ладить с PowerShell, и к сегодняшнему дню я могу сказать, что многое выполнил для своих ежедневных задач.Каждый день - новый день в школе, и теперь, когда я начинаю работать с функциями, я снова спотыкаюсь ... Вот моя проблема:

Даже с самой простой функцией, взятой из многих уроков для начинающих, это не такработая на своем рабочем ПК, ни на своем домашнем ПК, ни на административных серверах моей работы.

Например:

function MyDate {
    Get-Date
}

Сохраненный файл PS1 с именем MyDate.ps1 в локальной папке ипросто запустите эту крошечную штуку из командной строки PowerShell, как это

PS C:\PS> C:\PS\MyDate.ps1

Вот как это было в точности объяснено в учебнике по PS-функциям для чайников.Просто в учебнике вывод должен показывать дату.В моей ситуации просто ничего нет.Нет ошибок, нет информации, связанной с Red-PS, ничего!Если я использую функцию в своем полном сценарии так:

function MyDate {
    Get-Date
}
MyDate

PS C:\PS> C:\PS\MyDate.ps1

Montag, 1. Oktober 2018 19:28:32

Хорошо, тогда я получаю вывод даты.Хотите знать, почему не прямо из приглашения без вызова функции в сценарии, так как функции должны использоваться?И опять же, во многих из этих довольно простых примеров это должно сработать .. Где я тогда не прав?


Редактировать: Не уверен, что сейчас это правильная политика длядобавить больше обновлений к вопросу?

Я, вероятно, поделюсь более конкретным примером моих сценариев и того, как я хочу "преобразовать" его в функцию.Краткий пример:

$myServers = Get-Content D:\Servers\Windows2016.txt
foreach ($myServer in $myServers) {
    Get-Printer -ComputerName $myServer |
        Where-Object {$_.DeviceType -eq "Printer"} |
        Select Name, PortName
}

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

C:\Scripts\Our-Printers -File D:\Servers\Windows2016.txt

Our-Printers будет тогда моим именем функции.

Я уже пробовал это, но отбросил материал, хотя он не работал с первой попытки, поэтому я хотел начать с довольно простых вещей, и в данный момент мне кажется, что я этого не понимаю.Но, между прочим, в скрипте мои функции уже работали, просто они не сделаны так, чтобы требовать ввода таким образом, как в примере.Это означает, что я определил функции в большом скрипте, и благодаря этому я могу изменять заказы или даже пропускать определенные функции на основе пользовательского ввода ...

Ответы [ 2 ]

0 голосов
/ 01 октября 2018

Определение функции в скрипте означает, что вы пишете блок кода, который может быть вызван через символическое имя.Однако эта функция не вызывается автоматически при запуске сценария.Вам все еще нужно это сделать.

PS C:\> <b>Get-Content .\a.ps1</b>
function GetDate {
    Get-Date
}
PS C:\> <b>.\a.ps1</b>
PS C:\> <b>Get-Content .\b.ps1</b>
function GetDate {
    Get-Date
}
<i>GetDate                  # &larr; actually invoke the function</i>
PS C:\> <b>.\b.ps1</b>

Montag, 1. Oktober 2018 19:50:32

Только (скрипт-) код глобальной области действия в скрипте выполняется автоматически при вызове скрипта.

В зависимости от назначения вашего скриптаэто может или не может быть то, что вы хотите.Например, если вы намереваетесь просто запустить скрипт из какого-либо внешнего скрипта или команды, чтобы он что-то сделал, имеет смысл автоматически вызывать функцию при выполнении скрипта.Если, с другой стороны, вы намереваетесь использовать сценарий в качестве библиотеки, хранящей различные функции, которые вы хотите иметь возможность вызывать отдельно, вы бы исключили вызовы функций из сценария.Затем вы можете поставить сценарий в точках, как описал Матиас , и вызвать нужные вам функции.

PS C:\> <b>Get-Content .\a.ps1</b>
function GetDate {
    Get-Date
}
PS C:\> <b>. .\a.ps1</b>    <i># &larr; load the function definition into the current scope</i>
PS C:\> <b>GetDate</b>      # &larr; actually invoke the function

Montag, 1. Oktober 2018 19:50:32

Редактировать: Ваша конечная цельможет быть достигнуто в любом случае.Существуют файлы (называемые profile ), которые автоматически запускаются PowerShell при запуске.Вы можете определить функцию и поместить ее в соответствующий профиль (для пользователя или всей системы).После перезапуска PowerShell люди смогут вызывать функцию.

В качестве альтернативы вы можете поместить код в сценарий (не заключая его в функцию) и поместить этот сценарий в такое место, где его могут выполнить предполагаемые пользователи.

Какой из этих двух подходов предпочтителен для вашей ситуации, зависит от ряда факторов.У вас есть домен или рабочая группа?В случае домена, вы можете внести изменения в AD?У вас есть общее местоположение, куда вы можете поместить файлы?У вас есть система развертывания программного обеспечения?И так далее.

Еще один важный вопрос: будут ли пользователи вызывать код только из PowerShell или из других источников (например, CMD).В последнем случае обычно предпочтительнее использовать сценарий, а не функцию в профиле.

В любом случае вы бы параметризовали свой сценарий или функцию следующим образом:

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true)]
    [string]$File
)

$myServers = Get-Content $File
foreach ($myServer in $myServers) {
    Get-Printer -ComputerName $myServer |
        Where-Object {$_.DeviceType -eq "Printer"} |
        Select-Object Name, PortName
}

Определение параметра находится в начале скрипта или функции соответственно.

Добавить справку на основе комментариев , чтобы люди могли запустить Get-Help Our-Printers или Our-Printers -?, чтобы увидеть, как ониПредполагается использовать его, например,

<#
.SYNOPSIS
List printers.

.DESCRIPTION
List printers. The computers to check are read from a file.

.PARAMETER File
A file with a list of computer names (one per line).
#>

Использовать подтверждение параметра для принудительного ввода правильного ввода, например

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true)]
    [ValidateScript({Test-Path -LiteralPath $_})]
    [string]$File
)
0 голосов
/ 01 октября 2018

Если у вас есть определение функции в файле сценария и вы хотите «импортировать» эту функцию, вам нужно использовать оператор точечного источника (.):

PS C:\PS> . C:\PS\MyDate.ps1
PS C:\PS> MyDate
Montag, 1. Oktober 2018 19:39:18

Разница между использованием оператора . и простым вызовом сценария по имени заключается в том, что оператор . запускает сценарий в области вызова - это означает, что определение функции сохраняется в сеансе powershell после прекращения выполнения сценария.

Подробнее об областях вы можете прочитать в about_Scopes файле справки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...