반응형
처음에 이 기사를 읽고 있다는 것은 당신은 우선 틀림없이 Windows 소프트웨어 개발자군요.그리고 당신은 분명 소프트웨어를 쓰고 싶다는 강한 열정에 힘입어 소프트웨어를 쓰고 있겠지요.제가 하루 종일 코딩에 몰두하고 있는 것은 오직 코딩을 좋아하기 때문입니다.아마 이와 비슷하게 느끼고 있는 사람은 많은 것이 아닐까요.하루하루를 이렇게 즐겁게 보낼 방법이 또 있을까요?하지만 그것이야말로 함정입니다.잠시 멈춰 서서 소프트웨어를 쓰는 것의 경제적 측면을 생각해 보세요.우리는 이 일을 좋아서 하고 있지만, 먹이지 않으면 안 되는 가족이나 지불하지 않으면 안 되는 청구서도 있고, 때로는 휴일에 나가거나 하고 싶은 것이 본심일 것입니다.이것은 편향된 시각이 아니라, 우리의 소프트웨어를 사용하고 있는 사람도, 자신의 일에 관해서 똑같이 생각하고 있을 것이라고 생각됩니다.아무리 일을 좋아하고 그 일을 하지 않고는 못 배길지라도 일을 하면 그 노고가 보상되기를 바라고 있습니다.문제는 소프트웨어라는 제품은 최종 사용자 측에서 볼 때 매우 막연하다는 점입니다.그들이 볼 수 있는 것은 응용 프로그램 본체뿐이며, 그것도 컴퓨터 메모리에 전기가 통하는 아주 작은 시간뿐입니다.몇백시간이나 몇천시간에 걸쳐 개발이나 테스트를 한 제품처럼 보이지는 않으며 적어도 자동차나 냉장고 같은 물체와 물리적으로 비교할 수 있는 것은 아닙니다.솔직히 말하면 자동차나 냉장고를 훔치자고 생각한 적도 없는 부지런한 컴퓨터 사용자 중에도 소프트웨어를 친구와 빌려주는 것에 대해 아무런 거부감을 느끼지 못하는 사람이 많이 있고, 때로는 소프트웨어 부속의 사용허락계약을 위반한다는 것을 알면서도 대차행위를 하는 사람도 있습니다.소프트웨어는 CD상의 단지 비트에 불과하지 않습니까? 그런 소프트웨어를 형제나 친구에게 빌려주면서 도대체 뭐가 나쁘다는 걸까요?당신은 이 질문에 대한 답을 잘 아시잖아요! 그러한 사용자는 당신의 가혹한 노동에 대가를 치르지 않은 사람입니다.비즈니스 용어로 말하면, 당신은 그에 상응하는 수입을 올리지 못했다는 것을 의미합니다.충분한 수입을 얻지 못하면, 회사와 마찬가지로 당신도 파산할 수 밖에 없습니다.개인 레벨의 이야기로 말하면, 당신은 금융상의 의무(즉 지불해야 할 청구서)를 수행할 수 없게 되므로, 어딘가의 패스트 푸드 체인에서 일해서 어떻게든 지불 기일을 맞추거나, 파산 선고를 하고, 고속도로 아래에서 골판지 생활을 하게 됩니다.저는 그렇게 되는 건 질색이에요.그래서 사용자에는 어플리케이션의 대가와 제가 소프트웨어 설계, 개발, 테스트, 마케팅, 배포에 들인 노동에 대한 정당한 대가를 지불하는 것을 요구하고 싶습니다.이를 위한 유력한 해결책은 소프트웨어 라이선스입니다.소프트웨어 업계에서는 이 문제를 해결하기 위한 다양한 방법이 시도되어 왔습니다.이전의 소프트웨어는, 불법 카피 방지 장치가 설치된 미디어에서 판매되고 있었습니다(추가 트럭 첨부의 플로피 디스크를 기억하시는 분도 있을 것입니다).최근에는 어떤 소프트웨어 키를 입력해야 소프트웨어 패키지를 사용할 수 있는 방식이 많이 사용되고 있습니다.Microsoft는 고급 운영체제와 애플리케이션 제품(Office 등)에 관해서는 인터넷 기반의 온라인 인증을 도입했습니다.(Office는 아마도 지금까지 가장 많이 불법 복사가 이루어진 제품입니다).NET Framework에는 당신이 작성한 애플리케이션에 라이센스 기능을 넣기 위한 유용한 기술이 포함되어 있습니다.본고에서는 이 기술에 대해 소개합니다.라이선스 제어 당신이 지금까지 읽은 .NET 라이선스 관련 자료에서는 대부분의 경우, 라이선스 개념을 컨트롤과 연결시키지 않았습니까.즉, 컨트롤 개발자가 디자인 시 또는 실행 시 라이센스 기능을 컨트롤에 포함해서 배포하는 케이스입니다.이 경우에는 System.Windows.Forms.Control에서 파생된 어떤 클래스에 대해서도 Framework 라이센스를 적용할 수 있습니다.여기에는 Windows Forms 어플리케이션도 포함이 되는데 우선은 컨트롤에 대해서 다루도록 하겠습니다.그림 1은 기본적인 라이센스 제어 구조를 UML 의 정적 클래스 그림으로 나타낸 것입니다.그림2는 전체적인 실행 시퀀스를 나타내는 UML 시퀀스 그림입니다.라이선스가 있는 컨트롤은 컨스트럭터 안에서 License Manager에 라이선스를 요구합니다.license = License Manager. Validate (type of (My Licensed Control), this); 이 경우 라이센스부 컨트롤의 컨스트럭터는 My Licensed Control 클래스 내에서 구현됩니다.라이선스 오브젝트 자체에 대해서는 리소스가 터치되어 있을 때 그것을 적절히 처리한다는 점을 제외하고는 특별히 할 일이 없습니다(라이선스 구현에 의존합니다). 필요한 것은 라이선스 매니저를 호출해 라이선스를 요구하는 것뿐입니다.어떠한 이유로 라이선스가 허가되지 않았을 때는 Validate() 호출이 실패하여 예외가 생성되거나(예외가 필요한 경우) null 라이선스가 반환됩니다(예외를 억제하는 경우).어느 쪽이 될지는 LicenseProvider.GetLicense() 호출에 의해서 제어되지만 기본 Framework 구현에서는 예외가 생성됩니다.호출된 라이센스 매니저는 컨트롤의 라이센스 프로바이더의 Get License() 메서드를 호출합니다.그러면 .NET Framework 컴포넌트인 라이선스 매니저는 사용하는 라이선스 프로바이더를 어떻게 인식하게 될까요?실은, 라이센스 프로바이더를 지정하는 것은 개발자입니다. .NET의 종래적인 방법에 따라 속성이라는 메타데이터를 통해서 라이센스 프로바이더를 지정합니다. [License Provider(type of (My License Provider)]
public class MyLicensedControl : System . Windows . Forms . Control
{
...
} 라이센스 매니저는 라이센스 포함 컨트롤 클래스에 터치되어 있는 License Provider 속성을 찾습니다.License Provider 속성은 라이센스 프로바이더의 형을 컨스트럭터에 입력하는 것으로 받아들이기 때문에 라이센스 검증이 요구될 때 이 정보를 사용할 수 있습니다.라이센스 프로바이더는 License Provider 클래스에서 파생시켜야 하며 추상 메서드(Visual Basic으로 말하면 Must Override)의 Get License()를 오버라이드해야 합니다.public class MyLicenseProvider :
System . ComponentModel . LicenseProvider
{
...
public override License GetLicense (
LicenseContext context ,
Type type ,
object instance ,
bool allowExceptions )
{
...
}
}.NET에서의 라이센스 제어는 이상과 같은 흐름입니다만, 결국, 실제 라이센스 제어를 실시하고 있는 것은 GetLicense() 메서드입니다.독자들에게 불필요한 수고를 끼치지 않기 위해서 미리 알려드리자면, 사실 Framework에는 Lic File License Provider라고 하는 기본적인 라이센스 프로바이더가 준비되어 있습니다.완벽을 기하기 위해서는 여기서 Lic File License Provider 사용법을 설명해야 하는데, 자작 소프트웨어에 라이선스 기능을 넣으려고 진심으로 생각하는 사람이라면 아마 이런 단순한 방식보다는 좀 더 창의적인 방식을 사용하고 싶을 것입니다.따라서 Lic File License Provider에 대한 설명 후에 그러한 세련된 방식에 대해서도 알아보겠습니다.Lic File License Provider Lic File License Provider의 기능은 극히 간단합니다.라이센스 파일의 유무를 조사해 파일이 존재하는 경우는, 파일의 내용을 확인해 라이센스를 검증합니다.라이센스 파일은, 애플리케이션과 함께 디스크상에 보존되고 있는 경우도 있는가 하면, 앱 소스로서 인코딩되고 있는 경우도 있습니다(그 경우는 정보를 꺼내기 위한 추가 코드가 필요하게 됩니다).라이선스 파일이 존재하고 유효한 정보가 기록되어 있는 경우 이 라이선스 프로바이더가 라이선스 매니저에 라이선스를 발급하여 최종적으로 컨트롤에 라이선스를 허용합니다.그 이외의 경우에는 라이센스 프로바이더가 icense Exception을 느리게 하여 컨트롤은 사용할 수 없게 됩니다.Lic File License Provider는 Get License()를 오버라이드할 뿐만 아니라(오버라이드 필수), Is Key Valid()와 Get Key()라고 하는 추가 가상 메서드를 제공합니다.Lic File License Provider를 Framework의 구현대로 사용할 경우, GetKey() 메서드는 어셈블리의 실행 디렉토리 내에서 ′{full name}.lic′이라는 이름의 파일을 찾습니다.{full name}은 라이센스 컨트롤 클래스의 완전 유형명을 나타내며, 일반적으로 ′{assembly예를 들어 지금까지의 예에서 사용해 온 라이센스 부 컨트롤을 어셈블리 My Control Assembly가 공개하는 경우는 라이센스 파일의 이름은 다음과 같습니다.MyControlAssembly.MyLicensedControl.lic이 파일의 내용을 취득하면 IsKeyValid() 메서드는 그것을 문자열 「{licensedclass} is a licensed component.(온점을 포함)와 비교합니다.방금 전 예를 들자면, ′My Control Assembly.My Licensed Control.lic′ 파일에는 문자열 ′My Control Assembly.My Licensed Control is a licensed component.′가 포함되어 있을 것입니다.라이센스 파일이 없거나 파일 내용이 올바르지 않으면 라이센스 검증이 실패하며 컨트롤의 인스턴스화가 실패합니다.다운로드 샘플로서 MSDN의 샘플색 선택 콤보 박스 컨트롤에 라이센스 기능을 추가한 것을 준비했으므로, 그쪽도 참조해 주세요(기사 상부에서 다운로드할 수 있습니다).IsKeyValid()와 GetKey()는 가상 메서드이기 때문에 어딘가 다른 곳에서 라이센스 파일을 찾거나 다른 문자열(암호화된 문자열, 단순히 다른 문구를 사용하는 문자열 등)과 비교하거나 하는 새로운 클래스를 쉽게 파생할 수 있습니다.그러나, 아무리 좋은 실장이라고 해도, 기본적으로 라이센스 파일을 사용하고 있는 것에는 변함이 없습니다.기저 클래스가 그 기능을 제공하고 있기 때문입니다.이와는 전혀 다른 라이센스 방식을 구현하고 싶다면 License Provider에서 직접 라이센스 프로바이더를 파생시키는 것이 좋습니다.스스로 생각해 보는 편이 몸에 배기 쉬울 것 같아서 여기에서는 파생된 라이센스 파일 프로바이더의 예를 제시하지 않겠습니다.그 대신 다른 라이선스 방식을 몇 가지 소개해 드리도록 하겠습니다.라이선스 파일의 컴파일 라이선스 파일 이야기를 마치기 전에 lc.exe에 대해 언급하겠습니다.′lc.exe′ 는 .NET Framework 부속 라이센스 컴파일러로 라이센스 파일 정보를 취득하고 어셈블리 리소스로 인코딩하는 툴입니다.이 툴이 Framework에 부속되어 있는 건 좀 이상하지만(기본 구현인 LicFileLicense Provider는 리소스 기반의 라이센스 파일을 참조하지 않기 때문에), 이 툴은 재미있는 기능이 몇 개 있습니다.하나는 리소스 정보를 쉽게 생성할 수 있는데, 더 흥미로운 것은 여러 라이센스 파일을 하나의 리소스로 인코딩할 수 있다는 것입니다.이로 인해, 각각 다른 라이센스 파일 문자열을 가지는 여러 컨트롤의 라이센스 검증을 한 번에 실시할 수 있게 됩니다.단, 이 툴에는 큰 제약이 있습니다.그것은 컴파일한 모듈과 리소스를 어셈블하는데 어셈블링커(al.exe)를 사용해야 한다는 점입니다.명령줄 파의 사람에게는 문제가 없겠지만 우리와 같이 Visual Studio.NET을 사용하는 개발자에게는 큰 제약입니다. 왜냐하면 Visual Studio.NET에서는 멀티 모듈 어셈블리를 컴파일하거나 생성할 수 없기 때문입니다.(단 빌드 액션을 ′메워진 리소스′로 하면 리소스 출력을 프로젝트 파일에 포함시킬 수 있습니다.)여기에서는 Visual Studio .NET를 다루었습니다만, 어떤 버전의 Visual Studio(2002 또는 2003)에서도 라이센스부 컨트롤을 작성하기 위한 자동 지원은 없습니다.그럼 라이센스 포함 컨트롤을 작성하기 위해서는 어떻게 하면 좋은 것일까요.답변은 단순히 수동으로 라이센스 파일을 만들고 컴파일된 어셈블리와 함께 배포하는 것입니다.저는 항상 빌드 액션을 ′없음′으로 설정하고 라이선스 파일을 Visual Studio 프로젝트에 추가하는데, 이는 필수가 아닙니다.이렇게 하면 라이센스 파일이 다른 프로젝트/솔루션 파일과 함께 소스 저장소로 정리되므로 소스 코드 관리가 좀 쉬워지는 것 뿐입니다.계속해서 이 파일을 어셈블리의 실행 디렉토리에 수동으로 복사해야 합니다.다른 라이센스 방식 내가 봤을 때 Microsoft는 .NET Framework용 기본 라이센스 프로바이더를 준비해야 하기 때문에 ActiveX 컨트롤의 라이센스 기능과 매우 유사한 기능을 하는 라이센스 프로바이더를 구현한 것이 아닐까요.그러나 그와 동시에 Microsoft는 이러한 단순한 라이센스 방식을 자신들의 제품 소프트웨어에 사용할 생각은 없었던 것이 아닌가 하는 생각도 듭니다(적어도 중요한 것에 대해서는 그럴 의사가 없었을 것입니다).기본 방식을 사용하는 대신 보다 배포하기 쉽고, 현명하고, 뒤지기 어려우며, 무엇에나 사용할 수 있는 라이선스 방식을 작성해 보시면 어떨까요?그래서 또 다른 라이선스 방식을 생각해 보도록 하겠습니다.독자적인 방식을 사용하면, 자작의 컨트롤에 어떤 기능의 라이센스라도 짜 넣을 수 있습니다.예를 들어, 화요일에만 디자인 환경에서 사용할 수 있는 컨트롤이나 사용자 지역 일기예보가 ′맑음′일 경우에만 응용 프로그램 내에서 실행할 수 있는 컨트롤(사용자 주소의 우편번호를 취득하여 인터넷에서 해당 지역의 일기예보를 다운로드함) 등을 생각할 수 있습니다.이건 농담이 아니라 정말 이런 일이 가능한 겁니다.그렇게 할 필연성은 없지만, 그런 처리를 할 수 있을 정도로 유연한 라이센스 방식이라는 것입니다.이후로는 좀 더 현실적인 방법으로 레지스트리 라이센스 키를 사용하는 라이센스 방식을 소개합니다.하지만이방식에대해서자세히설명하기전에한가지주의해야할것이있어요.그것은, 이라는 것입니다.이게 대체 무슨 뜻일까요?이것은 즉, 어플리케이션 전체에 대해서도 컨트롤과 같은 방법으로 간단하게 라이센스 기능을 추가할 수 있다는 것입니다.지금부터 소개하는 방식은 컨트롤의 라이선스가 아니라 어플리케이션의 라이선스를 대상으로 하고 있습니다만, 실제로는 어느 쪽에도 적용할 수 있습니다.그럼 구체적인 설명으로 넘어가기 전에 배경 사정을 좀 더 설명해 둡시다.애플리케이션 라이선스와 컨트롤 라이선스의 기본적인 차이점은 라이선스를 언제 검증하느냐입니다.당신이 컨트롤이나 컴포넌트를 개발하여 생계를 유지하고 있다면, 타깃 시장은 다른 어플리케이션 개발자입니다.따라서 귀하 컨트롤의 라이선스는 컨트롤이 디자인 시에 Visual Studio 프로젝트에 삽입되었을 때 검증을 실시합니다.자체제작 컨트롤 라이브러리를 수백만 개씩 팔고 싶다면 실행 시 라이선스를 무료로 제공하거나 실행 시 라이선스를 일체 부과하지 않는 것이 일반적입니다.대국적으로 보면 타깃 시장의 어플리케이션 개발자는 어플리케이션을 계속 사용하도록 할 필요가 있습니다.그렇게 하면 그들은 더 많은 컨트롤을 당신에게서 사 줄 것이기 때문입니다.하지만 어플리케이션 라이선스의 경우는 이야기가 다릅니다.당신이 응용 프로그램을 개발할 때는 당신이 디자인할 때 응용 프로그램을 빌드합니다.따라서 디자인 시 라이선스를 자신에게 부과해도 의미가 없습니다.그 대신 사용자가 실행 시 적절한 라이선스 정보를 가지고 있는지 확인해야 합니다.Framework의 라이센스 아키텍처는 이 점을 고려한 설계로 Get License() 메서드를 호출했을 때 라이센스 요구 상태가 디자인인지 실행인지를 확인할 수 있습니다.이후 두 케이스 모두 소개하겠습니다만, 이번 예에서는 컨트롤의 라이선스 기능이 아니라 어플리케이션 전체의 라이선스 기능을 구현하는 방법을 다루고 싶기 때문에 실행 시에만 라이선스 검증을 하도록 하겠습니다.무엇보다, 이것은 중요한 차이이기 때문에 확실히 의식할 필요가 있습니다.레지스트리 베이스의 라이센스에서는, 특정의 값을 포함한 레지스트리 키의 유무를 조사한다고 하는 라이센스 방식을 실장합니다.애플리케이션 본체에는, 레지스트리치를 쓰기 위한 코드를 실장하지 않습니다.이 처리는 인스톨 프로그램에서 실시하도록 합니다.대부분의 어플리케이션은 어떤 형태로든 레지스트리를 사용하고 있기 때문에 개발에 큰 제한이 가해지지는 않습니다.저도 레지스트리의 등장 이후는, 인스톨 프로그램으로 레지스트리 키를 쓰도록 하고 있습니다.정말이라면 조금 더 스마트한 방법으로 레지스트리에 값을 쓸 수도 있는데, 이 예에서는 단순히 문자열 Installed를 쓰도록 하겠습니다.좀 더 세련된 구현방법에 대해서는 꼭 스스로 생각해 보시기 바랍니다(저도 속셈을 모두 밝힐 수는 없으니까요.여기에서는 다음과 같은 값을 찾습니다.HKEY_CURENT_USERSoftwareAcmeHostKeysde915e1-df71-3443-9f4d-32259ced2 여기서 제시된 GUID 값은 제가 제 응용 프로그램에 할당한 GUID입니다.Acme Software가 판매하고 있는 어플리케이션들은 각각 독자적인 GUID를 가지고 있습니다만, 저는 여러가지 고려한 결과 모든 어플리케이션에 동일한 라이센스 프로바이더를 사용하고 있습니다. .NET의 기능을 이용하여 모든 Acme Software 라이센스 키를 여기에 넣고 있기 때문에 키이름이 Host Keys 라고 되어 있습니다.당신의 어플리케이션에서는 적절한 곳으로 키를 이동시키세요.이 애플리케이션은 매우 단순합니다(그림 3을 참조).이 창이 뜨면 라이선스가 유효합니다.라이센스가 무효인 경우는, 그림 4와 같은 예외 다이얼로그 박스가 표시됩니다.이를 기능시키려면 새 응용 프로그램을 만들고 마법사를 통한 자동 생성 코드를 약간 수정해야 합니다.먼저 양해를 구합니다만, 여기서 Visual Basic 프로그래머를 따돌릴 생각은 없습니다.샘플 파일에는 똑같은 C#.NET 어플리케이션과 Visual Basic.NET 어플리케이션이 포함되어 있습니다.여기서 소개하고 있는 코드는 C#입니다만, Visual Basic 프로그래머에서도 대강은 간단하게 이해할 수 있을 것입니다.우선 메인 어플리케이션의 소스코드를 4군데 수정하고, 자체 라이센스 프로바이더를 기술해야 합니다.수정하는 4개소란 다음과 같습니다.응용 프로그램 클래스 선언(속성 몇 개 추가)
응용 프로그램 클래스의 컨스트럭터
응용 프로그램의 Dispose() 메서드
어플리케이션의 Main() 메서드 Guid Attribute를 사용하기 때문에 using구도 추가합니다.그럼 먼저 클래스 선언부터 알아보겠습니다.///
/// Summary description for frmMain .
/// < / summary >
[ GuidAttribute ( ′ 2de915e1 - df71 - 3443 - 9f4d - 32259c92 ced 2 ′ ) ]
[ LicenseProvider ( typeof ( RegistryLicenseProvider )) ]
public class frmMain : System . Windows . Forms . Form
{
...
}}이 클래스에 Guid Attribute 와 License Provider 라고 하는 속성을 추가했습니다.License Provider에 대해서는 앞에서 설명한 바와 같습니다.GuidAttribute의 목적은 이 애플리케이션 클래스에 GUID 또는 일의 수치를 할당하는 것입니다.이 속성은 보통 COM 상호운용기능을 위해 사용되는데, 여기에서는 기존 Framework 지원이 가지고 있는 단일 수치식별자를 응용프로그램 클래스에 할당하기 위해 재사용하고 있습니다(이를 통해 클래스 유형의 GUID를 나중에 쉽게 알아낼 수 있습니다).자체 속성을 생성할 수도 있는데, 그렇게 되면 Framework 내장형 GUID 검출 지원을 사용할 수 없게 됩니다.또한 GuidAttribute에 할당한 GUID 값이 레지스트리 키로 사용한 GUID 값과 일치하는 것에 주목하십시오.라이센스 프로바이더는 이 값을 반영하여 응용 프로그램의 레지스트리 라이센스 키 값을 생성합니다.여기서 GuidAttribute를 사용하기 때문에 이름공간 목록에 다음 행을 추가해 두어야 합니다. usingSystem.Runtime.Interop Services; 응용프로그램 클래스의 컨스트럭터에는 앞서 말한 코드를 추가합니다.private License _ license = null ;
public frmMain ( )
{
//
// Required for Windows Form Designer support
//
InitializeComponent ( ) ;
// Obtain the license
_ license = LicenseManager . Validate ( typeof ( frmMain ) , this ) ;
}}여기서는 라이센스 매니저의 Validate() 메서드를 호출하고 있을 뿐 특별한 것은 아무것도 하고 있지 않습니다.그러나 이 Validate() 메서드는 라이선스가 비활성화되면 예외를 슬로 할 수 있습니다.그래서 이 예외를 어딘가에서 파악해야 합니다.여기에 _license라고 하는 프라이빗 데이터 멤버를 추가하고 있다, 주목해 주시기 바랍니다.라이센스 방식에 따라서는 이 라이센스 오브젝트를 사용할 수도 있습니다만(이 예에서는 사용하지 않습니다), 어떤 경우에라도 어플리케이션의 종료시에 그 라이센스를 파기할 필요가 있습니다.이 때 라이선스에 할당되어 있는 자원을 적절하게 해방시켜야 하는 경우가 있습니다.그래서 응용 프로그램의 Dispose() 메서드를 다음과 같이 수정합니다.///
/// Clean up any resources being used .
/// < / summary >
protected override void Dispose ( bool disposing )
{
if ( disposing )
{
if ( components ! = null )
{
components . Dispose ( ) ;
}
if ( license ! = null )
{
license . Dispose ( ) ;
license = null ;
}
}
base . Dispose ( disposing );
}}여기서는 null 라이센스 여부를 확인하며, null이 아닐 경우 Dispose() 메서드를 호출하여 참조를 null로 합니다.이 예에서는 라이선스를 사용하지 않지만 라이선스가 해방되어야 하는 리소스를 가지고 있는 경우도 있기 때문에 이 메서드를 준비해야 됩니다.마지막으로 어플리케이션의 Main() 메서드를 수정하여 라이센스 매니저가 예외를 캐치할 수 있도록 하겠습니다.///
/// The main entry point for the application .
/// < / summary >
[ STAThread ]
static void Main ( )
{
// Create an instance of the licensed application
frmMain app = null ;
try
{
// This will throw a LicenseException if the
// license is invalid ... if we get an exception ,
// ′ app ′ will remain null and the Run ( ) method
// ( below ) will not be executed ...
app = new frmMain ( ) ;
} // try
catch ( Exception ex )
{
// Catch any error , but especially licensing errors ...
string strErr =
String . Format ( ′ Error executing application : ′ { 0 } ′ ′ ,
ex . Message ) ;
MessageBox . Show ( strErr ,
′ RegistryLicensedApplication Error ′ ,
MessageBoxButtons . OK ,
MessageBoxIcon . Error ) ;
} // catch
if ( app ! = null ) Application . Run ( app ) ;
}}앞에서도 말했듯이 라이센스 검증 처리의 대부분은 라이센스 프로바이더의 Get License() 메서드 내에서 이루어집니다.레지스트리 라이선스 프로바이더의 GetLicense() 메서드의 코드를 다음에 나타냅니다.(다운로드 샘플의 「RegistryLicenseProvider.cs」 소스 파일내에 있습니다)공개 재정의 라이센스 GetLicense()
라이센스 컨텍스트,
유형,
객체 인스턴스,
불 허용예외)
{
// 사용 모드에 대해 테스트합니다...실행 시간 대 설계 시간.
// 실행 시간만 확인합니다...
if(가명)사용 모드 == 라이센스 사용 모드.런타임)
{
// 확인할 레지스트리 키
레지스트리 키 라이센스 키 =
등록.현재 사용자.하위 키 열기(′소프트웨어′)Acme\HostKeys′;
if (licenseKey != null)
{
// 첫 번째 테스트 통과, 즉 의 존재 여부
// 레지스트리 키 자체. 이제 저장된 값 가져오기
// 앱의 GUID와 연결되어 있습니다.
문자열 strLic =
(문자열)라이센스 키.GetValue(유형).GUID.ToString(); // 반영됨!
if (strLic != null)
{
// 두 번째 테스트 통과(일부 값
// 앱의 GUID와 관련된 항목이 있습니다.
if ( 문자열).비교(′설치됨′, strLic, false) == 0 )
{
// 확인했습니다... 유효한 라이센스...
새 RuntimeRegistryLicense(유형) 반환;
} //일 경우
} //일 경우
} //일 경우
// 여기까지 왔다면, 면허 시험에서 떨어졌겠죠. 그럼 우리.
// 예외가 허용되는지 확인하고, 허용될 경우 swing
// 새 라이센스 예외...
if (허용)예외 == true )
{
새 라이센스 부여예외(유형,
예를 들어,
′사용권이 유효하지 않습니다.′;
} //일 경우
// 예외가 필요하지 않으므로 null만 반환합니다.
반환 null;
} //일 경우
그 외의
{
새 DesigntimeRegistryLicense(유형) 반환;
} // 기타
}ここで注目してほしいのは、現在の実行モードがデザイン時と実行時のどちらかを確認する部分のコードです。該当するif文は次のようになっています。if (context.사용 모드 == 라이센스 사용 모드.런타임)
{
... // 실행 시간 모드
}
그 외의
{
... // 설계 시간 모드
} // elseデザイン時モードの場合は、デザイン時ライセンスオブジェクトのインスタンスを作成して返します。return new designtimeregistrylicense(type);実行時モードの場合は、所定のレジストリキーを開き、アプリケーションのguidキー/値のペアを探します。ここでは次のようにしてレジストリキーを開きます。registrykey licensekey =
등록.현재 사용자.하위 키 열기(′소프트웨어′)Acme\HostKeys′;その後、オブジェクトから取得したアプリケーションguidに基づいてキーを生成します(ライセンスタイプにguidattributeを指定したことを思い出してください)。string strlic =
(문자열)라이센스 키.GetValue(유형).GUID.ToString();getvalue()メソッドは、キーに関連付けられている値かnullを返すので、まず戻り値がnullかどうかをテストします。その後、その戻り値を、有効なライセンスを表す正しい値と比較します。if ( strlic != null )
{
// 두 번째 테스트 통과(일부 값
// 앱의 GUID와 관련된 항목이 있습니다.
if ( 문자열).비교(′설치됨′, strLic, false) == 0 )
{
// 확인했습니다... 유효한 라이센스...
새 RuntimeRegistryLicense(유형) 반환;
} //일 경우
} // if検証が成功した場合は、実行時ライセンスオブジェクトの新しいインスタンスを返します。そうでない場合は、例外が許可されているかどうかを確認し、許可されている場合は新しいライセンス例外をスルーします。if ( allow예외 == true )
{
새 라이센스 부여예외(유형,
예를 들어,
′사용권이 유효하지 않습니다.′;
} // if例外が許可されていない場合は、単純にnullを返します。この例ではライセンスクラスが同じですが、同じにする必要はありません。実行時ライセンスのクラスを次に示します。public class runtimeregistrylicense : license
{
개인 유형;
공용 RuntimeRegistryLicense(유형)
{
if(유형 == null)
새 NullReferenceException(Null 참조 예외 생성)
′라이센스 유형 참조는 null일 수 없습니다.′;
this.type = type;
}
공용 재정의 문자열LicenseKey
{
얻다
{
// 응용 프로그램의 GUID만 반환
반환 유형입니다.GUID.ToString();
}
}
공개 무시 무효 처분()
{
}
}この例では新しいライセンスタイプをlicense基底クラスから派生させているので、licensekeyプロパティをオーバーライドする必要があります(これは抽象メソッドです)。これにより、要求されたときにアプリケーシした単純な「installed」という文字列を有効期限日時に置き換えることです(さらに値を暗号化することをお勧めします)。あるいは、もっと複雑な、アプリケーションの実行許可を要求するためにwindowsやwebサービスを呼び出すようなライセンスプロバイダを作成することもできます。私はどちらも実践したことがありますが、非常に効果的でした。また、前にも述べたとおり、何らかの無効化条件が与えられたときにライセならないのかと思った人もいるのではないでしょうか。결국 독자적인 라이센스 매니저와 라이센스 프로세스를 작성하는 것은 무리일까요? Framework를 사용하지 않는 라이센스 아키텍처 ― ― 예를 들어 GetLicense()부울 값을 하고 예외를 유효하게 하는 등의 방법은 있지 않을까요?(저로서는, GetLicense()부울 값을 전달보다 LicenseManger또는 라이센스부급에 속성 또는 속성을 할당하는 방안을 채용하고 싶습니다.현재 Framework의 기본 동작을 변경하는 방법은 다른 방법이 없기 때문에.) 제 생각에는 독자적인 라이센스 아키텍처가 아니라 Framework의 라이센스 아키텍처를 사용하는 것이 향후 도움이 될 것 같습니다.Framework에서 정해진 패턴을 따르다 보면 Framework에 변경이 가해져도 대응할 수 있습니다.또한 Framework 컴포넌트를 이용할 수 있기 때문에 재사용 및 유지보수 비용을 절약할 수 있습니다.라이선스 기능 자체에 관해서는 상상력에 따라 여러 가지가 실현 가능합니다.라이선스 기능을 장착하여 그동안 잃었던 수입을 되찾을까요?
public class MyLicensedControl : System . Windows . Forms . Control
{
...
} 라이센스 매니저는 라이센스 포함 컨트롤 클래스에 터치되어 있는 License Provider 속성을 찾습니다.License Provider 속성은 라이센스 프로바이더의 형을 컨스트럭터에 입력하는 것으로 받아들이기 때문에 라이센스 검증이 요구될 때 이 정보를 사용할 수 있습니다.라이센스 프로바이더는 License Provider 클래스에서 파생시켜야 하며 추상 메서드(Visual Basic으로 말하면 Must Override)의 Get License()를 오버라이드해야 합니다.public class MyLicenseProvider :
System . ComponentModel . LicenseProvider
{
...
public override License GetLicense (
LicenseContext context ,
Type type ,
object instance ,
bool allowExceptions )
{
...
}
}.NET에서의 라이센스 제어는 이상과 같은 흐름입니다만, 결국, 실제 라이센스 제어를 실시하고 있는 것은 GetLicense() 메서드입니다.독자들에게 불필요한 수고를 끼치지 않기 위해서 미리 알려드리자면, 사실 Framework에는 Lic File License Provider라고 하는 기본적인 라이센스 프로바이더가 준비되어 있습니다.완벽을 기하기 위해서는 여기서 Lic File License Provider 사용법을 설명해야 하는데, 자작 소프트웨어에 라이선스 기능을 넣으려고 진심으로 생각하는 사람이라면 아마 이런 단순한 방식보다는 좀 더 창의적인 방식을 사용하고 싶을 것입니다.따라서 Lic File License Provider에 대한 설명 후에 그러한 세련된 방식에 대해서도 알아보겠습니다.Lic File License Provider Lic File License Provider의 기능은 극히 간단합니다.라이센스 파일의 유무를 조사해 파일이 존재하는 경우는, 파일의 내용을 확인해 라이센스를 검증합니다.라이센스 파일은, 애플리케이션과 함께 디스크상에 보존되고 있는 경우도 있는가 하면, 앱 소스로서 인코딩되고 있는 경우도 있습니다(그 경우는 정보를 꺼내기 위한 추가 코드가 필요하게 됩니다).라이선스 파일이 존재하고 유효한 정보가 기록되어 있는 경우 이 라이선스 프로바이더가 라이선스 매니저에 라이선스를 발급하여 최종적으로 컨트롤에 라이선스를 허용합니다.그 이외의 경우에는 라이센스 프로바이더가 icense Exception을 느리게 하여 컨트롤은 사용할 수 없게 됩니다.Lic File License Provider는 Get License()를 오버라이드할 뿐만 아니라(오버라이드 필수), Is Key Valid()와 Get Key()라고 하는 추가 가상 메서드를 제공합니다.Lic File License Provider를 Framework의 구현대로 사용할 경우, GetKey() 메서드는 어셈블리의 실행 디렉토리 내에서 ′{full name}.lic′이라는 이름의 파일을 찾습니다.{full name}은 라이센스 컨트롤 클래스의 완전 유형명을 나타내며, 일반적으로 ′{assembly예를 들어 지금까지의 예에서 사용해 온 라이센스 부 컨트롤을 어셈블리 My Control Assembly가 공개하는 경우는 라이센스 파일의 이름은 다음과 같습니다.MyControlAssembly.MyLicensedControl.lic이 파일의 내용을 취득하면 IsKeyValid() 메서드는 그것을 문자열 「{licensedclass} is a licensed component.(온점을 포함)와 비교합니다.방금 전 예를 들자면, ′My Control Assembly.My Licensed Control.lic′ 파일에는 문자열 ′My Control Assembly.My Licensed Control is a licensed component.′가 포함되어 있을 것입니다.라이센스 파일이 없거나 파일 내용이 올바르지 않으면 라이센스 검증이 실패하며 컨트롤의 인스턴스화가 실패합니다.다운로드 샘플로서 MSDN의 샘플색 선택 콤보 박스 컨트롤에 라이센스 기능을 추가한 것을 준비했으므로, 그쪽도 참조해 주세요(기사 상부에서 다운로드할 수 있습니다).IsKeyValid()와 GetKey()는 가상 메서드이기 때문에 어딘가 다른 곳에서 라이센스 파일을 찾거나 다른 문자열(암호화된 문자열, 단순히 다른 문구를 사용하는 문자열 등)과 비교하거나 하는 새로운 클래스를 쉽게 파생할 수 있습니다.그러나, 아무리 좋은 실장이라고 해도, 기본적으로 라이센스 파일을 사용하고 있는 것에는 변함이 없습니다.기저 클래스가 그 기능을 제공하고 있기 때문입니다.이와는 전혀 다른 라이센스 방식을 구현하고 싶다면 License Provider에서 직접 라이센스 프로바이더를 파생시키는 것이 좋습니다.스스로 생각해 보는 편이 몸에 배기 쉬울 것 같아서 여기에서는 파생된 라이센스 파일 프로바이더의 예를 제시하지 않겠습니다.그 대신 다른 라이선스 방식을 몇 가지 소개해 드리도록 하겠습니다.라이선스 파일의 컴파일 라이선스 파일 이야기를 마치기 전에 lc.exe에 대해 언급하겠습니다.′lc.exe′ 는 .NET Framework 부속 라이센스 컴파일러로 라이센스 파일 정보를 취득하고 어셈블리 리소스로 인코딩하는 툴입니다.이 툴이 Framework에 부속되어 있는 건 좀 이상하지만(기본 구현인 LicFileLicense Provider는 리소스 기반의 라이센스 파일을 참조하지 않기 때문에), 이 툴은 재미있는 기능이 몇 개 있습니다.하나는 리소스 정보를 쉽게 생성할 수 있는데, 더 흥미로운 것은 여러 라이센스 파일을 하나의 리소스로 인코딩할 수 있다는 것입니다.이로 인해, 각각 다른 라이센스 파일 문자열을 가지는 여러 컨트롤의 라이센스 검증을 한 번에 실시할 수 있게 됩니다.단, 이 툴에는 큰 제약이 있습니다.그것은 컴파일한 모듈과 리소스를 어셈블하는데 어셈블링커(al.exe)를 사용해야 한다는 점입니다.명령줄 파의 사람에게는 문제가 없겠지만 우리와 같이 Visual Studio.NET을 사용하는 개발자에게는 큰 제약입니다. 왜냐하면 Visual Studio.NET에서는 멀티 모듈 어셈블리를 컴파일하거나 생성할 수 없기 때문입니다.(단 빌드 액션을 ′메워진 리소스′로 하면 리소스 출력을 프로젝트 파일에 포함시킬 수 있습니다.)여기에서는 Visual Studio .NET를 다루었습니다만, 어떤 버전의 Visual Studio(2002 또는 2003)에서도 라이센스부 컨트롤을 작성하기 위한 자동 지원은 없습니다.그럼 라이센스 포함 컨트롤을 작성하기 위해서는 어떻게 하면 좋은 것일까요.답변은 단순히 수동으로 라이센스 파일을 만들고 컴파일된 어셈블리와 함께 배포하는 것입니다.저는 항상 빌드 액션을 ′없음′으로 설정하고 라이선스 파일을 Visual Studio 프로젝트에 추가하는데, 이는 필수가 아닙니다.이렇게 하면 라이센스 파일이 다른 프로젝트/솔루션 파일과 함께 소스 저장소로 정리되므로 소스 코드 관리가 좀 쉬워지는 것 뿐입니다.계속해서 이 파일을 어셈블리의 실행 디렉토리에 수동으로 복사해야 합니다.다른 라이센스 방식 내가 봤을 때 Microsoft는 .NET Framework용 기본 라이센스 프로바이더를 준비해야 하기 때문에 ActiveX 컨트롤의 라이센스 기능과 매우 유사한 기능을 하는 라이센스 프로바이더를 구현한 것이 아닐까요.그러나 그와 동시에 Microsoft는 이러한 단순한 라이센스 방식을 자신들의 제품 소프트웨어에 사용할 생각은 없었던 것이 아닌가 하는 생각도 듭니다(적어도 중요한 것에 대해서는 그럴 의사가 없었을 것입니다).기본 방식을 사용하는 대신 보다 배포하기 쉽고, 현명하고, 뒤지기 어려우며, 무엇에나 사용할 수 있는 라이선스 방식을 작성해 보시면 어떨까요?그래서 또 다른 라이선스 방식을 생각해 보도록 하겠습니다.독자적인 방식을 사용하면, 자작의 컨트롤에 어떤 기능의 라이센스라도 짜 넣을 수 있습니다.예를 들어, 화요일에만 디자인 환경에서 사용할 수 있는 컨트롤이나 사용자 지역 일기예보가 ′맑음′일 경우에만 응용 프로그램 내에서 실행할 수 있는 컨트롤(사용자 주소의 우편번호를 취득하여 인터넷에서 해당 지역의 일기예보를 다운로드함) 등을 생각할 수 있습니다.이건 농담이 아니라 정말 이런 일이 가능한 겁니다.그렇게 할 필연성은 없지만, 그런 처리를 할 수 있을 정도로 유연한 라이센스 방식이라는 것입니다.이후로는 좀 더 현실적인 방법으로 레지스트리 라이센스 키를 사용하는 라이센스 방식을 소개합니다.하지만이방식에대해서자세히설명하기전에한가지주의해야할것이있어요.그것은, 이라는 것입니다.이게 대체 무슨 뜻일까요?이것은 즉, 어플리케이션 전체에 대해서도 컨트롤과 같은 방법으로 간단하게 라이센스 기능을 추가할 수 있다는 것입니다.지금부터 소개하는 방식은 컨트롤의 라이선스가 아니라 어플리케이션의 라이선스를 대상으로 하고 있습니다만, 실제로는 어느 쪽에도 적용할 수 있습니다.그럼 구체적인 설명으로 넘어가기 전에 배경 사정을 좀 더 설명해 둡시다.애플리케이션 라이선스와 컨트롤 라이선스의 기본적인 차이점은 라이선스를 언제 검증하느냐입니다.당신이 컨트롤이나 컴포넌트를 개발하여 생계를 유지하고 있다면, 타깃 시장은 다른 어플리케이션 개발자입니다.따라서 귀하 컨트롤의 라이선스는 컨트롤이 디자인 시에 Visual Studio 프로젝트에 삽입되었을 때 검증을 실시합니다.자체제작 컨트롤 라이브러리를 수백만 개씩 팔고 싶다면 실행 시 라이선스를 무료로 제공하거나 실행 시 라이선스를 일체 부과하지 않는 것이 일반적입니다.대국적으로 보면 타깃 시장의 어플리케이션 개발자는 어플리케이션을 계속 사용하도록 할 필요가 있습니다.그렇게 하면 그들은 더 많은 컨트롤을 당신에게서 사 줄 것이기 때문입니다.하지만 어플리케이션 라이선스의 경우는 이야기가 다릅니다.당신이 응용 프로그램을 개발할 때는 당신이 디자인할 때 응용 프로그램을 빌드합니다.따라서 디자인 시 라이선스를 자신에게 부과해도 의미가 없습니다.그 대신 사용자가 실행 시 적절한 라이선스 정보를 가지고 있는지 확인해야 합니다.Framework의 라이센스 아키텍처는 이 점을 고려한 설계로 Get License() 메서드를 호출했을 때 라이센스 요구 상태가 디자인인지 실행인지를 확인할 수 있습니다.이후 두 케이스 모두 소개하겠습니다만, 이번 예에서는 컨트롤의 라이선스 기능이 아니라 어플리케이션 전체의 라이선스 기능을 구현하는 방법을 다루고 싶기 때문에 실행 시에만 라이선스 검증을 하도록 하겠습니다.무엇보다, 이것은 중요한 차이이기 때문에 확실히 의식할 필요가 있습니다.레지스트리 베이스의 라이센스에서는, 특정의 값을 포함한 레지스트리 키의 유무를 조사한다고 하는 라이센스 방식을 실장합니다.애플리케이션 본체에는, 레지스트리치를 쓰기 위한 코드를 실장하지 않습니다.이 처리는 인스톨 프로그램에서 실시하도록 합니다.대부분의 어플리케이션은 어떤 형태로든 레지스트리를 사용하고 있기 때문에 개발에 큰 제한이 가해지지는 않습니다.저도 레지스트리의 등장 이후는, 인스톨 프로그램으로 레지스트리 키를 쓰도록 하고 있습니다.정말이라면 조금 더 스마트한 방법으로 레지스트리에 값을 쓸 수도 있는데, 이 예에서는 단순히 문자열 Installed를 쓰도록 하겠습니다.좀 더 세련된 구현방법에 대해서는 꼭 스스로 생각해 보시기 바랍니다(저도 속셈을 모두 밝힐 수는 없으니까요.여기에서는 다음과 같은 값을 찾습니다.HKEY_CURENT_USERSoftwareAcmeHostKeysde915e1-df71-3443-9f4d-32259ced2 여기서 제시된 GUID 값은 제가 제 응용 프로그램에 할당한 GUID입니다.Acme Software가 판매하고 있는 어플리케이션들은 각각 독자적인 GUID를 가지고 있습니다만, 저는 여러가지 고려한 결과 모든 어플리케이션에 동일한 라이센스 프로바이더를 사용하고 있습니다. .NET의 기능을 이용하여 모든 Acme Software 라이센스 키를 여기에 넣고 있기 때문에 키이름이 Host Keys 라고 되어 있습니다.당신의 어플리케이션에서는 적절한 곳으로 키를 이동시키세요.이 애플리케이션은 매우 단순합니다(그림 3을 참조).이 창이 뜨면 라이선스가 유효합니다.라이센스가 무효인 경우는, 그림 4와 같은 예외 다이얼로그 박스가 표시됩니다.이를 기능시키려면 새 응용 프로그램을 만들고 마법사를 통한 자동 생성 코드를 약간 수정해야 합니다.먼저 양해를 구합니다만, 여기서 Visual Basic 프로그래머를 따돌릴 생각은 없습니다.샘플 파일에는 똑같은 C#.NET 어플리케이션과 Visual Basic.NET 어플리케이션이 포함되어 있습니다.여기서 소개하고 있는 코드는 C#입니다만, Visual Basic 프로그래머에서도 대강은 간단하게 이해할 수 있을 것입니다.우선 메인 어플리케이션의 소스코드를 4군데 수정하고, 자체 라이센스 프로바이더를 기술해야 합니다.수정하는 4개소란 다음과 같습니다.응용 프로그램 클래스 선언(속성 몇 개 추가)
응용 프로그램 클래스의 컨스트럭터
응용 프로그램의 Dispose() 메서드
어플리케이션의 Main() 메서드 Guid Attribute를 사용하기 때문에 using구도 추가합니다.그럼 먼저 클래스 선언부터 알아보겠습니다.///
/// Summary description for frmMain .
/// < / summary >
[ GuidAttribute ( ′ 2de915e1 - df71 - 3443 - 9f4d - 32259c92 ced 2 ′ ) ]
[ LicenseProvider ( typeof ( RegistryLicenseProvider )) ]
public class frmMain : System . Windows . Forms . Form
{
...
}}이 클래스에 Guid Attribute 와 License Provider 라고 하는 속성을 추가했습니다.License Provider에 대해서는 앞에서 설명한 바와 같습니다.GuidAttribute의 목적은 이 애플리케이션 클래스에 GUID 또는 일의 수치를 할당하는 것입니다.이 속성은 보통 COM 상호운용기능을 위해 사용되는데, 여기에서는 기존 Framework 지원이 가지고 있는 단일 수치식별자를 응용프로그램 클래스에 할당하기 위해 재사용하고 있습니다(이를 통해 클래스 유형의 GUID를 나중에 쉽게 알아낼 수 있습니다).자체 속성을 생성할 수도 있는데, 그렇게 되면 Framework 내장형 GUID 검출 지원을 사용할 수 없게 됩니다.또한 GuidAttribute에 할당한 GUID 값이 레지스트리 키로 사용한 GUID 값과 일치하는 것에 주목하십시오.라이센스 프로바이더는 이 값을 반영하여 응용 프로그램의 레지스트리 라이센스 키 값을 생성합니다.여기서 GuidAttribute를 사용하기 때문에 이름공간 목록에 다음 행을 추가해 두어야 합니다. usingSystem.Runtime.Interop Services; 응용프로그램 클래스의 컨스트럭터에는 앞서 말한 코드를 추가합니다.private License _ license = null ;
public frmMain ( )
{
//
// Required for Windows Form Designer support
//
InitializeComponent ( ) ;
// Obtain the license
_ license = LicenseManager . Validate ( typeof ( frmMain ) , this ) ;
}}여기서는 라이센스 매니저의 Validate() 메서드를 호출하고 있을 뿐 특별한 것은 아무것도 하고 있지 않습니다.그러나 이 Validate() 메서드는 라이선스가 비활성화되면 예외를 슬로 할 수 있습니다.그래서 이 예외를 어딘가에서 파악해야 합니다.여기에 _license라고 하는 프라이빗 데이터 멤버를 추가하고 있다, 주목해 주시기 바랍니다.라이센스 방식에 따라서는 이 라이센스 오브젝트를 사용할 수도 있습니다만(이 예에서는 사용하지 않습니다), 어떤 경우에라도 어플리케이션의 종료시에 그 라이센스를 파기할 필요가 있습니다.이 때 라이선스에 할당되어 있는 자원을 적절하게 해방시켜야 하는 경우가 있습니다.그래서 응용 프로그램의 Dispose() 메서드를 다음과 같이 수정합니다.///
/// Clean up any resources being used .
/// < / summary >
protected override void Dispose ( bool disposing )
{
if ( disposing )
{
if ( components ! = null )
{
components . Dispose ( ) ;
}
if ( license ! = null )
{
license . Dispose ( ) ;
license = null ;
}
}
base . Dispose ( disposing );
}}여기서는 null 라이센스 여부를 확인하며, null이 아닐 경우 Dispose() 메서드를 호출하여 참조를 null로 합니다.이 예에서는 라이선스를 사용하지 않지만 라이선스가 해방되어야 하는 리소스를 가지고 있는 경우도 있기 때문에 이 메서드를 준비해야 됩니다.마지막으로 어플리케이션의 Main() 메서드를 수정하여 라이센스 매니저가 예외를 캐치할 수 있도록 하겠습니다.///
/// The main entry point for the application .
/// < / summary >
[ STAThread ]
static void Main ( )
{
// Create an instance of the licensed application
frmMain app = null ;
try
{
// This will throw a LicenseException if the
// license is invalid ... if we get an exception ,
// ′ app ′ will remain null and the Run ( ) method
// ( below ) will not be executed ...
app = new frmMain ( ) ;
} // try
catch ( Exception ex )
{
// Catch any error , but especially licensing errors ...
string strErr =
String . Format ( ′ Error executing application : ′ { 0 } ′ ′ ,
ex . Message ) ;
MessageBox . Show ( strErr ,
′ RegistryLicensedApplication Error ′ ,
MessageBoxButtons . OK ,
MessageBoxIcon . Error ) ;
} // catch
if ( app ! = null ) Application . Run ( app ) ;
}}앞에서도 말했듯이 라이센스 검증 처리의 대부분은 라이센스 프로바이더의 Get License() 메서드 내에서 이루어집니다.레지스트리 라이선스 프로바이더의 GetLicense() 메서드의 코드를 다음에 나타냅니다.(다운로드 샘플의 「RegistryLicenseProvider.cs」 소스 파일내에 있습니다)공개 재정의 라이센스 GetLicense()
라이센스 컨텍스트,
유형,
객체 인스턴스,
불 허용예외)
{
// 사용 모드에 대해 테스트합니다...실행 시간 대 설계 시간.
// 실행 시간만 확인합니다...
if(가명)사용 모드 == 라이센스 사용 모드.런타임)
{
// 확인할 레지스트리 키
레지스트리 키 라이센스 키 =
등록.현재 사용자.하위 키 열기(′소프트웨어′)Acme\HostKeys′;
if (licenseKey != null)
{
// 첫 번째 테스트 통과, 즉 의 존재 여부
// 레지스트리 키 자체. 이제 저장된 값 가져오기
// 앱의 GUID와 연결되어 있습니다.
문자열 strLic =
(문자열)라이센스 키.GetValue(유형).GUID.ToString(); // 반영됨!
if (strLic != null)
{
// 두 번째 테스트 통과(일부 값
// 앱의 GUID와 관련된 항목이 있습니다.
if ( 문자열).비교(′설치됨′, strLic, false) == 0 )
{
// 확인했습니다... 유효한 라이센스...
새 RuntimeRegistryLicense(유형) 반환;
} //일 경우
} //일 경우
} //일 경우
// 여기까지 왔다면, 면허 시험에서 떨어졌겠죠. 그럼 우리.
// 예외가 허용되는지 확인하고, 허용될 경우 swing
// 새 라이센스 예외...
if (허용)예외 == true )
{
새 라이센스 부여예외(유형,
예를 들어,
′사용권이 유효하지 않습니다.′;
} //일 경우
// 예외가 필요하지 않으므로 null만 반환합니다.
반환 null;
} //일 경우
그 외의
{
새 DesigntimeRegistryLicense(유형) 반환;
} // 기타
}ここで注目してほしいのは、現在の実行モードがデザイン時と実行時のどちらかを確認する部分のコードです。該当するif文は次のようになっています。if (context.사용 모드 == 라이센스 사용 모드.런타임)
{
... // 실행 시간 모드
}
그 외의
{
... // 설계 시간 모드
} // elseデザイン時モードの場合は、デザイン時ライセンスオブジェクトのインスタンスを作成して返します。return new designtimeregistrylicense(type);実行時モードの場合は、所定のレジストリキーを開き、アプリケーションのguidキー/値のペアを探します。ここでは次のようにしてレジストリキーを開きます。registrykey licensekey =
등록.현재 사용자.하위 키 열기(′소프트웨어′)Acme\HostKeys′;その後、オブジェクトから取得したアプリケーションguidに基づいてキーを生成します(ライセンスタイプにguidattributeを指定したことを思い出してください)。string strlic =
(문자열)라이센스 키.GetValue(유형).GUID.ToString();getvalue()メソッドは、キーに関連付けられている値かnullを返すので、まず戻り値がnullかどうかをテストします。その後、その戻り値を、有効なライセンスを表す正しい値と比較します。if ( strlic != null )
{
// 두 번째 테스트 통과(일부 값
// 앱의 GUID와 관련된 항목이 있습니다.
if ( 문자열).비교(′설치됨′, strLic, false) == 0 )
{
// 확인했습니다... 유효한 라이센스...
새 RuntimeRegistryLicense(유형) 반환;
} //일 경우
} // if検証が成功した場合は、実行時ライセンスオブジェクトの新しいインスタンスを返します。そうでない場合は、例外が許可されているかどうかを確認し、許可されている場合は新しいライセンス例外をスルーします。if ( allow예외 == true )
{
새 라이센스 부여예외(유형,
예를 들어,
′사용권이 유효하지 않습니다.′;
} // if例外が許可されていない場合は、単純にnullを返します。この例ではライセンスクラスが同じですが、同じにする必要はありません。実行時ライセンスのクラスを次に示します。public class runtimeregistrylicense : license
{
개인 유형;
공용 RuntimeRegistryLicense(유형)
{
if(유형 == null)
새 NullReferenceException(Null 참조 예외 생성)
′라이센스 유형 참조는 null일 수 없습니다.′;
this.type = type;
}
공용 재정의 문자열LicenseKey
{
얻다
{
// 응용 프로그램의 GUID만 반환
반환 유형입니다.GUID.ToString();
}
}
공개 무시 무효 처분()
{
}
}この例では新しいライセンスタイプをlicense基底クラスから派生させているので、licensekeyプロパティをオーバーライドする必要があります(これは抽象メソッドです)。これにより、要求されたときにアプリケーシした単純な「installed」という文字列を有効期限日時に置き換えることです(さらに値を暗号化することをお勧めします)。あるいは、もっと複雑な、アプリケーションの実行許可を要求するためにwindowsやwebサービスを呼び出すようなライセンスプロバイダを作成することもできます。私はどちらも実践したことがありますが、非常に効果的でした。また、前にも述べたとおり、何らかの無効化条件が与えられたときにライセならないのかと思った人もいるのではないでしょうか。결국 독자적인 라이센스 매니저와 라이센스 프로세스를 작성하는 것은 무리일까요? Framework를 사용하지 않는 라이센스 아키텍처 ― ― 예를 들어 GetLicense()부울 값을 하고 예외를 유효하게 하는 등의 방법은 있지 않을까요?(저로서는, GetLicense()부울 값을 전달보다 LicenseManger또는 라이센스부급에 속성 또는 속성을 할당하는 방안을 채용하고 싶습니다.현재 Framework의 기본 동작을 변경하는 방법은 다른 방법이 없기 때문에.) 제 생각에는 독자적인 라이센스 아키텍처가 아니라 Framework의 라이센스 아키텍처를 사용하는 것이 향후 도움이 될 것 같습니다.Framework에서 정해진 패턴을 따르다 보면 Framework에 변경이 가해져도 대응할 수 있습니다.또한 Framework 컴포넌트를 이용할 수 있기 때문에 재사용 및 유지보수 비용을 절약할 수 있습니다.라이선스 기능 자체에 관해서는 상상력에 따라 여러 가지가 실현 가능합니다.라이선스 기능을 장착하여 그동안 잃었던 수입을 되찾을까요?
반응형