북곽툴즈 개발기 ③ COM 자동화에서 만난 함정들
북곽툴즈 개발기.
COM 자동화는 사람이 클릭할 걸 기대하고 만든 GUI 프로그램을 무인으로 돌리는 일이다. 그래서 평소엔 그냥 누르고 지나갈 팝업과 모달이 전부 적이 된다. 변환기를 만들며 부딪힌 함정들을 정리한다.
함정 1: 한워드는 SaveAs가 없다
처음엔 doc/docx를 한워드(Hword)로 처리하려 했다. 그런데 한워드의 SaveAs를 호출하면 E_NOTIMPL, 즉 구현되지 않은 기능이라는 오류가 났다. 한워드 COM에는 저장 자동화가 들어 있지 않았다.
해결은 단순했다. 한워드를 쓰지 않고 doc·docx를 한글(HwpObject)로 처리하면 된다. 한글이 워드 문서를 충분히 잘 읽고 저장한다. 엔진 매트릭스에서 doc/docx의 입력 담당을 한글로 넘겼다.
함정 2: 팝업 하나에 영원히 멈춘다
변환이 그냥 멈추는 일이 있었다. 특히 docx(OOXML)로 저장할 때 한컴이 "이 형식으로 저장하면 일부 서식이 달라질 수 있다"는 경고 팝업을 띄우는데, 서버는 비대화형 환경이라 아무도 그 확인 버튼을 못 누른다. 그래서 프로세스가 팝업 앞에서 영원히 기다린다.
해결은 메시지 박스 모드를 바꾸는 것이었다. 검색으로 찾은 SetMessageBoxMode로 팝업을 자동 처리하게 했다.
$hwp = New-Object -ComObject 'HWPFrame.HwpObject'
$hwp.RegisterModule('FilePathCheckDLL', 'FilePathCheckerModule') # 경로 보안 경고 차단
$hwp.SetMessageBoxMode(0x00211411) # 팝업 자동 응답
$hwp.XHwpWindows.Item(0).Visible = $false # 창 숨김
$hwp.Open($env:HWP_IN, '', 'lock:false;forceopen:true;suspendpassword:true;')
$hwp.SaveAs($env:HWP_OUT, $env:HWP_FORMAT, '')
$hwp.Quit()한글은 보안 모듈을 등록하지 않으면 파일 경로마다 보안 확인 팝업을 또 띄운다. RegisterModule로 그것까지 막고, 창은 아예 숨기고, 파일은 잠금·암호 없이 강제로 연다. 한셀·한쇼도 똑같이 SetMessageBoxMode를 걸고, 한셀은 DisplayAlerts = $false를 추가했다.
함정 3: JPG를 달랬더니 PNG가 나온다
한쇼에서 슬라이드를 이미지로 내보낼 때, 처음엔 이미지 포맷을 숫자로 지정하는 SaveAs를 썼는데 JPG를 요청해도 결과는 PNG로 나왔다. 포맷 지정이 의도대로 먹지 않았다.
해결은 SaveAs 대신 Export를 쓰는 것이었다. Export는 포맷을 "JPG", "PNG" 같은 문자열로 받고, 슬라이드별 이미지 파일을 폴더에 떨군다.
$pres = $app.Presentations.Open($env:HS_IN, $true, $false, $false)
$w = 1600; $h = 1200
# 슬라이드 가로세로 비율로 높이 계산
$sw = $pres.PageSetup.SlideWidth; $sh = $pres.PageSetup.SlideHeight
if ($sw -gt 0) { $h = [int]($w * $sh / $sw) }
$pres.Export($env:HS_OUT, $env:HS_FILTER, $w, $h)슬라이드가 여러 장이면 이미지도 여러 장 나온다. 그래서 내보낸 이미지들을 JSZip으로 묶어 ZIP 한 개로 다운로드하게 했다. 슬라이드 비율을 그대로 쓰려고 PageSetup에서 가로세로를 읽어 높이를 계산한 것도 이때 넣었다.
함정 4: 변환에는 방향이 있다
모든 포맷이 양방향으로 변환되는 건 아니었다.
- PDF는 출력 전용이다. 자동화로 PDF를 다시 다른 문서로 여는 건 안 된다.
- ODT는 입력만 된다. 한글이 ODT를 열 수는 있어도 ODT로 저장하는 출력은 동작하지 않았다.
이런 비대칭을 매트릭스에 그대로 반영했다. 입력 목록과 출력 목록을 따로 두고, 가능한 조합만 SaveAs 방식에 등록하는 식이다. UI에서는 처음부터 안 되는 조합이 드롭다운에 뜨지 않으니 사용자가 헷갈릴 일이 없다.
배운 것
COM 자동화의 진짜 적은 변환 로직이 아니라 사람을 기다리는 UI였다. 팝업, 모달, 보안 확인 같은 것들. 이런 건 문서에 잘 안 나와서, 추측으로 때우기보다 검색하고 실제로 돌려보며 하나씩 확인하는 게 결국 빨랐다.