설치 프로그램 같은 부류를 작성하다 보면, 지금은 다른 프로세스에 의해 사용 중이기 때문에 건드릴 수 없는 파일을 다음 재부팅 때 교체(업그레이드 설치) 또는 삭제(제거)되도록 설정해야 할 필요가 있다.
(사용 중이어서 잠긴 파일도 놀랍게도 rename과 같은 드라이브 안의 이동은 가능하다. 단지 드라이브 바깥으로의 이동이나 삭제, 교체, 덮어쓰기가 안 될 뿐이다.)

이 분야에 관한 한 윈도우 API는 무척 자비심이 없었다. 윈도우 NT 계열과 9x 계열이 설정하는 방법이 서로 완전히 달랐기 때문이다.
전자의 경우 MoveFileEx라는 걸출한 API가 있어서 MOVEFILE_DELAY_UNTIL_REBOOT 플래그만 지정해 주면 됐다. 다음 재부팅 때 교체/삭제될 예정인 파일 목록은 레지스트리에 별도로 관리되는데, 이 위치 역시 MSDN에 문서화돼 있다.

이게 제일 깔끔한 방법인 반면 윈도우 9x에서는 이 방법을 쓸 수 없다.
윈도우 9x는 부팅 직전에 업데이트 또는 삭제해야 하는 파일의 리스트를 윈도우 디렉토리에 있는 wininit.ini 파일로부터 읽는다. 거기에 뭔가 의미 있는 값이 있다면, 바로 그 때 “Windows가 일부 구성요소를 업데이트하고 있습니다. 몇 분 정도 시간이 소요될 수 있습니다”란 친근한 메시지를 부팅 중에 텍스트 모드에서 영어로 잠시 보여준다. 아마 9x 유저들은 이 메시지를 기억할 것이다.

이 처리를 다 마치고 나면 wininit.ini 파일은 wininit.bak로 개명된다.
이 일을 하는 프로그램은 wininit.exe라는 프로그램이다. 그런데 얘는 본격적인 32비트 운영체제가 로딩되기 전에 잠깐 실행되는 완벽한 16비트 도스용 프로그램일 뿐이다. 그래서 wininit.ini 리스트에는 긴 파일 이름(LFN)을 쓸 수 없다는 무지하게 불편한 제약이 걸린다. 파일 이름이야 그렇다 치지만 폴더 이름까지 공백 하나 표현 못하니 얼마나 불편하리요.

지울 때야 LONGFI~1.TXT 이렇게 지정하면 되겠지만 옛 파일을 LFN 방식의 새 파일로 깔끔하게 교체하는 건 불가능하다는 뜻이기도 하다. 정 하고 싶으면 rename을 부팅 때 강제로 해 주는 다른 프로그램을 RunOnce 이런 레지스트리에 넣기라도 해야 한다.

또 하나 고려할 만한 점으로..
인스톨러가 프로그램을 설치/제거하다가 일부 파일을 건드리지 못했다면 “다음 프로그램이 이 파일을 사용 중입니다” 이러면서 파일을 사용 중인 프로그램 나열까지 띄워 주면 무척 좋을 것이다. (MSI는 실제로 그렇게 해 주고 있다.)

이 기능을 직접 구현하려면 현재 로딩되어 있는 모듈(EXE/DLL)의 리스트를 얻어 오는 API를 써야 하는데 이 역시 윈도우 9x와 NT가 사용하는 API 계보가 완전히 달랐다. 전자는 ToolHelp라고 불렸고 후자는 Process Status API였는데 다행히 윈도우 2000에는 9x의 ToolHelp API도 추가되어서 API가 일종의 통합을 이뤘다.

한편, 저런 이유 때문에 일부 파일을 결국 교체나 삭제를 못 한 경우 인스톨러는 “작업을 완료하려면 재부팅이 필요합니다. 지금 하시겠습니까?”라고 묻는 게 일반적이다. 하지만 대다수의 사용자는 귀차니즘에 입각하여 ‘아니요’를 고르고 만다.

그런데, 그렇게 재부팅을 미루고 언인스톨러를 종료했는데 그 상태에서 사용자가 그 프로그램을 다시 설치한 경우 꽤 문제가 된다. (변덕 한번 심하기도 하다. -_-)
잘 만들어진 인스톨러라면, 이 경우 교체하거나 삭제하기로 요청해 놓은 파일의 예약을 도로 취소해야 한다. 안 그러면 그렇게 재설치 한 후 다음에 운영체제를 재시작하는 순간 재앙이 벌어질 수도 있다.

따라서 원칙대로라면 건드리지 못한 파일이 없더라도 인스톨러는 wininit.ini 같은 목록을 뒤져 봐야 한다. 그것도 운영체제 계열 별로 완전히 다른 접근 방식으로 말이다. 요즘이야 9x 계열은 사실상 신경 쓸 필요도 없어지긴 했지만. 참고로 MSI가 저것까지 똑똑하게 알아서 처리해 주는지는 테스트 안 해 봤다.

결론은, 인스톨러는 완성도 높게 잘 만들려면 현 프로그램의 설치/제거 상태부터 시작해서, 저런 지저분한 API 차이까지 감안해 가며 귀찮게 따져야 하는 게 무지하게 많다는 것. IME 하나 만들려면 지저분한 잡일이 너무 많으니 MS에서 TSF를 개발한 것처럼, 저런 작업을 표준화하고 자동화하기 위해서 MSI라는 것을 안 만들 수가 없었을 것이다.

MSI는 파일을 복사하고 쓰는 제 본연의 기능 면에서 완성도는 무척 높은 것을 인정하지만, 같은 MS에서 개발한 AppLocale 같은 프로그램하고도 UI가 충돌을 일으킨다는 점은 심히 유감이다. -_-

Posted by 사무엘

2010/01/10 23:46 2010/01/10 23:46
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/40

Trackback URL : http://moogi.new21.org/tc/trackback/40

Comments List

  1. 란마 2010/11/16 11:25 # M/D Reply Permalink

    자동업데이트 구현하고 있습니다.
    말씀하신대로 변덕이 심한 유저를 고려하자니 머리가 복잡해지는데요..
    현재 변경할 수 없는 파일들 때문에 재부팅 후 업데이트가 완료되는 것을
    구현하려고 합니다.
    MoveFileEx를 이용하는 방법과..
    자체적으로 작은 실행 프로그램을 만들어서 레지스트리의 RunOnce에 등록해 두고 윈도우 시작 시에 실행하면서 직접 파일을 엎어치는 방법이 떠오르는데요, 용묵님은 어떤 방식이 괜찮다고 보시나요?

    첫번째 방법은 단지 파일복사만 되는거라, 레지스트리 등록/해제같은 부가적인 일을 할 수 없는거 같습니다(혹시 방법이 있나요?)

    두번째 방법은 '업데이트 대상이 되는 프로그램'이 '작은 실행 프로그램'보다 먼저 실행될 가능성이 존재하는거 같네요..
    실제로 저같은 경우도 윈도우 시작되고 마우스 컨트롤 되자마자 바로 원하는 프로그램을 더블클릭하는 급한 성격이라..ㅡ.,ㅡ;
    -> 지금 테스트해보니 RunOnce에 등록되어 실행된 프로그램이 종료되기 전까지 바탕화면에 아이콘 안뜨고 대기하고 있네요. 두번째 방법으로 하는게 좋겠네요..
    그런데 RunOnce에 등록된 프로그램이 어떤 이유로 종료되지 않는다면... 흠.. 안전모드가 있군요 ㅎ

    1. 사무엘 2010/11/17 01:06 # M/D Permalink

      윈도우 프로그래머이시군요. 반갑습니다. ^^
      아무래도 파일을 지우거나 위치 이동, 대체만 하는 건 MoveFileEx가 간편합니다. 그러나 좀더 복잡한 작업이 필요하다면 작은 별도의 프로그램 실행+RunOnce가 필요할 것 같습니다. 단, 후자의 방법을 사용하는 경우, 작은 프로그램 자신을 제거하는 테크닉 같은 것도 필요해지니 경우의 수는 더 늘어나겠죠.

      설치/제거라든가 자동 업데이트 기능을 손으로 직접 짜려면 요즘은 또 UAC나 권한 같은 쪽도 알아야 되고.. 너무 복잡해요. 권한이 없으면 Program files 디렉터리의 파일을 건드리질 못하게 되니까..;;

Leave a comment
« Previous : 1 : ... 2168 : 2169 : 2170 : 2171 : 2172 : 2173 : 2174 : 2175 : 2176 : ... 2204 : Next »

블로그 이미지

그런즉 이제 애호박, 단호박, 늙은호박 이 셋은 항상 있으나, 그 중에 제일은 늙은호박이니라.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2024/12   »
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 31        

Site Stats

Total hits:
3044232
Today:
1424
Yesterday:
2435