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.