최근에 다단계 인증과 관련해서 Credential Provider를 확장해서 만들 일이 있어 급히 하나 만들어 봤다.

방법은 예전에 쓴 아래 글 참조.


>> 참조: Winlogon GINA/Credential Provider 커스터마이징



C++로 Credential Provider 기본 코드를 작성하고

다단계 인증의 세부 코드 및 UI는 쉽게 유지 보수가 가능한 C# DLL로 만들어 

WinForm으로 WebBrowser를 임베딩하여 실행하는 방식으로 만들었다.

(C++에서 C# DLL을 호출하는 방법은 역시 위 참조 글(7, 8번)에 기록되어 있다.)



그런데, Windows 10 64비트 OS를 기준으로 만들었더니

Windows 7 64비트 OS에서는 정상 동작하지 않는 문제가 있어 하나하나 확인하고 수정해야 했다.



Windows 10에서는 정상 동작하나 Windows 7에서는 오류가 발생한 대표적인 문제들은,



1. Advice()와 UnAdvice() 함수 호출이 전혀 다른 점

Windows 10에서는 로그인 화면에서 ID/Password를 입력할 때 Advice() 및 UnAdvice()가 최초 한번씩만 호출되었는데 Windows 7에서는 매번 커서를 누를 때마다 Advice() 및 UnAdvice() 두 함수가 계속 반복 호출되었다. 그래서 해당 함수들 내에 만들어 두었던 외부 DLL 로딩/언로딩 처리 부분을 다른 곳으로 옮겨야 했다. 결과적으로는 옮긴 곳이 더 적절한 위치인 것 같아... 잘 옮겼다는 생각.



2. System.Windows.Forms.Timer가 동작하지 않는 점

Windows 10에서와 달리 Windows 7에서는 Credential Provider에서 실행시킨 C# WinForm에서 System.Windows.Forms.Timer의 Tick 이벤트가 전혀 발생하지 않았다. Single Thread(STA) 환경에서만 동작한다는 얘기들이 인터넷에 많은 것으로 보아 아마 Credential Provider 실행 환경은 Multi Thread 환경이기 때문에 그런 것 같은데, 그럼 왜 Windows 10에서는 정상 실행되었을까?
Windows 10의 System.Windows.Forms.Timer 설계에 변경이 생긴 것일까? MTA에서도 동작하도록?


>> 참고: https://stackoverflow.com/questions/18327567/system-windows-forms-timer-not-firing



3. WebBrowser 컨트롤의 Navigate()가 먹통이 되는 점

Windows 10에서는 아무 문제없이 잘 됐는데 Windows 7에서는 WebBrowser 네비게이션이 아예 동작하지 않아서 도대체 무엇이 문제인지 찾아 봤더니 Windows 7 64비트 OS의 DEP(Data Execution Prevention) 관련 문제라는 글들이 많이 보였고, AnyCPU가 아닌 32비트로 컴파일하면 해결된다는 얘기도 있었지만 그럴 수 없는 환경이었기 때문에 시도해보진 못했다. 64비트에서도 완벽하게 동작하는 방식이어야 했기 때문이다.


>> 참고: https://social.msdn.microsoft.com/Forums/windows/en-US/5ff0030b-12be-42d1-abf5-d74b6f18abf3/webbrowser-control-svg-and-windows-7?forum=winforms

대신, 아예 WebBrowser 컨트롤로 웹 화면을 보여주던 방식을 없애 버리고, 별도 Web API를 호출하여 원하는 값(이미지)을 얻어와 화면상에 이미지로 표현하는 방식으로 대수술을 해야 했다. (말은 쉽지... 털썩.)



4. System.Timers.Timer에서 WinForm의 InvokeRequired가 항상 true인 점

Multithread 환경이지만 매초마다 ProgressBar를 움직이게 하기 위해서는 어쨌든 Timer를 사용해야 했기 때문에 System.Windows.Forms.Timer 대신 궁여지책으로 사용한 것이 System.Timers.Timer였는데, 희한하게도 ProgressBar를 업데이트하기 위해 InvokeRequired를 체크하면 늘 항상 true로 결과가 리턴되었다. 어째서지? 하면서 System.Threading.Timer로 바꿔보기도 하고 public method로 바꾸어 외부에서 호출해 보기도 하는 등 며칠간 별의 별 짓을 다 해봤지만 해결이 안되었다.


결론은, InvokeRequired를 체크하지 않고 그냥 실행하면 되는 것이었다.


>> 참고: https://www.codeproject.com/Questions/616034/how-to-use-System-Timers-Timer-to-control-a-progre



헐... 한 마디로 삽질... 며칠 간 삽질만 했다. 미친 척 하고 그냥 한번 실행해 보면 됐을텐데...


그런데, 아직도 왜 그냥 호출하면 되는지 당최 이유를 모르겠다. 

InvokeRequired 상태니까 그냥은 정상 업데이트 동작이 안돼야 하는데 말이다. 대체 왜 되는 걸까?




결국, Windows 7 버전은 겉보기에는 똑같지만 내부 코드는 완전히 다른 별도 버전이 되고 말았다.
이것 참.




Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]