Microsoft MVP성태의 닷넷 이야기
DDK: 2. Device Driver 응용 프로그램의 빌드 스크립트 [링크 복사], [링크+제목 복사],
조회: 30232
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 3개 있습니다.)
Device Driver 응용 프로그램의 빌드 스크립트

아래의 이야기에 이어서.

Visual Studio 2010 - Device Driver 제작- Hello World 예제
; https://www.sysnet.pe.kr/2/0/919

그럼, 지난번 만들어 둔 예제 프로젝트를 기반으로 다중 플랫폼들에 설치를 할 수 있도록 그에 맞는 *.sys 파일을 생성하는 배포 스크립트 파일을 만들어 볼까요? ^^




목표는 다음과 같습니다.

  1. x86, x64 버전으로 빌드
  2. Windows XP, 2003, Windows Server 2008 / R2 버전 지원
  3. 배포

차근차근히 하나씩 채워보면,

우선, 명령행 빌드 환경을 점검해야 합니다. 이 부분은 일반적인 "Visual Studio Command Prompt (2010)"에 설정된 PATH 값과 이외의 필요에 맞는 환경 변수를 정의합니다.

SET FrameworkVersion=v4.0.30319
SET PATH=C:\Windows\Microsoft.NET\Framework\%FrameworkVersion%;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\;C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\BIN;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Tools;C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\VCPackages;C:\Program Files (x86)\HTML Help Workshop;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;D:\Tools\SysInternals;

FOR /F %%I IN ("%0") DO SET CURRENTDIR=%%~dpI

SET BUILDCONFIG=Release
SET DriverName=DeviceDriverSample
SET SERVICENAME32=%DriverName%32
SET SERVICENAME64=%DriverName%64

자, ^^ 이제 msbuild로 예전에 살펴봤던 대로 x86과 x64 빌드를 해주면 되겠지요.

MSBuild를 이용한 VC++ 프로젝트 빌드
; https://www.sysnet.pe.kr/2/0/871

msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:Platform=Win32;Configuration=%BUILDCONFIG% /p:TargetName=%SERVICENAME32%
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:Platform=x64;Configuration=%BUILDCONFIG% /p:TargetName=%SERVICENAME64%

위와 같은 정도면 일단 x86 버전과 x64 버전은 정상적으로 출력이 됩니다. 그런데 Device Driver의 경우 보통, 윈도우 운영체제마다 달리해서 제작이 되곤 합니다. 그래서 x86/x64 버전에 대한 구분을 운영체제별로 해주는 것이 좋습니다. 이를 위해 출력 폴더를 다음과 같은 식으로 잡아주는 것이 좋겠고,

/bin/win7
    /win2003
    /vista
    /winxp

그럼, Windows 7 / 2008 R2용으로 빌드하고 싶은 경우에는 OutDir 환경 변수를 다음과 같이 맞춰주면 됩니다.

SET TARGETOS=win7
msbuild ... /p:OutDir=%CURRENTDIR%\bin\%TARGETOS%

그런데, 여기서 고려해야 할 사항이 있지요. 운영체제마다 소스 코드 내에 사용되는 구조체 필드의 offset 값, 상수값들이 틀릴 수 있기 때문에 이에 대한 지원을 포함시켜 주어야 합니다. 물론, 이런 경우 프로젝트를 다르게 가져가는 것보다는 적절한 "전처리기"를 정의해서 소스 코드를 단일하게 관리하는 것이 더 편한데요.

예를 들어, 다음과 같이 DDK의 VER_PRODUCTBUILD에 따라 내부 정의를 달리하는 ntifs.h 파일을 include 하는 경우라면,

#include <ntddk.h>
#include "ntifs.h"

다음과 같이 외부에서 정의 가능한 TARGET_PLATFORM_VER 전처리기를 끼워두고,

#include <ntddk.h>

#if defined( TARGET_PLATFORM_VER )
#if defined(VER_PRODUCTBUILD)
#undef VER_PRODUCTBUILD 
#define VER_PRODUCTBUILD TARGET_PLATFORM_VER
#else
#define VER_PRODUCTBUILD TARGET_PLATFORM_VER
#endif
#endif
#include "ntifs.h"

그런 후에, "MSBuild를 이용한 VC++ 프로젝트 빌드" 글에서 설명했던 것처럼, TARGET_PLATFORM_VER 전처리기를 msbuild에서 제어할 수 있도록 vcxproj 파일의 PreprocessorDefinitions를 바꿔주면 다음과 같이 개별 운영체제에 맞는 sys 파일을 생성할 수 있는 msbuild 배치가 구성됩니다.

REM 32 bit Windows XP
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=2600 ...

REM 32 bit Windows 2003
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=3790 ...

와~~~ 그럼, 다음과 같은 정도의 빌드 스크립트를 구성하면 XP/2003/Vista/2008/2008 R2까지 개별 32/64비트 sys 파일이 생성되겠군요. ^^

REM Windows XP 32/64
SET TARGETOS=winxp
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=2600 /p:Platform=Win32;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample32 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=2600 /p:Platform=x64;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample64 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\

REM Windows 2003 32/64
SET TARGETOS=win2003
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=3790 /p:Platform=Win32;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample32 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=3790 /p:Platform=x64;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample64 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\

REM Windows Vista/2008 32/64
SET TARGETOS=vista
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=6002 /p:Platform=Win32;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample32 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=6002 /p:Platform=x64;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample64 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\

REM Windows 7/2008 R2 32/64
SET TARGETOS=win7
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=7600 /p:Platform=Win32;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample32 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\
msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" /p:PLATFORM_PREPROCESSOR=7600 /p:Platform=x64;Configuration=%BUILDCONFIG% /p:TargetName=DeviceDriverSample64 /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\

마지막으로 배포는... 해당 VPC를 각각 만들어 두어서 복사 작업만 해주면 됩니다. 다음과 같이. ^^

SET TESTPC=WIN7X64EN
robocopy %CURRENTDIR%bin \\%TESTPC%\d$\devicetest /S
SET TESTPC=win2003x86
robocopy %CURRENTDIR%bin \\%TESTPC%\d$\devicetest /S
SET TESTPC=win2008x86
robocopy %CURRENTDIR%bin \\%TESTPC%\d$\devicetest /S

그런데, 배포를 단순 복사하는 것만으로는 좀 아쉽죠. 복사하기 전 서비스를 중지 -> 복사 -> 서비스 시작하는 작업을 해주면 더 좋을 것 같습니다. 그럼 sc.exe 가 떠오르는 군요. ^^
SET TESTPC=WIN7X64EN
SET SERVICENAME64=%DriverName%64

sc \\%TESTPC% stop "%SERVICENAME64%"
robocopy %CURRENTDIR%bin \\%TESTPC%\d$\devicetest /S
sc \\%TESTPC% start "%SERVICENAME64%"

최초의 배포 한번은 오류가 날 테지만 상관없습니다. 다음 빌드부터는 편하게 자동으로 업데이트 되는 효과를 얻을 테니.




참고로, 윈도우 운영체제가 Windows 7 x64/2008 R2부터는 정식 인증서로 서명하지 않은 드라이버는 올라오지 않게 됩니다. 이를 위해 우선, "테스트 인증서"로 서명해야 하는데요. 여기서는 다음에 첨부한 인증서를 가져다가,

인증서 관련(CER, PVK, SPC, PFX) 파일 만드는 방법
; https://www.sysnet.pe.kr/2/0/863

아래의 글에서 설명한 방법 대로,

Appinit_Dlls로 구현한 환경변수 설정 DLL
; https://www.sysnet.pe.kr/2/0/883

singtool.exe를 이용해서 서명하는 작업을 빌드 스크립트에 추가하였습니다.

Signtool sign /v /sm /n "mytest" %CURRENTDIR%bin\%TARGETOS%\%SERVICENAME64%.sys

그다음, 아래와 같이 대상 운영체제에서 미리 관리자 권한으로 명령어를 실행해 두고 재부팅합니다.

=== Windows 7 / 2008 R2 ====
bcdedit /set TESTSIGNING ON

위의 명령어가 실행된 PC에서는 "테스트 인증서"로 서명된 디바이스 드라이버를 로드할 수 있도록 허용되어지고, 구분을 쉽게 하기 위해 바탕 화면에는 "Test Mode Windows 7 Build 7600"과 같은 메시지가 나타납니다.




기타 몇 가지 더... ^^

위의 sc.exe를 이용해서 대상 서비스를 로드/해제하게 되는데요. 이에 앞서 드라이버를 시스템에 등록해 주어야 합니다. 이런 경우, 쉽게 사용할 수 있는 툴이 "OSR Driver Loader"인데요. 다음의 경로에서 다운로드 받을 수 있습니다.

OSR Online - Driver Loader 
; http://www.osronline.com/article.cfm?article=157

device_driver_build_script_1.png

이 외에, 가상 머신에 대한 windbg 연결이 필요한 데, 그에 관해서는 다음의 글을 참조합니다.

원격 컴퓨터 디버깅 - VPC 설정
; https://www.sysnet.pe.kr/2/0/265

위의 글에서는 Virtual Server를 기준으로 설명하고 있지만, Hyper-V에서도 설정은 유사합니다.

그리고 중요한 것 하나 더!

소스 코드 형상관리는 잊으시면 안되죠. ^^ 이 부분은, 다음의 글을 참고하셔서 필요한 부분을 지금까지 위에서 설명한 빌드 스크립트에 추가해 주시면 되겠습니다.

배치 파일로 팀 빌드 구성
; https://www.sysnet.pe.kr/2/0/905

첨부한 파일은 제가 예제로 구성한 build.bat 파일과 예제 프로젝트입니다.



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

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/27/2021]

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

비밀번호

댓글 작성자
 



2010-10-22 12시12분
위의 글을 읽어보신 분들은, 아래의 글을 꼭 읽어주세요. ^^

Device Driver 응용 프로그램의 빌드 스크립트 - 두 번째 이야기
; http://www.sysnet.pe.kr/2/0/936
kevin25
2020-02-16 09시19분
HyperSine/Windows10-CustomKernelSigners
; https://github.com/HyperSine/Windows10-CustomKernelSigners
정성태

... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12211정성태4/27/202019275개발 환경 구성: 486. WSL에서 Makefile로 공개된 리눅스 환경의 C/C++ 소스 코드 빌드
12210정성태4/20/202020721.NET Framework: 903. .NET Framework의 Strong-named 어셈블리 바인딩 (1) - app.config을 이용한 바인딩 리디렉션 [1]파일 다운로드1
12209정성태4/13/202017425오류 유형: 614. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우 (2)
12208정성태4/12/202015995Linux: 29. 리눅스 환경에서 C/C++ 프로그램이 Segmentation fault 에러가 발생한 경우
12207정성태4/2/202015849스크립트: 19. Windows PowerShell의 NonInteractive 모드
12206정성태4/2/202018448오류 유형: 613. 파일 잠금이 바로 안 풀린다면? - The process cannot access the file '...' because it is being used by another process.
12205정성태4/2/202015114스크립트: 18. Powershell에서는 cmd.exe의 명령어를 지원하진 않습니다.
12204정성태4/1/202015129스크립트: 17. Powershell 명령어에 ';' (semi-colon) 문자가 포함된 경우
12203정성태3/18/202017965오류 유형: 612. warning: 'C:\ProgramData/Git/config' has a dubious owner: '...'.
12202정성태3/18/202021214개발 환경 구성: 486. .NET Framework 프로젝트를 위한 GitLab CI/CD Runner 구성
12201정성태3/18/202018454오류 유형: 611. git-credential-manager.exe: Using credentials for username "Personal Access Token". [1]
12200정성태3/18/202018542VS.NET IDE: 145. NuGet + Github 라이브러리 디버깅 관련 옵션 3가지 - "Enable Just My Code" / "Enable Source Link support" / "Suppress JIT optimization on module load (Managed only)"
12199정성태3/17/202016182오류 유형: 610. C# - CodeDomProvider 사용 시 Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '...\f2_6uod0.tmp'.
12198정성태3/17/202019537오류 유형: 609. SQL 서버 접속 시 "Cannot open user default database. Login failed."
12197정성태3/17/202018838VS.NET IDE: 144. .NET Core 콘솔 응용 프로그램을 배포(publish) 시 docker image 자동 생성 - 두 번째 이야기 [1]
12196정성태3/17/202015962오류 유형: 608. The ServicedComponent being invoked is not correctly configured (Use regsvcs to re-register).
12195정성태3/16/202018277.NET Framework: 902. C# - 프로세스의 모든 핸들을 열람 - 세 번째 이야기
12194정성태3/16/202021004오류 유형: 607. PostgreSQL - Npgsql.NpgsqlException: sorry, too many clients already
12193정성태3/16/202017946개발 환경 구성: 485. docker - SAP Adaptive Server Enterprise 컨테이너 실행 [1]
12192정성태3/14/202019980개발 환경 구성: 484. docker - Sybase Anywhere 16 컨테이너 실행
12191정성태3/14/202021064개발 환경 구성: 483. docker - OracleXE 컨테이너 실행 [1]
12190정성태3/14/202015644오류 유형: 606. Docker Desktop 업그레이드 시 "The process cannot access the file 'C:\Program Files\Docker\Docker\resources\dockerd.exe' because it is being used by another process."
12189정성태3/13/202021249개발 환경 구성: 482. Facebook OAuth 처리 시 상태 정보 전달 방법과 "유효한 OAuth 리디렉션 URI" 설정 규칙
12188정성태3/13/202026036Windows: 169. 부팅 시점에 실행되는 chkdsk 결과를 확인하는 방법
12187정성태3/12/202015620오류 유형: 605. NtpClient was unable to set a manual peer to use as a time source because of duplicate error on '...'.
12186정성태3/12/202017408오류 유형: 604. The SysVol Permissions for one or more GPOs on this domain controller and not in sync with the permissions for the GPOs on the Baseline domain controller.
... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...