본문 바로가기
운영체제 (LNX,WIN)

PowerShell로 원격 컴퓨터 정보를 엑셀에 삽입하기

by 날으는물고기 2010. 1. 5.

PowerShell로 원격 컴퓨터 정보를 엑셀에 삽입하기

스크립트를 작성할 때는 각자 익숙한 방법에 안주하기 쉽습니다. 매번 같은 방법으로 똑같은 결과를 얻으려 합니다.
예를 들어 모니터링과 관련해서, Windows PowerShell을 사용하면 로컬 컴퓨터의 프로세스 사용률에 대한 유용한 스냅숏을 쉽게 얻을 수 있습니다. Get-Process cmdlet을 사용하면 그림 1과 같은 깔끔한 출력을 얻게 됩니다.
그림 1 Get-Process를 사용하여 로컬 프로세스 살펴보기

Get-Process cmdlet의 결과는 다양한 상황에서 유용하게 사용할 수 있습니다. 대표적인 예로 열린 핸들의 수, 메모리 소모량에 대한 몇 가지 보기, CPU 사용률의 스냅숏 등을 표시합니다. 또한 Windows PowerShell 2.0에서는 Get-Process를 –computername 매개 변수와 함께 사용하여 원격 컴퓨터에서 이러한 개요 정보를 검색할 수 있습니다. 이렇게 편리한데 왜 다른 정보를 조사하는 데 사용하는 사람이 없을까요?
문제는 긴 데이터 열에 너무 많은 정보가 숨겨져 있다는 점입니다. 이러한 모든 데이터는 다시 또 중요한 세부 정보를 내포한 경우가 많습니다. 앞으로 Windows PowerShell 2.0에서 –computername 매개 변수를 지원하게 되면 좋겠지만 지금은 네트워크 관리자에게 아무런 소용이 없습니다. 따라서 원격 시스템을 모니터링하고 실질적으로 유용한 방식으로 정보를 표시하려면 WMI(Windows Management Instrumentation)와 Win32_Process WMI 클래스를 사용할 수밖에 없습니다. Get-Process의 출력이 너무 장황하다고 생각했다면 그림 2에 나와 있는 Win32_Process의 출력을 잘 살펴보십시오.
그림 2 WMI를 사용하여 프로세스 보기

자, 그럼 네트워크 관리자가 사용되는 메모리 용량에 대한 읽기 쉬운 보고서를 얻으려면 어떻게 해야 할까요? 바로 이 부분에서 발상을 전환하고 Excel 자동화로 눈길을 돌려야 합니다. 대부분 컴퓨터에 Microsoft Office Excel이 설치되어 있을 것입니다. 그리고 Scripting Guy와 마찬가지로 전문가는 아니지만 Microsoft Office system에 포함된 Excel을 유용하게 사용하고 있을 것입니다.
Excel을 자동화하는 것은 많이 어려울까요? Microsoft가 Excel에서 작동하도록 특별히 설계된 자동화 모델을 만든 덕분에 사실 Excel 자동화는 쉬운 편이라고 할 수 있습니다. 프로그램 ID는 Excel.Application이며 COM 개체입니다. Excel.Application 개체 인스턴스를 만들면 기본적으로 Excel이 시작 및 실행되지만 표시되지는 않습니다. 그러나 visible 속성을 사용하면 Excel을 표시할 수 있습니다.
Excel.Application 개체를 만들고 visible 속성의 상태를 쿼리한 다음 visible 속성을 true로 설정하는 코드는 다음과 같습니다.
PS C:\> $excel = New-Object -ComObject Excel.Application
PS C:\> $excel.Visible
False
PS C:\> $excel.Visible = $true

이렇게 설정하면 Excel 응용 프로그램의 셸과 유사한 다소 생소한 형태의 Excel 보기가 나타납니다(그림 3 참조). 통합 문서나 스프레드시트 없이 Excel 창만 있는 모습이라는 것을 알 수 있습니다.
그림 3 통합 문서나 스프레드시트가 없는 Excel 창

따라서 이 응용 프로그램에 통합 문서를 추가해야 합니다. 통합 문서를 추가하려면 workbook 개체의 add 메서드를 사용합니다. workbook 개체는 기본 Excel.Application 개체에서 액세스합니다. 다음에서 보듯이 Excel.Application 개체에는 $workbook이라는 변수에 workbook 개체가 저장됩니다. 
$workbook = $excel.Workbooks.add()

이제 특정 스프레드시트에 연결해야 합니다. Excel에 통합 문서를 추가하면 기본적으로 3개의 스프레드시트가 통합 문서에 추가됩니다. 이러한 스프레드시트는 번호로 지정할 수 있습니다. 다음 코드에서는 첫 번째 스프레드시트에 연결하고 반환된 spreadsheet 개체를 $sheet라는 변수에 저장합니다.
$sheet = $workbook.worksheets.Item(1)

다음으로 해당 스프레드시트에 데이터를 씁니다. Excel 스프레드시트의 정보는 셀에 저장됩니다. 셀은 스프레드시트에 존재하므로 $sheet 변수에 저장된 spreadsheet 개체를 사용하여 특정 셀에 액세스합니다. 이때는 스프레드시트의 행과 열을 나타내는 번호를 사용하면 됩니다. 여기서 한 가지 까다로운 점은 Excel 스프레드시트에서 행은 숫자이고 열은 문자라는 사실입니다. 그러나 자동화 모델을 사용할 때는 행과 열이 모두 숫자입니다. 첫 번째 숫자는 행을 나타내고 두 번째 숫자는 열을 나타냅니다. 다음과 같이 특정 셀에 값을 할당하기만 하면 셀에 쓸 수 있습니다.
$sheet.cells.item(1,1) = "Test"

Excel.Application 개체에 통합 문서를 추가하고 스프레드시트의 셀에 데이터를 추가하고 나면 Excel 통합 문서가 그림 4와 같이 됩니다. 
그림 4 셀에 값 추가

지금까지 설명한 내용을 한번 유용하게 사용해 보겠습니다. WMI에서 프로세스 정보의 컬렉션을 가져와 Excel 스프레드시트에 각 프로세스의 이름 및 메모리 사용량을 기록한 다음 사용된 메모리를 알기 쉽게 보여 주는 차트를 만들어봅니다. 이는 WriteProcessInformationToExcel.ps1의 기능을 잘 보여 주는 예라고 할 수 있습니다. 전체 스크립트는 TechNet Magazine 웹 사이트에서 다운로드할 수 있습니다.
먼저 Get-WmiObject cmdlet를 사용하여 프로세스에 대한 정보의 컬렉션을 검색하는 것으로 스크립트를 시작합니다. Win32_Process WMI 클래스를 사용하여 정보를 가져온 다음 $processes 변수에 저장합니다.
$processes = Get-WmiObject -class Win32_Process

이제 Excel.Application 개체의 인스턴스를 만들어 $excel 변수에 저장한 다음 응용 프로그램을 표시하고 통합 문서를 추가합니다. 모든 Excel 자동화 과정에서는 일반적으로 이 단계를 수행하게 됩니다. 해당 코드는 다음과 같습니다.
$excel = new-object -comobject excel.application
$excel.visible = $true
$workbook = $excel.workbooks.add()

Excel에서 성가신 부분 중 하나는 통합 문서에 항상 3개의 스프레드시트가 만들어진다는 점입니다. 대개 스프레드시트를 하나도 다 채우기가 어렵기 때문에 3개까지는 필요가 없습니다. 다행히 자동화 시에는 worksheets 컬렉션을 사용하여 세 번째 스프레드시트에 연결하고 delete 메서드를 호출함으로써 불필요한 스프레드시트를 삭제할 수 있습니다. 그리고 두 번째 스프레드시트도 같은 방법으로 삭제할 수 있습니다.
$workbook.workSheets.item(3).delete()
$workbook.WorkSheets.item(2).delete()

다음으로 남은 스프레드시트의 이름을 바꿉니다. ADO(ActiveX Data Objects)를 사용하여 Excel 스프레드시트를 쿼리할 경우 연결 문자열에 스프레드시트 이름을 사용하게 되므로 이는 중요한 단계라고 할 수 있습니다. 따라서 코드를 직관적이고 읽기 쉽도록 만들려면 스프레드시트에 논리적인 이름을 사용해야 합니다. 스프레드시트 이름을 바꾸려면 해당 스프레드시트의 name 속성에 새 값을 할당하면 됩니다. 다음은 첫 번째 스프레드시트의 이름을 "Processes"로 바꾸는 코드입니다.
$workbook.WorkSheets.item(1).Name = "Processes"

이제 이름을 바꾼 스프레드시트에 연결해야 합니다. worksheets 개체의 Item 메서드를 사용합니다. 이때 Item 메서드에는 스프레드시트 이름을 지정합니다.
$sheet = $workbook.WorkSheets.Item("Processes")

스프레드시트의 첫 번째 행에는 머리글 정보가 들어갑니다. 이 행에 테두리를 표시하고 속성 이름을 굵은 글꼴로 변경합니다. 결과적으로 데이터는 둘째 행부터 시작되므로 카운터 변수 $x에 2라는 값을 할당합니다.
$x = 2

다음으로 4줄의 코드로 4개의 열거형을 만듭니다. 열거형은 Excel에서 특정 형식의 옵션에 대해 허용되는 값을 알리는 데 사용됩니다. 예를 들어 xlLineStyle 열거형은 이중선, 점선 등 표시할 선의 종류를 결정하는 데 사용됩니다. 이러한 열거형 값 MSDN에 설명되어 있습니다.
코드를 알아보기 쉽도록 사용할 네 가지 열거형 각각에 대해 바로 가기 별칭을 만듭니다. 실질적으로 말하면 열거형 이름을 나타내는 문자열을 [type]에 넣는 것입니다. 이 기법은 상당히 유용합니다.
$lineStyle = "microsoft.office.interop.excel.xlLineStyle" -as [type]
$colorIndex = "microsoft.office.interop.excel.xlColorIndex" -as [type]
$borderWeight = "microsoft.office.interop.excel.xlBorderWeight" -as [type]
$chartType = "microsoft.office.interop.excel.xlChartType" -as [type]

이제 첫 번째 행의 서식을 지정해야 합니다. 굵은 글꼴로 변경하고 선을 xlDashDot로 정의하고 색이 자동으로 지정되도록 하고 테두리 두께를 보통으로 설정합니다.
For($b = 1 ; $b -le 2 ; $b++)
{
 $sheet.cells.item(1,$b).font.bold = $true
 $sheet.cells.item(1,$b).borders.LineStyle = $lineStyle::xlDashDot
 $sheet.cells.item(1,$b).borders.ColorIndex = $colorIndex::xlColorIndexAutomatic
 $sheet.cells.item(1,$b).borders.weight = $borderWeight::xlMedium
}

서식 지정이 끝나면 item 메서드로 셀을 선택하고 행과 열의 좌표를 지정하여 첫 번째 행에 값을 할당합니다. 다음으로 값을 직접 할당하여 열 머리글을 작성합니다.
$sheet.cells.item(1,1) = "Name of Process"
$sheet.cells.item(1,2) = "Working Set Size"

이제 WMI 쿼리 결과로 생성된 $processes 변수에 저장되어 있는 프로세스 정보를 적절한 셀에 넣어야 합니다. foreach 문을 사용하여 프로세스 정보 수집을 반복합니다. $process 변수를 수집을 위한 열거자(자리 표시자)로 정의하고 첫 번째 및 두 번째 열에 각각 name 속성과 workingSetSize 속성을 쓰도록 선택합니다.
바로 여기서 $x 변수가 사용됩니다. 둘째 행부터 시작하고 프로세스 수집을 반복하면서 $x 변수의 값을 증가시켜 항상 컬렉션의 현재 행을 가리키도록 합니다. 따라서 프로세스 정보의 $processes 컬렉션에 저장된 모든 데이터에 대해 코드를 반복할 수 있는 것입니다.
Foreach($process in $processes)
{
 $sheet.cells.item($x, 1) = $process.name
 $sheet.cells.item($x,2) = $process.workingSetSize
 $x++
} #end foreach

Excel 스프레드시트가 완성되면 셀 크기가 저장된 데이터 크기와 일치하도록 열 크기를 조정합니다. 이때 사용할 열 좌표를 지정하여 범위를 만들 수도 있지만 스프레드시트의 usedRange 속성을 사용하는 편이 간단합니다. range 개체를 만든 경우에는 EntireColumn 속성을 선택하고 AutoFit 메서드를 사용하여 열 크기를 조정합니다. 이 메서드는 항상 데이터를 반환하므로 결과를 Out-Null cmdlet에 전달합니다. 이렇게 하면 콘솔에 불필요한 정보가 어지럽게 출력되지 않아 좋습니다. 사용할 코드는 다음과 같습니다.
$range = $sheet.usedRange
$range.EntireColumn.AutoFit() | out-null

여기까지만 하면 모든 프로세스의 이름과 메모리 작업 집합이 표시된 깔끔한 스프레드시트를 얻을 수 있습니다. 그러나 한 걸음 더 나가서 차트까지 만들어보도록 하겠습니다. 차트는 쉽게 만들 수 있습니다. 통합 문서에서 charts 개체의 add 메서드를 사용합니다. 이 메서드는 불필요한 정보까지 반환하므로 다음과 같이 결과를 Out-Null cmdlet에 전달합니다.
$workbook.charts.add() | out-null  

위의 명령을 실행하면 꺾은선형 차트가 추가됩니다. 다른 종류의 차트를 정의하려면 차트 종류 열거형 값 중 하나를 사용해야 합니다. 이때 xl3DPieExploded 형식과 같은 microsoft.office.interop.excel.xlChartType 열거형 값 중 하나를 사용해도 됩니다. 이름으로도 알 수 있지만 xl3DPieExploded 형식은 쪼개지는 3차원 원형 차트를 만듭니다. 이 열거형을 ActiveChart 개체의 chartType 속성에 할당합니다. 그런 다음 $range 변수에 정의한 범위를 차트의 데이터 원본으로 할당합니다. 화면에서 결과는 꺾은선형 차트가 순간적으로 표시되었다가 3차원 원형 차트가 쪼개지는 것으로 나타납니다. 코드는 다음과 같습니다.
$workbook.ActiveChart.chartType = $chartType::xl3DPieExploded
$workbook.ActiveChart.SetSourceData($range)

재미삼아 원형 차트를 한번 회전시켜 보겠습니다. 차트를 회전시키려면 ActiveChart 개체의 rotation 속성을 사용합니다. 그리고 for 문을 사용하여 카운트를 360까지 15씩 증가시킵니다. 360은 원의 각도이며 차트는 한 번에 15도씩 회전하면서 원을 만듭니다. 결과는 꽤 멋지게 나타납니다. 코드는 다음과 같습니다.
For($i = 1 ; $i -le 360 ; $i +=15)
{
 $workbook.ActiveChart.rotation = $i
}

마지막으로 스프레드시트를 저장해야 합니다. 스프레드시트를 저장하려면 먼저 Test-Path cmdlet을 사용하여 같은 이름의 스프레드시트가 이미 있는지 확인합니다. 같은 이름의 스프레드시트가 있으면 Remove-Item cmdlet을 사용하여 기존 스프레드시트를 삭제한 다음 $strPath 변수에 저장된 위치에 현재 통합 문서를 저장합니다. Excel.Application 개체의 ActiveWorkbook 개체와 SaveAs 메서드를 사용하여 통합 문서를 저장합니다. 저장된 스프레드시트의 복사본이 없으면 ActiveWorkbook 개체의 SaveAs 메서드를 사용하여 바로 저장합니다.
IF(Test-Path $strPath)
  { 
   Remove-Item $strPath
   $Excel.ActiveWorkbook.SaveAs($strPath)
  }
ELSE
  {
   $Excel.ActiveWorkbook.SaveAs($strPath)
  }

이 스크립트를 실행하면 그림 5와 같은 차트가 나타납니다.
그림 5 Processes 쪼개진 원형 차트

스프레드시트 자체는 Processes 탭에 있습니다. 그림 6은 열 머리글, 테두리로 선택한 점선 스타일, 굵은 글꼴의 열 머리글을 보여 줍니다. 프로세스 이름 및 작업 집합 속성이 두 개의 데이터 열로 표시됩니다.
그림 6 완성된 스프레드시트

지금까지 보았듯이 Excel.Application 자동화 모델을 사용하면 서버에서 가져온 데이터를 Excel의 풍부하고 강력한 분석 및 차트 작성 도구를 활용하여 처리할 수 있습니다.


Perl로 하는 예제 코드
- http://talhatariq.wordpress.com/2006/06/20/a-perl-script-to-list-process-info-through-wmi-local-remote/

참고:
1. PowerShell 로 워드 문서 만들기
 - http://www.microsoft.com/technet/scriptcenter/resources/qanda/may09/hey0513.mspx
2. PowerShell 로 MySQL 사용하기
 - http://programming.torensma.net/2009/01/connect_powershell_to_mysql/
3. PowerShell 로 브라우저 컨트롤하기
 - http://msdn.microsoft.com/ko-kr/magazine/cc337896.aspx

출처 : http://swbae.egloos.com
728x90

댓글