성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
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'>OpenTabletDriver를 (관리자 권한으로 실행하지 않고도) 관리자 권한의 프로그램에서 동작하게 만드는 방법</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;' > (WACOM도 지원하는) Tablet 공통 디바이스 드라이버 - OpenTabletDriver ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12632'>https://www.sysnet.pe.kr/2/0/12632</a> </pre> <br /> OpenTabletDriver 프로그램이 관리자 권한의 프로그램이 실행됐을 때는, 즉 UAC 권한 상승 창이 뜨는 프로그램에서는 태블릿 입력이 안 된다는 문제를 설명했고 그것의 원인이 UIPI(User Interface Privilege Isolation) 제약이라고 했습니다. 그런데, 사실 이것은 UAC 권한 상승 창이 뜨지 않는 프로그램에서도 발생할 수 있습니다. 왜냐하면, 마이크로소프트의 경우 자사의 인증서로 서명해 특별 관리를 하는 프로그램에 한해 "UAC 권한 상승 창"이 뜨지 않으면서도 관리자 권한을 갖는 프로그램들을 제공하기 때문입니다. 대표적으로 "작업 관리자(Task Manager)"를 비롯해 각종 MMC(Microsoft Management Console) 기반의 관리 프로그램들이 그것입니다.<br /> <br /> 따라서, OpenTabletDriver을 관리자 권한으로 실행하지 않으면 여간 불편한 것이 아닙니다.<br /> <br /> 그래도 그나마 희망이 있다면, 마이크로소프트가 일반 권한의 프로그램에서도 UIPI 제약을 벗어날 수 있는 방법을 제공하고 있으며 이에 대해서는 아래의 글에서 이미 자세하게 설명했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > UAC - 관리자 권한 없이 UIPI 제약을 없애는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12633'>https://www.sysnet.pe.kr/2/0/12633</a> </pre> <br /> OpenTabletDriver에 저 방법을 적용하기 위한 가장 큰 장애물은 바로 app.manifest에 대한 처리입니다. 이 파일은 응용 프로그램 빌드 단계에서 제공되어야 하기 때문에 반드시 소스 코드를 빌드할 수 있는 사람만이 이것을 처리할 수 있습니다.<br /> <br /> 따라서, 원래는 OpenTabletDriver 프로그램을 배포하는 사람에게 저 작업을 부탁해야 하는데요, 다행히 OpenTabletDriver는 Open Source로 공개된 것이기에,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > OpenTabletDriver/OpenTabletDriver ; <a target='tab' href='https://github.com/OpenTabletDriver/OpenTabletDriver'>https://github.com/OpenTabletDriver/OpenTabletDriver</a> </pre> <br /> 우리도 저것을 git clone해서 직접 빌드하는 식으로 처리하면 됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 자, 그럼 단계별로 한 번 해볼까요? ^^<br /> <br /> 당연히 git clone을 해 소스 코드를 다운로드하고,<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> <span style='color: blue; font-weight: bold'>git clone https://github.com/OpenTabletDriver/OpenTabletDriver.git</span> </pre> <br /> 비주얼 스튜디오로 로드해 전체 빌드를 합니다. (경고 하나 없이 아주 깨끗하게 빌드가 됩니다. ^^)<br /> <br /> 그다음, .\OpenTabletDriver\Configurations 디렉터리를 .\OpenTabletDriver.Daemon\bin\Debug 하위에 모두 복사합니다. (또는, 자신에게 해당하는 태블릿 설정이 있는 파일과 그것의 부모 디렉터리 구조만 복사해도 됩니다.)<br /> <br /> 이후 OpenTabletDriver.Daemon.exe를 실행하면 다음과 같은 출력이 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [Detect:Info] Searching for tablet 'Wacom CTL-460' [Detect:Debug] Using device 'CTL-460'. [Detect:Debug] Using report parser type 'OpenTabletDriver.Tablet.TabletReportParser'. [Detect:Debug] Device path: \\?\hid#vid_056a&pid_00d4&mi_00&col02#7&131af743&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030} [Device:Debug] Set tablet feature: 02-02 [Detect:Info] Found tablet 'Wacom CTL-460' [Detect:Warning] Failed to find auxiliary device, express keys may be unavailable. [Display:Debug] DPI Awareness enabled [Settings:Info] Output mode: Absolute Mode [Settings:Info] Display area: [5760x1080@<2880, 540>:0°], [Settings:Info] Tablet area: [147.2x92@<73.6, 46>:180°], [Settings:Info] Clipping: Enabled [Settings:Info] Ignoring reports outside area: Disabled [Settings:Info] Tip Binding: [Mouse Button Binding: Left]@1% [Settings:Info] Eraser Binding: []@0% [Settings:Info] Pen Bindings: [0, Mouse Button Binding: Left], [1, Mouse Button Binding: Right] [Settings:Info] Express Key Bindings: [0, ], [1, ], [2, ], [3, ], [4, ], [5, ], [6, ], [7, ] [Settings:Info] Driver is auto-enabled. </pre> <br /> 이렇게 Daemon을 실행해 둔 상태에서 ".\OpenTabletDriver.UX.Wpf\bin\Debug\OpenTabletDriver.UX.Wpf.exe" 프로그램을 실행하면 됩니다. 이후, 설정을 하고 플러그인도 설치를 한 후 설정값을 저장하고 종료합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 프로젝트를 빌드해 보고 알았지만, 사실상 사용자 모드 device driver를 설치하는 작업은 OpenTabletDriver.Daemon.exe 프로세스입니다. 따라서 그것만 실행해도 됩니다. OpenTabletDriver.UX.Wpf.exe는 단지 User Interface를 제공해 플러그인을 설치하거나 값을 설정할 수 있는 편의 환경만 제공하는데 의미가 있습니다.<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;' > UAC - 관리자 권한 없이 UIPI 제약을 없애는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12633'>https://www.sysnet.pe.kr/2/0/12633</a> </pre> <br /> <ol> <li><a target='tab' href='https://www.sysnet.pe.kr/2/0/11318'>"Application Manifest File" 파일 추가</a> 후, uiAccess를 true로 설정</li> <li><a target='tab' href='https://www.sysnet.pe.kr/2/0/12588'>인증서 생성(하고 로컬에 등록) </a> 및 EXE 파일 서명</li> <li>C:\Program Files\OpenTabletDriver 폴더를 생성하고 그 하위에 .\OpenTabletDriver.Daemon\bin\Debug 빌드 결과물 모두 복사</li> </ol> <br /> 작업들을 수행하면 됩니다. 그리고 그 작업은 OpenTabletDriver.Daemon 프로젝트에 대해서만 하면 되고, 모든 처리를 완료했으면 이제 OpenTabletDriver.Daemon.exe를 일반 권한으로 수행해도 작업 관리자 등의 프로그램에서 정상적으로 동작하는 것을 확인할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이렇게 일반 권한으로 수행해도 되기 때문에 <a target='tab' href='https://support.microsoft.com/en-us/windows/add-an-app-to-run-automatically-at-startup-in-windows-10-150da165-dcd9-7230-517b-cf3c295d89dd'>해당 프로그램의 단축 아이콘을 생성해 "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup" 폴더에 놓으면</a> 됩니다. 그럼 윈도우가 부팅되어 로그인했을 때 자연스럽게 "Autorun"이 되기 때문에 별다른 수작업을 하지 않아도 태블릿 사용을 할 수 있게 됩니다.<br /> <br /> 자, 그럼 지난 글에서 이야기했던 <a target='tab' href='https://www.sysnet.pe.kr/2/0/12632#cons'>불편한 점 3가지</a> 중 2번과 3번이 해결되었습니다. 그럼, 기왕에 소스 코드가 있으니 (최대 절전 모드에서 복원했을 때 태블릿이 동작을 하지 않는) 1번도 해결해 볼까요? ^^<br /> <br /> 방법은 간단하게, 윈도우 운영체제가 Resume되었을 때 다시 태블릿을 연결하도록 하면 되는데, 대충 분석을 해보면 OpenTabletDriver.Daemon 프로젝트의 DriverDaemon.cs 파일에 이런 식으로 코드를 추가하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // ...[생략]... public class DriverDaemon : IDriverDaemon { public DriverDaemon() { Log.Output += (sender, message) => { LogMessages.Add(message); Console.WriteLine(Log.GetStringFormat(message)); Message?.Invoke(sender, message); }; Driver.TabletChanged += (sender, tablet) => { TabletChanged?.Invoke(sender, tablet); if (debugging) { if (Driver.TabletReader != null) Driver.TabletReader.Report += DebugReportHandler; if (Driver.AuxReader != null) Driver.AuxReader.Report += DebugReportHandler; } }; Driver.DevicesChanged += async (sender, args) => { if (await GetTablet() == null && args.Additions.Count() > 0) await DetectTablets(); }; // Install-Package Microsoft.Win32.SystemEvents <span style='color: blue; font-weight: bold'>if (OperatingSystem.IsWindows() == true) { #pragma warning disable CA1416 // Validate platform compatibility SystemEvents.PowerModeChanged += async (object sender, PowerModeChangedEventArgs e) => { if (e.Mode == PowerModes.Resume) { await DetectTablets(); } }; #pragma warning restore CA1416 // Validate platform compatibility }</span> LoadUserSettings(); } // ...[생략]... } </pre> <br /> 이렇게 변경하고 다시 서명, "%ProgramFiles%\OpenTabletDriver"에 복사하면 끝! ^^<br /> <br /> 이걸로 모든 단점은 해결되었지만, 그래도 유일하게 고칠 수 없는 딱 한 가지가 있습니다. 바로, 윈도우의 그림 암호(Picture Password) 화면에서는 태블릿 인식이 안 된다는 점입니다. 어쩔 수 없습니다, 이게 꼭 필요하다면 OpenTabletDriver를 포기하고 태블릿 제조사와 함께 제공되는 device driver를 그대로 사용해야 합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, <a target='tab' href='https://github.com/OpenTabletDriver/OpenTabletDriver/releases/tag/v0.5.3.1'>0.5.3.1</a> 버전의 "<a target='tab' href='https://github.com/OpenTabletDriver/OpenTabletDriver/releases/download/v0.5.3.1/OpenTabletDriver.win-x64.zip'>OpenTabletDriver.win-x64.zip</a>" 파일의 압축을 해제한 Configurations 폴더의 json 파일 스키마가 현재(2021-04-23) Opentablet 솔루션에서는 바뀌었으므로 주의해야 합니다. 만약 github 프로젝트로 지난 버전의 json 파일을 로드하면 다음과 같은 식의 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Newtonsoft.Json.JsonSerializationException HResult=0x80131500 Message=Error converting value "AgI=" to type 'System.Collections.Generic.List`1[System.Byte[]]'. Path 'DigitizerIdentifiers[1].FeatureInitReport', line 43, position 33. Source=Newtonsoft.Json StackTrace: at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) This exception was originally thrown at this call stack: Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(object, System.Type, System.Type) Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(object, System.Globalization.CultureInfo, System.Type) Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(Newtonsoft.Json.JsonReader, object, System.Globalization.CultureInfo, Newtonsoft.Json.Serialization.JsonContract, System.Type) Inner Exception 1: ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List`1[System.Byte[]]. </pre> <br /> 오류가 발생한 json은,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > "VendorID": 1386, "ProductID": 212, "InputReportLength": 9, "OutputReportLength": null, "ReportParser": "OpenTabletDriver.Tablet.TabletReportParser", <span style='color: blue; font-weight: bold'>"FeatureInitReport": "AgI=",</span> "OutputInitReport": null, "DeviceStrings": {}, "InitializationStrings": []" </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;' > "VendorID": 1386, "ProductID": 212, "InputReportLength": 11, "OutputReportLength": null, "ReportParser": "OpenTabletDriver.Vendors.SkipByteTabletReportParser", <span style='color: blue; font-weight: bold'>"FeatureInitReport": [ "AgI=" ],</span> "OutputInitReport": null, "DeviceStrings": {}, "InitializationStrings": [] </pre> <br /> 이외에도 많은 것이 변경되었으므로 전체적으로 OpenTabletDriver.Daemon 프로그램의 초기화가 진행되지 않습니다. 또한, 0.5.3.1 버전의 Plugin 들과 현재 github 버전의 소스 코드는 호환이 안 되어서 OpenTabletDriver.Daemon.exe 실행 시에 다음과 같은 (경고라고 볼 수 없는) 오류 로그가 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [Plugin:Debug] Loading plugin 'HawkuFilters' [Plugin:Warning] Plugin 'HawkuFilters, Version=1.0.0.0' can't be loaded and is likely out of date. </pre> <br /> 메시지가 의미하는 바에 따라 HawkuFilters.dll을 (로드는 했으나) 타입 생성을 하지 못해 사용하지 않습니다. 정상적이라면 그냥 다음과 같이 로그가 나와야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [Plugin:Debug] Loading plugin 'HawkuFilters' [Detect:Info] Searching for tablet 'Wacom CTL-460' </pre> <br /> 따라서, 만약 <a target='tab' href='https://github.com/OpenTabletDriver/OpenTabletDriver/releases/tag/v0.5.3.1'>v0.5.3.1</a>의 Configurations 파일을 그대로 사용하고 싶다면 github의 소스 코드를 "v0.5.3.1"로 태그되어 있는 버전으로 돌려서 작업을 해야 합니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='opentabletdriver_uipi_1.png' src='/SysWebRes/bbs/opentabletdriver_uipi_1.png' /><br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1721
(왼쪽의 숫자를 입력해야 합니다.)