테스트를 위해 ATL 프로젝트를 하나 작성했는데 약간의 문제는 있었지만 HelloWorld 함수를 하나 추가한 COM 서버 예제를 작성했습니다.//…[생략]…[ object, uuid(53ad801e-eaa0-49b5-80b0-0a00222ec0a4), dual, nonextensible, pointer_default(unique)] interface IATLSimpleObject : IDispatch{[id(1)] HRESULT HelloWorld([in] BSTR text);};[ uuid(240e2ba0-1248-48d2-9165-0fdb5d40c710), version(1.0),]library ATLProject1Lib{ importlib(“stdole2.tlb”); [ uuid(9818df4f-d77f-4d1d-a094-82632f6a0ffd) ] coclass ATLSimpleObject { [default] interface IATLSimpleObject; };};import “shobjidl. idl”;STDMETHODIMP CATLSimpleObject::HelloWorld(BSTR text){ int needBytes = WideCharToMultiByte(CP_ACP, 0, text, -1, NULL, 0, NULL, NULL); char *ptr = new char[needBytes] ; WideCharToMultiByte(CP_ACP, 0, text, -1, ptr, needBytes, NULL, NULL); printf(“%s HelloWorld\n “, ptr); delete []ptr; return S_OK;} 개인적으로 레지스트리를 교란하는 것을 싫어하기 때문에 위의 프로젝트를 빌드와 함께 등록하고 싶지 않기 때문에 프로젝트 설정에서 “Linker”/”General” 카테고리의 “Register Output” 속성을 “No”로 설정했습니다. (사실 Visual Studio를 관리자 권한으로 실행하지 않으면 빌드 시 오류가 발생합니다.) 테스트를 위해 ATL 프로젝트를 하나 작성했는데 약간의 문제는 있었지만 HelloWorld 함수를 하나 추가한 COM 서버 예제를 작성했습니다.//…[생략]…[ object, uuid(53ad801e-eaa0-49b5-80b0-0a00222ec0a4), dual, nonextensible, pointer_default(unique)] interface IATLSimpleObject : IDispatch{[id(1)] HRESULT HelloWorld([in] BSTR text);};[ uuid(240e2ba0-1248-48d2-9165-0fdb5d40c710), version(1.0),]library ATLProject1Lib{ importlib(“stdole2.tlb”); [ uuid(9818df4f-d77f-4d1d-a094-82632f6a0ffd) ] coclass ATLSimpleObject { [default] interface IATLSimpleObject; };};import “shobjidl. idl”;STDMETHODIMP CATLSimpleObject::HelloWorld(BSTR text){ int needBytes = WideCharToMultiByte(CP_ACP, 0, text, -1, NULL, 0, NULL, NULL); char *ptr = new char[needBytes] ; WideCharToMultiByte(CP_ACP, 0, text, -1, ptr, needBytes, NULL, NULL); printf(“%s HelloWorld\n “, ptr); delete []ptr; return S_OK;} 개인적으로 레지스트리를 교란하는 것을 싫어하기 때문에 위의 프로젝트를 빌드와 함께 등록하고 싶지 않기 때문에 프로젝트 설정에서 “Linker”/”General” 카테고리의 “Register Output” 속성을 “No”로 설정했습니다. (사실 Visual Studio를 관리자 권한으로 실행하지 않으면 빌드 시 오류가 발생합니다.)

물론, 저렇게만 하고 실행하면 COM 개체를 찾을 수 없으므로 “System. 런타임. Interop Services. (상호 운용 서비스). COMException” 예외가 발생합니다. 시스템. 런타임. Interop Services. (상호 운용 서비스). COMException HResult=0x80040154 메시지=retrie CLSID {9818DF4F-D77F-4D1D-A094-82632F6A0 탑재 컴포넌트의 COM 클래스의 공장 출하 시 FFD}가 다음 에러로 인해 실패하였습니다. 80040154 Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)). Source=WinFormsApp1 스택 트레이스: WinFormsApp1에 있습니다. 폼 1. Form1_Load(객체 송신자, EventArge)를 시스템에서 실행합니다. 창. 폼. 폼. OnLoad (Event Argse)… [생략]… 이를 해결하려면, 예전에 정리했던 글에 따라,Registry 등록 과정 없이 COM 개체 사용 – 두 번째 이야기; https://www.sysnet.pe.kr/2/0/1167manifest 파일을 내장해야 합니다. 오랜만이니 이 과정까지 마저 마무리를 해볼까요? ^^우선, manifest 파일은 1) 수작업으로 직접 만들 수도 있고, 2) “COMRegFreeManifest”와 같은 도구를 이용할 수도 있습니다. 편의상 ^^ 도구를 이용하겠습니다. C:\temp>COMMERegFreeManifest。exe ATLProject1.dllC:\temp> dir *.manifest /bATLProject1.dll.manifestSample.exe.manifest 이렇게 인생한 ALL Project 1.dll.manifest 파일과 ALL Project 1.dll을 C# 프로 젝트에 “링크로서 추가”로 추가해 출력 디렉토리에 카피<Project Sdk=”Microsoft. NET.Sdk”> <PropertyGroup> <OutputType> WinExe</OutputType> <TargetFramework> net8.0-windows</TargetFramework> <Nullable> <UseWindowsForms> true</UseWindowsForms>> <ImplicitiveUsings</Implicitutings>> </PropertyGroup>>アイテムグループ> <なし=”..\x64\デバッグ\ATLProject1.dll” Link=”ATLProject1.dll”> <CopyToOutputDirectory> 新着情報の保存</CopyToOutputDirectory> </None> <None Include=”..\x64\デバッグ\ATLProject1.dll.manifest” Link=”ATLProject1.dll.manifest”> <CopyToOutputDirectory> 新着情報の保存</CopyToOutputDirectory> </None> </ItemGroup> <ItemGroup> <ReferenceInclude=”ATLProject1Lib”> <HintPath>..\x64\デバッグ\ATLProject1Lib.dll</HintPath> </Reference> </ItemGroup> </Project> 빌드 시마다 출력 폴더(예를 들어, “bin\Debug\n )et8.0-windows”)에 DLL, manifest 파일이 복사됩니다. 물론, 이전의 과정은 수작업으로 했으므로 이후 변경 과정에서 불편함을 겪을 수 있으므로 적절하게 Build Events 등을 이용해 COMRegFreeManifest 등의 실행을 자동화하는 것이 좋습니다.// “Build Events” / “Post-Build Event”pushd $(OutDir)COMMegFreeManifest $(TargetFileName)tlbimp /machine:X64(TargetFileName)popd 물론, 저렇게만 하고 실행하면 COM 개체를 찾을 수 없으므로 “System. 런타임. Interop Services. (상호 운용 서비스). COMException” 예외가 발생합니다. 시스템. 런타임. Interop Services. (상호 운용 서비스). COMException HResult=0x80040154 메시지=retrie CLSID {9818DF4F-D77F-4D1D-A094-82632F6A0 탑재 컴포넌트의 COM 클래스의 공장 출하 시 FFD}가 다음 에러로 인해 실패하였습니다. 80040154 Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)). Source=WinFormsApp1 스택 트레이스: WinFormsApp1에 있습니다. 폼 1. Form1_Load(객체 송신자, EventArge)를 시스템에서 실행합니다. 창. 폼. 폼. OnLoad (Event Argse)… [생략]… 이를 해결하려면, 예전에 정리했던 글에 따라,Registry 등록 과정 없이 COM 개체 사용 – 두 번째 이야기; https://www.sysnet.pe.kr/2/0/1167manifest 파일을 내장해야 합니다. 오랜만이니 이 과정까지 마저 마무리를 해볼까요? ^^우선, manifest 파일은 1) 수작업으로 직접 만들 수도 있고, 2) “COMRegFreeManifest”와 같은 도구를 이용할 수도 있습니다. 편의상 ^^ 도구를 이용하겠습니다. C:\temp>COMMERegFreeManifest。exe ATLProject1.dllC:\temp> dir *.manifest /bATLProject1.dll.manifestSample.exe.manifest 이렇게 인생한 ALL Project 1.dll.manifest 파일과 ALL Project 1.dll을 C# 프로 젝트에 “링크로서 추가”로 추가해 출력 디렉토리에 카피<Project Sdk=”Microsoft. NET.Sdk”> <PropertyGroup> <OutputType> WinExe</OutputType> <TargetFramework> net8.0-windows</Targ
그래도 아직 마지막 작업이 남아있습니다. ^^ 바로 Windowns Forms EXE 프로젝트의 manifest 파일에 ATL Project 1.dll.manifest 파일을 참조하도록 설정을 하셔야 합니다. 이를 위해 “Add”/ “New Item…”을 선택하고 “Application Manifest File(Windows Only)” 항목을 “app.manifest” 이름으로 생성하고 다음 내용을 추가합니다.<?xml version=”1.0″ encoding=”utf-8″? ><assembly manifestVersion=”1.0″ xmlns=”urn:schemas-microsoft-com:asm.v1″> <assemblyIdentity version=”1.0.0.0″ name=”MyApplication.app”/> <!– ···[省略] ··· –><dependency> <dependentAssembly dependencyType=”install” codebase=”ATLProject1.dll.manifest”> <assemblyIdentity name=”ATLProject1.dll” version=”1.0.0.0″ type=”win32″ /> </dependentAssembly></dependency></assembly>그런데, 이렇게 하고 나서 빌드하면 이런 경고가 나올 것입니다. warning MSB3270: There was a mismatch between the processor architecture of the project being built “MSIL” and the processor architecture of the reference “ATLProject1Lib”, “AMD64”. This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references、 or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.無視してもいいですが, 그래도 COMDLL이 nativeDLL이기 때문에 x64에 빌드된 것이기 때문에 C#프로젝트도 AnyCPU보다는 x64에 명시하는 것이 좋습니다. 이후 다시 빌드하면 경고도 없고 실행 시(레지스트리 등록이 없음에도 불구하고) COM 객체 사용에 문제없이 잘 동작합니다. (첨부파일은 이 글의 예제 프로젝트를 포함합니다.) 그래도 아직 마지막 작업이 남아있습니다. ^^ 바로 Windowns Forms EXE 프로젝트의 manifest 파일에 ATL Project 1.dll.manifest 파일을 참조하도록 설정을 하셔야 합니다. 이를 위해 “Add”/ “New Item…”을 선택하고 “Application Manifest File(Windows Only)” 항목을 “app.manifest” 이름으로 생성하고 다음 내용을 추가합니다.<?xml version=”1.0″ encoding=”utf-8″? ><assembly manifestVersion=”1.0″ xmlns=”urn:schemas-microsoft-com:asm.v1″> <assemblyIdentity version=”1.0.0.0″ name=”MyApplication.app”/> <!– ···[省略] ··· –><dependency> <dependentAssembly dependencyType=”install” codebase=”ATLProject1.dll.manifest”> <assemblyIdentity name=”ATLProject1.dll” version=”1.0.0.0″ type=”win32″ /> </dependentAssembly></dependency></assembly>그런데, 이렇게 하고 나서 빌드하면 이런 경고가 나올 것입니다. warning MSB3270: There was a mismatch between the processor architecture of the project being built “MSIL” and the processor architecture of the reference “ATLProject1Lib”, “AMD64”. This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references、 or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.無視してもいいですが, 그래도 COMDLL이 nativeDLL이기 때문에 x64에 빌드된 것이기 때문에 C#프로젝트도 AnyCPU보다는 x64에 명시하는 것이 좋습니다. 이후 다시 빌드하면 경고도 없고 실행 시(레지스트리 등록이 없음에도 불구하고) COM 객체 사용에 문제없이 잘 동작합니다. (첨부파일은 이 글의 예제 프로젝트를 포함합니다.)

