프로그래밍/VC++

ActiveX로 인스톨러 만들기

panpro 2007. 3. 8. 10:44

ActiveX Installer 만들기

ActiveX 를 만들다보면, Cab파일을 만들어서 배포하는데, 잘 안되는경우가 있습니다.

시스템을 리부팅해야 한다는둥, 이전버젼이 계속 안지워지고, 매번 계속 다운을 받는다든가

하는 상황이 발생할때가 있습니다.

물론 inf랑 cab파일 다 잘만들었을때 얘기죠

그래서 저는 , 강제로, 이전버젼의 aCtiveX를 강제로 삭제하고, 새로운버젼을 시스템 디렉토리에

복사한다음, regsvr32까지 해주는 프로그램을 만들어서 씁니다.

cab파일을 받았을때 AcitveX를 설치하고 등록하고 업데이트 하는 일을 명시적으로 직접

프로그램에서 하는거죠 .


Required Skill

1. ActiveX ( ???.ocx) 파일을 실행파일에 포함시키는 방법

2. 파일을 regsvr32 사용해서 실제로 등록 하는 방법 ( 로컬컴퓨터의 regsvr32 를 이용하는것이 아니라

실제 구현한 함수를 사용합니다. )

References

1. Q/A 보드 184574 번글, 이승훈님의 '바이너리 리소스'라는 제목의 글을 참조하십시오 .

2. Tip And Trick , 2039번글, 하형욱님(-_-)의 'Regsvr Function'이라는 제목의 글을 참조하십시오.


Logique

1. OCX를 resource에 넣어서, exe파일에 같이 들어가게 합니다.

2. exe가 실행되면 , resource에 있는 ocx 파일을 로컬컴퓨터의 System Directory에 복사합니다.

( modeCreate 해서 이전파일을 지워주시구요 )

3. regsvr 함수를 사용하여 복사한 ocx를 등록해줍니다.


Another Information

CAB파일을 만들때는 다음과 같이 INF 파일을 만들어줍니다.


[Version]
signature="$CHICAGO$"
AdvancedINF=2.0

[Setup Hooks]
InstallHook=InstallHook

[InstallHook]
run=%EXTRACT_DIR%컴파일해서만든프로그램이름.exe -remote


웹페이지에 넣을때는 OCX 를 기준으로 해서 하던 것 처럼 해주시구요.

cab파일 만들때는 . exe랑 inf 만 해주면 되겠지요. , OCX에 대한 정보가 없으니 inf가 정말 간단해졌습니다.


그럼 로컬에 있는 버젼을 체크해서 버젼이 낮으면 

서버에 있는 cab파일을 다운받고 ( 여기까지는 자동이죠? )

inf 있는 내용대로 설치를 시작합니다.

위와 같이 적어져먼 InstallHook에 명시된 프로그램이 실행되므로,

우리가 프로그래밍한대로 , 수동으로 ocx복사하고, 등록까지 되겠죠. 


장점 :   설치를 프로그램에서 명시적으로 하므로 , 설치때 특별한 일을 해줄수 있습니다.

           (만든 사람이름을 따로 보여준다든가. .등등의. )

단점 : cab파일의 크기가 커집니다. 프로그램이 60k 가 좀 넘으므로, Ocx 를 패키징 하는것보다

        몇십 K 정도 더 커지겠죠.


바이너리 리소스...
1. 자신을 오픈하는 방법
CreateFile()에 FILE_SHARE_READ 옵션을 주시면 가능할 것도 같은데 해보지 않아서 장담
할 수 없군요.

2. 실행 파일에 합치는 방법

프로그램의 리소스에 바이너리 데이터를 추가할 수 있습니다.
컴파일이 될 때 합쳐집니다.


(프로젝트명).rc2에 아래와 같이 추가합니다.

/////////////////////////////////////////////////////////////////////////////
// Add manually edited resources here...
IDR_DATA1 DATA Data.zip

/////////////////////////////////////////////////////////////////////////////

IDR_DATA1은 리소스 데이터를 오픈할 때 쓸 이름입니다.
DATA는 리소스의 종류입니다.
Data.zip은 실제 파일명입니다.
프로젝트의 소스코드가 있는 폴더에 파일이 존재해야 에러없이 컴파일됩니다.
(즉, 컴파일 될 때 실행 파일 안으로 합쳐집니다.)

아래의 함수를 참고해서 사용하시기 바랍니다.

BOOL CTestDlg::SaveResource(LPTSTR lpName, LPTSTR lpPathName)
{
  BOOL bRtn;
  LPTSTR lpRes;
  HRSRC hResInfo;
  HANDLE hRes;
  DWORD dwSize;
 
  // Find the wave resource.
  hResInfo = FindResource (NULL, lpName, "DATA");
 
  if (hResInfo == NULL)
      return FALSE;
 
  // Load the wave resource.
  hRes = LoadResource (NULL, hResInfo);
 
  if (hRes == NULL)
      return FALSE;
 
  // Get size of resource.
  dwSize = SizeofResource(NULL, hResInfo);

  // Lock the wave resource and play it.
  lpRes = (LPTSTR)LockResource (hRes);

 
  if (lpRes != NULL)
       { // 실제 파일로 저장하는 부분
      CFile file;
      file.Open(lpPathName, CFile::modeCreate|CFile::modeWrite);
      file.Write(lpRes, dwSize);
      file.Close();
       }
  else
      bRtn = 0;
 
  return bRtn;
}


그럼...


Regsvr Function

regsvr32 소스가 있길래 거기서 함수를 간추려 올립니다.
파라메터에는 등록할 라이브러리 경로를 적어주시면 되겠죠..
등록해지 할때는 중간의 _szDllRegSvr 값을 _szDllUnregSvr로 교체 해 주심됩니다.

#include
#include
#include
#include

#define FAIL_ARGS   1
#define FAIL_OLE    2
#define FAIL_LOAD   3
#define FAIL_ENTRY  4
#define FAIL_REG    5

int regLib (const char *LibraryName)
{   
const char* _szDllRegSvr = "DllRegisterServer";
const char* _szDllUnregSvr = "DllUnregisterServer";

int iReturn = 0;
  HRESULT (STDAPICALLTYPE * lpDllEntryPoint)(void);

  BOOL bVisualC = FALSE;
  BOOL bUnregister = FALSE;
  LPCSTR pszDllEntryPoint = _szDllRegSvr;
  LPCSTR pszDllName = LibraryName;

  if (FAILED(OleInitialize(NULL))) {
      return FAIL_OLE;
  }

  SetErrorMode(SEM_FAILCRITICALERRORS); 

      HINSTANCE hLib = LoadLibraryEx(pszDllName, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);

      if (hLib < (HINSTANCE)HINSTANCE_ERROR) {
          TCHAR szError[12];
          wsprintf(szError, _T("0x%08lx"), GetLastError());

          iReturn = FAIL_LOAD;
          goto CleanupOle;
      }

      (FARPROC&)lpDllEntryPoint = GetProcAddress(hLib,
pszDllEntryPoint);

      if (lpDllEntryPoint == NULL) {
          TCHAR szExt[_MAX_EXT];
          _tsplitpath(pszDllName, NULL, NULL, NULL, szExt);

          if ((_stricmp(szExt, ".dll") != 0) && (_stricmp
(szExt, ".ocx") != 0))
          {
     
          }
          else
          {
             
          }

          iReturn = FAIL_ENTRY;
          goto CleanupLibrary;
      }

     
      if (FAILED((*lpDllEntryPoint)())) {
          iReturn = FAIL_REG;
          goto CleanupLibrary;
      }

CleanupLibrary:
      FreeLibrary(hLib);
 
CleanupOle:
  OleUninitialize();

  return iReturn;
}

by 빼빼로 | 2007-02-22 16:16 | Visual C++ | 트랙백 | 덧글(0)

트랙백 주소 : http://zoomout.egloos.com/tb/949444
내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]