성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
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# - 키움 Open API+ 사용 시 Registry 등록 없이 KHOpenAPI.ocx 사용하는 방법</h1> <p> 아래의 글을 보고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 한 권으로 끝내는 주식 자동매매 프로그램 만들기 ; <a target='tab' href='https://wikidocs.net/book/1930'>https://wikidocs.net/book/1930</a> 2.2 API 설치하기 환경설정 ; <a target='tab' href='https://wikidocs.net/17635'>https://wikidocs.net/17635</a> 3.1 프로그램에서 HTS처럼 로그인하기 ; <a target='tab' href='https://wikidocs.net/17646'>https://wikidocs.net/17646</a> </pre> <br /> 실습하는 중에 키움 증권 웹 사이트의,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 키움 Open API+ ; <a target='tab' href='https://www1.kiwoom.com/nkw.templateFrameSet.do?m=m1408000000'>https://www1.kiwoom.com/nkw.templateFrameSet.do?m=m1408000000</a> </pre> <br /> "키움 Open API+ 모듈 다운로드" 링크를 통해 설치를 하게 되면 KHOpenAPI.ocx가 레지스트리에 등록됩니다. 그리고 그것을 사용해 Windows Forms 응용 프로그램을 구성하는 실습을 하게 되는데요. 혹시 이번에도 레지스트리 등록 없이,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Registry 등록 없이 COM 개체 사용 ; <a target='tab' href='https://www.sysnet.pe.kr/2/1/262'>https://www.sysnet.pe.kr/2/1/262</a> </pre> <br /> 파일 복사 만으로 실행할 수도 있지 않을까 싶어서 시도를 해봤습니다. ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이전에도 설명했지만,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Registry 등록 과정 없이 COM 개체 사용 - 두 번째 이야기 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/1167'>https://www.sysnet.pe.kr/2/0/1167</a> </pre> <br /> ocx 파일을 레지스트리에 등록하지 않으려면 이를 서술하는 manifest 파일이 있어야 합니다. 그리고 해당 파일에 기술할 정보는 oleview.exe를 이용하면 쉽게 구할 수 있습니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='khopenapi_regfree_1.png' src='/SysWebRes/bbs/khopenapi_regfree_1.png' /><br /> <br /> 이를 바탕으로 다음과 같은 2개의 manifest 파일을 만들 수 있고,<br /> <br /> [KHOpenAPI.ocx.manifest 파일]<br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;'> <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.1" processorArchitecture="x86" name="KHOpenAPI.ocx" type="win32"> </assemblyIdentity> <file name="KHOpenAPI.ocx"> <comClass clsid="{a1574a0d-6bfa-4bd7-9020-ded88711818d}" threadingModel="Apartment" tlbid="{6d8c2b4d-ef41-4750-8ad4-c299033833fb}" progid="KHOPENAPI.KHOpenAPICtrl.1" /> <typelib tlbid="{6d8c2b4d-ef41-4750-8ad4-c299033833fb}" version="1.2" helpdir="" resourceid="0" flags="CONTROL,HASDISKIMAGE" /> </file> <comInterfaceExternalProxyStub name="_DKHOpenAPI" iid="{CF20FBB6-EDD4-4BE5-A473-FEF91977DEB6}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}" baseInterface="{00000000-0000-0000-C000-000000000046}" tlbid="{6d8c2b4d-ef41-4750-8ad4-c299033833fb}"> </comInterfaceExternalProxyStub> </assembly> </pre> <br /> [WindowsFormsApp1.exe.manifest 파일]<br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <?xml version="1.0" encoding="utf-8"?> <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <requestedExecutionLevel level="asInvoker" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> </application> </compatibility> <dependency> <dependentAssembly asmv2:dependencyType="install" asmv2:codebase="KHOpenAPI.ocx.manifest" asmv2:size="1058"> <assemblyIdentity name="KHOpenAPI.ocx" version="1.0.0.1" processorArchitecture="x86" type="win32" /> </dependentAssembly> </dependency> </asmv1:assembly> </pre> <br /> 이 2개의 파일을 프로젝트에 추가 후 "Copy if newer" 옵션으로 설정합니다. 마지막으로 프로젝트 설정 창에서 Application / Resources 영역의 "Manifest" 값을 "Create application without a manifest"로 맞춘 후,<br /> <br /> <img alt='mage_command_line_6.png' src='/SysWebRes/bbs/mage_command_line_6.png' /><br /> <br /> 빌드하면 됩니다. 물론, "키움 Open API+ 모듈 다운로드"로 설치한 "OpenAPI" 폴더의 모든 파일을 Windows Forms EXE 파일이 있는 폴더에 그대로 복사해줘야 합니다. 이후부터는 해당 폴더를 원하는 PC에 그대로 XCopy(Robocopy) 배포를 하면 끝!<br /> <a name='sample_code'></a> <br /> 실제로 다음과 같이 로그인 테스트를 호출한 코드 실행 시,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.axKHOpenAPI1.OnEventConnect += AxKHOpenAPI1_OnEventConnect; } private void AxKHOpenAPI1_OnEventConnect(object sender, AxKHOpenAPILib._DKHOpenAPIEvents_OnEventConnectEvent e) { if (e.nErrCode != 0) { MessageBox.Show(e.nErrCode.ToString()); } else { string userId = axKHOpenAPI1.GetLoginInfo("USER_ID"); this.Text = userId; } } private void button1_Click(object sender, EventArgs e) { if (this.axKHOpenAPI1.CommConnect() < 0) { MessageBox.Show("Failed to call CommConnect API"); } } } } </pre> <br /> 이렇게 잘 실행되는 것을 확인할 수 있습니다.<br /> <br /> <img alt='khopenapi_regfree_2.png' src='/SysWebRes/bbs/khopenapi_regfree_2.png' /><br /> <br /> (<a target='tab' href='https://github.com/stjeong/reg_free_kiwoom_openapi'>이 글의 예제 코드는 github에 등록</a>해 두었으니 참고하세요.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 제가 증권 쪽 API는 처음 보는 것인데, 다소 Legacy스러운 면이 있더군요. 일례로 Unicode를 제대로 지원하지 않아 "Use Unicode UTF-8 for worldwide language support" 옵션이 설정된 윈도우에서는,<br /> <br /> <img alt='cmd_support_han_4.png' src='/SysWebRes/bbs/cmd_support_han_4.png' /><br /> <br /> 다음과 같이 KOA Studio 등의 UI 중 한글이 완전히 깨져나오는 문제가 있습니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='khopenapi_regfree_3.png' src='/SysWebRes/bbs/khopenapi_regfree_3.png' /><br /> <br /> 그래도 KOA Studio는 실행이라도 되지만, 영웅문 HTS 프로그램은 아예 실행 도중 비정상 종료를 해버립니다. 심지어 Open API를 사용하는 Windows Forms 응용 프로그램도 로그인하자마자 다음과 같은 이벤트 로그를 남기며,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Log Name: Application Source: .NET Runtime Date: 2020-01-27 오전 12:16:58 Event ID: 1026 Task Category: None Level: Error Keywords: Classic User: N/A Computer: TESTPC Description: Application: WindowsFormsApp1.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: exception code e06d7363, exception address 761F35D2 </pre> <br /> 비정상 종료를 합니다.<br /> <br /> 또 하나 Legacy스러운 면이 있다면 x86 32비트만 지원할 뿐 64비트는 지원하지 않는다는 것입니다. 그리고 꽤나 결정적인 문제점인데, 우리가 일반적으로 알고 있는 "Open API"라는 성격에는 맞지 않게 INITECH이나 AhnLab 모듈에 엮어있다는 점과 "로그인"을 하는 방식이 CommConnect 호출 후 별도 프로세스(opstarter.exe)에서 뜬 "로그인 창"을 반드시 거쳐야 한다는 점에서 "서비스화"된 응용 프로그램에서는 사용할 수 없다는 점입니다. (혹시, <a target='tab' href='https://www.sysnet.pe.kr/2/0/12134'>이런 제약이 없는 증권사의 OpenAPI</a>를 알고 계신 분은 덧글 부탁드립니다. ^^)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, OCX 컨트롤을 Windows Form에 둔 후 실행했을 때 "((System.ComponentModel.ISupportInitialize)(this.axKHOpenAPI1)).EndInit();" 코드에서 다음과 같은 오류가 발생한다면?<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > System.Runtime.InteropServices.COMException HResult=0x80040154 Message=Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)) Source=System.Windows.Forms StackTrace: at System.Windows.Forms.UnsafeNativeMethods.CoCreateInstance(Guid& clsid, Object punkOuter, Int32 context, Guid& iid) at System.Windows.Forms.AxHost.CreateWithLicense(String license, Guid clsid) at System.Windows.Forms.AxHost.CreateInstanceCore(Guid clsid) at System.Windows.Forms.AxHost.CreateInstance() at System.Windows.Forms.AxHost.GetOcxCreate() at System.Windows.Forms.AxHost.TransitionUpTo(Int32 state) at System.Windows.Forms.AxHost.CreateHandle() at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) at System.Windows.Forms.AxHost.EndInit() at WindowsFormsApp1.Form1.InitializeComponent() in c:\temp\WindowsFormsApp1\WindowsFormsApp1\Form1.Designer.cs:line 53 at WindowsFormsApp1.Form1..ctor() in c:\temp\WindowsFormsApp1\WindowsFormsApp1\Form1.cs:line 16 at WindowsFormsApp1.Program.Main() in c:\temp\WindowsFormsApp1\WindowsFormsApp1\Program.cs:line 18 </pre> <br /> 또는 디버그 없이 실행했다면 이벤트 로그에 이런 오류가 남을 수 있는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Log Name: Application Source: .NET Runtime Date: 1/26/2020 8:15:45 PM Event ID: 1026 Task Category: None Level: Error Keywords: Classic User: N/A Computer: TESTPC Description: Application: WindowsFormsApp1.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.Runtime.InteropServices.COMException at System.Windows.Forms.UnsafeNativeMethods.CoCreateInstance(System.Guid ByRef, System.Object, Int32, System.Guid ByRef) at System.Windows.Forms.AxHost.CreateWithLicense(System.String, System.Guid) at System.Windows.Forms.AxHost.CreateInstanceCore(System.Guid) at System.Windows.Forms.AxHost.CreateInstance() at System.Windows.Forms.AxHost.GetOcxCreate() at System.Windows.Forms.AxHost.TransitionUpTo(Int32) at System.Windows.Forms.AxHost.CreateHandle() at System.Windows.Forms.Control.CreateControl(Boolean) at System.Windows.Forms.Control.CreateControl(Boolean) at System.Windows.Forms.AxHost.EndInit() at WindowsFormsApp1.Form1.InitializeComponent() at WindowsFormsApp1.Form1..ctor() at WindowsFormsApp1.Program.Main() </pre> <br /> Windows Forms 프로젝트의 출력을 "Any CPU" 또는 "x64"로 한 경우입니다. 즉, (위에서도 언급했지만) "키움 Open API+"는 64비트 환경을 지원하지 않으므로 명시적으로 "x86"으로 설정하고 빌드해야 합니다.<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1446
(왼쪽의 숫자를 입력해야 합니다.)