2009년 6월 22일 월요일

IIS를 설치하기전에 asp.net 2.0이상을 먼저 설치하고 IIS를 설치했을경우

문제
  IIS를 설치하기전에 asp.net 2.0이상을 먼저 설치하고 IIS를 설치했을경우
asp.net 2.0이상이 설치되어있음에도 IIS는 이를 인식하지 못한다.

해결
  이럴경우 aspnet_regiis명령을 이용하여 IIS(Internet Information Service)에 재설치를 해주면 문제가 해결이 된다.

방법
  aspnet_regiis명령을 이용하기 위해서는 Visual Studio 명령 프롬프트를 사용하는게 좋다.
aspnet_regiis.exe 파일은 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 위치에 존재한다.
Visual Studio 명령 프롬프트를 이용하면 해당 경로가 Path설정이 되어있기때문에 어디서든 실행이 가능하다.
하지만 실행창에서 cmd라는 명령으로 얻어지는 명령 프롬프트는 해당 경로가 path설정이 되어있지 않기때문에
aspnet_regiis.exe 파일이 존재하는 폴더로 이동을 해야한다.(요즘같이 폴더명이 길어지는 시대에는 번거롭다.^^)

Visual Studio 명령 프롬프트를 사용한 화면


기본 명령 프롬프트를 사용한 화면


aspnet_regiis 속성은 아래와 같다.
사용예)  c:>aspnet_regiis -i


                              -- ASP.NET 등록 옵션 --

-i           이 버전의 ASP.NET을 설치하고 IIS 메타베이스 루트에 있는 스크립트맵
과 루트 아래의 모든 스크립트맵을
             업데이트합니다. 하위 버전의 기존 스크립트맵은 이 버전으로 업그레이
드됩니다.

-ir          이 버전의 ASP.NET을 설치하고 등록만 합니다. IIS의 스크립트맵은 업데
이트하지 않습니다.

-iru         이 버전의 ASP.NET을 설치합니다. ASP.NET을 사용하는 기존 응용 프로그
램이 있으면 IIS의 스크립트맵을
             업데이트하지 않습니다.

-enable      -enable을 -i, -ir 또는 -r와 함께 지정하면 IIS 보안 콘솔(IIS 6.0 이
상)에서도 ASP.NET을
             사용할 수 있게 됩니다.

-disable     -disable을 -i, -ir 또는 -r와 함께 지정하면 IIS 보안 콘솔(IIS 6.0 이
상)에서 ASP.NET을
             사용할 수 없게 됩니다.

-s <경로>      지정한 경로에 이 버전의 스크립트맵을 재귀적으로 설치합니다.
             예: aspnet_regiis.exe -s W3SVC/1/ROOT/SampleApp1

-sn <경로>     지정한 경로에 이 버전의 스크립트맵을 비재귀적으로 설치합니다.

-r           이 버전의 ASP.NET을 설치하고 IIS 메타베이스 루트에 있는 스크립트맵
과 루트 아래의 모든 스크립트맵을
             업데이트합니다. 기존 스크립트맵은 원래 버전에 관계없이 이 버전으로
업그레이드됩니다.

-u           이 버전의 ASP.NET을 제거합니다. 이 버전에 대한 기존 스크립트맵은 시
스템에 설치되어 있는 남은 ASP.NET 중
             가장 높은 버전으로 다시 매핑됩니다.

-ua          시스템에서 모든 버전의 ASP.NET을 제거합니다.

-k <경로>      지정한 경로에서 모든 버전의 ASP.NET에 대한 모든 스크립트맵을 재귀
적으로 제거합니다.
             예: aspnet_regiis.exe -k W3SVC/1/ROOT/SampleApp1

-kn <경로>     지정한 경로에서 모든 버전의 ASP.NET에 대한 모든 스크립트맵을 비재
귀적으로 제거합니다.

-lv          시스템에 설치되어 있는 모든 버전의 ASP.NET을 상태 및 설치 경로와 함
께 나열합니다.

-lk          ASP.NET이 스크립트 매핑되어 있는 모든 IIS 메타베이스 키의 모든 경로
를 버전과 함께 나열합니다. 부모 키에서
             ASP.NET 스크립트맵을 상속 받는 키는 표시되지 않습니다.

-c           각 IIS 사이트 디렉터리의 aspnet_client 하위 디렉터리에 이 버전에 대
한 클라이언트측 스크립트를
             설치합니다.

-e           각 IIS 사이트 디렉터리의 aspnet_client 하위 디렉터리에서 이 버전에
대한 클라이언트측 스크립트를
             제거합니다.

-ea          각 IIS 사이트 디렉터리의 aspnet_client 하위 디렉터리에서 모든 버전
에 대한 클라이언트측 스크립트를
             제거합니다.

-ga <사용자>    지정한 사용자 또는 그룹에 ASP.NET에서 사용하는 IIS 메타베이스 및
 기타 디렉터리에 대한 액세스 권한을
             부여합니다.


                                -- 구성 암호화 옵션 --

-pe 섹션       구성 섹션을 암호화합니다. 선택적 인수:
             [-prov provider] 이 공급자를 사용하여 암호화합니다.
             [-app virtual-path] 이 가상 경로에서 암호화합니다. 가상 경로는 슬래
시로 시작해야 합니다. 가상 경로가
             '/'인 경우 해당 사이트의 루트를 나타냅니다. -app를 지정하지 않으면
루트 web.config가 암호화됩니다.
             [-site site-name-or-ID] -app에 지정한 가상 경로의 사이트입니다. 지
정하지 않으면 기본 웹
             사이트가 사용됩니다.
             [-location sub-path] 위치 하위 경로입니다.
             [-pkm] web.config 대신 machine.config를 암호화/해독합니다.

-pd 섹션       구성 섹션의 암호를 해독합니다. 선택적 인수:
             [-app virtual-path] 이 가상 경로에서 암호를 해독합니다. 가상 경로는
 슬래시로 시작해야 합니다. 가상
             경로가 '/'인 경우 해당 사이트의 루트를 나타냅니다. -app를 지정하지
않으면 루트 web.config가
             암호화됩니다.
             [-site site-name-or-ID] -app에 지정한 가상 경로의 사이트입니다. 지
정하지 않으면 기본 웹
             사이트가 사용됩니다.
             [-location sub-path] 위치 하위 경로입니다.
             [-pkm] web.config 대신 machine.config를 암호화/해독합니다.

-pef 섹션 web-app-physical-dir
             구성 섹션을 암호화합니다. 선택적 인수:
             [-prov provider] 이 공급자를 사용하여 암호화합니다.

-pdf 섹션 web-app-physical-dir
             구성 섹션의 암호를 해독합니다.

-pc 컨테이너     ContainerName에 RSA 키 쌍을 만듭니다. 선택적 인수:
             [-size key-size] 키 크기입니다. 기본값은 1024입니다.
             [-pku] 시스템 컨테이너가 아니라 사용자 컨테이너를 사용합니다.
             [-exp] 개인 키를 내보낼 수 있도록 만듭니다.
             [-csp provider] 사용할 Csp 공급자입니다.

-pz 컨테이너     ContainerName을 삭제합니다. 선택적 인수:
             [-pku] 시스템 컨테이너가 아니라 사용자 컨테이너를 사용합니다.

-pi 컨테이너 파일  Xml 파일에서 RSA 키 쌍을 가져옵니다. 선택적 인수:
             [-pku] 시스템 컨테이너가 아니라 사용자 컨테이너를 사용합니다.
             [-exp] 내보낼 수 있는 키를 만듭니다.
             [-csp provider] 사용할 Csp 공급자입니다.

-px 컨테이너 파일  RSA 키 쌍을 Xml 파일로 내보냅니다. 선택적 인수:
             [-pku] 시스템 컨테이너가 아니라 사용자 컨테이너를 사용합니다.
             [-pri] 개인 키를 포함합니다.
             [-csp provider] 사용할 Csp 공급자입니다.

-pa 컨테이너 계정  계정에 대한 액세스 권한을 컨테이너에 추가합니다. 인수:
             [-pku] 시스템 컨테이너가 아니라 사용자 컨테이너를 사용합니다.
             [-csp provider] 사용할 Csp 공급자입니다.
             [-full] 전체 액세스 권한을 추가합니다. 기본값은 읽기 권한입니다.

-pr 컨테이너 계정  계정에 대한 액세스 권한을 컨테이너에서 제거합니다. 인수:
             [-pku] 시스템 컨테이너가 아니라 사용자 컨테이너를 사용합니다.
             [-csp provider] 사용할 Csp 공급자입니다.


-- 구성 원격 액세스 옵션 --

-config+     구성에 원격으로 액세스할 수 있도록 설정합니다.

-config-     구성에 원격으로 액세스할 수 없도록 설정합니다.

2009년 6월 8일 월요일

Processing untyped messages from MSMQ binding

Now that .NET 3.0 is finally released, I am putting in some hours to see how it can be implemented in our infrastructure. Up front the power and flexibility of the framework is a bit overwhelming, however, the tools that are included are great. For example Service Configuration Editor has a great way to specify every setting required and optional for setting up WCF communication.

One of the components that I was looking to replace is a MSMQ Message Processing application. Basically it is a custom written MSMQ Trigger service. Well.. here goes.

WCF includes a binding for interconnecting with non-WCF MSMQ implementations. I've created the final prototype from the basic service sample, and created a ServiceContract interface and implementation class

[ServiceContract()]
public interface IMessageProcessor
{
   [OperationContract(IsOneWay = true)]
   void ProcessMessage(MsmqMessage<Stream> msg);
}

public class MessageProcessor : IMessageProcessor
{
   public void ProcessMessage(MsmqMessage<Stream> msg)
   {
      using (StreamReader sr = new StreamReader(msg.Body))
      {
         MessageBox.Show("Hello: " + sr.ReadToEnd());
         sr.Close();
      }
   }
}

Then added created a main form, and added start/stop events
 
internal static ServiceHost myServiceHost = null;
internal static void StartService()
{
   // Instantiate new ServiceHost
   myServiceHost = new ServiceHost(typeof(MessageProcessor));
   myServiceHost.Open();
}
internal static void StopService()
{
   // Call StopService from your shutdown logic (i.e. dispose method)
   if (myServiceHost.State != CommunicationState.Closed)
   myServiceHost.Close();
}
private void MainForm_Load(object sender, EventArgs e)
{
   StartService();
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
   StopService();
}

The next step is to setup the app.config configuration file.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
   <system.serviceModel>
      <behaviors>
         <serviceBehaviors>
            <behavior name="Throttling">
               <serviceThrottling maxConcurrentCalls="2" />
            </behavior>
         </serviceBehaviors>
      </behaviors>
      <bindings>
         <msmqIntegrationBinding>
         <binding name="NewBinding0" exactlyOnce="false" serializationFormat="Stream" />
         </msmqIntegrationBinding>
      </bindings>
      <services>
         <service behaviorConfiguration="Throttling" name="WCFMQListener.MessageProcessor">
            <endpoint address="msmq.formatname:DIRECT=OS:.\private$\testqueue" binding="msmqIntegrationBinding"bindingConfiguration="NewBinding0" contract="WCFMQListener.IMessageProcessor" />
         </service>
      </services>
   </system.serviceModel>
</configuration>

The most time I've spent was to figure out how to read the non-xml formatted message. The key is to declare the method as

void ProcessMessage(MsmqMessage<Stream> msg);

and to adjust binding in the configuration file

serializationFormat="Stream"

The message can be read just as easily as a binary array.


출처 : http://blog.tfanshteyn.com/2006_11_01_archive.html