달력

072018  이전 다음

  • 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
  •  
  •  
  •  
  •  


ActiveX의 안정성 코드에 대해 좋은글 링크

http://ancdesign.tistory.com/18

Posted by 알이씨


최근 시간이 없는 관계로..

포스팅이 늦었다. ㅜㅜ; 그래서 간단하게 정리해보고자 한다.

이후 질문 답 형식으로 완성해야겠다. ㅜㅜ; 요즘 넘 바뻐서. 흑.. ㅜㅜ;

프로젝트 생성이나 컨트롤 추가를 모르시는 분이 계시려나... 혹시 모른다면

나중에 올려드리겠습니다.

워드로 정리 해놓은 것을 옮기느라 보기가 안좋을 수 있습니다. 이해해주세요~

그리고 대부분의 내용은 Devpia나 웹상에서 제가 검색한 내용을 토대로 재작성 하였습니다.

==================================================================

1. ATL Project 생성 (필자는 ApLauncher로 생성)
  - 옵션에서 Support MFC를 체크 하도록 한다.

2. ATL Control 추가 (필자는 ApBroker로 생성)
  - 옵션은 걍 다음 다음으로 넘겨버렸다. -ㅁ-;

3. 레지스트리 수정

ApBroker.rgs 파일 수정


 

HKCR

{

             ApLauncher.ApBroker.1 = s 'ApBroker Class'

             {

                           CLSID = s '{FC9E01FE-A5E6-43FD-A925-9D5F6803E779}'

             }

             ApLauncher.ApBroker = s 'ApBroker Class'

             {

                           CLSID = s '{FC9E01FE-A5E6-43FD-A925-9D5F6803E779}'

                           CurVer = s 'ApLauncher.ApBroker.1'

             }

             NoRemove CLSID

             {

                           ForceRemove {FC9E01FE-A5E6-43FD-A925-9D5F6803E779} = s 'ApBroker Class'

                           {

                                        ProgID = s 'ApLauncher.ApBroker.1'

                                        VersionIndependentProgID = s 'ApLauncher.ApBroker'

                                        ForceRemove 'Programmable'

                                        InprocServer32 = s '%MODULE%'

                                        {

                                                     val ThreadingModel = s 'Apartment'

                                        }

                                        val AppID = s '%APPID%'

                                       

                                        Elevation

                                {

                                          val Enabled = d 1

                                }

                                val LocalizedString = s '@%MODULE%,-101'

                                       

                                        ForceRemove 'Control'

                                        ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 103'

                                        'MiscStatus' = s '0'

                                        {

                                            '1' = s '%OLEMISC%'

                                        }

                                        'TypeLib' = s '{B0EA13FC-8B95-4C3E-9627-D8937BFEDBCD}'

                                        'Version' = s '1.0'

                           }

             }

}


 

주의 : String Table 101번에 대한 String 추가할 것


빨간색으로 된 부분이 추가 되어야 하는 부분이다. 이 때 101번 String은 권한 상승시에 사용된다. (각자 확인 해보세요~)


ApLauncher.rgs 수정

HKCR

{

             NoRemove AppID

             {

                           '%APPID%' = s 'ApLauncher'

                           {

                                val DllSurrogate = s ''

                     }

                           'ApLauncher.DLL'

                           {

                                        val AppID = s '%APPID%'

                           }

             }

}

4. Broker 함수 추가


이제 권한 상승 함수와 실제 다이얼로그를 띄우는 부분을 추가해야 겠다.

프로젝스 프로퍼티창에서
  - IApBroker – Add – Add Method - RunBroker
함수 추가

  - IApBroker – Add – Add Method - RunProgram 함수 추가
  - IsVistaOS 함수와 CoCreateInstanceAsAdmin 함수 추가(어디든 CApBroker 클래스가 참조할 수 있으면 됩니다.
     클래스 함수로 포함시키면 좋겠지요...

 
isVistaOS 함수 착성

BOOL IsVistaOS(void)
{
 BOOL bIsVista = FALSE;
 OSVERSIONINFO sInfo;
 sInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
 //
 // OS VERSION CHECK.
 //
 if(::GetVersionEx(&sInfo)) {
  if( sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
   sInfo.dwMajorVersion >= 6 &&
   sInfo.dwMinorVersion >= 0) { // Windows VISTA
   bIsVista = TRUE;

  }
 }

 return bIsVista;
}



CoCreateInstanceAsAdmin 함수 작성

HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv, BOOL bAdministrator)

{

             BIND_OPTS3 bo;

             WCHAR  wszCLSID[50];

             WCHAR  wszMonikerName[300];

 

             StringFromGUID2(rclsid, wszCLSID, sizeof(wszCLSID)/sizeof(wszCLSID[0]));

             HRESULT hr = S_OK ;

 

             if( bAdministrator)

                           hr = StringCchPrintfW(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:Administrator!new:%s", wszCLSID);

             else

                           hr = StringCchPrintfW(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:HighestAvailable!new:%s", wszCLSID);

 

             if (FAILED(hr))

                           return hr;

             memset(&bo, 0, sizeof(bo));

             bo.cbStruct = sizeof(bo);

             bo.hwnd = hwnd;

             bo.dwClassContext  = CLSCTX_LOCAL_SERVER;

             return CoGetObject(wszMonikerName, &bo, riid, ppv);

}

 


 

RunBroker 함수 작성

STDMETHODIMP CApBroker::RunBroker(void)

{

             AFX_MANAGE_STATE(AfxGetStaticModuleState());

 

             HRESULT                                                                  hr;

             HWND                                                          hwnd = NULL;

             IApBroker*            objElevator = NULL;           

             const GUID                                                   guidCurrentObject = CLSID_ApBroker;

             const IID                                         iidCurrentObject = IID_IApBroker;

 

             CoInitialize(NULL);

            

             if(!IsVistaOS()) {

                           //

                           // VISTA 가아닌경우.

                           //

                           RunProgram();

 

                           return S_OK;

             }

 

             //

             // 권한상승(ELEVATION)

             //

             hr = CoCreateInstanceAsAdmin(NULL, guidCurrentObject, iidCurrentObject, (void**)(&objElevator), TRUE);

 

             //

             // EXECUTE

             //

 

             if(SUCCEEDED(hr)) {

                           // do work.

                           objElevator->RunProgram();

 

                           // release.                       

                           objElevator->Release();

 

                           return S_OK;

             } else {

                           //

                           // Elevation 실패.

                           //

                           CString sErr;

                           sErr.Format(_T("CoCreateInstanceAsAdmin failed! HResult: %x"), hr);

                           ::MessageBox(NULL, sErr, _T("ApBroker") , MB_OK);

             }

            

             return S_OK;

}


위에서 Vista인 경우와 아닌 경우로 나뉘어 Vista인 경우 권한 상승 후 프로그램을

실행하고 있습니다. 이부분을 유의해서 보시면 됩니다.
 

RunProgram 함수 작성

STDMETHODIMP CApBroker::RunProgram(void)

{

             AFX_MANAGE_STATE(AfxGetStaticModuleState());

             // TODO: Add your implementation code here

             CDlgMain m_DlgMain;

             m_DlgMain.DoModal();

 

             return S_OK;

}

 

자 지금까진 공통적인 부분이었고 저기 CDlgMain m_DlGmain; 부분을 봅시다.
필자는 다이얼로그를 하나 추가해서 연결해 두었습니다.

그리고 CApBroker::RunProgram 안에서 호출하고 있습니다.

따라서 기존 MFC 프로그래밍 하는 것처럼 코딩하시고 권한 상승 부분만 ATL을 이용합니다.

필자는 ATL을 해본적도 없고 MFC를 좀 하던차에 ActiveX를 만들어야 했기 때문에

좀 편하게 코딩해보가 이런 꼼수를 사용했습니다.
(더 확실한 것은 아예 모두 MFC로 만드는 것이겠지요. 필자는 하다하다 포기했습니다.
 방법을 아시는 분은 링크좀.. ㅡㅡ;)


5. 안정성 코드 추가

안정성 코드는 이 엑티브 엑스를 정말로 실행해도 됩니까? 하는 것을 빼게 해줍니다.
그냥 빨간 부분 추가만 해주시면 됩니다.

ApLauncher.cpp 수정

  - CreateComponentCategory 함수 추가
  - RegisterCLSIDInCategory 함수 추가

HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{

    ICatRegister* pcr = NULL ; // interface pointer
    HRESULT hr = S_OK ;

    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
   NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
 if (FAILED(hr)) {
  return hr;
 }

    // Make sure the HKCR\Component Categories\{..catid...}
    // key is registered
    CATEGORYINFO catinfo;
    catinfo.catid = catid;
    catinfo.lcid = 0x0409 ; // english

 // Make sure the provided description is not too long.
 // Only copy the first 127 characters if it is
 int len = (int)wcslen(catDescription);
 if (len>127)
  len = 127;
    wcsncpy_s(catinfo.szDescription, catDescription, len);
 // Make sure the description is null terminated
 catinfo.szDescription[len] = '\0';

    hr = pcr->RegisterCategories(1, &catinfo);
 pcr->Release();
 
 return hr;
}


 

HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
// Register your component categories information.
    ICatRegister* pcr = NULL ;
    HRESULT hr = S_OK ;
    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
   NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
    if (SUCCEEDED(hr))
    {
       // Register this category as being "implemented" by
       // the class.
       CATID rgcatid[1] ;
       rgcatid[0] = catid;
       hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
    }

    if (pcr != NULL)
        pcr->Release();
 
 return hr;
}


 빨간 부분 추가

STDAPI DllRegisterServer(void)

{

    // registers object, typelib and all interfaces in typelib

    HRESULT hr = _AtlModule.DllRegisterServer();

#ifdef _MERGE_PROXYSTUB

    if (FAILED(hr))

        return hr;

    hr = PrxDllRegisterServer();

#endif

 

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

             // 안전성코드추가SAFE FOR SCRIPTING.

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

             const CATID CATID_SafeForScripting =

             { 0x7dd95801, 0x9882, 0x11cf, { 0x9f, 0xa9, 0x00, 0xaa, 0x00, 0x6c, 0x42, 0xc4 } };

             const CATID CATID_SafeForInitializing =

             { 0x7dd95802, 0x9882, 0x11cf, { 0x9f, 0xa9, 0x00, 0xaa, 0x00, 0x6c, 0x42, 0xc4 } };

             REFCLSID clsidCurrentActiveX = CLSID_ApBroker;

            

 

             CoInitialize( NULL );

 

             if (FAILED( CreateComponentCategory(CATID_SafeForScripting, L"Controls that are safely scriptable") )) {

                           return ResultFromScode(SELFREG_E_CLASS);

             }

 

             if (FAILED( CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data") )) {

                           return ResultFromScode(SELFREG_E_CLASS);

             }

 

             if (FAILED( RegisterCLSIDInCategory(clsidCurrentActiveX, CATID_SafeForScripting) )) {

                           return ResultFromScode(SELFREG_E_CLASS);

             }

 

             if (FAILED( RegisterCLSIDInCategory(clsidCurrentActiveX, CATID_SafeForInitializing) )) {

                           return ResultFromScode(SELFREG_E_CLASS);

             }

 

             return hr;

}

================================================================
에고에고 힘들다.  있는거 가져다 붙이는 것도 힘드네요.

다시 말씀드리자면 이 방법은 MFC 이용하여 권한 상승을 하지는 않습니다.

정확히는 ATL 기반에서 권한 상승하고 MFC를 쓰는 것이지요.

포스팅이 너무 늦어버렸네요..
Posted by 알이씨


ActiveX를 이용하여 런처를 만들어야 하는 프로젝트가 떨어졌다.

MFC만 주구장창 해오다가 ActiveX라니... 난감하다..

ActiveX를 알아보니 MFC로도 만들 수 있다고 한다. 그래서 열심히 만들었다.

다이얼로그 하나 추가해서 뚝딱뚝딱 만들었다. 뭐 술술 진행되는 듯 했다.

윈도 xp, 2003에서 테스트를 마치고... Vista에서 돌려보았다.

털썩... 되질 않는다... 파일을 가져와서 복사를 못한다..

그것도 그럴것이 c:\ 밑에 프로젝트 이름으로 해서 디렉토리를 만들고 파일을 넣었으니..

Vista에서는 UAC(User Account Control)라는 보안 기능에 의해 익스플로어는 로우 레벨이란다.

로우 레벨은 c:\ 밑에 디렉토리 못만든단다. 파일복사도 안되고.... 아... 난감하다.

그래서 여기저기 자료를 뒤적거리기 시작했다. 그런데 죄다 ATL로 만든 ActiveX다.

난 또 생각했다. MFC로도 할 수 있을거야.. 그럴거야...

그러다가 포기했다. Registe 건들이는 부분이 ATL에는 rgs파일에 친절히 나와 있는데

MFC에서는 당최 모르겠다. (저와 같은 생각하는 초보 ActiveX 제작자는 없으려나 -_-)

그래서 생각했다 ATL에서 MFC처럼 하겠노라고...

작업 과정은 다음과 같다.

1. ATL 에서 권한 상승에 관련된 작업을 한다.
2. Dialog를 하나 띄워서 그곳에 런처에 관련된 기능을 구현한다.

위와 같이 하면 쉽게 해결될거 같다.

다음 Article에 ATL에서 권한 상승을 시키는 방법을 말해보고자 한다. 씨이익~
Posted by 알이씨


ActiveX  배포에 대한 좋은 글
출처 : Devpia
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=676548&ref=676532
========================================================================
안녕하세요, 놀고먹는 백수입니다.
 

 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 정도 더 커지겠죠.
Posted by 알이씨


Visual Studio 2005에서 ActiveX에 관련된 자료를 찾고 있다.

현재 이 시점에서 개념 조차 모르는 상황인데.. 자 이제 또 달려야한다.

ActiveX에 Smart Client까지 다 알게 되면 어느정도 웹어플들을 손쉽게 만들 수 있지 않을까.

일단은 MFC위주로 자료를 찾아보았다.

아래는 그 링크들~



http://msdn.microsoft.com/library/kor/default.asp?url=/library/KOR/vccore/html/_core_activex_control_topics.asp


ATL은 나중에 찾아봐야겠다.

M$ 애들은 참 여러가지 많이도 만들어놔서 골치아프게.. ㅡㅡ^


참고 : 위 링크는 계속해서 추가 됩니다. (최종 업데이트 07년 8월 29일)
Posted by 알이씨

티스토리 툴바