.NET General2006. 3. 5. 00:42

지난 주와 지지난 주 토요일, 그러니까 2월 18일, 25일에 MCPD Beta Exam에 응시해서, 시험을 치뤘다. MCPD는 Microsoft Certified Professional Developer 의 약자로, 이번에 MS에서 닷넷 프레임워크 2.0의 출시와 함께, 새롭게 만들어진 자격증이다. 저는 MCAD를 갖고 있는데, 어느날 beta exam에 무료로 응시해보라는 메일이 왔다. 나중에 어차피 한번 쳐볼까 하는 시험이라서, 공부도 많이 못 했고, 결정적으로…^^;; 기출문제 덤프도 없어서 많이 불안했지만 뭐 불합격해도 본전이라는 생각으로 쳐봤다.


18일에 친건 MCPD Web Application Developer 였고, 25일에는 MCPD Windows Application Developer였다. (MS 자격증 홈페이지를 보면 이것 말고도 Distributed Application Developer라는 게 하나 더 있는데 그건 이번에는 없었다.) 18일에 첫 시험을 쳤을 땐 상당히 당황했다. 처음에 30문제가 나오길래 문제 수가 줄어든 줄 알고 좋아했었는데, 알고보니 30문제/1시간씩 총 3개의 섹션이 있는 것이었다. 그렇게 3시간. 그리고 처음 섹션의 1시간이 끝나면, 그 섹션의 시험문제는 다시 재검토할 수가 없다. 즉 3과목 시험을 연속으로 치는 거랑 비슷하다고 보면 된다.


1,2번째 섹션은 두 시험 다 기존 MCSD, MCAD 시험과 유사한 형태라고 보시면 된다. 언어와 기술에 대한 기본적인 이해가 필요한 문제들이 나온다. 좀 치사하게 나오기 때문에 주의가 필요하다는 것은 기존 시험 쳐보신 분들은 다들 알 것이다. (이게 바로 덤프가 반드시 필요한 이유이기도 하다) 그리고 좀 특기할 것은 이번에 C#에서 (처음에 시험 start 버튼을 누르면 언어 선택 화면이 나오고 거기서 VB, C#, C++ 중에서 고를 수 있다) 추가된 제네릭 (public class GenericList<T> 이런 형태로 쓰는거) 에 대한 문제가 꽤 나왔다. 그리고 두 시험 다 UI에서 데이터를 비동기 형식으로 가져오는 부분에 대한 문제도 여러 개 나왔던 것으로 기억한다.


그리고, 좀 기존에 비해서 특이했던 것이 마지막 섹션이다. 마지막 섹션 30문제는 말하자면, 디자인에 관한 문제들이다. 애플리케이션, 시스템 배포 등에 대해서 상황을 설명하고 그 중 최적의 솔루션, 혹은 문제를 해결하는 방안에 대해서 질문한다. 예를 들면 분산 시스템 환경에서 firewall에서 어떤 포트를 열어야 클라이언트에서 웹 서버에 접속할 수 있는지, 또는 특정 환경에서 클라이언트 배포 방법으로 Windows Installer 가 나은지 아니면 click once 기술이 나은지 등등의 문제가 출제되었다.


시험 방식도 새롭고, 문제도 새로운 스타일의 문제가 많이 나와서 조금은 개선되었다고 말할 수 있을 것 같다. 특히 좀전에 언급한 마지막 섹션같은 경우는 지식도 중요하지만 경험이 있다면 더 쉽게 풀수 있지 않을까 생각이 된다. 아무래도 진정한 실력 평가는 그런 것이 되어야 한다라고 생각했기 때문에, 올바른 방향으로 시험이 발전되었다고 생각한다. 물론 덤프가 나온다면, 뭐 똑같아 지겠지만 말이다.

* 일단 시험은 봤는데, 결과는 바로 나오지는 않았다. 아마 beta라서 그런 것 같은데, 성적은 메일로 준다고 마지막에 나와서 차라리 다행이라고 생각했다..^^;;

Posted by kkongchi
Team Foundation Server2006. 2. 28. 00:57

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/TmFndFund.asp 문서의 요약으로, 회사 내부 세미나 용으로 작성한 것이다.


Team Foundation Server Fundamentals: A Look at the Capabilities and Architecture


What Is Team Foundation Server?


기능
Version control: 소스코드와 다른 버전 컨트롤이 필요한 산출물
Work item tracking: 버그, 요구사항, 작업, 시나리오 등의 추적이 필요한 아이템들
Project management functions: 소프트웨어 프로세스에 기반한 팀 프로젝트의 형성과 엑셀, 프로젝트를 사용한 계획/추적을 가능하게 한다.
Team build: 빌드를 위한 공통적인 프로세스를 가능하게 한다.
Data collection and reporting: 팀 파운데이션 서버에서 모아진 정보를 기반으로 해서 현재 프로젝트의 상태를 평가할 수 있게 해준다
The Team Project Portal; 셰어포인트 서비스를 이용해서 팀 커뮤니케이션의 중심을 제공한다.
Team Foundation Shared Services: 공통적인 기반구조 서비스를 제공해서 확장가능하고, 이 서비스들에 기반한 도구를 만들 수 있게 해준다.


The Shape of Team Foundation






Elements of Team Foundation Server
Project Management
 
  작업 항목 Tracking 기능을 통해서 프로젝트의 진행 상황과 위험도 등을 알 수 있다.
프로젝트 템플릿 기능을 통해서, 프로젝트 프로세스를 환경에 적합하게 맞출 수 있다.
디폴트 프로세스 템플릿 (MSF For Agile / MSF For CMMI)
이 템플릿은 확장/변형 가능해서 프로젝트나 환경에 맞게 고칠 수 있다.

Version Control
 
  SQL 서버를 사용
check-in, check-out, version management, and diff/merge
Shelving (보류) 등의 새로운 기능을 추가
체크인 정책(테스트, 코드 리뷰 등)
Work Item Tracking

버그, 요구사항, 시나리오, 작업 등의 모니터링이 필요한 항목들을 저장/관리할 수 있다. (작업 항목의 유형, 그에 따른 추가적인 필드등은 확장 가능하다)
Visual Studio IDE, 엑셀, 프로젝트 등에서 작업이 가능

Team Build

빌드를 수행하는 간단한 방식을 제공
테스트, 코드 리뷰, 작업 항목 업데이트 등의 기능을 빌드와 동시에 수행 가능
“빌드 서버” 기능을 지원
각 빌드의 로그(진행상황, 결과)등을 기록한다. 이 결과는 SQL에서 분석되어서 리포트된다.
Data Collection and Reporting
  모든 데이터는 SQL 에 저장
각 데이터는 DataWarehouse로 모여져서 분석된다.(SQL Analysis Service)
SQL Reporting Service를 통해서 리포트 형태로 출력될 수 있다.

The Project Portal

프로젝트 커뮤니케이션의 포탈로 이용할 수 있다.
문서 라이브러리 기능
프로젝트 템플릿에 따른 문서 샘플이 제공된다.

Shared Services

  모든 서비스는 확장 가능하도록 설계되었으며, Custom 툴을 만들어서 사용할 수 있다.

Architected for Extensibility


Linking service

  데이터 요소들 간의 느슨한 결합 관계를 연결시키는데 쓸 수 있다.
예를 들면, 버그와 그 버그를 해결하기 위해 수정한 소스 코드를 연결하는 데 쓸 수 있다.

Security service

팀 파운데이션 서버 보안 관련 API를 제공한다.
IT 서비스 팀이 팀 파운데이션 서버의 보안을 조정할 수 있는 툴을 만들 수도 있고, 다른 툴들에서 권한 부여용 API로도 사용할 수 있다.

Eventing service

웹 서비스 기반의 publish/subscribe 구조이다.
구독자는 특정 이벤트가 일어났을 때, 알림을 받을 수 있다. 이 구독자는  이메일 주소일 수도 있고, 웹 서비스일 수도 있다
Classification service

Linking service와 결합해서, 팀 파운데이션 서버 산출물들을 분류하는데 쓰인다.
예를 들어, 테스트는 모듈 단위로 분류되지만, 이 분류 서비스를 사용해서 팀 단위로도 분류할 수 있다.

Registration service
  새로운 도구가 추가되었을 때, 그 도구의 산출물 유형이나 이벤트 스키마 등등은 registration service 를 통해서 등록된다.

그 외 기능

VSIP (Visual Studio Industry Partner Program) 패키지를 통해서 Visual Studio IDE에 통합시키거나, 혹은 별도의 닷넷 프로그램을 만들 수도 있다.
새로운 툴과 관련된 도구들을 프로젝트 생성 마법사에 추가시킬 수도 있다.
새로운 툴과 데이터를 팀 익스플로러의 트리 노드에 추가시킬 수도 있다.
데이터 웨어하우스 스키마를 확장시켜서, 새로운 툴과 관련한 데이터만을 가져올 수도 있다.
Posted by kkongchi
asp.net2006. 2. 25. 00:42

HTTP 압축은 gzip 등의 알고리즘을 사용해서, HTTP 를 통해서 전송되는 데이터의 양을 최고 50%로 압축하는 기술이다. ASP.NET 으로 만든 페이지들의 사이즈가 커서 Response Time 이 느리거나, 낮은 대역폭 - 이를테면 56K 라인 - 의 사용자들까지도 지원할려고 한다면, 그리고 더 많은 사용자를 지원하기 위해서 서버의 대역폭을 아껴쓰고자 할 때 상당히 유용하다.

HTTP 압축을 위한 상용 모듈도 있지만, Windows 2003에 내장된 IIS 6.0에서는 자체적으로도 지원을 한다. IIS 관리자에서 아주 간단하게 설정을 할 수 있다. IIS 관리자를 열어서, 트리의 "웹 사이트" 노드에다 마우스 오른쪽 버튼을 클릭하면 나오는 메뉴 중에서 속성을 선택한다. 그리고 "서비스" 탭을 선택하면 다음과 같은 화면이 나올텐데, 간단하게 체크만 해주고, IIS를 한번 Restart 시켜주면 바로 HTTP 압축을 사용할 수가 있다.




하지만, 이렇게만 했을 경우에 ASP.NET 의 aspx 는 압축되어서 내려가지 않는다. IIS가 압축하는 파일 유형에 포함되어 있지 않기 때문이다. aspx도 포함을 시키기 위해서는 WIN_DIR\System32\inetsrv\metabase.xml 파일을 편집해야 합니다. 이 파일에서 <IIsCompressionScheme> 노드를 찾아야 합니다
<IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/deflate"
HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"
HcCreateFlags="0"
HcDoDynamicCompression="TRUE"
HcDoOnDemandCompression="TRUE"
HcDoStaticCompression="FALSE"
HcDynamicCompressionLevel="0"
HcFileExtensions="htm
html
txt"
HcOnDemandCompLevel="10"
HcPriority="1"
HcScriptFileExtensions="asp
dll
exe
  aspx"
>
</IIsCompressionScheme>
<IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/gzip"
HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"
HcCreateFlags="1"
HcDoDynamicCompression="TRUE"
HcDoOnDemandCompression="TRUE"
HcDoStaticCompression="TRUE"
HcDynamicCompressionLevel="0"
HcFileExtensions="htm
html
txt"
HcOnDemandCompLevel="10"
HcPriority="1"
HcScriptFileExtensions="asp
dll
exe
  aspx"
>
</IIsCompressionScheme>

빨간 색으로 되어 있는 부분처럼, aspx확장자를 추가시켜주면 그때부터 aspx파일에 대해서도 IIS가 HTTP 압축을 수행할 것이다. (이 파일은 편집하기 위해서 IIS를 잠시 멈춰야 편집을 할 수 있다)

당연한 거겠지만, 압축을 수행하는 서버와 압축된 컨텐트를 받아서 풀어서 보여줘야 하는 클라이언트 양쪽에 약간씩의 CPU 부담이 있다. 하지만 30-50%에 이르는 압축율은 성능 향상과 대역폭 절약이라는 엄청난 이점을 가져오기 때문에, Windows 2003을 사용하는 웹 사이트에서는 충분히 사용할만한 기술인 것 같다.
Posted by kkongchi
asp.net2006. 2. 24. 00:23

지난번에 모 회사의 그룹웨어 시스템을 만드는 프로젝트에 참가한 적이 있다. ASP.NET 웹애플리케이션인데, 여기 고객들이 어느 날은 웹 페이지의 소스를 보더니, 이상한 것이 있다고 하는 거였다. 뭔지 봤더니 ASP.NET Viewstate를 보시고 말한 것이었다. 실제로, 굉장히 이상해 보인다. 전혀 의미를 알 수 없는 이상한 글자들이 적지도 않게 있으니까. 고객 입장에서는 페이지 속도가 느린 것이 혹시 이것 때문이 아닌가 싶었나 보다.


그럼 Viewstate란? .NET Framework SDK의 설명을 참조해보겠다. "페이지 자체를 포함하여 Web Forms 페이지의 각 컨트롤에는 기본 Control 컨트롤에서 상속된 ViewState 속성이 있습니다. 뷰 상태는 ASP.NET 페이지 프레임워크에서 페이지를 렌더링하기 직전에 페이지와 각 컨트롤 값을 자동으로 저장할 때 사용됩니다. 페이지가 게시될 때 페이지 처리에서 처음 수행되는 작업이 뷰 상태 복원입니다"


그럼, ASP.NET 코드를 한 번 보면

public class WebForm1 : System.Web.UI.Page

{

protected System.Web.UI.WebControls.Label Label1;

protected System.Web.UI.WebControls.Button Button1;

protected System.Web.UI.WebControls.Label Label2;

private void Page_Load(object sender, System.EventArgs e)

{

if(!Page.IsPostBack)

{

this.Label1.Text = "Label1";

this.Label2.Text = "Label2";

}

}

private void Button1_Click(object sender, System.EventArgs e)

{

this.Label2.Text = "Button Clicked";

}

}


페이지가 로드될 때, 라벨1과 라벨2에는 각각의 텍스트가 들어가게 된다. 버튼을 눌러서 Post-Back이 일어난다면 어떻게 될까? 버튼 클릭 이벤트에 있는 대로 라벨2의 텍스트는 "Button clicked"라고 바뀐다. 그러면 label1은? Button_click 이벤트가 일어나기 전에 page_load가 한번 더 실행이 되지만, if문을 사용해서 Page가 IsPostBack이 아닐 때만 라벨에 텍스트를 넣는 코드가 실행이 되는 것이다. 그러면 label1은 비어있을까? 다들 알겠지만, label1에는 "label1"이라는 텍스트가 그대로 유지가 되게 된다. 바로 이 값을 유지하기 위해서, ASP.NET이 페이지와 페이지의 각 컨트롤의 상태를 암호화시킨 형태로 HTML의 히든 필드로 넣어둔 것이 바로 Viewstate이다. 이 코드를 실행시킨 페이지의 소스를 보면 이런 형태로 뷰 스테이트가 들어가 있을 것이다.

<input type="hidden" name="__VIEWSTATE" value="dDwzMTkxMTg2NDc7dDw7bDxpPDE+Oz47bD

x0PDtsPGk8MT47aTwzPjs+O2w8dDxwPHA8bDxUZXh0Oz47bDxMYWJlbDE7Pj47Pjs7Pjt0PH

A8cDxsPFRleHQ7PjtsPEJ1dHRvbiBDbGlja2VkOz4+Oz47Oz47Pj47Pj47PhHZi18rwfZPDuHEtU+

SD6bOswOI" />


그런데 이 뷰스테이트는 양날의 검이라고도 할 수 있다. 개발자들에게는 편리한 프로그래밍 방법을 제공하지만, 주의깊게 사용하지 않는다면 성능에 엄청난 마이너스가 되기 때문이다. 기본적으로 모든 페이지와 모든 컨트롤에 뷰스테이트가 활성화되어 있기 때문이다. 그래서 불필요한 모든 컨트롤에도 뷰스테이트가 들어가게 되는 것이다. 실제로 지금 하고 있는 프로젝트에서 트리 컨트롤을 사용한 페이지가 있었는데, 페이지 로드에서 언제나 모든 데이터를 바인딩하는 로직으로 짜여져 있었기 때문에 뷰스테이트가 전혀 필요없는 구조였다. 그런데 뷰스테이트는 모든 컨트롤에 활성화되어 있었고, 뷰스테이트를 뺐더니 렌더링된 HTML의 사이즈가 70%로 감소했다.

페이지 수준에서 뷰스테이트를 비활성화시킬려면, aspx페이지의 가장 위에 있는 <@Page>지시문에  EnableViewState="false"라고 써주면 된. 컨트롤 태그 에이와 같이 직접 해줘도 된다.

<asp:Label id="Label1" enableViewState="False" runat="server"></asp:Label>


일반적인권장사항은 "서버 컨트롤 뷰 상태는 필요할 때만 저장합니다". 위에서도 말했지만 뷰스테이트는 디폴트로 모두 활성화되어 있기 때문에, 성능에 엄청난 영향을 주는 경우가 아주 많다.

Posted by kkongchi
C# & VB.NET2006. 2. 23. 16:10

IIS의 기본 인증으로 설정된 웹서비스의 경우를 호출하기 위해서는 실제 기본 인증의 개념 그대로, ID, PW 를 넘겨줘야 인증을 통과할 수가 있다. 그냥 호출하게 되면 UnauthorizedAccessException이 발생하게 된다.

  1. localhost.Service1 oService = new WebApplication.localhost.Service1();
  2. //ID, PW, 도메인 이름으로 새로운 Credential 을 생성한다
  3. System.Net.NetworkCredential oCredential = new System.Net.NetworkCredential("id", "pw", "domain_name");
  4. System.Net.CredentialCache oCache = new System.Net.CredentialCache();
  5. oCache.Add(new Uri(oService.Url), "Basic", oCredential);
  6. //호출하는 서비스의 Credential을 위에서 만든 새로운 Credential로 생성한다.
  7. oService.Credentials = oCache;
  8. Response.Write(oService.HelloWorld());

통합인증의 경우는 아래 코드처럼 현재 로그인한 사용자의 Credential로 넘기면 호출할 수 있다.

  1. oService.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
Posted by kkongchi
.NET General2006. 2. 20. 18:27

NAnt를 혹시 사용해보셨는지?

Ant는 원래 Java에서 사용하던 빌드 툴이다. C에서 사용하는 Make와 같은 역할을 하지만 역시 Java답게 운영체제나 시스템에 독립적인 빌드환경을 제공하기 위해서 Apache그룹에서 만든 빌드 프레임워크인데, NAnt는 SourceForge 커뮤니티에서 제작한 Ant의 .NET 버전이라고 생각하면 된다.

아래와 같은 빌드정의 파일(.build)을 XML포맷으로 만들고 그 파일이 있는 디렉토리에서 NAnt라고 Command-Line 명령을 실행하기만 하면 된다. 비주얼 스튜디오를 열지않고도 빌드를 할 수 있고, Nightly Build(Daily)도 가능하며, 서비스 형태로 몇 시간 혹은 몇 분마다 빌드를 하는 것도 가능하다. 그리고 컴파일뿐만 아니라 여러가지 부가적인 작업들도 실행을 시킬 수가 있다. 밑의 예제처럼 NUnit 테스트, FxCop을 이용한 코드 리뷰 등도 가능하다.


  1. <?xml version="1.0"?>
  2. <!- 프로젝트 이름 지정 -->
  3. <project name="AntTest" default="build">
  4. <target name="build">
  5.   <echo message="Building AntTest ...."/>
  6.   <tstamp property="build.date" pattern="yyyyMMdd" verbose="true" />
  7.   <echo message="{build.date}"/>
  8.    <!-- 프레임워크 버전을 지정 -->
  9.    <available type="FrameworkSDK" resource="net-1.1" property="net-1.1.frameworksdk.present" />
  10.    <!-- 빌드할 솔루션을 지정. 이 솔루션을 컴파일하게 된다 -->
  11.    <solution configuration="debug" solutionfile="AntTestSln\AntTestSln.sln">
  12.    <!-- 웹 프로젝트는 웹경로를 지정해야 한다-->
  13.    <webmap>
  14.    <map url="http://localhost/AntTestWeb/AntTestWeb.csproj" path="..\WEB\AntTestWeb.csproj" />
  15.    </webmap>
  16.    </solution>
  17.     <!-- NUnit 을 사용해서 유닛테스트를 수행한다. 물론 NUnit 테스트용으로 만든 어셈블리에 한해서 -->
  18.     <nunit2>
  19.     <formatter type="Xml" usefile="true" extension=".xml" outputdir="TEST\results" />
  20.     <test assemblyname="TEST\bin\debug\TEST.dll"/>
  21.     </nunit2>
  22.     <!-- FxCop 으로 코드리뷰를 수행한다 -->
  23.     <exec program="FxCopCmd" commandline="/file:COM\bin\Debug\com.dll /out:review\review.xml" />
  24.     <!-- NUnit Report를 사용해서 NUnit 유닛테스트 결과를 리포트에 기록한다 -->
  25.     <nunit2report out="TEST\results\NUnitReport(No-Frame).html" >
  26.     <fileset>
  27.         <includes name="TEST\results\TEST.dll-results.xml" />
  28.     </fileset>
  29.     <summaries>
  30.         <includes name="TEST\bin\debug\TEST.xml" />
  31.     </summaries>
  32.     </nunit2report>
  33.     <mail
  34.               from="buildmaster@project.com"
  35.               tolist="buildmaster@project.com"
  36.               subject="{build.date} 빌드가 완료되었습니다"
  37.               mailhost="mail.project.com">
  38.     </mail>
  39. </target>
  40. </project>
 
Posted by kkongchi
C# & VB.NET2006. 2. 20. 14:41

그냥 서버에 접속해서 이벤트로그를 보면 되지 않느냐라고 생각하실 수도 있지만...
단일한 관리용 웹페이지에서 이벤트로그, DB의 로그 등을 모두 보고 싶어 할 수도 있다.
아래 코드는 C#으로 작성한 ASP.NET 페이지로, 주어진 이름의 이벤트로그의 데이터를 읽어와서 그리드에 바인딩시키는 코드이다.

  1. private void Page_Load(object sender, System.EventArgs e){
  2.   this.DataGrid1.DataSource = this.GetData("Comm.SQL");
  3.   this.DataGrid1.DataBind();
  4. }
  5. private DataSet GetData(string eventLogName){
  6.   System.Diagnostics.EventLog oLog = null;
  7.   System.Diagnostics.EventLogEntryCollection oEntryCollection = null;
  8.   System.Data.DataSet dsEventLog = null;
  9.   System.Data.DataTable dtEventLog = null;
  10.   try{
  11.        dsEventLog = new DataSet("EventLogDataList");
  12.        dtEventLog = new DataTable(eventLogName);
  13.        dtEventLog.Columns.Add("Type");
  14.        dtEventLog.Columns.Add("Day");
  15.        dtEventLog.Columns.Add("Time");
  16.        dtEventLog.Columns.Add("Source");
  17.        dtEventLog.Columns.Add("Category");
  18.        dtEventLog.Columns.Add("Event");
  19.        dtEventLog.Columns.Add("User");
  20.        dtEventLog.Columns.Add("Machine");
  21.        oLog = new System.Diagnostics.EventLog(eventLogName);
  22.        oEntryCollection = oLog.Entries;
  23.        for(int i=0;i<oEntryCollection.Count;i++){
  24.            string[] arrLogEntry = new string[8];
  25.            arrLogEntry[0] = oEntryCollection[i].EntryType.ToString();
  26.            arrLogEntry[1] = oEntryCollection[i].TimeGenerated.ToShortDateString();
  27.            arrLogEntry[2] = oEntryCollection[i].TimeGenerated.ToShortTimeString();
  28.            arrLogEntry[2] = "<a href='webform2.aspx?LogName=" + eventLogName + "&Index=" + i.ToString() + "'>" + arrLogEntry[2] + "</a>";
  29.            arrLogEntry[3] = oEntryCollection[i].Source;
  30.            arrLogEntry[4] = oEntryCollection[i].Category;
  31.            arrLogEntry[5] = oEntryCollection[i].EventID.ToString();
  32.            arrLogEntry[6] = oEntryCollection[i].UserName;
  33.            arrLogEntry[7] = oEntryCollection[i].MachineName;
  34.             dtEventLog.Rows.Add(arrLogEntry);
  35.      }
  36.      dsEventLog.Tables.Add(dtEventLog);
  37.   }
  38.   catch(Exception ex)
  39.   {
  40.        throw ex;
  41.   }
  42.   return dsEventLog;
  43. }


위 코드는 이벤트뷰어와 똑같은 칼럼 순서로 이벤트 리스트를 그리드에 뿌리게 된다.
2번째 칼럼은 원래는 시간 데이터인데, 거기에 링크를 거는 부분이 있다.
이벤트 뷰어에서도 더블 클릭을 하면 이벤트에 대한 자세한 사항을 나타내는 창이 뜨는데,
아래는 바로 그 링크에서 연결되는 Detail 화면을 뿌리기 위한 코드이다.

  1. protected System.Web.UI.HtmlControls.HtmlInputText txtDay;
  2. protected System.Web.UI.HtmlControls.HtmlInputText txtTime;
  3. protected System.Web.UI.HtmlControls.HtmlInputText txtType;
  4. protected System.Web.UI.HtmlControls.HtmlInputText txtSource;
  5. protected System.Web.UI.HtmlControls.HtmlInputText txtCategory;
  6. protected System.Web.UI.HtmlControls.HtmlInputText txtEvent;
  7. protected System.Web.UI.HtmlControls.HtmlInputText txtUser;
  8. protected System.Web.UI.HtmlControls.HtmlInputText txtMachine;
  9. protected System.Web.UI.HtmlControls.HtmlTextArea txtDescription;
  10. private void Page_Load(object sender, System.EventArgs e)
  11. {
  12.   try
  13.   {
  14.     string strLogName = Request["LogName"];
  15.     string strIndex = Request["Index"];
  16.     int nIndex = Convert.ToInt32(strIndex);
  17.     this.SetContent(strLogName, nIndex);
  18.   }
  19.   catch(Exception ex)
  20.   {
  21.     Response.Write(ex.ToString());
  22.   }
  23. }
  24. private void SetContent(string logName, int index)
  25. {
  26.   System.Diagnostics.EventLog oLog = null;
  27.   System.Diagnostics.EventLogEntry oEntry = null;
  28.   try
  29.   {
  30.     oLog = new System.Diagnostics.EventLog(logName);
  31.     oEntry = oLog.Entries[index];
  32.     this.txtDay.Value = oEntry.TimeGenerated.ToShortDateString();
  33.     this.txtTime.Value = oEntry.TimeGenerated.ToLongTimeString();
  34.     this.txtType.Value = oEntry.EntryType.ToString();
  35.     this.txtSource.Value = oEntry.Source;
  36.     this.txtCategory.Value = oEntry.Category;
  37.     this.txtEvent.Value = oEntry.EventID.ToString();
  38.     this.txtUser.Value = oEntry.UserName;
  39.     this.txtMachine.Value = oEntry.MachineName;
  40.     this.txtDescription.Value = oEntry.Message;
  41.   }
  42.   catch(Exception ex)
  43.   {
  44.     throw ex;
  45.   }
  46. }
 
Posted by kkongchi