작성자: Gurpreet Singh
소개
IIS 7.0 이상의 관리 도구는 모듈을 연결하기 위한 확장 가능한 플랫폼입니다. 개발자는 자체 UI 기능을 작성할 수 있으며 intemgr에 의해 일류 시민으로 취급됩니다.
이 연습에서는 처음부터 UI 모듈을 만드는 방법을 보여 줍니다. 모듈을 만든 다음 IIS 팀을 만드는 모범 사례를 보여 줍니다.
작업은 두 개의 어셈블리를 만드는 것으로 구성됩니다. 프로세스는 두 단계로 요약할 수 있습니다.
- 클라이언트 어셈블리 만들기
- 서버 어셈블리 만들기
새 inetmgr은 사용자 인터페이스 논리와 코드 조작 서버 설정 간의 클린 분리를 적용하는 아키텍처와 같은 웹 서비스를 사용하도록 설계되었습니다. 이 작업은 주로 ModuleService 및 ModuleServiceProxy라는 두 클래스를 통해 수행됩니다. ModuleService 파생 클래스는 ModuleProvider ServiceType 속성을 통해 ModuleProvider와 함께 assosciated됩니다.
빈 솔루션 만들기
시작을 클릭하고 프로그램을 클릭하고 Microsoft Visual Studio 2005 또는 Microsoft Visual C# 2005 Express Edition을 실행합니다. 파일 메뉴에서새 프로젝트 옵션을 선택하고 다른 프로젝트 형식 및 Visual Studio 솔루션으로 이동합니다. 오른쪽에서 빈 솔루션을 선택하고 솔루션 이름을 ExtensibilityDemo로 지정합니다.
클라이언트 어셈블리 만들기
클라이언트 어셈블리를 만드는 데 설명된 작업은 다음으로 구성됩니다.
- 클라이언트 어셈블리에 대한 프로젝트 설정
- ModuleServiceProxy 만들기
- ModuleListPage를 만들고 ModuleServiceProxy를 사용합니다.
- 모듈 클래스 만들기
클라이언트 어셈블리에 대한 프로젝트 설정
솔루션 Explorer 솔루션을 마우스 오른쪽 단추로 클릭하고 추가 및 새 프로젝트를 선택하여 이 창을 시작합니다. 오른쪽 창에서 Visual C# 및 클래스 라이브러리를 선택하고 프로젝트의 이름을 클라이언트로 지정합니다.
솔루션 탐색기에서 상황에 맞는 메뉴 삭제 옵션을 사용하여 해당 파일을 사용하지 않으므로 기본적으로 추가된 Class1.cs 파일을 제거합니다.
참조 추가... 프로젝트 메뉴에서 찾아보기 탭을 사용하여 Microsoft.Web.Management.dll 대한 참조를 추가하고 \Windows\system32\inetsrv 디렉터리를 검색합니다. inetmgr에서 모듈을 만들기 위한 확장성 클래스가 포함된 디렉터리입니다. System.Windows.Forms에서 일부 클래스를 참조하려고 하므로 System.Windows.Forms에 대한 참조도 포함합니다.
모범 사례: 클라이언트 프로젝트의 Microsoft.Web.Administration.dll 참조하지 마세요.
InetMgr 내에서 라이브러리를 사용해야 하는 요구 사항 중 하나는 GAC 내에 등록해야 한다는 것입니다. 이를 위해 DLL의 이름이 강력한지 확인해야 합니다. Visual Studio는 새 이름을 쉽게 만들 수 있는 방법을 제공합니다. 어셈블리에 서명하려면 프로젝트 속성 으로 이동하고 서명 탭으로 이동하여 어셈블리 서명을 클릭합니다. 대화 상자에서 키 이름을 ExtensibilityDemoKey로 지정하고 암호로 내 키 파일 보호를 선택 취소합니다.
확인을 눌러 어셈블리에 서명합니다. 또한 어셈블리가 GAC에 있도록 하기 때문에 컴파일할 때마다 GAC에 자동으로 추가되도록 빌드 후 이벤트를 추가합니다. 이렇게 하면 새 기능을 추가할 때 디버그하고 변경할 수 있습니다. 이를 위해 빌드 이벤트 탭을 선택하고 다음 빌드 후 이벤트 명령줄을 추가합니다.
gacutil.exe /if "$(TargetPath)"
마지막으로 프로젝트 속성을 닫고 파일 메뉴에서모두 저장 옵션을 선택합니다. 이제 빌드 메뉴에서 빌드 솔루션을 사용하여 프로젝트를 컴파일할 수 있습니다. 그러면 dll이 자동으로 빌드되고 GAC에 추가됩니다.
참고: vsvars32.bat 설정 명령이 오류 코드 9009에서 작동하지 않는 경우 다음과 같이 gacutil.exe 전체 경로를 추가하여 빌드 후 이벤트에 추가된 명령을 바꿀 수도 있습니다.
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /if "$(TargetPath)
ModuleServiceProxy 만들기
ModuleServiceProxy는 ModuleService 클래스에서 메서드를 호출하는 프로세스를 간소화하는 클래스입니다. 이 클래스는 로컬 서버를 관리하거나 웹 관리 서비스(wmsvc)를 사용하여 원격 머신을 관리할 때 논리를 추상화하기 때문에 중요합니다.
이 샘플에서는 "appSettings"의 읽기 콘텐츠를 작성합니다. 프로젝트 메뉴에서 새 항목 추가 옵션을 선택합니다. 코드를 선택하고 파일 이름으로 DemoModuleServiceProxy를 입력합니다.
다음과 같이 표시되도록 코드를 변경합니다.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Management.Client;
using Microsoft.Web.Management.Server;
namespace Client {
internal class DemoModuleServiceProxy : ModuleServiceProxy {
public ArrayList GetAppSettings() {
return (ArrayList )Invoke("GetAppSettings");
}
}
}
프록시 작성은 ModuleServiceProxy에서 파생된 클래스를 작성하고 서버 쪽의 ModuleService에서 메서드를 호출하는 간단한 문제입니다.
ModuleListPage 만들기
프로젝트 메뉴에서 새 항목 추가 옵션을 선택합니다. 코드를 선택하고 파일 이름으로 DemoModuleListPage.cs를 입력합니다.
다음과 같이 표시되도록 코드를 변경합니다.
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using Microsoft.Web.Management.Client.Win32;
using Microsoft.Web.Management.Server;
namespace Client {
internal class DemoModuleListPage : ModuleListPage {
private ColumnHeader _keyColumnHeader;
private ColumnHeader _valueColumnHeader;
private DemoModuleServiceProxy _serviceProxy;
private DemoModuleServiceProxy ServiceProxy {
get {
if (_serviceProxy == null) {
_serviceProxy = (DemoModuleServiceProxy)CreateProxy(typeof(DemoModuleServiceProxy));
}
return _serviceProxy;
}
}
protected override void InitializeListPage() {
_keyColumnHeader = new ColumnHeader();
_keyColumnHeader.Text = "Key";
_keyColumnHeader.Width = 200;
_valueColumnHeader = new ColumnHeader();
_valueColumnHeader.Text = "Value";
_valueColumnHeader.Width = 200;
ListView.Columns.Add(_keyColumnHeader);
ListView.Columns.Add(_valueColumnHeader);
}
protected override void OnActivated(bool initialActivation) {
base.OnActivated(initialActivation);
if (initialActivation) {
GetAppSettings();
}
}
private void GetAppSettings() {
StartAsyncTask("Getting Settings", new DoWorkEventHandler(GetSettings),
new RunWorkerCompletedEventHandler(GetSettingsCompleted));
}
private void GetSettings(object sender, DoWorkEventArgs e) {
e.Result = ServiceProxy.GetAppSettings();
}
private void GetSettingsCompleted(object sender, RunWorkerCompletedEventArgs e) {
ListView.BeginUpdate();
try {
ArrayList settingsList = (ArrayList)e.Result;
foreach (PropertyBag bag in settingsList) {
ListViewItem item = new ListViewItem();
item.Text = (string)bag[0];
item.SubItems.Add((string)bag[1]);
ListView.Items.Add(item);
}
}
finally {
ListView.EndUpdate();
}
}
}
}
이 데모에서는 ModuleListPage 클래스를 확장합니다. InitializeListPage 메서드를 재정의하여 열을 초기화하고 listview에 추가합니다. 또한 OnActivated 메서드를 재정의합니다. 이 페이지에 액세스할 때 이 메서드가 호출됩니다.
모듈 클래스 만들기
이는 모든 기존 개체에 대한 클라이언트 쪽의 진입점입니다. Initialize, GetService 및 Dispose라는 세 가지 기본 메서드가 있습니다. 페이지 등록, 페이지에 범주 할당 등과 같은 모든 작업이 수행되는 메서드입니다. 가 완료되었습니다.
프로젝트 메뉴에서 새 항목 추가 옵션을 선택합니다. 코드를 선택하고 파일 이름으로 DemoModule.cs를 입력합니다.
다음과 같이 표시되도록 코드를 변경합니다.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Web.Management.Client;
namespace Client {
internal class DemoModule : Module {
protected override void Initialize(IServiceProvider serviceProvider, Microsoft.Web.Management.Server.ModuleInfo moduleInfo) {
base.Initialize(serviceProvider, moduleInfo);
IControlPanel controlPanel = (IControlPanel)GetService(typeof(IControlPanel));
controlPanel.RegisterPage(new ModulePageInfo(this, typeof(DemoModuleListPage), "DemoPage"));
}
}
}
DemoModule은 Initialize 메서드를 재정의합니다. 먼저 기본 클래스에서 Initialize를 호출합니다. 그런 다음 GetService를 통해 제어판 서비스에 액세스합니다. 그런 다음 ControlPanel의 RegisterPage를 통해 자신을 등록합니다.
서버 어셈블리 만들기
서버 어셈블리는 두 개의 기본 클래스를 작성하는 것으로 구성됩니다.
- 모듈 공급자
- 모듈 서비스
또한 서버는 Microsoft.Web.Management.dll 및 Microsoft.Web.Management.Administration.dll \Windows\System32\inetsrv 디렉터리에서 두 개의 기본 어셈블리를 참조해야 합니다. 첫 번째 어셈블리는 intemgr용 UI를 만드는 모든 프레임워크 클래스로 구성되고 두 번째 어셈블리는 구성 읽기 및 쓰기 구성을 위한 클래스로 구성됩니다.
솔루션 Explorer 솔루션을 마우스 오른쪽 단추로 클릭하고 추가 및 새 프로젝트를 선택하여 창을 시작합니다. 오른쪽 창에서 Visual C# 및 클래스 라이브러리를 선택하고 프로젝트의 이름을 서버로 지정합니다.
솔루션 탐색기에서 상황에 맞는 메뉴 삭제 옵션을 사용하여 해당 파일을 사용하지 않으므로 기본적으로 추가된 Class1.cs 파일을 제거합니다.
참조 추가... 프로젝트 메뉴에서 찾아보기 탭을 사용하여 Microsoft.Web.Management.dll 참조를 추가하고 Microsoft.Web.Management.Administration.dll\ Windows\system32\inetsrv 디렉터리를 검색합니다. inetmgr에서 모듈을 만들기 위한 확장성 클래스가 포함된 디렉터리입니다.
InetMgr 내에서 라이브러리를 사용해야 하는 요구 사항 중 하나는 GAC 내에 등록해야 한다는 것입니다. 이를 위해 DLL이 강력한 이름인지 확인해야 합니다. Visual Studio는 새 이름을 쉽게 만들 수 있는 방법을 제공합니다. 어셈블리에 서명하려면 프로젝트 속성 으로 이동하고 서명 탭으로 이동하여 어셈블리 서명을 클릭합니다. 드롭다운에서 찾아보기를 클릭합니다. 대화 상자에서 클라이언트 폴더로 이동하여 ExtensibilityDemoKey 를 선택하고 열기를 누릅니다. 프로젝트 속성을 저장합니다.
확인을 눌러 어셈블리에 서명합니다. 또한 어셈블리가 GAC에 있도록 하기 때문에 컴파일할 때마다 GAC에 자동으로 추가되도록 빌드 후 이벤트를 추가합니다. 이렇게 하면 새 기능을 추가할 때 디버그하고 변경할 수 있습니다. 이를 위해 빌드 이벤트 탭을 선택하고 다음 빌드 후 이벤트 명령줄을 추가합니다.
gacutil.exe /if "$(TargetPath)"
마지막으로 프로젝트 속성을 닫고 파일 메뉴에서모두 저장 옵션을 선택합니다. 이제 빌드 메뉴에서 빌드 솔루션을 사용하여 프로젝트를 컴파일할 수 있습니다. 그러면 dll이 자동으로 빌드되고 GAC에 추가됩니다.
참고: vsvars32.bat 설정 명령이 오류 코드 9009에서 작동하지 않는 경우 다음과 같이 gacutil.exe 전체 경로를 추가하여 빌드 후 이벤트에 추가된 명령을 바꿀 수도 있습니다.
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /if "$(TargetPath)"
모듈 서비스 만들기
이 작업에서는 새 ModuleService를 만듭니다. 기본 구성 파일을 읽거나 쓰기 위해 Microsoft.Web.Administration.dll 사용하는 클래스입니다.
프로젝트 메뉴에서 새 항목 추가 옵션을 선택합니다. 새 항목 추가 대화 상자에서 코드 템플릿을 선택하고 파일 이름으로 DemoModuleService.cs 를 입력합니다.
다음과 같이 표시되도록 코드를 변경합니다.
using System.Collections;
using Microsoft.Web.Administration;
using Microsoft.Web.Management.Server;
namespace Server {
internal class DemoModuleService : ModuleService {
[ModuleServiceMethod(PassThrough = true)]
public ArrayList GetAppSettings() {
ArrayList settingsList = new ArrayList();
ConfigurationSection appSettingsSection =
ManagementUnit.Configuration.GetSection(@"appSettings");
ConfigurationElementCollection settingsCollection = appSettingsSection.GetCollection();
foreach (ConfigurationElement element in settingsCollection) {
PropertyBag bag = new PropertyBag();
bag[0] = element.GetAttributeValue("key");
bag[1] = element.GetAttributeValue("value");
settingsList.Add(bag);
}
return settingsList;
}
}
}
AssemblyRef 클래스 만들기
여기서는 AssemblyRef 클래스를 만듭니다. 이 클래스는 moduleprovider에서 참조되어 모듈 클래스를 인스턴스화합니다.
프로젝트 메뉴에서 새 항목 추가 옵션을 선택합니다. 새 항목 추가 대화 상자에서 코드 템플릿을 선택하고 파일 이름으로 DemoModuleProvider.cs 를 입력합니다.
using System.Reflection;
internal static class AssemblyRef {
private static string client;
internal static string Client {
get {
if (client == null) {
AssemblyName assemblyName = typeof(AssemblyRef).Assembly.GetName();
string assemblyFullName = assemblyName.FullName;
client = assemblyFullName.Replace(assemblyName.Name, "Client");
}
return client;
}
}
}
모듈 공급자 만들기
여기서는 모듈 공급자를 만듭니다. Inetmgr에서 모듈을 등록하기 위한 기본 진입점입니다. 이러한 모듈 공급자는 Administration.config 나열됩니다.
프로젝트 메뉴에서 새 항목 추가 옵션을 선택합니다. 새 항목 추가 대화 상자에서 코드 템플릿을 선택하고 파일 이름으로 DemoModuleProvider.cs 를 입력합니다.
다음과 같이 표시되도록 코드를 변경합니다.
using System;
using Microsoft.Web.Management.Server;
namespace Server {
internal class DemoModuleProvider : ModuleProvider {
public override ModuleDefinition GetModuleDefinition(IManagementContext context) {
return new ModuleDefinition(Name, "Client.DemoModule," + AssemblyRef.Client);
}
public override Type ServiceType {
get {
return typeof(DemoModuleService);
}
}
public override bool SupportsScope(ManagementScope scope) {
return true;
}
}
}
Administration.Config 항목 추가
이 섹션에서는 moduleProviders 목록의 administration.config 항목을 추가합니다. 어셈블리의 전체 이름은 \Windows\Assembly 폴더에서 찾을 수 있습니다. 어셈블리 클라이언트를 검색하고 마우스 오른쪽 단추로 클릭하고 속성을 클릭합니다.
어셈블리의 전체 이름은 이 창에서 확인할 수 있습니다. 예를 들어 내 경우 어셈블리의 전체 이름은 Server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e788138af6131538입니다. moduleProviders에서 administration.config 추가해야 하는 항목은 다음과 입니다.
<moduleProviders>
<..
<add name="DemoModule" type="Server.DemoModuleProvider,Server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e788138af6131538"/>
../ moduleProviders>
참고
이 항목을 추가하면 이 모듈은 서버 연결에 대해서만 등록됩니다.
솔루션을 빌드하고 inetmgr을 실행하면 다음 스크린샷이 표시됩니다.
요약
inetmgr의 확장성 모델을 사용하고 고유한 사용자 지정 페이지를 만드는 방법을 배웠습니다. 이후 문서에서는 taskItems를 추가하고 구성 파일에 쓰는 방법에 대해서도 설명합니다.