안녕하세요.
현재 C# (.NET Framework 4.7.2) 환경에서 문서와 포럼을 참고하여 프로그램을 개발하고 있습니다.
개발 중 한글 버전별 동작 차이가 발생하여 문의드립니다.
개발 환경
- Language : C#
- Framework : .NET Framework 4.7.2
발생 현상
1. ReplaceAction 동작 차이
아래 코드에서:
bool isReplaceActionForFileSaveAs_S =
_hwp.ReplaceAction("FileSaveAs_S", "HwpCustomSaveAs");
- 한글 2024 :
true
- 한글 2018 :
true
- 한글 2014 :
false
한글 2014에서만 ReplaceAction()이 실패하며 다른 포럼 게시글에 FileSaveAs_S_EX 로도 시도 해보았으나 동일 합니다. (매크로 정의 참고로 재 확인)
2. 이벤트 등록 오류
아래와 같이 이벤트를 등록하고 있습니다.
_hwp.DocumentBeforeSave += OnBeforeSave;
_hwp.DocumentAfterSave += OnAfterSave;
_hwp.DocumentAfterClose += OnAfterClose;
- 한글 2024 : 정상 동작
- 한글 2018 : 정상 동작
- 한글 2014 : “해당 인터페이스를 지원하지 않습니다.” 예외 발생
문의사항
ReplaceAction("FileSaveAs_S", "HwpCustomSaveAs")가 한글 2014에서 false를 반환하는 것이 정상 동작인지 궁금합니다.
DocumentBeforeSave, DocumentAfterSave, DocumentAfterClose 이벤트는 한글 2014에서 지원되지 않는 인터페이스인지 궁금합니다.
- 만약 한글 2014에서 지원되지 않는 기능이라면, 해당 기능들이 어떤 버전부터 지원되는지 확인할 수 있는 자료가 있을까요?
감사합니다.
추가로 한글 2014 VP 버전은 9.1 에서 테스트 결과
HwpObject hwpobj; = new HwpObject(); 로 사용 할 경우
“널 참조 포인터를 스텁에 전달했습니다” 가 발생 하여
dynamic hwpObject;
Type hwpType = Type.GetTypeFromProgID(“HWPFrame.HwpObject.2”);
hwpObject = Activator.CreateInstance(hwpType);
로 변경 하였고, 이 경우에는 정상적으로 실행이 되며
hwpObject.ReplaceAction() 은 TRUE로 정상 동작 합니다.
다만 dynamic 으로 되어 DocumentBeforSave와 같은 이벤트를 추가 할 수 없어
HwpObject _hwpobj;
_hwpobj = (HwpObject)hwpObject;
로 캐스팅을 하여
_hwpobj.NewDocument += HwpObject_NewDocument;
_hwpobj.DocumentAfterClose += HwpObject_DocumentAfterClose;
이벤트 생성 시 동일하게
“해당 인터페이스를 지원하지 않습니다” 예외가 발생 합니다.
안녕하세요
dynamic 으로 되어 DocumentBeforSave와 같은 이벤트를 추가 하려면
dynamic 객체를 IConnectionPointContainer로 캐스팅 → FindConnectionPoint(IID {F04A09A0-F319-40D5-88CA-CA439CC6820C}) → Advise(sink)로 싱크를 직접 연결하면 됩니다.
감사합니다.
using System;
using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;
// 1) 이벤트 소스 dispinterface 정의 (Interop 어셈블리 대용)
// GUID = 한글이 등록한 _DIHwpObjectEvents IID, 메서드는 DISPID로 매핑
[ComVisible(true)]
[Guid("F04A09A0-F319-40D5-88CA-CA439CC6820C")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IHwpObjectEvents
{
[DispId(4)] void NewDocument(int newVal);
[DispId(8)] void DocumentBeforeSave(int newVal);
[DispId(9)] void DocumentAfterSave(int newVal);
[DispId(10)] void DocumentAfterClose(int newVal);
// 필요한 이벤트만 선언해도 됨(나머지 DISPID는 서버가 무시). 전체 목록은 아래 표 참고.
}
// 2) 싱크 구현 — 서버가 Invoke(dispid)로 호출하면 해당 메서드가 실행됨
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class HwpObjectEventSink : IHwpObjectEvents
{
public void NewDocument(int v) { /* ... */ }
public void DocumentBeforeSave(int v) { /* 저장 직전 처리 */ }
public void DocumentAfterSave(int v) { /* 저장 직후 처리 */ }
public void DocumentAfterClose(int v) { /* 닫힘 후 처리 */ }
}
// 3) 연결 (Interop 어셈블리 없이 객체 생성 + Advise)
public class HwpAutomation
{
private static readonly Guid DIID_HwpObjectEvents =
new Guid("F04A09A0-F319-40D5-88CA-CA439CC6820C");
private dynamic _hwp;
private ComTypes.IConnectionPoint _cp; // GC 방지 위해 필드로 보관
private HwpObjectEventSink _sink; // GC 방지 위해 필드로 보관
private int _cookie;
public void Start()
{
Type t = Type.GetTypeFromProgID("HWPFrame.HwpObject.2");
_hwp = Activator.CreateInstance(t);
// 메서드 호출은 그대로 dynamic 사용
bool ok = _hwp.ReplaceAction("FileSaveAs_S", "HwpCustomSaveAs"); // true
// 이벤트 연결: 서버의 연결점을 직접 조회 → Advise
var cpc = (ComTypes.IConnectionPointContainer)_hwp;
Guid iid = DIID_HwpObjectEvents;
cpc.FindConnectionPoint(ref iid, out _cp);
_sink = new HwpObjectEventSink();
_cp.Advise(_sink, out _cookie);
}
public void Stop()
{
if (_cp != null && _cookie != 0)
{
_cp.Unadvise(_cookie);
_cookie = 0;
}
}
}