Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

(시리즈 글이 21개 있습니다.)
Windows: 226. Win32 C/C++ - Dialog에서 값을 반환하는 방법
; https://www.sysnet.pe.kr/2/0/13284

Windows: 227. Win32 C/C++ - Dialog Procedure를 재정의하는 방법
; https://www.sysnet.pe.kr/2/0/13285

Windows: 228. Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법
; https://www.sysnet.pe.kr/2/0/13286

Windows: 229. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 윈도우를 직접 띄우는 방법
; https://www.sysnet.pe.kr/2/0/13287

Windows: 230. Win32 - 대화창의 DLU 단위를 pixel로 변경하는 방법
; https://www.sysnet.pe.kr/2/0/13288

Windows: 231. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 자식 윈도우를 생성하는 방법
; https://www.sysnet.pe.kr/2/0/13289

Windows: 232. C/C++ - 일반 창에도 사용 가능한 IsDialogMessage
; https://www.sysnet.pe.kr/2/0/13292

Windows: 233.  Win32 - modeless 대화창을 modal처럼 동작하게 만드는 방법
; https://www.sysnet.pe.kr/2/0/13295

Windows: 234. IsDialogMessage와 협업하는 WM_GETDLGCODE Win32 메시지
; https://www.sysnet.pe.kr/2/0/13296

Windows: 235. Win32 - Code Modal과 UI Modal
; https://www.sysnet.pe.kr/2/0/13297

Windows: 237. Win32 - 모든 메시지 루프를 탈출하는 WM_QUIT 메시지
; https://www.sysnet.pe.kr/2/0/13299

Windows: 238. Win32 - Modal UI 창에 올바른 Owner(HWND)를 설정해야 하는 이유
; https://www.sysnet.pe.kr/2/0/13300

Windows: 242. Win32 - 시간 만료를 갖는 MessageBox 대화창 구현 (쉬운 버전)
; https://www.sysnet.pe.kr/2/0/13305

Windows: 243. Win32 - 윈도우(cbWndExtra) 및 윈도우 클래스(cbClsExtra) 저장소 사용 방법
; https://www.sysnet.pe.kr/2/0/13306

Windows: 244. Win32 - 시간 만료를 갖는 MessageBox 대화창 구현 (개선된 버전)
; https://www.sysnet.pe.kr/2/0/13312

Windows: 245. Win32 - 시간 만료를 갖는 컨텍스트 메뉴와 윈도우 메시지의 영역별 정의
; https://www.sysnet.pe.kr/2/0/13315

Windows: 246. Win32 C/C++ - 직접 띄운 대화창 템플릿을 위한 Modal 메시지 루프 생성
; https://www.sysnet.pe.kr/2/0/13329

Windows: 247. Win32 C/C++ - CS_GLOBALCLASS 설명
; https://www.sysnet.pe.kr/2/0/13330

Windows: 248. Win32 C/C++ - 대화창을 위한 메시지 루프 사용자 정의
; https://www.sysnet.pe.kr/2/0/13332

Windows: 249. Win32 C/C++ - 대화창 템플릿을 런타임에 코딩해서 사용
; https://www.sysnet.pe.kr/2/0/13333

Windows: 250. Win32 C/C++ - Modal 메시지 루프 내에서 SetWindowsHookEx를 이용한 Thread 메시지 처리 방법
; https://www.sysnet.pe.kr/2/0/13334




Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법

이번에는 다음의 글로 시작하는 시리즈 6개를 제 맘대로 정리해 봤습니다. ^^

The evolution of dialog templates – Introduction
; https://devblogs.microsoft.com/oldnewthing/20040617-00/?p=38833




비주얼 스튜디오로 기본 생성한 C/C++ 윈도우 프로젝트를 보면 텍스트 형식의 RC 파일이 하나 들어 있고, 그 안에 IDD_ABOUTBOX 대화창으로 식별되는 텍스트가 추가돼 있습니다.

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Project1"
FONT 8, "MS Shell Dlg"
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
    LTEXT           "Project1, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (c) 2023",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "OK",IDOK,113,41,50,14,WS_GROUP
END

C# 세대에게 설명하자면, "폼 디자이너"의 초기 모델이라고 보면 될 듯합니다. ^^ 실제로 Visual studio는 위의 대화창 템플릿을 읽어들여 다음과 같이 디자인 창을 띄워 사용자가 컨트롤을 쉽게 추가/삭제/배치할 수 있도록 돕습니다.

dialog_template_part1_1.png

단지 C# Windows Forms 프로젝트의 경우에는 디자인 창의 내용을 C# 코드로 직렬화하는 반면, 위의 dialog template 파일은 Win32 리소스 문법에 따라 직렬화한다는 차이가 있는 정도입니다.

실제로 여러분은 Resource Compiler(rc.exe)를 이용해 위의 dialog template만을 담은 파일을 컴파일할 수 있습니다. 이를 위해 필요한 include와 상수를 정의하고,

#include "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um\Windows.h"

#define IDD_ABOUTBOX              103
#define IDR_MAINFRAME			128
#ifndef IDC_STATIC
#define IDC_STATIC				-1
#endif

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Project1"
FONT 8, "MS Shell Dlg"
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
    LTEXT           "Project1, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (c) 2023",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "OK",IDOK,113,41,50,14,WS_GROUP
END

Visual Studio 명령행 창에서 다음과 같이 명령을 내리면 됩니다.

c:\temp> rc test.rc
Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

그럼, 결과 파일로 res 확장자를 가진 이진 파일이 생성됩니다.

00 00 00 00 20 00 00 00 FF FF 00 00 FF FF 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
34 01 00 00 20 00 00 00 FF FF 05 00 FF FF 67 00 
00 00 00 00 30 10 09 04 00 00 00 00 00 00 00 00 
01 00 FF FF 00 00 00 00 00 00 00 00 C8 00 C8 80 
04 00 00 00 00 00 AA 00 3E 00 00 00 00 00 41 00 
62 00 6F 00 75 00 74 00 20 00 50 00 72 00 6F 00 
6A 00 65 00 63 00 74 00 31 00 00 00 08 00 00 00 
...[생략]...
29 00 20 00 32 00 30 00 32 00 33 00 00 00 00 00 
00 00 00 00 00 00 00 00 01 00 03 50 71 00 29 00 
32 00 0E 00 01 00 00 00 FF FF 80 00 4F 00 4B 00 
00 00 00 00

비주얼 스튜디오로 C/C++ Windows 응용 프로그램을 빌드하면 저 res 2진 파일을 EXE/DLL 바이너리에 추가합니다. 그리고 다시 코드에서는 저 내용 중 원하는 대화상자, 이번 글에서는 IDD_ABOUTBOX 식별자로 구분되는 리소스의 내용을 이렇게 추출할 수 있습니다.

HRSRC hrsrc = ::FindResource(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), RT_DIALOG);
HGLOBAL hglobal = ::LoadResource(hInst, hrsrc);
LPVOID lpv = ::LockResource(hglobal);
DWORD resSize = SizeofResource(hInst, hrsrc);

BYTE* pBuffer = (BYTE*)lpv;
wchar_t buffer[1024] = { 0 };

for (int i = 1; i <= resSize; i++)
{
    wsprintf(buffer, L"%02X ", pBuffer[i - 1]);
    OutputDebugString(buffer);
                        
    if (i % 16 == 0)
    {
        OutputDebugString(L"\n");
    }
}
                    
::FreeResource(hglobal);

출력 내용은 우리가 컴파일했던 test.res의 5번째 줄부터 해당하는 바이트가 동일하게 나옵니다.

01 00 FF FF 00 00 00 00 00 00 00 00 C8 00 C8 80 
04 00 00 00 00 00 AA 00 3E 00 00 00 00 00 41 00 
62 00 6F 00 75 00 74 00 20 00 50 00 72 00 6F 00 
6A 00 65 00 63 00 74 00 31 00 00 00 08 00 00 00 
00 01 4D 00 53 00 20 00 53 00 68 00 65 00 6C 00 
6C 00 20 00 44 00 6C 00 67 00 00 00 00 00 00 00 
00 00 00 00 03 00 00 50 0E 00 0E 00 15 00 14 00 
FF FF FF FF FF FF 82 00 FF FF 80 00 00 00 00 00 
00 00 00 00 00 00 00 00 80 00 02 50 2A 00 0E 00 
72 00 08 00 FF FF FF FF FF FF 82 00 50 00 72 00 
6F 00 6A 00 65 00 63 00 74 00 31 00 2C 00 20 00 
56 00 65 00 72 00 73 00 69 00 6F 00 6E 00 20 00 
31 00 2E 00 30 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 02 50 2A 00 1A 00 72 00 08 00 
FF FF FF FF FF FF 82 00 43 00 6F 00 70 00 79 00 
72 00 69 00 67 00 68 00 74 00 20 00 28 00 63 00 
29 00 20 00 32 00 30 00 32 00 33 00 00 00 00 00 
00 00 00 00 00 00 00 00 01 00 03 50 71 00 29 00 
32 00 0E 00 01 00 00 00 FF FF 80 00 4F 00 4B 00 
00 00 00 00 

그리고 위의 2진 파일의 내용을 해석하는 방법을 시리즈의 2~5번째 글에서 소개합니다.

The evolution of dialog templates – 16-bit Classic Templates
; https://devblogs.microsoft.com/oldnewthing/20040618-00/?p=38803

The evolution of dialog templates – 16-bit Extended Templates
; https://devblogs.microsoft.com/oldnewthing/20040622-00/?p=38773

The evolution of dialog templates – 32-bit Classic Templates
; https://devblogs.microsoft.com/oldnewthing/20040621-00/?p=38793

The evolution of dialog templates – 32-bit Extended Templates
; https://devblogs.microsoft.com/oldnewthing/20040623-00/?p=38753

버전별로 4개의 dialog template이 제공되는데 이 관계를 아래의 그림에서 잘 나타내고 있습니다.

dialog_template_part1_2.png

16비트 포맷에 해당하는 DIALOG는 Windows 1.0 시절에, 16비트 DIALOGEX는 Windows 95와 후속 버전만 지원합니다. 그리고 각각의 버전이 다시 32비트 포맷으로 포팅됐습니다. 아주 오래된 프로그램이 아니라면 현재 32-bit DIALOGEX 이외의 형식은 구경조차 힘들 것입니다.

따라서, 예전 버전의 해석 방식은 각각 "The evolution of dialog templates – 16-bit Classic Templates", "The evolution of dialog templates – 16-bit Extended Templates", "The evolution of dialog templates – 32-bit Classic Templates" 글에서 설명하고 있으니 참고하시고, 이번 글에서는 위의 예제로 나온 바이너리를 해석해야 하므로 "32-bit Extended Templates"을 기준으로 설명합니다.




대화창의 헤더(32-bit extended header)는 다음과 같은 구조체로 시작한다고 합니다.

WORD  wDlgVer;      // version number - always 1
WORD  wSignature;   // always 0xFFFF
DWORD dwHelpID;     // help ID
DWORD dwExStyle;    // window extended style

DWORD dwStyle;      // dialog style
WORD  cItems;       // number of controls in this dialog, 즉 대화창 1개에 65,535개까지의 컨트롤을 담을 수 있음
WORD  x;            // x-coordinate
WORD  y;            // y-coordinate
WORD  cx;           // width
WORD  cy;           // height

이 글의 예제에서 사용한 리소스의 경우에는 각각 다음과 같은 정보로 연결될 수 있고,

wDlgVer == 1
wSignature == 0xffff
dwHelpID == 0
dwExStyle == 0

dwStyle == DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
        == 2160591048 == 80 C8 00 C8
cItems == BEGIN/END 사이의 컨트롤 수 == ICON/LTEXT/LTEXT/DEFPUSHBUTTON 총 4개
x == 0 
y == 0
cx == 170 (0xaa)
cy == 62 (0x3e)

실제로 위의 바이트를 LockResource로 구한 바이트 배열에서 찾을 수 있습니다.

01 00 FF FF 00 00 00 00 00 00 00 00 C8 00 C8 80
04 00 : 컨트롤 수
00 00 : x
00 00 : y
AA 00 : cx
3E 00 : cy

그다음은 3개의 문자열 정보가 나오는데,

00 00: menu name 문자열 또는 ordinal
00 00: class name 문자열
41 00 62 00 6F 00 75 00 74 00 20 00 50 00 72 00 6F 00 6A 00 65 00 63 00 74 00 31 00 00 00: CAPTION 문자열 "About Project1"

해당 값이 문자열(위의 경우 "About Project1")인 경우라면 UNICODE 값과 함께 끝을 알리는 null 문자(\0\0)가 나옵니다. 반면 ordinal로 표현된다면 0xff, 0x00이 먼저 나오고 이어서 ordinal 2바이트가 나온다고 합니다. 예를 들어 위에서 menu name의 ordinal 값이 "2A 00"이라면 다음의 4바이트가 기록되는 것입니다.

FF 00 2A 00 

어쨌든 위의 예제에서는 menu와 class name에 할당된 문자열이 없기 때문에 널 종료 문자(\0\0)만이 있습니다. (참고로 대화창의 class name 지정은 지난 예제에서 설명한 적이 있습니다.)




그다음은 가변 항목이 나오는데요, 대화창의 STYLE에,

STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Project1"
FONT 8, "MS Shell Dlg"

위와 같이 DS_SETFONT가 설정돼 있다면 함께 명시한 FONT 정보가 나온다고 합니다.

WORD wPoint;        // point size
WORD wWeight;       // font weight
BYTE bItalic;       // 1 if italic, 0 if not
BYTE bCharSet;      // character set
WCHAR szFontName[]; // variable-length

08 00: point size
00 00: font weight (0x0000 == FW_DONTCARE)
00: 1 if italic, 0 if not
01: character set, 0x01 = DEFAULT_CHARSET
4D 00 53 00 20 00 53 00 68 00 65 00 6C 00 6C 00 20 00 44 00 6C 00 67 00 00 00: "MS Shell Dlg" (널 종료 문자 포함)

자, 그다음부터는 이제 cItems에 지정한 컨트롤의 수만큼 다음의 정보들이 DWORD(4바이트) 정렬로 나열됩니다.

DWORD dwHelpID;     // help identifier
DWORD dwExStyle;    // window extended style
DWORD dwStyle;      // window style
WORD  x;            // x-coordinate (DLUs)
WORD  y;            // y-coordinate (DLUs)
WORD  cx;           // width (DLUs)
WORD  cy;           // height (DLUs)
DWORD dwID;         // control ID, 32비트 값이긴 하지만 WM_COMMAND 등의 메시지에서는 여전히 16비트 값으로 다루기 때문에 사실상 16비트만 사용 가능

WCHAR szClassName[];// variable-length (possibly ordinal)
WCHAR szText[];     // variable-length (possibly ordinal)
WORD  cbExtra;      // amount of extra data
BYTE  rgbExtra[cbExtra]; // extra data follows (usually none)

szClassName, szText, rgbExtra 때문에 크기가 가변적이므로 고정 레코드로 읽어들일 수 없다는 점이 귀찮군요. 그래도 4개밖에 없으니 ^^ 아래와 같이 정리해 봤습니다.

00 00 00 00: dwHelpID
00 00 00 00: dwExStyle
03 00 00 50: window style, 0x50000003, 아마도 WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000) | SS_ICON (0x03)
0E 00: x (14)
0E 00: y (14)
15 00: cx (21)
14 00: cy (20)
FF FF FF FF: control ID (-1)
FF FF 82 00: szClass == ordinal 0x0082 == static
FF FF 80 00: szText == ordinal 0x0080
00 00: cbExtra
00 00: 위의 cbExtra가 0이므로 이후 rgbExtra 바이트 배열이 아님. 4바이트 정렬이므로 padding 바이트 

00 00 00 00: dwHelpID
00 00 00 00: dwExStyle
80 00 02 50: window style, 0x50020080, 아마도 WS_GROUP(0x020000) | WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000) | SS_NOPREFIX(0x80)
2A 00: x (42)
0E 00: y (14)
72 00: cx (114)
08 00: cy (8)
FF FF FF FF: control ID (-1)
FF FF 82 00: szClass == ordinal 0x0082 == static
50 00 72 00 6F 00 6A 00 65 00 63 00 74 00 31 00 2C 00 20 00 56 00 65 00 72 00 73 00 69 00 6F 00 6E 00 20 00 31 00 2E 00 30 00 00 00: "Project1, Version 1.0" 문자열
00 00: cbExtra
00 00: 위의 cbExtra가 0이므로 이후 rgbExtra 바이트 배열이 아님. 4바이트 정렬이므로 padding 바이트 

00 00 00 00: dwHelpID 
00 00 00 00: dwExStyle
00 00 02 50: window style, 0x50020000, 아마도 WS_GROUP(0x020000) | WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000)
2A 00: x (42)
1A 00: y (26)
72 00: cx (114)
08 00: cy (8)
FF FF FF FF: control ID (-1)
FF FF 82 00: szClass == ordinal 0x0082 == static
43 00 6F 00 70 00 79 00 72 00 69 00 67 00 68 00 74 00 20 00 28 00 63 00 29 00 20 00 32 00 30 00 32 00 33 00 00 00: "Copyright (c) 2023"
00 00: cbExtra

00 00 00 00: dwHelpID 
00 00 00 00: dwExStyle
01 00 03 50: window style, 0x50030001, 아마도 WS_GROUP(0x020000) | WS_TABSTOP(0x010000) | WS_CHILD(0x40000000) | WS_VISIBLE(0x10000000) | BS_DEFPUSHBUTTON(0x01)
71 00: x (113)
29 00: y (41)
32 00: cx (50)
0E 00: cy (14)
01 00 00 00: control ID == IDOK(0x01)
FF FF 80 00: szClass == ordinal 0x0080 == button
4F 00 4B 00: "OK"
00 00: cbExtra
00 00: 위의 cbExtra가 0이므로 이후 rgbExtra 바이트 배열이 아님. 4바이트 정렬이므로 padding 바이트 

그러니까 결국, DialogBox 등의 함수들은 res로 컴파일된 바이너리에서 리소스 ID에 해당하는 대화창 정보를 위와 같은 포맷에 따라 해석해 CreateWindow로 보여주는 것입니다. 좀 ^^ 대단하지 않나요?

게다가... 이런 작업들이 Windows 1.0 시절부터 Win32 API와 그에 따른 Visual C++ 초기 IDE 도구가 협업해 대화창에 대한 Form 디자이너를 제공하고 있었다는 것은 매우 혁신적인 아이디어가 아니었을까 싶습니다. 제가 리눅스는 잘 몰라서 확실히 언급할 수는 없지만 아마 제대로 된 폼 디자이너를 아직도 갖추지 못한 것에 비하면 1985년에 이런 생각을 했다는 것에 놀랍기까지 합니다.




이렇게 해서 olenewthing의 6개 글 중 5개를 정리했습니다. 나머지 하나는,

The evolution of dialog templates – Summary
; https://devblogs.microsoft.com/oldnewthing/20040624-00/?p=38733

총정리를 다음의 표 하나로 제시하고 있습니다.

dialog_template_part1_3.png

즉, 4개의 DIALOG Template 버전이 있지만 16비트/32비트에 대한 차이와 약간의 필드 추가 등을 제외하면 거의 비슷합니다.




약간의 첨언을 하자면.

대화창에 포함할 수 있는 컨트롤의 수가 WORD 2바이트로 제한이 되는데요, 사실 이건 제약이라고 볼 수 없습니다. 왜냐하면,

Why is the limit of window handles per process 10,000?
; https://devblogs.microsoft.com/oldnewthing/20070718-00/?p=25963

프로세스 하나가 생성할 수 있는 User Object가 10,000개로 제한이 되기 때문에 Dialog Template의 제약은 오히려 현재로서는 가능성이 없는 수준입니다.

또한, 위에서 설명한 dialog 포맷에 해당하는 구조체가 winuser.h 헤더 파일에 정의돼 있는데,

DLGTEMPLATE structure (winuser.h)
; https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgtemplate

/*
 * original NT 32 bit dialog template:
 */
typedef struct {
    DWORD style;
    DWORD dwExtendedStyle;
    WORD cdit;
    short x;
    short y;
    short cx;
    short cy;
} DLGTEMPLATE;

DLGITEMTEMPLATE structure (winuser.h)
; https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-dlgitemtemplate

/*
 * 32 bit Dialog item template.
 */
typedef struct {
    DWORD style;
    DWORD dwExtendedStyle;
    short x;
    short y;
    short cx;
    short cy;
    WORD id;
} DLGITEMTEMPLATE;

아쉽게도 이 글에서 설명한 "32-bit Extended Templates" 유형이 아닌 "32-bit Classic Templates"에 해당하니 유의할 필요가 있습니다.

마지막으로, 본문에서 컨트롤들의 클래스에 대한 ordinal id를 설명 없이 언급했지만, 기본적인 컨트롤은 다음의 내용으로 문서에 나와 있습니다.

0x0080  Button
0x0081  Edit
0x0082  Static
0x0083  List box
0x0084  Scroll bar
0x0085  Combo box




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 10/26/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




1  2  3  4  5  6  7  [8]  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13392정성태7/16/20232577오류 유형: 872. Oracle - ORA-01031: insufficient privileges
13391정성태7/14/20232752닷넷: 2132. C# - sealed 클래스의 메서드를 callback 호출했을 때 인라인 처리가 될까요?
13390정성태7/12/20232745스크립트: 53. 파이썬 - localhost 호출 시의 hang 현상
13389정성태7/5/20232697개발 환경 구성: 684. IIS Express로 호스팅하는 웹을 WSL 환경에서 접근하는 방법
13388정성태7/3/20232752오류 유형: 871. 윈도우 탐색기에서 열리지 않는 zip 파일 - The Compressed (zipped) Folder '[...].zip' is invalid. [1]파일 다운로드1
13387정성태6/28/20232782오류 유형: 870. _mysql - Commands out of sync; you can't run this command now
13386정성태6/27/20232858Linux: 61. docker - 원격 제어를 위한 TCP 바인딩 추가
13385정성태6/27/20232960Linux: 60. Linux - 외부에서의 접속을 허용하기 위한 TCP 포트 여는 방법
13384정성태6/26/20232885.NET Framework: 2131. C# - Source Generator로 해결하는 enum 박싱 문제파일 다운로드1
13383정성태6/26/20232594개발 환경 구성: 683. GPU 런타임을 사용하는 Colab 노트북 설정
13382정성태6/25/20232656.NET Framework: 2130. C# - Win32 API를 이용한 윈도우 계정 정보 (예: 마지막 로그온 시간)파일 다운로드1
13381정성태6/25/20232931오류 유형: 869. Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
13380정성태6/24/20232551스크립트: 52. 파이썬 3.x에서의 동적 함수 추가
13379정성태6/23/20232592스크립트: 51. 파이썬 2.x에서의 동적 함수 추가
13378정성태6/22/20232526오류 유형: 868. docker - build 시 "CANCELED ..." 뜨는 문제
13377정성태6/22/20235835오류 유형: 867. 파이썬 mysqlclient 2.2.x 설치 시 "Specify MYSQLCLIENT_CFLAGS and MYSQLCLIENT_LDFLAGS env vars manually" 오류
13376정성태6/21/20232712.NET Framework: 2129. C# - Polly를 이용한 클라이언트 측의 요청 재시도파일 다운로드1
13375정성태6/20/20232419스크립트: 50. Transformers (신경망 언어모델 라이브러리) 강좌 - 2장 코드 실행 결과
13374정성태6/20/20232529오류 유형: 866. 파이썬 - <class 'AttributeError'> module 'flask.json' has no attribute 'JSONEncoder'
13373정성태6/19/20233663오류 유형: 865. 파이썬 - pymssql 설치 관련 오류 정리
13372정성태6/15/20232528개발 환경 구성: 682. SQL Server TLS 통신을 위해 사용되는 키 길이 확인 방법
13371정성태6/15/20232546개발 환경 구성: 681. openssl - 인증서 버전(V1 / V3)
13370정성태6/14/20232639개발 환경 구성: 680. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 - TLS 1.2 지원
13369정성태6/13/20232494개발 환경 구성: 679. PyCharm(을 비롯해 JetBrains에 속한 여타) IDE에서 내부 Window들의 탭이 없어진 경우
13368정성태6/13/20232652개발 환경 구성: 678. openssl로 생성한 인증서를 SQL Server의 암호화 인증서로 설정하는 방법
13367정성태6/10/20232749오류 유형: 864. openssl로 만든 pfx 인증서를 Windows Server 2016 이하에서 등록 시 "The password you entered is incorrect" 오류 발생
1  2  3  4  5  6  7  [8]  9  10  11  12  13  14  15  ...