성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Roll A Lisp In C - Reading ; https...
[정성태] Java - How to use the Foreign Funct...
[정성태] 제가 큰 실수를 했군요. ^^; Delegate를 통한 Bein...
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - 하나의 바이너리로 환경에 맞게 32비트/64비트 EXE를 실행하는 방법</h1> <p> 닷넷 프로그램에서 AnyCPU를 사용하면 32비트/64비트 운영체제에서 그에 맞게 실행됩니다. 그런데 때로는 64비트에서조차도 32비트로 실행하고 싶은 경우가 있습니다.<br /> <br /> 현실적인 예를 하나 들면, OLEDB 데이터 제공자가 64비트만 설치된 시스템이 있다면 그것을 이용하는 프로그램도 64비트로 실행해야 합니다. 반면 32비트 제공자만 설치된 경우라면 프로그램 역시 32비트로 동작해야 합니다. 이럴 때 사용할 수 있는 트릭으로 sysinternals 도구처럼 64비트 용 실행 파일을 리소스로 포함하고 있다가 적절한 환경에 맞게 실행하는 방법이 있습니다.<br /> <br /> 간단하게 한번 만들어 볼까요? ^^<br /> <br /> 우선 다음의 글에 설명한 내용으로 .csproj 파일의 AssemblyName을 이용해<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > AssemblyName을 .csproj에서 바꾼 경우 빌드 오류 발생하는 문제 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11327'>http://www.sysnet.pe.kr/2/0/11327</a> </pre> <br /> 32비트/64비트에 따라 EXE 이름을 다음과 같이 맞춰줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 32비트: x86x64test.exe 64비트: x86x64test64.exe </pre> <br /> 그다음, 64비트 EXE를 32비트용 EXE가 빌드될 때 리소스 파일로 포함하는 것입니다. 32비트 빌드에서만 포함해야 하므로 다음과 같이 .csproj 파일에 직접 입력해 줘야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <ItemGroup Condition="'$(Platform)' == 'AnyCPU'"> <EmbeddedResource Include="$(ProjectDir)bin\x64\$(Configuration)\x86x64test64.exe"> <Link>x86x64test64.exe</Link> </EmbeddedResource> </ItemGroup> </pre> <br /> 물론 이렇게 하면 AnyCPU를 빌드하기 전에 x64용으로 한 번은 빌드해줘야 합니다. (왜냐하면 x86x64test64.exe 파일을 리소스로 포함하기 때문에.)<br /> <br /> 따라서 나중에 빌드 스크립트를 만들 때는 x64용을 먼저 빌드하고 AnyCPU를 차례로 빌드하면 됩니다. 이제 나머지는 코드로 작성하면 됩니다. 예를 들어 다음의 2개 파일 중 어느 것이 있느냐에 따라 그에 맞게 x86 또는 x64를 실행하도록 구성할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\Program Files\Common Files\microsoft shared\OFFICE14\ACEOLEDB.DLL ==> x64로 실행 C:\Program Files (x86)\Common Files\microsoft shared\OFFICE14\ACEOLEDB.DLL ==> x86으로 실행 </pre> <br /> 이를 위한 startup 코드는 다음과 같이 구성하면 됩니다. (코드가 약간 복잡한 듯 보여도 전형적인 패턴이므로 그대로 복사해 사용할 수 있습니다.)<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Diagnostics; using System.IO; namespace x86x64test { class Program { static void Main(string[] args) { Console.WriteLine("Is64bit: " + Environment.Is64BitProcess); if (Environment.Is64BitProcess == false) { // x86 OLEDB 제공자가 설치되어 있지 않다면? if (FileCheck(TargetPlatform.x86) == false) { // x64 OLEDB 제공자가 설치되어 있지 않다면? if (FileCheck(TargetPlatform.x64) == false) { Console.WriteLine("NO OLEDB Provider (x86/x64)"); return; } RunAs64bit(); return; } } else { if (FileCheck(TargetPlatform.x64) == false) { Console.WriteLine("NO OLEDB Provider (x64)"); return; } } Console.WriteLine("run your code"); } private static void RunAs64bit() { string x64FileName = "x86x64test64.exe"; ExtractResource(x64FileName); ProcessStartInfo psi = new ProcessStartInfo(); psi.UseShellExecute = false; psi.FileName = x64FileName; using (Process child = Process.Start(psi)) { child.WaitForExit(); } } private static void ExtractResource(string resFileName) { string curPath = Path.GetDirectoryName(typeof(Program).Assembly.Location); string resTargetPath = Path.Combine(curPath, resFileName); if (File.Exists(resTargetPath) == true) { return; } using (System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resFileName)) { using (System.IO.FileStream fileStream = new System.IO.FileStream(resTargetPath, System.IO.FileMode.Create)) { stream.CopyTo(fileStream); } } } private static bool FileCheck(TargetPlatform platform) { string targetFolder = null; if (platform == TargetPlatform.x86) { targetFolder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); } else { if (Environment.Is64BitOperatingSystem == true) { targetFolder = Environment.GetEnvironmentVariable("ProgramW6432"); } else { targetFolder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); } } string filePath = Path.Combine(targetFolder, "common files", "microsoft shared", "OFFICE14", "ACEOLEDB.DLL"); Console.WriteLine("Checked: " + filePath); return File.Exists(filePath); } enum TargetPlatform { None, x86, x64 } } } </pre> <br /> 자, 그럼 테스트를 해볼까요? ^^<br /> <br /> 해당 OLEDB 데이터 제공자가 설치되지 않은 PC에서 실행하면 다음과 같은 출력 결과를 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > D:\temp>x86x64test.exe Is64bit: False Checked: C:\Program Files (x86)\common files\microsoft shared\OFFICE14\ACEOLEDB.DLL Checked: C:\Program Files\common files\microsoft shared\OFFICE14\ACEOLEDB.DLL NO OLEDB Provider (x86/x64) </pre> <br /> 그리고 x86용 OLEDB 데이터 제공자가 있다면 현재의 x86 프로세스 내에서 처리를 완료합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > D:\temp>x86x64test.exe Is64bit: False Checked: C:\Program Files (x86)\common files\microsoft shared\OFFICE14\ACEOLEDB.DLL run your code </pre> <br /> 반면 x64용 OLEDB 데이터 제공자가 있다면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp>x86x64test.exe Is64bit: False Checked: C:\Program Files (x86)\common files\microsoft shared\OFFICE14\ACEOLEDB.DLL Checked: C:\Program Files\common files\microsoft shared\OFFICE14\ACEOLEDB.DLL Is64bit: True Checked: C:\Program Files\common files\microsoft shared\OFFICE14\ACEOLEDB.DLL run your code </pre> <br /> 처음 x86x64test.exe 실행 파일이 구동되었지만 x86 OLEDB 데이터 제공자가 없어 x64 OLEDB 데이터 제공자를 체크했는데 존재하므로 리소스 파일로 포함되어 있던 x86x64test64.exe 파일을 동일한 폴더에 풀어 놓은 다음 실행을 했습니다.<br /> <br /> (<a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1174&boardid=331301885'>첨부한 파일은 이 글의 예제 프로젝트를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1903
(왼쪽의 숫자를 입력해야 합니다.)