Hey, Scripting Guy!로컬 사용자 및 그룹에 대한 순진한 이야기

Microsoft Scripting Guys

이 기사의 코드 다운로드: HeyScriptingGuy2007_04.exe (151KB)

파일과 폴더에 대한 보안 설명자는 어떻게 관리해야 합니까?

믿기 어렵겠지만 한때 Scripting Guy가 별로 똑똑하지 못했던 적도 있습니다. 물론, 오래전 이야기지요. 믿기 힘든 이야기죠? 아니라고요? 지금도 별로 똑똑해 보이지 않는다고요? 왜 그렇게 생각하시죠? 혹시 얼마 전에 Scripting Guy 중 한 명이 새로 산 TV를 연결하지 못해 애먹는 모습을 보셨나요?

그 Scripting Guy를 대신해 변명을 하자면 새 TV를 연결하는 것은 로켓 공학과는 다르지 않습니까? 사실 로켓 공학보다 훨씬 더 복잡하지요. TV를 연결하는 것 자체는 세 가닥의 비디오 케이블과 두 가닥의 오디오 케이블만 연결하면 되는 간단한 일이지만, 거기에 VCR, DVD 플레이어, Xbox®까지 연결하고 범용 리모컨에서 모든 장치를 인식하도록 해야 하니까요. 거기에 비하면 인공위성을 화성 궤도에 띄우는 것 정도는 식은 죽 먹기지요.

놀랍게도 그 Scripting Guy는 결국 모든 연결 작업을 완벽하게 마무리했습니다. 그러나 장치를 모두 켜도 화면이나 소리가 전혀 나오지 않았습니다. 그래서 모든 연결을 꼼꼼하게 재차 확인하고 설명서를 전부 읽고 놓친 정보가 없는지 인터넷에서 검색까지 해 보았지만 소용이 없었습니다. 그런데 전자 제품의 신에게 MP3 플레이어를 제물로 바치려던 찰나에 케이블 선을 벽면의 케이블 TV 단자에 연결하지 않았다는 사실을 알게 되었습니다.

참고: 이렇게 장치를 연결하기가 어려운 것은 분명 굉장히 많은 장치가 있기 때문일 것이다라고 생각하시겠지요? 사실 이 Scripting Guy도 같은 생각입니다. 그렇지만 이 Scripting Guy는 새로운 장치를 구입하는 데 대해 가족 투표를 할 때마다 늘 2-0으로 이기곤 합니다. 2-1이 아니라 2-0으로 말입니다. 어떻게 된 일인지 이 Scripting Guy의 아버지는 투표권이 없었던 모양입니다. 뭐, 기록이 없으니 확인할 길은 없지만요.

그렇다고 그 아버지가 방관만 하고 있었던 것은 아닙니다. 그러나 아직까지 UN은 그 집에 선거 관리 위원회를 보내지 않고 있으니 어찌할 도리가 없지요.

잘 생각해 보면 Scripting Guy들(특히 새 TV를 연결하려던 사람)은 순진할 따름이지 그렇게 바보는 아닙니다. Scripting Guy들은 Microsoft® Windows® 2000 Scripting Guide를 계획할 당시에 책의 구성에 대해 여러 전문가로부터 도움을 구해야 했습니다. 그 과정에서 삭제된 단원 중 하나가 바로 로컬 사용자 및 그룹을 관리하는 방법에 대한 단원이었습니다. 전문가는 "로컬 사용자 및 그룹 관리? 이런 내용이 왜 필요하죠?"라고 말하더군요. "대체 누가 이런 내용을 넣을 생각을 했죠? 로컬 사용자와 그룹을 관리하는 방법을 누가 알고 싶어 하겠습니까?"라고 말이죠.

그랬는데, 뒤늦게 원통하게도 우리 "전문가"들을 제외한 모두가 로컬 사용자 및 그룹에 대해 알고 싶어한다는 사실을 알게 되었습니다. 저희는 매주 사용자들로부터 컴퓨터에서 사용자를 로컬 그룹에 추가하거나 로컬 그룹에서 사용자를 제거하거나 로컬 Administrator 암호를 바꾸는 방법을 묻는 전자 메일을 엄청나게 받았습니다.

스크립트 센터 스크립트 리포지토리에 이러한 작업을 수행하는 방법을 보여 주는 몇 가지 샘플 스크립트가 있긴 하지만 대부분 한번에 한 컴퓨터에서만 사용할 수 있는 스크립트입니다. 하지만 여러 컴퓨터에서 동시에 이러한 작업을 수행하는 방법을 알고 싶어하는 독자가 많습니다. 한 대의 컴퓨터에서만 로컬 Administrator 암호를 변경한다고요? 그러한 작업은 현실적으로 전혀 도움이 되지 않습니다. 사내의 모든 컴퓨터에서 이러한 작업을 수행하거나 적어도 OU의 모든 컴퓨터 또는 모든 메일 서버에 대해 이러한 작업을 수행해야 하는 경우가 대부분입니다.

Scripting Guide가 2003에 출간되었으니, 거의 4년 동안 같은 내용의 전자 메일 메시지 공세를 받아온 셈입니다. 얼마 전에는 Scripting Guy 중 한 명이 "또 독자 중 한 명이 Excel® 스프레드시트에서 컴퓨터 이름을 읽어 각 컴퓨터에서 로컬 Administrator 암호를 바꾸는 방법에 대해 문의해 왔다"면서, "이게 가능하기는 한 겁니까?"라고 반문하더군요.

뭐, 4년이 걸리긴 했지만 결국 방법을 알아냈습니다. 그림 1에 그 방법이 나와 있습니다.

Figure 1 마침내 찾아낸 방법!

On Error Resume Next

Set objExcel = CreateObject(“Excel.Application”)
Set objWorkbook = objExcel.Workbooks.Open(“C:\Scripts\Test.xls”)
objExcel.Visible = True

i = 2

Do Until objExcel.Cells(i, 1).Value = “”
    strComputer = objExcel.Cells(i, 1).Value   
    Set objUser = GetObject(“WinNT://” & strComputer & “/Administrator”)
    If Err = 0 Then
         objUser.SetPassword “egTY634!alK2”
         objExcel.Cells(i, 2).Value = Now
    End If
    Err.Clear
    i = i + 1
Loop

참고: 아시다시피 이 스크립트를 작성하기가 특히 어려워서 4년이나 걸린 것은 아니고 우리는 무슨 일을 하든 그만큼 시간이 걸립니다. Scripting Guy의 송년 파티를 한번 놓치면 또 언제 그런 기회가 올지 모르는 것과 마찬가지지요.

이 스크립트는 스프레드시트에서 컴퓨터 이름을 가져와 각 컴퓨터에서 로컬 Administrator 암호를 변경합니다. 이 작업을 수행하는 방법을 최대한 간단하게 보여 주기 위해 그림 2와 같은 매우 간단하고 짧은 스프레드시트를 사용하도록 하겠습니다. 간단한 스프레드시트가 없다면 지금 당장 새로 만드십시오.

그림 2 컴퓨터의 필수 항목 목록

그림 2** 컴퓨터의 필수 항목 목록 **(더 크게 보려면 이미지를 클릭하십시오.)

그림에서 볼 수 있는 것처럼 특별한 것은 없습니다. 열 1(열 A)에는 암호를 변경해야 하는 모든 컴퓨터의 이름이 나열되어 있습니다. 열 2(열 B)에는 각 컴퓨터의 Administrator 암호를 마지막으로 변경한 날짜와 시간이 기록됩니다. 따라서 Administrator 암호가 모두 동기화된 상태로 관리되고 있는지 확인할 수 있습니다.

스크립트에 대해 설명하자면, 먼저 On Error Resume Next 문을 사용합니다. 보통 우리는 스크립트에 오류 처리 기능을 추가하지 않습니다. 오류 처리 기능이 필요 없다고 생각해서가 아니라 스크립트를 가능한 한 이해하기 쉽도록 짧고 간단하게 만들기 위해서입니다. 그러나 이 예에서는 On Error Resume Next 문이 중요한 역할을 합니다. 지금 우리가 작성하는 스크립트는 많은 수의 컴퓨터에 연결하게 되는데, 컴퓨터 중 하나가 꺼져 있다면 어떻게 될까요? 오류 처리 기능만 있다면 아무 문제가 없을 것입니다. 오류가 발생하기는 하겠지만 스크립트에서 오류를 처리하고 작업을 계속 진행할 수 있을 테니까요. 그러나 오류 처리 기능이 없다면 Scripting Guy가 TV를 처음 설치할 때 겪었던 것과 같은 문제를 겪게 될 것입니다. 스크립트를 실행해도 아무 결과도 얻지 못하게 되는 것이죠.

다음으로 아래의 코드 블록을 사용하여 Excel.Application 개체의 인스턴스를 만들고 해당 Excel 인스턴스가 화면에 표시되도록 한 다음 C:\Scripts\Test.xls 스프레드시트를 엽니다.

Set objExcel = CreateObject _
    (“Excel.Application”)
Set objWorkbook = objExcel.Workbooks.Open _
    (“C:\Scripts\Test.xls”)
objExcel.Visible = True

그리고 마지막으로 i라는 카운터 변수에 값 2를 할당했습니다. 이 변수는 스프레드시트에서 현재 행을 추적하는 데 사용됩니다.

참고: 그렇다면 변수 i에 2라는 값을 할당한 이유는 무엇일까요? 간단합니다. 스프레드시트를 자세히 살펴보면 행 1은 머리글 행이고 실제 데이터는 행 2부터 시작한다는 사실을 알 수 있습니다.

이제 아시겠죠? Scripting Guy가 YPbPr1 케이블을 연결하는 데에는 서툴지 모르지만 스크립팅에 대해서는 일가견이 있다는 사실을 말이죠.

뭐, 적어도 가끔은 말입니다.

이제 본 작업을 실행할 준비가 다 되었습니다. 먼저 열 1에서 빈 셀에 도달할 때까지 실행되는 Do Until 루프를 설정합니다. 따라서 어떠한 경우라도 열 1의 셀은 비워 둘 수 없습니다. 스크립트가 빈 행에 도달하면 데이터의 끝에 도달한 것으로 간주하여 루프와 스크립트가 끝나기 때문입니다. 이러한 문제를 해결하는 방법이 몇 가지 있기는 하지만 그냥 스프레드시트에 빈 행이 없도록 하는 것이 가장 간단합니다.

루프에서는 먼저 행 i, 열 1의 셀에 있는 값을 strComputer라는 변수에 할당합니다. 앞서 설명했듯이 처음 루프를 실행하면 i에 2가 할당되므로 행 2, 열 1의 셀 값을 사용하여 작업을 실행하게 됩니다. 그리고 다음 코드 줄을 사용하여 변수 strComputer로 표시되는 컴퓨터의 로컬 Administrator 계정에 대한 개체 참조(objUser)를 만듭니다.

Set objUser = GetObject(“WinNT://” & _
    strComputer & “/Administrator”)

이 스크립트를 실행했을 때 문제가 발생하면 여기서 중지됩니다. 네트워크 문제가 있다거나 컴퓨터의 전원이 꺼져 있다거나 Scripting Guy 중 한 명이 DVD 플레이어를 잘못 연결해서 미국 서부 지역 전체가 정전이 되었다면 말이지요. 이러한 일이 발생하면 컴퓨터에 연결할 수 없게 됩니다. 때문에 VBScript Err 개체의 값을 바로 확인해야 합니다.

If Err = 0 Then

Err 개체의 값이 0이면 아무 문제 없이 컴퓨터와 Administrator 계정에 연결할 수 있습니다. Err의 값이 0이 아니면 연결 시도가 실패합니다. 컴퓨터에 연결할 수 없다면 당연히 암호를 변경할 수도 없으므로 해당 컴퓨터에서 암호 변경을 시도할 필요조차 없습니다.

모든 작업이 순조롭게 진행되고 오류가 발생하지 않으면 다음 두 줄의 코드를 실행합니다.

objUser.SetPassword “egTY634!alK2”
objExcel.Cells(i, 2).Value = Now

첫 번째 줄에는 로컬 Administrator의 계정에 새 암호 egTY634!alK2를 할당하기 위해 SetPassword 메서드가 사용되었습니다. (아이의 이름을 암호로 사용하지는 않으시겠지요?) 두 번째 줄에서는 VBScript Now 함수를 사용하여 행 i, 열 2의 셀에 현재 날짜와 시간을 기록합니다. Password Changed 열은 원격 컴퓨터에 연결하여 실제로 암호를 변경할 수 있는 경우에만 업데이트됩니다. 컴퓨터에 연결할 수 없으면 해당 Password Changed 필드가 업데이트되지 않습니다. 따라서 성공적으로 실행된 작업과 실패한 작업을 구분할 수 있습니다.

이것이 의미하는 바가 무엇인지 궁금하실 것입니다. 이는 루프를 처음 실행할 때 스프레드시트가 그림 3과 같이 된다는 의미입니다.

그림 3 첫 번째 암호를 다시 설정한 후의 컴퓨터 목록

그림 3** 첫 번째 암호를 다시 설정한 후의 컴퓨터 목록 **(더 크게 보려면 이미지를 클릭하십시오.)

자, 이제 컴퓨터 1에 대해서는 작업을 충분히 실행했으니 다음 컴퓨터로 넘어가기 전에 간단히 정리하기만 하면 됩니다.

Err.Clear
i = i + 1

이 두 줄의 코드는 간단하지만 매우 중요합니다. Scripting Guy가 작성하는 코드는 언제나 중요하지만 말입니다! 첫 번째 줄은 Err 개체를 0으로 다시 설정합니다. 오류가 발생하지 않으면 이 프로세스는 불필요합니다. Err가 이미 0으로 설정되어 있으니까요. 그러나 오류가 발생했다면 Err가 0이 아닌 다른 값으로 설정되므로 Err 개체를 수동으로 다시 설정하는 것이 필요합니다. 왜일까요? Error 개체는 오류만 추적하고 성공한 작업은 추적하지 못하기 때문입니다. 예를 들어 컴퓨터 1에서 문제가 발생하여 연결할 수 없다고 가정해 봅니다. 그리고 설명을 위해 Error 개체가 99로 설정되었다고 가정해 보겠습니다.

그리고 루프를 계속 실행하여 컴퓨터 2에 성공적으로 연결했다면 Err 값은 어떻게 설정될까요? 그렇습니다. Err 값은 여전히 99로 설정되어 있습니다. Err 개체 값은 오류가 발생할 때만 변경되므로 오류가 발생하지 않으면 계속 현재 값이 유지되기 때문입니다.

이 문제가 그렇게 중요한 것일까요? 그렇습니다. 연결이 성공하는 경우에 컴퓨터의 암호를 변경하는 것이 아니라 Err가 0인 경우에만 암호를 변경합니다. 그리고 99는 0이 아닙니다. 계산기로 확인해 보았는데, 확실히 다릅니다! 앞에서 소개한 Scripting Guy의 아버지가 가족 투표에서 행사한 99표가 결국 0이 된 경우를 제외하면 말입니다. 이 경우 컴퓨터 2에 연결하는 데 성공했다 하더라도 Err가 0이 아닌 값으로 설정되어 있고, Err 값이 0이 아니면 로컬 Administrator 암호 변경을 시도조차 하지 않기 때문에 이 문제는 중요합니다.

다시 말해, Err 값이 변경될 때마다 값을 0으로 다시 설정해야만 스크립트가 오류가 발생한 것으로 인식하는 상황을 방지할 수 있습니다. 그렇다면 Err 개체를 0으로 다시 설정하려면 어떻게 해야 할까요? 맞습니다. Err.Clear를 호출하기만 하면 됩니다.

다음으로 i의 값을 1 증가시킵니다. 왜일까요? 처음으로 루프를 실행할 때에는 행 2, 열 1의 컴퓨터에 연결해야 했으므로 변수 i의 값은 2였습니다. 두 번째로 루프를 실행할 때는 행 3, 열 1의 컴퓨터에 연결해야 하고, i는 작업을 실행할 행을 나타내는 변수이므로 i의 값을 3으로 설정해야 합니다. 그리고 다들 알다시피 2+1=3입니다. (계산기가 있어서 참 다행이죠?) 이렇게 해야만 루프를 실행하고 스프레드시트의 다음 컴퓨터에 대해 프로세스를 반복할 수 있습니다.

이만하면 우리가 더 이상 그렇게 순진하지만은 않다는 것을 보여 준 듯해서 만족스럽지만, 이 스크립트 자체로는 독자들이 전자 메일로 문의한 질문에 충분한 답이 되지 않는다는 사실은 잘 알고 있습니다. 이 기사를 읽은 독자가 "그 Excel과 관련한 기사는 도움이 많이 되었습니다만, OU의 모든 컴퓨터나 텍스트 파일에 나열된 모든 컴퓨터에서 로컬 Administrator 암호를 변경하는 작업은 어떻게 해야 합니까? 또한 컴퓨터의 팝업 목록을 표시하고 목록 상자에서 선택할 수 있도록 하고 싶습니다. 그리고 또..."라고 말할 수도 있으니까요.

결론부터 말하자면, 걱정하지 않아도 됩니다. 독자가 원한다면 Scripting Guy는 무엇이든 합니다. 4년만 기다려 주신다면 말이죠. 스크립트 센터에는 여러 컴퓨터에 대해 스크립트를 간단히 실행할 수 있도록 하는 컴퓨터 서식 파일이 여러 개 게시되어 있습니다. 예를 들어 OU의 모든 컴퓨터에서 로컬 Administrator 암호를 변경하는 작업도 아무 문제 없이 처리할 수 있습니다. 그림 4와 같이 OU의 모든 컴퓨터에 대해 스크립트를 실행하는 서식 파일을 사용하면 됩니다.

Figure 4 OU를 대상으로 스크립트 실행

On Error Resume Next

Set objOU = GetObject(“LDAP://OU=Finance,dc=fabrikam,dc=com”)
objOU.Filter = Array(“Computer”)

For Each objComputer in objOU
    strComputer = objComputer.CN

    ‘ 
=====================================================================
    ‘ Insert your code here
    ‘ 
=====================================================================

    Set objComputer = GetObject(“WinNT://” & strComputer & “”)
    objComputer.Filter = Array(“User”)
    For Each objUser in objComputer
        Wscript.Echo objUser.Name
    Next

    ‘ 
=====================================================================
    ‘ End
    ‘ 
=====================================================================

Next

서식 파일에서 "Insert your code here"라고 표시된 구역이 보이십니까? 이 구역의 샘플 코드를 삭제하고 이 칼럼에서 로컬 Administrator 암호를 변경하는 코드를 복사해 넣기만 하면 됩니다. 즉, 샘플 코드를 다음 코드로 바꾸면 되는 거죠.

Set objUser = GetObject(“WinNT://” & _
    strComputer & “/Administrator”)
If Err = 0 Then
    objUser.SetPassword “egTY634!alK2”
End If
Err.Clear

이 예에서는 로그에 결과가 기록되지 않지만 로그를 기록하는 코드도 쉽게 추가할 수 있습니다. 샘플 코드를 바꾼 후에는 연결 문자열 LDAP://OU=Finance,dc=fabrikam,dc=com을 변경하여 원하는 OU 중 하나를 가리키도록 하면 됩니다.

사실 이들 서식 파일이 게시된 지는 일 년도 더 되었습니다. 당시만 해도 우리는 스크립트 센터에서 가장 인기 있는 게시물이 될 것이라고 생각했습니다. 그러나 예상은 완전히 빗나갔습니다. 여러 컴퓨터에 대해 스크립트를 실행하는 방법을 묻는 전자 메일은 거의 매일 받았지만, 이들 서식 파일을 사용하는 독자는 거의 없었습니다. 사람들은 이러한 서식 파일이 있는지조차 몰랐던 것 같습니다. 하지만 이제 microsoft.com/technet/scriptcenter/scripts/templates에 이러한 서식 파일이 게시되어 있다는 사실을 아셨으니 많이 이용해 주시기 바랍니다. 흠, 우리 사이트를 방문하기 싫어서 사용하지 않은 것이 아니라면 말입니다.

이제 Scripting Guy가 더 이상 순진하지 않다는 사실은 증명되었는데, 그렇다면 더 이상 바보도 아닌 것일까요? 이렇게 말하고 싶군요. 얼마 전 Scripting Guy 중 한 명이 주말에 집을 수리하겠다고 한 적이 있습니다. 월요일에 출근해 보니 엄지 손가락을 크게 다쳐 피가 계속 흐르고 있었고 다리에도 상처가 있더군요.

Scripting Guy에게 이 정도는 큰일도 아니랍니다.

Microsoft Scripting Guys는 Microsoft의 업무를 담당하는, 정확히 말하면 Microsoft에 고용된 직원입니다. 이들은 야구 경기를 하거나, 감독하거나, 관람하는 등의 일상적인 다른 활동을 하지 않을 때 TechNet 스크립트 센터를 운영합니다. 자세한 내용은 https://www.microsoft.com/korea/technet/scriptcenter/default.mspx에서 확인하십시오.

© 2008 Microsoft Corporation 및 CMP Media, LLC. All rights reserved. 이 문서의 전부 또는 일부를 무단으로 복제하는 행위는 금지됩니다..