ⓟrogramming/PowerShell

POWERSHELL SCRIPT - 스크립트 흐름 제어 구문

뚱땡이 우주인 2018. 7. 1. 15:01

IF 문

$ServiceName = "Hyper-V 가상 컴퓨터 관리"
$HostName = hostname
$Service = Get-Service -DisplayName $ServiceName -ErrorAction SilentlyContinue

If (-Not $Service){
    $ServiceName + "는" + $HostName + "에 설치되지 않았습니다."
    Write-Host "Hyper-V 서비스를 설치합니다."
    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
} ElseIf($Service.Status -eq "Running"){
    $ServiceName + "가 동작 중입니다."
} Else {
    $ServiceName + "가 중지되었습니다."
    Start-Service -Name $Service.Name
}

네이티브 DOS 명령인 hostName으로 현재 컴퓨터 이름을 가져와 변수에 저장


$Service = Get-Service -DisplayName $ServiceName -ErrorAction SilentlyContinue


에서는 'Hyper-V 가상 컴퓨터 관리' 라는 이름의 서비스를 찾아서 변수에 저장


If (-Not $Service)

부정 연사자인 -Not 에 의해 If문이 참이 되어 Hyper-V 서비스를 설치하는 구문이 실행


ElseIf($Service.Status -eq "Running"

서비스 상태가 실행 상태인지 확인


Else {
$ServiceName + "가 중지되었습니다."
Start-Service -Name $Service.Name
}

마지막으로 서비스가 중지된 경우 다시 시작시키는 구문을 실행




Switch 문

Switch 키워드 다음에 스위치를 사용하지 않으면 기본적으로 대소문자를 구분하지 않는다. 평가되는 값에 대해 정확한 일치를 평가하는 -exact 스위치가 사용된다.


구문 형식

Switch [-regex|-wildcard\-exact] [-casesensitive] (평가 되는 값)
{
조건1 {동작}
.....
Default {동작}
}
Switch문의 형식


옵션 

 설명

 평가되는 값

  •  Switch ($Option)
  • Switch (1,3), Switch("Red")
  • Switch (1..7)
  • Switch (Get-Service)

 -regex

 평가되는 값에 대해 정규식 조건 매칭

 -wildcard

 와일드카드 문자 조건 매칭

 -exact

 정확한 일치 조건 

 -casesensitive

 대소문자 구분

 -조건N

 


예) 위도우의 논리 디스크 정보를 확인해 디스크 유형에 따라 정보를 표시

$drive = Get-CimInstance -ClassName Win32_LogicalDisk `
-Filter "DeviceID='C:'"

switch ($drive.DriveType) {
    3 { Write "로컬 고정 디스크" }
    5 { Write "광학 디스크 장치" }
    Default { Write "기타 장치" }
}


Get-CimInstance 명령어

윈도우에서 시스템 전반의 자원에 대한 정보를 저장하는 CIM 리포지토리(일종의 데이터베이스)를 다루는 명령 중 하나.



switch 문의 평가되는 값 부분에 Get-Service를 실행한다.

실행 시점에 가져온 객체 컬렉션의 각 값($_)에 일치하는 조건 스크립트 블록을 평가해 동작을 수행한다.

switch (Get-Service)
{
{$_.status -eq "Running"}{"실행중인 서비스:"+$_.name}
{$_.status -eq "Stopped"}{"중단된 서비스:"+$_.name}
}




와일드카드 패턴 사용 

와일드카드 패턴을 이용할 시 일치 여부를 비교하는 대상이 무엇인지 구문에 알려주는 매개변수를 지정해야 한다.

아래 예제는 컴퓨터 이름에 따라 메시지를 출력하는 예제이다.


만약 컴퓨터 이름이 SEOUL-CL1 이라면  "SEOUL-CL1*" "SEOUL*" "*1" 와 모두 일치하므로 3개의 스크립트 블록이 실행된다. 이처럼 Switch 문은 If문과 달리 첫 번째 일치 조건만 실행하지 않고 각각의 일치하는 스크립트 블록을 모두 실행한다.

#환경 변수에서 컴퓨터 이름을 가져온다,
$name = Get-Content Env:\COMPUTERNAME
#Switch 문 블록
switch -Wildcard ($name) {
    "SEOUL-CL1*" {
        Write-Host "이 컴퓨터는 클라이언트다."
    }
    "SEOUL*" {
        Write-Host "이 컴퓨터는 SEOUL에 있다."
    }
    "*DC*" {
        Write-Host "이 컴퓨터는 도메인 컨트롤러다."
    }
    "*1" {
        Write-Host "첫 번째 컴퓨터다."
    }
    Default {
        Write-Host "일치하는 내용이 없다."
    }
}



만약 다중으로 일치하는 상황을 피하고자 한다면 Break 키워드를 사용하면 된다.

$name = Get-Content Env:\COMPUTERNAME
Switch -Wildcard ($name) {
    "SEOUL-CL1*" {
        Write "이 컴퓨터는 클라이언트다."
        break
    }
    "SEOUL*" {
        Write "이 컴퓨터는 BUSAN에 있다."
    }
    "*DC*" {
        Write "이 컴퓨터는 도메인 컨트롤러다."
        break
    }
    "*1" {
        Write "첫 번째 컴퓨터다."
    }
    Default {
        Write "일치하는 내용이 없다."
    }
}



ForEach문

다수의 개체를 담고 있는 컬렉션을 열면서 한 번에 하나의 개체에 어떤 처리를 해야할 경우 사용


ForEach ($temp in $Collection)
{
#$temp에 대한 처리 구문
}

ForEach 문은 $Collection에 저장된 개체들을 임시 변수인 $temp에 하나씩 담아 스크립트 블록 내의 코드로 반복 처리한다.


아래 코드는 ComupterNames.txt 파일에 한 줄에 컴퓨터 이름을 하나씩 읽어서 출력하는 명령이다.

#컴퓨터 이름 컬렉션을 변수에 저장한다.
$ComputerNames = Get-Content ComputerNames.txt
#컬렉션의 컴퓨터 이름 목록을 하나씩 처리한다.
ForEach ($pcname in $ComputerNames) {
Write-Host "현재 컴퓨터 이름은 $pcname 입니다."

}



$Services = Get-Service
ForEach ($Service in $Services) {
Write-Host "현재 서비스는 $($Service.name) 입니다."
}




For 문

For ($num=0 ; $num -le 9 ; $num++) {
Write-Host "Computer $num"
}


#컬렉션(배열) 만들기
$fruits = @("사과","오렌지","수박","배","포도","딸기","바나나")

#컬렉션 처리
For ($i=0; $i -lt $fruits.Length; $i++) {
$fruits[$i]
}



# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_for?view=powershell-6
Get-Help about_For -ShowWindows     




While문

#컬렉션(배열) 만들기
$fruits = @("사과","오렌지","수박","배","포도","딸기","바나나")

#컬렉션 처리
$i=0
While ($i -lt $fruits.Length) # lt : less then
{
$fruits[$i]
$i++
}



Do 문


Do-While 문을 사용한 메모장 프로그램 실행

# Start-Process : https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-6
$NumOfNotepad=0
do
{
$NumOfNotepad++
$NotePadID=Start-Process -FilePath notepad
}
while ($NumOfNotepad -le 2)



Do-Until문

$NumOfNotepad=0
do
{
$NumOfNotepad++
$NotePadID=Start-Process -FilePath notepad
}
until ($NumOfNotepad -gt 2)

메모장의 개수가 3인 되는 순간 Do 문은 끝난다.



Break 와 Continue문

$NumOfShots = 0
while ($True)
{
$MovingTarget = (Get-Date).Second
if ($MovingTarget -eq $NumOfShots)
{
Write-Host "이동 목표를 맞추는데 사용된 슈팅 횟수(s):$NumOfShots"
Break
}
$NumOfShots++
}



다음 예제는 ForEach문을 사용해 현재 시스템의 프로세스 목록 중에서 물리 메모리를 250MB 이상 사용하는 프로세스만 출력하도록 한다.

$ProcessLists = Get-Process
foreach ($Process in $ProcessLists)
{
if (($Process.PM/1MB) -le 250)
{
Continue
}
Write-Output ($Process.Name+'은 250MB 이상의 메모리를 사용한다.')
}



* 실습



$NumOfNotepad=0
# 동적 배열 변수를 ArrayList 형식의 변수를 만듬
$PIDs = New-Object System.Collections.ArrayList
do
{
$NumOfNotepad++
$NotePadID=Start-Process -FilePath notepad -PassThru
# 실행된 메모장의 프로세스 ID를 가져와 배열에 추가
$PIDs.Add($NotePadID.Id)
}
while ($NumOfNotepad -le 3)

# 1초간 정지
Start-Sleep -Seconds 1

do
{
$NumOfNotepad--
# 배열에 저장된 프로세스 ID를 사용하여 메모장을 종료
Stop-Process -Id $PIDs[$NumOfNotepad]
}
until (0 -ge $NumOfNotepad)

# 배열의 모든 내용을 지움
$PIDs.Clear()