천객만래 [千客萬來] (It has an interminable succession of visitors)

[개발/VC++] 리소스 DLL 만들기 



리소스 전용 DLL은 아이콘, 비트맵, 문자열 및 대화 상자 등의 리소스만 들어 있는 DLL입니다. 리소스 전용 DLL을 사용하면 여러 프로그램 간에 동일한 리소스 집합을 쉽게 공유할 수 있습니다. 여러 언어로 지역화된 리소스가 있는 응용 프로그램을 제공하는 것도 좋은 방법입니다(MFC 응용 프로그램의 지역화된 리소스: 위성 DLL 참조).

리소스 전용 DLL을 만들려면 새로운 Win32 DLL(비 MFC) 프로젝트를 만든 다음 이 프로젝트에 리소스를 추가합니다.

  • 새 프로젝트 대화 상자에서 Win32 프로젝트를 선택한 다음 Win32 프로젝트 마법사에서 DLL 프로젝트 형식을 지정합니다.

  • 해당 DLL에 사용할 문자열 또는 메뉴와 같은 리소스가 포함된 새 리소스 스크립트를 만든 다음 .RC 파일로 저장합니다.

  • 프로젝트 메뉴에서 기존 항목 추가를 선택한 다음 새로 만든 .rc 파일을 프로젝트에 삽입합니다.

  • /NOENTRY 링커 옵션을 지정합니다. /NOENTRY 옵션은 링커가 _main에 대한 참조를 DLL에 링크하지 않도록 하며, 리소스 전용 DLL을 만들 때 반드시 사용해야 합니다.

  • DLL을 빌드합니다.

리소스 전용 DLL을 사용하는 응용 프로그램은 LoadLibrary를 호출하여 명시적으로 DLL에 링크해야 합니다. 리소스에 액세스하려면 모든 종류의 리소스에 대해 작동하는 일반 함수인 FindResource 및 LoadResource를 호출하거나 다음과 같은 특정 리소스 관련 함수 중 하나를 호출해야 합니다.

  • FormatMessage

  • LoadAccelerators

  • LoadBitmap

  • LoadCursor

  • LoadIcon

  • LoadMenu

  • LoadString

응용 프로그램이 리소스 사용을 마친 경우에는 FreeLibrary를 호출해야 합니다.

개념


============================================
※ 빌드하기 전에 프로젝트->속성->링커->명령줄 메뉴에서 추가옵션란에 "/NOENTRY" 옵션을 추가해준다.
릴리즈 모드로 컴파일해서 *.dll 생성된 파일을 확인후 리소스 DLL 사용

사용예:

HMODULE hRes = NULL;
hRes = LoadLibrary("cs.dll");
// hRes NULL이 아니면 성공
LoadString(hRes, IDS_STRING101, str, 256);
hMenu=LoadMenu(hRes, "IDR_MENU1");

Posted by SB패밀리
출처 : http://www.jiniya.net

DllMain에서 다음 작업들은 절대로 하지 말 것.

1.LoadLibrary, LoadLibraryEx 호출. 데드락이나 크래시를 유발한다.
2.다른 스레드와 동기화. 데드락을 유발한다.
3.로더 락을 획득하려는 코드가 가지고 있는 동기화 오브젝트를 획득하려는 시도. 데드락을 유발한다.
4.CoInitializeEx를 사용한 COM 스레드 초기화. 특정 조건이 충족될 경우 이 함수는 LoadLibraryEx를 호출한다.
5.레지스트리 함수들. 이 함수들은 advapi32.dll에 구현되어 있다. advapi32.dll이 초기화 되지 않았다면 크래시가 발생할 수 있다.
6.CreateProcess 호출. 프로세스 생성은 다른 DLL을 로드할 수 있다.
7.ExitThread 호출. DLL 디태치(detach) 과정 중에 스레드를 종료하면 로더 락을 다시 획득하도록 만들 수 있다. 이는 데드락이나 크래시가 유발된다.
8.CreateThread 호출. 동기화만 하지 않는다면 스레드 생성은 괜찮을 수 있다. 하지만 위험하다.
9.네임드 파이프나 네임드 오브젝트 생성 (2000만 해당한다). 윈도우 2000에서 네임드 오브젝트 생성은 터미널 서비스 DLL에서 구현되어 있다. 해당 DLL이 초기화되어 있지 않다면 크래시.
10.CRT에 포함된 메모리 관리 함수들. CRT DLL이 초기화되어 있지 않다면 크래시.
11.user32.dll이나 gdi32.dll에 포함된 함수 호출. 일부 함수들은 다른 DLL을 로드하고, 이 사실은 크래시가 발생할 수 있다는 것을 의미한다.
12.관리된 코드 사용.

* 가장 아름다운 DllMain은 존재하지 않는 것이다 (비어 있는 함수 바디).
** 그래도 먼가 하고 싶다면 kernel32.dll에 포함된 함수 중에 위에서 언급되지 않은 것들만 쓰도록 한다. kernel32.dll이 초기화는 운영체제가 보장해 준다. 
*** 글로벌 오브젝트에 대한 초기화 코드 또한 DllMain 과정에 포함된다. 따라서 글로벌 오브젝트의 생성자 내지는 초기화 함수 부분에 위에서 언급한 내용이 있어서는 안된다.
**** 초기화를 하지 말란 소린가? 아니다. 지연시키라는 말이다.
Posted by SB패밀리

[개발/MFC] regsvr32.exe 를 사용하지 않고 ActiveX DLL을 레지스트리에 등록하기

activeX DLL 을 regsvr32를 사용하지 않고 등록하는 방법이 델파이로 된게 있어서 가져왔다.
직접 만들어서 해볼려고 하니 시간이 부족하다...


Unit Unit1;

Interface

Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

Type
TForm1 = Class(TForm)
btRegistryDll: TButton;
btUnRegistryDll: TButton;
Procedure btRegistryDllClick(Sender: TObject);
Procedure btUnRegistryDllClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
End;

Var
Form1: TForm1;

Implementation

{$R *.DFM}

Procedure TForm1.btRegistryDllClick(Sender: TObject);
Type
TDllRegisterServer = Function: HResult; stdcall;
Var
DllRegisterServer: TDllRegisterServer;
hinstance1: HINST;
Begin
hinstance1 := LoadLibrary('Project2.dll');
DllRegisterServer := GetProcAddress(hinstance1, 'DllRegisterServer');
If Assigned(DllRegisterServer) Then DllRegisterServer;
FreeLibrary(hinstance1);
End;

Procedure TForm1.btUnRegistryDllClick(Sender: TObject);
Type
TDllUnregisterServer = Function: HResult; stdcall;
Var
DllUnregisterServer:TDllUnregisterServer;
hinstance1: HINST;
Begin
hinstance1 := LoadLibrary('Project2.dll');
DllUnregisterServer := GetProcAddress(hinstance1, 'DllUnregisterServer');
If Assigned(DllUnregisterServer) Then DllUnregisterServer;
FreeLibrary(hinstance1);
End;

End.


출처: http://blog.naver.com/erroring/150097804539

 
Posted by SB패밀리

 

[개발/VC++] 리소스 DLL 만들기

 

리소스 전용 DLL은 아이콘, 비트맵, 문자열 및 대화 상자 등의 리소스만 들어 있는 DLL입니다. 리소스 전용 DLL을 사용하면 여러 프로그램 간에 동일한 리소스 집합을 쉽게 공유할 수 있습니다. 여러 언어로 지역화된 리소스가 있는 응용 프로그램을 제공하는 것도 좋은 방법입니다(MFC 응용 프로그램의 지역화된 리소스: 위성 DLL 참조).

리소스 전용 DLL을 만들려면 새로운 Win32 DLL(비 MFC) 프로젝트를 만든 다음 이 프로젝트에 리소스를 추가합니다.

  • 새 프로젝트 대화 상자에서 Win32 프로젝트를 선택한 다음 Win32 프로젝트 마법사에서 DLL 프로젝트 형식을 지정합니다.

  • 해당 DLL에 사용할 문자열 또는 메뉴와 같은 리소스가 포함된 새 리소스 스크립트를 만든 다음 .RC 파일로 저장합니다.

  • 프로젝트 메뉴에서 기존 항목 추가를 선택한 다음 새로 만든 .rc 파일을 프로젝트에 삽입합니다.

  • /NOENTRY 링커 옵션을 지정합니다. /NOENTRY 옵션은 링커가 _main에 대한 참조를 DLL에 링크하지 않도록 하며, 리소스 전용 DLL을 만들 때 반드시 사용해야 합니다.

  • DLL을 빌드합니다.

리소스 전용 DLL을 사용하는 응용 프로그램은 LoadLibrary를 호출하여 명시적으로 DLL에 링크해야 합니다. 리소스에 액세스하려면 모든 종류의 리소스에 대해 작동하는 일반 함수인 FindResourceLoadResource를 호출하거나 다음과 같은 특정 리소스 관련 함수 중 하나를 호출해야 합니다.

  • FormatMessage

  • LoadAccelerators

  • LoadBitmap

  • LoadCursor

  • LoadIcon

  • LoadMenu

  • LoadString

응용 프로그램이 리소스 사용을 마친 경우에는 FreeLibrary를 호출해야 합니다.

개념

DLL


============================================
※ 빌드하기 전에 프로젝트->속성->링커->명령줄 메뉴에서 추가옵션란에 "/NOENTRY" 옵션을 추가해준다.
릴리즈 모드로 컴파일해서 *.dll 생성된 파일을 확인후 리소스 DLL 사용

사용예:

HMODULE hRes = NULL;
hRes = LoadLibrary("cs.dll");
// hRes NULL이 아니면 성공
LoadString(hRes, IDS_STRING101, str, 256);
hMenu=LoadMenu(hRes, "IDR_MENU1");
Posted by SB패밀리

DLL이나 OCX를 레지스트리에 등록하거나 제거..
regsvr32를 이용한다..

예)
regsvr32 "C:ProjectNeoTest 2.60_Output_Debugeoweboardax.ocx"
regsvr32 /u  "C:ProjectNeoTest 2.60_Output_Debugeoweboardax.ocx"
regsvr32 /s  "C:ProjectNeoTest 2.60_Output_Debugeoweboardax.ocx"
regsvr32 /s /u  "C:ProjectNeoTest 2.60_Output_Debugeoweboardax.ocx"
regsvr32 /s /c  "C:ProjectNeoTest 2.60_Output_Debugeoweboardax.ocx"

/u : Unregister
/s : Silent
/c : Console output

regsvr32는 DLL이나 OCX를 호출하고, DLL내부의 DllRegisterServer()과 DllUnregisterServer()을 호출하는 역할을 한다.
만약 regsvr32를 사용하지 않고 직접 등록하려면 다음과 같이 할 수 있다..(Devpia 참고..)

// Usage
AfxMessageBox( RegFunc("MsComm.ocx") );  

CString RegFunc(LPCTSTR lpOCXName) 
{

CString systemDir = _T("");
CString FindFileName = _T("");

::GetSystemDirectory(  systemDir.GetBuffer(255), 255);

FindFileName.Format("%s\%s", systemDir, lpOCXName);

HINSTANCE h = ::LoadLibrary(FindFileName);

if (h != NULL) {
FARPROC pFunc = ::GetProcAddress(h,"DllRegisterServer");
if (pFunc != NULL)
{
(*pFunc)();
} else {
FindFileName.Format("%s 등록 실패 되었읍니다.", lpDiscript);
return FindFileName; 
}
::FreeLibrary(h);

FindFileName.Format("%s 등록 되었읍니다.", lpDiscript);
return FindFileName;
} else {
FindFileName.Format("%s 등록 실패 되었읍니다.", lpDiscript);
return FindFileName;

}


출처: http://ninvu.egloos.com/1936098
Posted by SB패밀리