PowerShell에서 파일에서 함수를 정의하고 PowerShell 명령 줄에서 어떻게 호출합니까?


243

사용자 정의 함수를 정의하려는 .ps1 파일이 있습니다.

파일 이름이 MyFunctions.ps1이라고 가정하고 내용은 다음과 같습니다.

Write-Host "Installing functions"
function A1
{
    Write-Host "A1 is running!"
}
Write-Host "Done"

이 스크립트를 실행하고 이론적으로 A1 기능을 등록하려면 .ps1 파일이있는 폴더로 이동하여 파일을 실행하십시오.

.\MyFunctions.ps1

이 결과는 다음과 같습니다.

Installing functions
Done

그러나 A1을 호출하려고하면 해당 이름으로 명령 / 기능이 없다는 오류가 발생합니다.

The term 'A1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
 of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:3
+ A1 <<<<
    + CategoryInfo          : ObjectNotFound: (A1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

일부 PowerShell 개념을 오해해야합니다. 스크립트 파일에서 함수를 정의 할 수 없습니까?

참고 이미 '를 RemoteSigned'내 실행 정책을 설정했는지. 그리고 파일 이름 앞에 점을 사용하여 .ps1 파일을 실행하는 것을 알고 있습니다.. \ myFile.ps1


PS 시작시로드 기능에 대한 링크 : sandfeld.net/powershell-load-your-functions-at-start-at
— Andrew

답변:


262

PowerShell 명령 줄에서 다음을 시도하십시오.

. .\MyFunctions.ps1
A1

도트 연산자는 스크립트 포함에 사용됩니다.


11
"자식 컨텍스트 대신 현재 컨텍스트에서이를 실행합니다"라는 의미입니다.
— JasonMArcher 16:17에

15
그것은 의미 소스 이 파일의 내용을. bash 와 동일합니다 . ss64.com/bash/period.html
— inquam

2
. \ MyFunctions.ps1을 먼저 실행하지 않으면 (ISE에서) 적어도 잘 작동하지 않는 것 같습니다. powershell.exe에서 엄격하게 실행하는 것이 확실하지 않습니다.
— Mike Cheel

1
도트 소싱이 스크립트가 아닌 pwd에 상대적인 경로를 사용하는 것이 반 직관적이라고 생각했기 때문에 사람들이 JoeG의 답변을보고 모듈을 사용하도록 권장합니다.
— Spork

5
@ 스포크 . "$PSScriptRoot\MyFunctions.ps1". 그 참조하기 전에, v3에서 시작 Availalbe stackoverflow.com/questions/3667238/... . 매우 일반적입니다.
— yzorg

233

당신이 말하는 것은 도트 소싱 입니다. 그리고 그것은 악하다. 그러나 걱정하지 마십시오. 모듈 로 원하는 것을 수행하는 더 쉽고 쉬운 방법이 있습니다 (이것보다 훨씬 무섭게 들립니다). 모듈 사용의 주요 이점은 필요한 경우 쉘에서 모듈을 언로드하고 함수의 변수가 쉘로 들어 가지 않도록 유지하는 것입니다 (함수 파일을 소스로 표시하면 변수 중 하나에서 셸에서 기능을 수행하면 의미하는 바를 볼 수 있습니다).

먼저 모든 기능이 포함 된 .ps1 파일의 이름을 MyFunctions.psm1 (방금 모듈을 만들었습니다!)로 이름을 바꿉니다. 이제 모듈이 제대로로드 되려면 파일을 사용하여 특정 작업을 수행해야합니다. 먼저 Import-Module에서 모듈을 확인하려면 (이 cmdlet을 사용하여 모듈을 셸에로드) 특정 위치에 있어야합니다. 모듈 폴더의 기본 경로는 $ home \ Documents \ WindowsPowerShell \ Modules입니다.

해당 폴더에 MyFunctions라는 폴더를 작성하고 MyFunctions.psm1 파일을 파일에 넣으십시오 (모듈 파일은 PSM1 파일과 정확히 동일한 이름의 폴더에 있어야합니다).

완료되면 PowerShell을 열고 다음 명령을 실행하십시오.

Get-Module -listavailable

MyFunctions라는 이름의 모듈이 표시되면 올바르게 수행했으며 모듈을로드 할 준비가 된 것입니다 (이것이 올바르게 설정되었는지 확인하기 위해 한 번만 수행하면 됨).

모듈을 사용하려면 쉘에 다음을 입력하십시오 (또는 $ profile에이 행을 넣거나 스크립트의 첫 번째 행으로 두십시오).

Import-Module MyFunctions

이제 기능을 실행할 수 있습니다. 이것에 대한 멋진 점은 일단 10-15 개의 기능이 있으면 커플의 이름을 잊어 버릴 것입니다. 모듈에있는 경우 다음 명령을 실행하여 모듈의 모든 기능 목록을 얻을 수 있습니다.

Get-Command -module MyFunctions

꽤 달콤하고 앞면에 설치하는 데 약간의 노력이 가치가 있습니다.


6
함수가 주어진 PowerShell 응용 프로그램에만 해당되는 경우는 어떻습니까? PS1 패키지를 설치하여 어딘가에서 작업을 수행한다면 프로파일의 모든 기능을 원하지 않을 수 있습니다.
— Ian Patrick Hughes

3
이 경우 해당 특정 응용 프로그램에 대한 모듈을 만들고 스크립트를 실행하기 전에 (대화식으로 작업하는 경우)로드하거나 스크립트 내에로드합니다. 그러나 일반적으로 주어진 작업에만 해당되는 코드가 있으면 스크립트에서 해당 기능을 원할 것입니다. 개인적으로 나는 일반적으로 한 가지 일을하는 함수 만 작성합니다. 코드 조각이 하이퍼 전문화되어 있으면 함수 또는 모듈로 코드를 래핑하는 것이 실제로 의미가 없습니다 (동일한 코드를 사용하는 여러 스크립트가 없으면 의미가 있습니다).
— JoeG

17
모듈 파일이 PSM1 파일과 이름이 정확히 같은 폴더에있을 필요는 없습니다. 다음과 같이 할 수 있습니다 Import-Module .\buildsystem\PSUtils.psm1
— Michael Freidgeim

2
@MichaelFreidgeim는 단지 변경과 같은 간단 경우 .에 Import-Module, 즉, 난 그냥 점 소싱와 마찬가지로, 내가 원하는 디렉토리에있을 수 있고 확장의 이름을 변경하고, 모듈은 특정 폴더에 배치 할 필요가 없습니다 범위 지정의 이점을 고려하여 모듈에 대해 점 소싱을 수행해야 할 이유가 있습니까? (물론 이러한 범위의 "문제"가 원하는 것이 아니라면)
— Abdul

2
@Abdul, 도트 소싱이 더 간단하고 모듈이 훨씬 강력합니다. 참조 stackoverflow.com/questions/14882332/...
— 마이클 Freidgeim

17

. "$PSScriptRoot\MyFunctions.ps1" MyA1Func

v3부터는 PowerShell 스크립트의 파일 시스템 위치를 얻는 방법 을 참조하십시오 . . 매우 일반적입니다.

추신 : 나는 '모든 것이 모듈입니다'규칙에 가입하지 않습니다. 내 스크립트는 다른 개발자가 GIT 외부에서 사용하므로 스크립트를 실행하기 전에 특정 장소에 물건을 넣거나 시스템 환경 변수를 수정하는 것을 좋아하지 않습니다. 그것은 단지 스크립트 (또는 둘 또는 셋)입니다.


FWIW에서는 모듈에서 스크립트를 실행하기 위해 이러한 작업을 수행 할 필요가 없습니다.
— Nick Cox

@NickCox 나는 그 몇 가지 예를보고 싶습니다. 있니? 예제가 OSS 프로젝트 인 경우 +10 특히 PS 모듈의 예는 상대 경로 (PSModulePath가 아니거나 PSModulePath를 사용자 정의하지 않은)를 통해로드되고 사소한 예 (즉, 모듈이 일반 스크립트 범위 지정에 비해 이점이있는 경우)입니다.
— yzorg 2016

FluentMigrator.PowerShell 모듈을 상대 경로에서 자주 가져옵니다 . 이를 통해 소스 제어를 확인하고 모두가 동일한 버전을 사용하고 있는지 확인할 수 있습니다. 잘 작동한다.
— Nick Cox

모듈 대 스크립트로 패키징하는 상대적인 장단점이 확실하지 않습니다. 아마도 저자와 논의해야 할 것입니까? 에 대한 민첩성 Get-Command -Module FluentMigrator.PowerShell이 꽤 좋은 것 같아요 ?
— Nick Cox

@NickCox 해당 명령에서 모듈 경로를 완전히 규정하지 않았으므로 모듈을 전역 모듈 폴더에 복사하거나 GIT 폴더를 전역 환경 변수에 추가하지 않으면 찾을 수 없습니다. 방금 내 요점을 보여준 것 같아
— yzorg

7

스크립트 파일에서 함수를 정의 할 수 있습니다 (로드 할 때 Powershell 프로파일을 통해로드하는 경향이 있습니다).

먼저 다음을 실행하여 함수가로드되었는지 확인해야합니다.

ls function:\ | where { $_.Name -eq "A1"  }

그리고 목록에 표시되는지 확인하십시오 (1의 목록이어야 함). 그러면 어떤 결과를 얻었는지 알려주십시오!


1
PowerShell에서 함수는 디렉토리로 취급되므로 c : \ 또는 d : \와 동일합니다. 마찬가지로 백 슬래시없이 작동하므로 ls 기능 : | 여기서 {$ _. Name -eq "A1"}
— Jonny

4

다음에 기능을 추가 할 수 있습니다.

c:\Users\David\Documents\WindowsPowerShell\profile.ps1

기능을 사용할 수 있습니다.


3

파일에 호출 / 노출하려는 주요 기능이 하나만있는 경우 다음을 사용하여 파일을 시작할 수도 있습니다.

Param($Param1)

그런 다음 예를 들어 다음과 같이 호출 할 수 있습니다.

.\MyFunctions.ps1 -Param1 'value1'

함수를 가져 오지 않고 해당 함수 만 쉽게 호출하려는 경우 훨씬 편리합니다.


또한 오늘 (내 동료가 말 해준 후) PowerShell이 ​​자동으로 [CmdletBinding()]특성을 추가하고 고급 기능으로 무료로 업그레이드 한다는 것을 알았 습니다. :-)
— bergmeister

1

Function-Dumb ()라는 메서드가있는 Dummy-Name.psm1이라는 모듈 파일이 있다고 가정합니다.

Import-Module "Dummy-Name.psm1";
Get-Command -Module "Function-Dumb";
#
#
Function-Dumb;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.