Я разработал функцию PowerShell, которая выполняет ряд действий, связанных с подготовкой сайтов SharePoint Team. В конечном итоге я хочу, чтобы функция возвращала URL-адрес подготовленного сайта в виде строки, поэтому в конце моей функции у меня будет следующий код:
$rs = $url.ToString();
return $rs;
Код, который вызывает эту функцию, выглядит следующим образом:
$returnURL = MyFunction -param 1 ...
Так что я ожидаю строку, но это не так. Вместо этого это объект типа System.Management.Automation.PSMethod. Почему он возвращает этот тип вместо типа String?
powershell
ChiliYago
источник
источник
Ответы:
PowerShell имеет действительно дурацкую семантику возврата - по крайней мере, если смотреть с более традиционной точки зрения программирования. Есть две основные идеи, чтобы обернуть голову вокруг:
Таким образом, следующие два блока сценария будут эффективно выполнять одно и то же:
Переменная $ a во втором примере остается как вывод для конвейера, и, как уже упоминалось, весь вывод возвращается. Фактически, во втором примере вы можете полностью опустить возврат и получить то же поведение (возврат будет подразумеваться, когда функция естественным образом завершает работу и завершается).
Без большего определения вашей функции я не могу сказать, почему вы получаете объект PSMethod. Я предполагаю, что у вас, вероятно, есть несколько строк, которые не фиксируются и помещаются в выходной конвейер.
Также стоит отметить, что вам, вероятно , не нужны эти точки с запятой - если вы не вкладываете несколько выражений в одну строку.
Вы можете прочитать больше о семантике возврата на странице about_Return в TechNet или вызвав
help return
команду из самой PowerShell.источник
write-debug
после установки переменной$DebugPreference = "Continue"
вместо"SilentlyContinue"
echo
был проблемой для меня! Эта маленькая сторона очень и очень важна. Я возвращал хеш-таблицу, следуя всему остальному, но все же возвращаемое значение оказалось не таким, как я ожидал. Снялecho
и работал как шарм.Эта часть PowerShell, пожалуй, самый глупый аспект. Любые посторонние результаты, генерируемые во время функции, будут загрязнять результат. Иногда нет никакого выхода, а затем при некоторых условиях есть некоторый другой незапланированный выход, в дополнение к вашему запланированному возвращаемому значению.
Итак, я удаляю назначение из исходного вызова функции, чтобы вывод выводился на экран, а затем пошагово, пока что-то, что я не планировал, не появилось в окне отладчика (с помощью PowerShell ISE ).
Даже такие вещи, как резервирование переменных во внешних областях, вызывают вывод, например,
[boolean]$isEnabled
который будет досадно выплевывать False, если вы не сделаете это[boolean]$isEnabled = $false
.Еще одна хорошая
$someCollection.Add("thing")
вещь, которая выплевывает счет новой коллекции.источник
[boolean]$a
в powershell фактически не объявляет переменную $ a. Вы можете подтвердить это, следуя за этой строкой со строкой,$a.gettype()
и сравнить этот вывод с тем, когда вы объявляете и инициализируете со строкой$a = [boolean]$false
.>
и<
уже используются для перенаправления потока ввода-вывода в / из файлов.>=
записывает стандартный вывод в файл с именем=
.С PowerShell 5 у нас теперь есть возможность создавать классы. Измените вашу функцию на класс, и return вернет только объект, непосредственно предшествующий ему. Вот очень простой пример.
Если бы это была функция, ожидаемый результат был бы
но в качестве класса возвращается только целое число 808979. Класс является своего рода гарантией того, что он вернет только объявленный или недействительный тип.
источник
static
методы. Ведущий к синтаксису[test_class]::return_what()
return 808979
, функция или нет.Write-Output
? Здесь упоминается не вывод консоли, а вывод функции / командлета. Если вы хотите сбросить материал на консоли естьWrite-Verbose
,Write-Host
иWrite-Error
функция, среди других. В принципе,Write-Output
ближе кreturn
семантике, чем к процедуре вывода на консоль. Не злоупотребляйте этим, используйтеWrite-Verbose
для многословия, вот для чего это.В качестве обходного пути я возвращал последний объект в массиве, который вы получили из функции ... Это не очень хорошее решение, но лучше, чем ничего:
В целом, более однолинейный способ написать то же самое может быть:
источник
$b = $b[-1]
было бы проще получить последний элемент или массив, но еще проще было бы просто не выводить значения, которые вам не нужны.write-host
его для непосредственного вывода.Я передаю простой объект Hashtable с единственным членом результата, чтобы избежать сумасшествия возврата, поскольку я также хочу выводить на консоль. Это действует через проход по ссылке.
Вы можете увидеть реальный пример использования в моем проекте GitHub unpackTunes .
источник
Трудно сказать, не глядя на код. Убедитесь, что ваша функция не возвращает более одного объекта, и что вы фиксируете результаты, полученные из других вызовов. Что вы получаете за:
Во всяком случае, два предложения:
Приведите объект к строке:
Или просто заключите его в двойные кавычки, как указано выше, но короче, чтобы напечатать:
источник
"$rs"
-return
требуется только при раннем возврате из функции. Оставлять возврат лучше идиома PowerShell.Описание функций, приведенных Люком в этих сценариях, кажется правильным. Я только хочу понять основную причину, и команда разработчиков PowerShell сделает что-то с этим поведением. Это кажется довольно распространенным явлением и стоило мне слишком много времени на отладку.
Чтобы обойти эту проблему, я использовал глобальные переменные, а не возвращал и использовал значение из вызова функции.
Вот еще один вопрос об использовании глобальных переменных: установка глобальной переменной PowerShell из функции, где имя глобальной переменной является переменной, переданной функции
источник
Следующий просто возвращает 4 в качестве ответа. Когда вы заменяете выражения add для строк, возвращается первая строка.
Это также можно сделать для массива. Пример ниже вернет «Текст 2»
Обратите внимание, что вы должны вызывать функцию под самой функцией. В противном случае при первом запуске он выдаст ошибку, что он не знает, что такое «StartingMain».
источник
Существующие ответы верны, но иногда вы не возвращаете что-то явно с помощью a
Write-Output
или areturn
, но в результатах функции есть какое-то загадочное значение. Это может быть вывод встроенной функции, такой какNew-Item
Весь этот дополнительный шум создания каталога собирается и выводится на выходе. Простой способ смягчить это - добавить
| Out-Null
в конецNew-Item
оператора, или вы можете присвоить результат переменной и просто не использовать эту переменную. Это будет выглядеть так ...New-Item
Вероятно, наиболее известный из них, но другие включают всеStringBuilder.Append*()
методы, а такжеSqlDataAdapter.Fill()
метод.источник