본문 바로가기

OS-서버/윈도우

Powershell 잡지식

반응형

 

● 쉘 실행 정책 허용 설정

 

PS C:\Windows\system32> C:\Users\jdh52\Desktop\window_script.ps1
이 시스템에서 스크립트를 실행할 수 없으므로 C:\Users\jdh52\Desktop\window_script.ps1 파일을 로드할 수 없습니다. 자세한 내용은 http://go.microsoft.com/fwlink/?LinkID=135170의 about_Execution_Policies를 참조하십시오.
    + CategoryInfo          : 보안 오류: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnauthorizedAccess

 

▣ 해결방법

파워쉘을 관리자권한으로 실행 한 후 스크립트 사용 정책 허용하기

PS C:\Windows\system32> executionpolicy
Restricted   ← 제한됨

PS C:\Windows\system32> Set-ExecutionPolicy Unrestricted  ← 제한 풀기

PS C:\Windows\system32> executionpolicy
Unrestricted ← 제한되지 않음 


 

☆ PS (ISE) 편집기에서 초기 스크립트 실행 허용

Set-ExecutionPolicy RemoteSigned -Force
cs

 

☆ 모든 스크립트 허용

Set-ExecutionPolicy Bypass
cs

 

 

 

● 파워쉘 버전확인

Get-Host | Select-Object Version
cs

 

시스템 요구 사항

https://docs.microsoft.com/ko-kr/powershell/scripting/setup/windows-powershell-system-requirements?view=powershell-6

 

● 파워쉘 파일 include

. C:\Users\powershell_file.ps1
cs

앞에 .을 붙이고 include할 경로를 입력한다.

 

● 랜덤 값 추출 

1..1000000 | Get-Random
cs

숫자 범위안에서 값을 랜덤으로 가져온다.

 

● 레지스트리 읽기 , 쓰

Get-ItemProperty -Path "path" # Read
Set-ItemProperty -Path "path" -Name "Key_name" -Value "key_value" # Write
cs

 

 

● 파일 디렉터리 생성

New-Item -Path "C:\" -Name "test.txt" -ItemType "File"
New-Item -Path "C:\" -Name "test" -ItemType "directory"
cs

'' 경로에 대한 액세스가 거부되었습니다. 라는 에러 메시지가 뜨면

관리자 권한으로 실행한다.

 

● 파워쉘 파일을 EXE 파일로 변환

https://gallery.technet.microsoft.com/scriptcenter/PS2EXE-GUI-Convert-e7cb69d5

 

1. 한글은 깨질 우려가 있으므로 ps1의 인코딩BigEndianUnicode로 변경한다.

2. Set-ExecutionPolicy Bypass [ 스크립트 실행정책을 모두 허용한다 ]

    unrestricted를 사용해도 되지만 스크립트 실행 시 

   매번 허용여부를 물어보기 때문에 Bypass를 사용한다.

3. 사용하려면 NetFramework 4.0이상 버전 필요

 

원격 컴퓨터와 연결되었는지 테스트

1
2
3
Test-Connection -ComputerName "대상 서버 IP 또는 호스트 이름" -count 1 -quiet
# count : Ping을 한번보낸다.
# quiet : 부울 값만 반환하도록 한다.
cs

  

● 파일 합치기

 

① 특정 폴더에서 실행

cmd /c copy /* result.txt
cs

 

② 모든 하위 폴더에서 실행

1
2
3
4
5
6
7
8
$Folder = "C:\Users\jdh52\OneDrive\바탕 화면\새 폴더"
 
foreach($Dir_Name in Get-ChildItem $Folder)
$Folder_Path = "$Folder`\" + "$Dir_Name`\" + '*'
$Save = "$Folder`\" + "$Dir_Name`\" + 'result.txt'
cmd /c copy /"$Folder_Path" "$Save"
}
cs

  위 코드는 \새 폴더밑에 있는 모든 폴더를 순회하며 각 폴더의 내용끼리 

  합쳐지고 결과 또한 각 폴더에 저장된다.

 

● 개행 제거

 

1
$Text.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries)
cs

 

   [Environment]::NewLine는 캐리지 리턴 또는 줄 바꿈 중 하나로 분리된다. 

   따라서 배열은 실제 문자열에 산재 된 빈 요소로 끝난다.

   RemoveEmptyEntries옵션은 Split 메서드에 빈 요소를 포함하지 않도록 한다.

 

 

● 배열

 

# 배열의 맨 마지막 요소
$Array = @(1,2,3)
$Array[-1# result : 3
 
# splice - 지정된 요소 가져오기
## Sample array
$arr = 'one''two''three''four''five'
 
## 세 번째 요소로 시작하는 요소를 모두 반환한다.
$arr[1..($arr.Count-1)]
 
# 중복값 찾기
$array = 'A''B''C''C'
($array | Group-Object | Where-Object -FilterScript {$_.Count -gt 1}).Values
 
# 중복값 제거하기
$arr = @(1,2,3,4,5,5,6,7,8,9,0,0)
$arr = $arr | select -Unique
 
# 정렬 및 중복 제거
$arr = @(1,5,6,1,2)
$arr = $arr | sort -Unique 
## 중복을 제거하고 싶지않다면 -Unique 옵션을 뺀다.
 
cs

 

 

● 값 존재 유무 확인

if ( [String]::IsNullOrEmpty($var-eq $true )
   { echo "값이 없습니다." }
cs

 

● 파일 존재 유무 확인

if ( (Test-Path 'C:\0.jpg'-eq $true )
{
  echo "파일이 존재합니다."
}
cs

 

 

● 파일 제어

1
2
3
Set-Content -Path "C:\Users\test.txt" -Value ""  # Create
Add-Content -Path "C:\Users\test.txt" -Value "Hello Powershell" # Write
Get-Content -Path "C:\Users\test.txt"  # Read
cs

 

● 자료 검색

 

○ Select-String - 문자열을 찾아서 행을 반환한다.

1
2
Get-Content -Path "C:\Users\test.txt" | Select-string "Hello" # 파이프라인을 통한 검색
Select-String -Path "C:\Users\test.txt" -Pattern "Hello" #  일반 검색
cs

 

원하는 항목을 기준으로 아래 몇 째줄 까지의 정보를 보고자 한다면

Context 파라미터를 사용한다.  ex) Ipconfig | select-string LAN -context 0,6

 

○ match - 일치하는 패턴이 있는지 검사하는 표현식이다. 

1
2
3
4
$str = "hello PowerShell 31"
$str -match "\d+" # 매칭된 값은 Matches에 저장된다. 
$Matches[0]
# 출력값 : 31 -  
cs

 

 

 

● 파일 확장자 분리 및 확장자 획득

$file_name = 'abc123.txt'
$file_index = $file_name.IndexOf('.'
# indexOf(문자를 만날 경우 해당 위치를 반환한다)
 
if ( $file_index -gt 0 )
{
$FileName = $file_name.Substring(0,$file_index
$FileExt = $file_name.Substring($file_index,$file_name.Length - $file_index)
# Substring(해당 문자열에서 위치1~위치2 사이의 텍스트만 잘라서 보여준다)
 
echo $FileName #abc123
echo $FileExt #.txt
$file_name = [System.IO.Path]::GetExtension($file_name)
echo $file_name # .txt
cs

 

 

● 변수에 있는 명령어 실행

$Path = 'C:\Users\Administrator\Desktop\'
$cmd = 'Dir --Path "' + $Path + '"'
Invoke-Expression $cmd
cs

 

 

● 동영상 길이 추출 

 

① 특정 폴더에 있는 동영상 파일들의 길이를 추출하여 보여준다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$Length = @()
 
$Folder = "C:\Users\jdh52\OneDrive\바탕 화면\새 폴더\striming1"
 
foreach ($file in Get-ChildItem -Filter *.ts $Folder) {
      
    $Name = $file.Name
    $LengthColumn = 27
    $objShell = New-Object -ComObject Shell.Application 
    $objFolder = $objShell.Namespace($Folder)
    $objFile = $objFolder.ParseName($Name)
    $Len = $objFolder.GetDetailsOf($objFile$LengthColumn
 
 
    $Object = New-Object System.Object
    $Object | Add-Member -type NoteProperty -Name FileName -Value $Name
    $Object | Add-Member -type NoteProperty -Name Length -Value $len
    
  $Length += $Object
    }
 
    $Length
 
 
cs

 

② 특정 폴더를 기준으로 모든 하위 폴더를 순회한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$Length = @()
 
$Folder = "C:\Users\jdh52\OneDrive\바탕 화면\새 폴더"
 
foreach ($file in Get-ChildItem --Filter *.ts $Folder) {
      
    $Name = $file.Name
    $LengthColumn = 27
    $objShell = New-Object -ComObject Shell.Application 
    $objFolder = $objShell.Namespace($file.DirectoryName)
    $objFile = $objFolder.ParseName($Name)
    $Len = $objFolder.GetDetailsOf($objFile$LengthColumn
 
 
    $Object = New-Object System.Object
    $Object | Add-Member -type NoteProperty -Name FileName -Value $Name
    $Object | Add-Member -type NoteProperty -Name Length -Value $len
 
    $Length += $Object
 
    }
 
$Length
cs

 

 

 

● 웹 요청 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-6

 

① Method 

GET : Invoke-WebRequest -Method Get -Uri "http://test.com/board.php"
 
 
  POST: Invoke-WebRequest -Uri "http://test/login.php" -Method Post -Body @{
                user_id = "$id"
                user_pw = "$pw"
}
cs

 

② 파일 다운

# 웹 파일 다운 & 웹 텍스트 파일 다운
(New-Object System.Net.WebClient).DownloadFile('http://test/1.pdf','1.pdf')
(New-Object System.Net.WebClient).DownloadString('http://test/1.txt')
# SSL 인증 무시 
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true};
cs

 

 

● HTML 파싱

 

url에 해당하는 타이틀과 내용을 가져온다.

 
$url = invoke-WebRequest -URi "http://test.com/12"
 
$title = $url.ParsedHtml.IHTMLDocument2_TITLE
$out_text = $url.ParsedHtml.body.getElementsByClassName('this_class')[0].outerText
cs

 

 

● 시간 함수 

1
2
Get-Date -Format "yyyy/MM/dd HH시 mm분(dddd)" 
# result : 2019-09-01 09시 42분(일요일)
cs

 

 

● 브라우저 열기 

1
2
3
4
5
6
7
8
# 크롬
$browser = [System.Diagnostics.Process]::Start( "chrome.exe""-incognito http://www.naver.com")
 
# 인터넷 익스플로러
$url = 'http://www.naver.com'
$IE=new-object -com internetexplorer.application
$IE.navigate2($url)
$IE.visible=$true
cs

 

 

● 문자열 합치기 

1
2
3
4
5
6
7
8
$z = "a""b""c"
-join $z
## abc
 
$z = "a""b""c"
$z = $z -join ','
$z
## a,b,c
cs

 

 

 

● CSV 파일 다루기 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# CSV 파일 생성 및 추출
 
$csv_Path = 'C:\Users\Administrator\Desktop\test.csv'
 
# 방법1
$header = 'Number','Name'
$data = @(1,2-join ','
$data2 = @('a','b'-join ','
ConvertFrom-Csv -InputObject $data,$data2 -Header $header | Export-Csv $csv_Path -NoType 
 
# 방법2
$report = New-Object psobject
$report | Add-Member -MemberType NoteProperty -name Number -Value $data
$report | Add-Member -MemberType NoteProperty -name Name -Value $data2
$report | export-csv $csv_Path -NoTypeInformation
 
 
## result
Number      Name                                   
------            ----                                   
1                   2                                      
a                   b                                      
 
# CSV 파일 가져오기
Import-Csv -Path $csv_Path
# csv 추가
$report | export-csv -Append $Setting_Csv -NoTypeInformation -Force
cs

 

 

 

● 현재 PS 파일 위치 반환

 

1
2
$Current_path = Get-Location
echo $Current_path.Path
cs

 

 

 

● bool 형태로 변환

 

1
2
3
4
5
6
7
$result = "true"
try {
$result = [System.Convert]::ToBoolean($result)
} catch [FormatException] {
$result = $false
}
# result → True
cs

 

 

● 시스템 경로를 웹 url로 변경 

 

1
2
3
4
$Path = 'C:\Users\Administrator\Desktop\블 로 그.txt'
$System_Path = ([System.Uri]$Path).AbsoluteUri
$System_Path 
# file:///C:/Users/Administrator/Desktop/%EB%B8%94%20%EB%A1%9C%20%EA%B7%B8.txt
cs

 

 

● 환경변수 사용

$Save_file_path = $env:systemdrive + '\users\' + $env:username + '\desktop' Set-Location $Save_file_path
# desktop 이동
cs

 

PowerShell에서 %PATH%와 같은 방식으로 환경변수를 사용할 수 없다.

환경변수를 사용하기 위해서는 $env: 라는 접두어를 붙여줘야한다.

 

 

● 특수 문자 이스케이프 

1
2
3
$Data = "!$#"
[RegEx]::Escape($Data)
# !\$\#
cs

 

 

 

URL 인코딩 - 디코딩

1
2
3
4
5
6
7
[Reflection.Assembly]::LoadWithPartialName("System.Web"| Out-Null
 
$URL = 'http://www.naver.com'
$Encode = [System.Web.HttpUtility]::UrlEncode($URL)
$Decode = [System.Web.HttpUtility]::UrlDecode($Encode)
 
# http%3a%2f%2fwww.naver.com - http://www.naver.com
cs

 

 

 

● 운영체제 구성 정보 확인 

1
systeminfo
cs

 

조회항목 

호스트 이름,OS 이름,OS 버전,OS 제조업체,OS 구성,OS 빌드 종류,등록된 소유자,등록된 조직,제품 ID,원래 설치 날짜,시스템 부트 시간,시스템 제조업체,

시스템 모델,시스템 종류,프로세서

 

BIOS 버전,Windows 디렉터리,시스템 디렉터리,부팅 장치,시스템 로캘,입력 로캘,표준 시간대, 총 실제 메모리,사용 가능한 실제 메모리,가상 메모리 최대 크기,

가상 메모리 사용 가능,가상 메모리 사용 중,페이지 파일 위치,도메인,로그온 서버,업데이트 핫픽스

 

 

● Copy & Paste 

1
2
3
"copy_text" | clip
Set-Clipboard "copy_text" [System.Windows.Forms.SendKeys]::SendWait("^v")
cs

1번 혹은 2번 기능을 사용하면 된다. 

파워쉘을 exe로 만들었을 때 1번 기능은 특수문자가 깨지는 증상이 발생될 수있다.

 

키코드 확인

https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ff731008(v=technet.10)

 

 

 

● 특정 폴더 및 파일 열기

1
2
3
Invoke-Item 'C:\Users\파일.txt' # 파일 열기
Invoke-Item 'C:\Users\폴더' # 해당 경로에서 탐색기 열기
# Invoke-Item 별칭 = ii
cs

 

 

 

● 백그라운드 작업 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 시작
 
## 유형1
$job1 = start-job { Get-ChildItem }
 
 
## 유형2
$scriptblock = { 
        while($true
        { 
        Start-Sleep -Milliseconds 400
        echo "abc" 
        } 
 
 
$job2 = start-job -ScriptBlock $scriptblock
 
 
# 중지
Stop-Job $job
 
# 작업이 완료될 때까지 대기
wait-job $job
 
# 상태 확인
$job.JobStateInfo.State # Completed or Running
 
# 작업결과 수신
Receive-Job $job
cs

 

 

 

● 키입력 받기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$signature = @'
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] 
public static extern short GetAsyncKeyState(int virtualKeyCode); 
'@
 
# load signatures and make members available
$API = Add-Type -MemberDefinition $signature -Name 'Keypress' -Namespace API -PassThru
 
# wait for 'A'
$waitFor = 'A'
$ascii = [byte][char]$waitFor.ToUpper()
 
do 
{
  Start-Sleep -Milliseconds 40
} until ($API::GetAsyncKeyState($ascii-eq -32767)
cs

 

'A'를 입력받으면 프로그램이 종료된다. 

user32 API를 이용하여 구현할 수 있으며 , 응용하여 키로거를 구현할 수 있다.

https://gist.github.com/dasgoll/7ca1c059dd3b3fbc7277

 

 

● IE에서 html 수집

1
2
3
4
5
6
7
8
$ie = new-object -ComObject "InternetExplorer.Application"
$url = "http://jdh5202.tistory.com/479"
$ie.visible = $true
$ie.navigate($url)
while($ie.Busy) { Start-Sleep -Milliseconds 100 }
$ie.Document.getElementsByClassName('tt_article_useless_p_margin'> "C:\Users\jdh52\Desktop\output.html"
$ie.Stop()
$ie.Quit()
cs

 

 

 

● 특정 문자 뒤의 값을 추출

1
2
3
4
5
6
7
8
9
10
11
$content = 'ABCDEFG (title) 제목입니다.'
$select_str = "(title)"
$sel_idx = $select_str.Length
 
$title = ($content | Select-String $select_str)
$title_idx = $title.Matches.Index
$title = $title.ToString()
 
$title =  $title.Substring( $title_idx + $sel_idx$title.Length - $sel_idx - $title_idx )
$title
# 제목입니다.
cs

 

 

 

● 특정 문자의 위치를 모두 반환

1
2
("Words words words" | Select-String "words" -AllMatches).Matches.Index
# 0,6,12
cs

 

 

● 배열인지 체크

1
2
$a = 1,2,4,5,6,7
$a -is [array]
cs

 

 

● 현재 ps 스크립트가 실행되고 있는 경로 얻기 

 
 
1
2
3
$fullPathIncFileName = $MyInvocation.MyCommand.Definition # Script 파일의 full path
$currentScriptName = $MyInvocation.MyCommand.Name # Script 파일 이름
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName""# Script 폴더
cs

 

● 파워쉘 특수문자 제거

 
1
2
3
$c = 'This_is my code !@# characters are not $ allowed% remove spaces ^&*(){}[]/_:;,.?/"'''
$c -replace '\W','-'
# This_is-my-code-----characters-are-not---allowed--remove-spaces-----------_--------
cs

 

 

● 환경변수 사용

 
1
2
3
# PowerShell에서 출력 시 %PATH%와 같은 방식으로 환경변수를 사용할 수 없다.
# PowerShell에서 환경변수를 사용하기 위해서는 $env: 라는 접두어를 붙여줘야한다.
$Save_file_path = $env:systemdrive + '\users\' + $env:username + '\desktop'
cs

 

 

● 입력창 사용

 
1
2
 
[Void] [Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") $response = [Microsoft.VisualBasic.Interaction]::InputBox('Enter your input.', 'Sample Input Box','출력될 내용')
cs

 

 

● 현재 스크립트 위치 설정

 
1
2
 
$scriptPath = $(get-location).Path; Set-Location $scriptPath
cs

 

 

 

● 화면 해상도 설정

 
1
2
 
(Get-WmiObject -Class Win32_VideoController).CurrentHorizontalResolution[0] # 가로 (Get-WmiObject -Class Win32_VideoController).CurrentVerticalResolution[0] # 세로
cs

 

 

● 디렉터리 경로 획득

 
1
 
$dirName=[System.IO.Path]::GetDirectoryName("c:\temp\newdata.txt") # c:\temp
cs

 

 

● 파일 텍스트 검색

 
1
2
3
4
 
# 파일 내의 특정 텍스트가 존재하는 파일을 하나만 표시한다. 
Get-ChildItem -Recurse *.* | Select-String -Pattern "foobar" | Select-Object -Unique Path
# .. 일치하는 파일 하나와 줄 번호를 표시한다.
dir | Select-String -List "text"
cs

 

● 관리자 권한 실행 체크 및 관리자 권한으로 실행

$currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
powershell -command "Start-Process -verb runas powershell"

 

● 사용자 입력박스 출력 

[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') 
$select = [Microsoft.VisualBasic.Interaction]::InputBox('메뉴 번호', '메뉴 선택')

 

반응형

'OS-서버 > 윈도우' 카테고리의 다른 글

Powershell 원격에서 ssh 명령 실행 , 파일 전송  (0) 2018.03.20
Powershell XML  (0) 2018.03.20
Powershell 원격 제어  (0) 2018.03.20
Powershell Alias  (0) 2018.03.20
Powershell 기본 문법  (2) 2018.03.20