IT

PowerShell의 함수 반환 값

lottoking 2020. 6. 1. 08:09
반응형

PowerShell의 함수 반환 값


SharePoint Team 사이트 구축 과 관련된 여러 가지 작업을 수행하는 PowerShell 기능을 개발했습니다 . 궁극적으로 함수가 프로비저닝 된 사이트의 URL을 문자열로 반환하기를 원하므로 함수 끝에서 다음 코드를 갖습니다.

$rs = $url.ToString();
return $rs;

이 함수를 호출하는 코드는 다음과 같습니다.

$returnURL = MyFunction -param 1 ...

따라서 String을 기대하지만 그렇지 않습니다. 대신 System.Management.Automation.PSMethod 유형의 개체입니다. 왜 문자열 유형 대신 해당 유형을 반환합니까?


PowerShell은 적어도 더 전통적인 프로그래밍 관점에서 볼 때 실제로 이상한 반환 의미를 가지고 있습니다. 머리를 감싸는 두 가지 주요 아이디어가 있습니다.

  • 모든 출력이 캡처되어 반환됩니다
  • 리턴 키워드는 실제로 논리적 종료점을 나타냅니다.

따라서 다음 두 스크립트 블록은 정확히 동일한 기능을 수행합니다.

$a = "Hello, World"
return $a

 

$a = "Hello, World"
$a
return

두 번째 예의 $ a 변수는 파이프 라인의 출력으로 유지되며 언급 된대로 모든 출력이 반환됩니다. 실제로 두 번째 예에서는 리턴을 완전히 생략하고 동일한 동작을 수행 할 수 있습니다 (기능이 자연스럽게 완료되고 종료됨에 따라 리턴이 암시됩니다).

더 많은 함수 정의가 없으면 PSMethod 객체를 얻는 이유를 말할 수 없습니다. 내 생각에는 캡처되지 않고 출력 파이프 라인에 배치되는 몇 줄이있을 것입니다.

또한 한 줄에 여러 표현식을 중첩하지 않는 한 세미콜론이 필요하지 않을 수도 있습니다.

TechNet about_Return 페이지에서 또는 help returnPowerShell 자체 에서 명령을 호출하여 리턴 시맨틱에 대해 자세히 읽을 수 있습니다 .


PowerShell의이 부분은 아마도 가장 어리석은 부분 일 것입니다. 함수 중에 생성 된 외부 출력은 결과를 오염시킵니다. 때때로 출력이없는 경우가 있으며, 일부 조건에서는 계획된 반환 값 외에 계획되지 않은 다른 출력이있을 수 있습니다.

따라서 원래 함수 호출에서 할당을 제거하므로 출력이 화면에서 끝난 다음 디버거 창에서 계획하지 않은 것이 튀어 나올 때까지 ( PowerShell ISE 사용 ) 단계별로 진행 합니다.

외부 범위에서 변수를 예약하는 것과 같은 것조차도 출력을 유발 [boolean]$isEnabled합니다 [boolean]$isEnabled = $false. 이러한 경우를 제외하고는 성가신 False를 뱉어냅니다 .

또 다른 좋은 방법 $someCollection.Add("thing")은 새로운 수집 횟수를 내뿜는 것입니다.


PowerShell 5를 사용하면 이제 클래스를 만들 수 있습니다. 함수를 클래스로 변경 하면 return은 바로 앞의 객체 반환합니다. 여기에 간단한 예가 있습니다.

class test_class {
    [int]return_what() {
        Write-Output "Hello, World!"
        return 808979
    }
}
$tc = New-Object -TypeName test_class
$tc.return_what()

이것이 함수라면 예상되는 결과는

Hello World
808979

그러나 클래스로 반환되는 유일한 것은 정수 808979입니다. 클래스는 선언되거나 void 유형 만 반환한다는 보증과 같습니다.


해결 방법으로 함수에서 돌아온 배열의 마지막 객체를 반환했습니다 ... 훌륭한 솔루션은 아니지만 아무것도 아닌 것보다 낫습니다.

someFunction {
   $a = "hello"
   "Function is running"
   return $a
}

$b = someFunction
$b = $b[($b.count - 1)]  # Or
$b = $b[-1]              # Simpler

I pass around a simple Hashtable object with a single result member to avoid the return craziness as I also want to output to the console. It acts through pass by reference.

function sample-loop($returnObj) {
  for($i = 0; $i -lt 10; $i++) {
    Write-Host "loop counter: $i"
    $returnObj.result++
  }
}

function main-sample() {
  $countObj = @{ result = 0 }
  sample-loop -returnObj $countObj
  Write-Host "_____________"
  Write-Host "Total = " ($countObj.result)
}

main-sample

You can see real example usage at my GitHub project unpackTunes.


It's hard to say without looking at at code. Make sure your function doesn't return more than one object and that you capture any results made from other calls. What do you get for:

@($returnURL).count

Anyway, two suggestions:

Cast the object to string:

...
return [string]$rs

Or just enclose it in double quotes, same as above but shorter to type:

...
return "$rs"

Luke's description of the function results in these scenarios seems to be right on. I only wish to understand the root cause and the PowerShell product team would do something about the behavior. It seems to be quite common and has cost me too much debugging time.

To get around this issue I've been using global variables rather than returning and using the value from the function call.

Here's another question on the use of global variables: Setting a global PowerShell variable from a function where the global variable name is a variable passed to the function


The following simply returns 4 as an answer. When you replace the add expressions for strings it returns the first string.

Function StartingMain {
  $a = 1 + 3
  $b = 2 + 5
  $c = 3 + 7
  Return $a
}

Function StartingEnd($b) {
  Write-Host $b
}

StartingEnd(StartingMain)

This can also be done for an array. The example below will return "Text 2"

Function StartingMain {
  $a = ,@("Text 1","Text 2","Text 3")
  Return $a
}

Function StartingEnd($b) {
  Write-Host $b[1]
}

StartingEnd(StartingMain)

Note that you have to call the function below the function itself. Otherwise, the first time it runs it will return an error that it doesn't know what "StartingMain" is.


As an alternative to return I would suggest Write-Output.

Write-Output can take input from pipeline and forward it either down the pipeline or print it to the console if it is the last command.

However, Write-Output does not end the script as return would do, which can be an advantage if output should be used, forwarded, etc. in a loop.

참고URL : https://stackoverflow.com/questions/10286164/function-return-value-in-powershell

반응형