C# & VB.NET2006. 6. 21. 00:27

클래스를 참조하지 않은 상태에서, DLL로부터 동적으로 클래스를 로드해서 써야 경우가 있다. 그럴때는 .NET에서 제공하는 Reflection API사용해서 클래스를 로드하고 인스턴스화할 있다. 다음 코드와같이 사용하면 된다.

System.Reflection.Assembly assm =

System.Reflection.Assembly.LoadFile(@"D:\Assemblies\SomeAssembly.dll");

object obj = assm.CreateInstance("FullClassName");

Posted by kkongchi
C# & VB.NET2006. 5. 12. 03:00

네이버가 구글처럼 웹 문서 검색, 지식인 검색 등의 기능을 원격에서 호출할 수 있는 API 서비스를 오픈했다. 현재는 베타 테스트 중이고 하루에 기능을 사용할 수 있는 횟수가 한정되어 있지만 이 API를 사용해서 실제 네이버 웹 문서 검색 페이지와 똑같은 기능을 하는 페이지를 만들어 볼 수 있다.

자세한 사항은 여기로 -> http://openapi.naver.com/
사용하려면 회원 가입을 해서 키를 하나 받아야 한다.

다음 소스는 이 API를 사용해서 네이버 웹 문서를 검색하는 페이지를 Visual Studio 2005, C#으로 만들어 본 샘플이다.

먼저 페이지 디자인.
간단하게 검색어를 입력하는 텍스트 박스와 검색을 실행하는 버튼으로 구성했다.


네이버 API를 통해서 검색한 결과는 다음과 같이 RSS 포맷으로 반환이 된다.

<?xml version="1.0" encoding="UTF-8" ?>
<rssversion="2.0">
<channel>
<title>Naver Open API - webkr ::'go'</title>
<link>http://search.naver.com</link>
<description>Naver Search Result</description>
<lastBuildDate>Tue, 11 Apr 2006 14:36:33 +0900</lastBuildDate>
<total>18992582</total>
<start>1</start>
<display>10</display>
  <item>
  <title><b>GO</b>.com</title>
  <link>http://www.go.com/</link>
  <description>... Victims, Military Personnel Sell Rations Online Government Report Finds Ready-to-Eat Meals for Sale on eBay...... trailers and the latest buzz on... Harry Potter and the Goblet of Fire , X-Men 3 , Spider-Man 3 , more... Tonight...</description>
  </item>
</channel>
</rss>

아래부터는 코드이다. 위의 RSS XML을 파싱해서, 목록으로 뿌려주는 것이다.
버튼 클릭 이벤트에서 실제 기능을 구현하도록 작성했다.

protected void Button1_Click(object sender, EventArgs e)
{    
//네이버 API는 정의된 URL을 호출해서 RSS타입의 XML을 받을 수 있도록 구성되어 있다
//URL 호출을 위해서 WebClient 클래스를 하나 선언하고, 인스턴스화한다

System.Net.WebClient oClient = new System.Net.WebClient();

  //네이버 API URL을 구성한다. GET방식으로 이루어져 있기 때문에 QueryString을 추가한다
//이 예제는 국내 웹 문서 검색을 하는 예제이다

oClient.QueryString.Add("key", "YourKey"); //회원가입 시에 받은 키
  oClient.QueryString.Add("target", "webkr"); //웹문서 검색
oClient.QueryString.Add("display", "100"); //100개의 결과 디스플레이
oClient.QueryString.Add("start", "1"); //1페이지부터 시작
  oClient.QueryString.Add("query", this.TextBox1.Text); //텍스트박스에 입력받은 텍스트를 검색어로 설정한다
  oClient.Encoding = System.Text.Encoding.UTF8; //반드시 인코딩은 UTF-8, 네이버 API의 규칙이다.

  //구성된 URL을 호출해서, 그 결과를 문자열로 받는다
  string s = oClient.DownloadString("http://openapi.naver.com/search");

  //문자열을 XMLDocument 객체로 로드한다
  System.Xml.XmlDocument oXmlDoc = new System.Xml.XmlDocument();
oXmlDoc.LoadXml(s);
 
//XPATH정규식을 통해서 item항목, 즉 검색 결과 항목들만을 뽑아낸다
  System.Xml.XmlNodeList oNodeList = oXmlDoc.SelectNodes("/rss/channel/item");

  //검색결과 화면을 위한 HTML 테이블 구성
  System.Web.UI.HtmlControls.HtmlTable oTable = new HtmlTable();
oTable.Width = "800";
oTable.Align = "left";
oTable.Border = 0;
oTable.CellPadding = 0;
oTable.CellSpacing = 0;

  //item항목 리스트에서 For Loop를 돌면서, 검색결과를 하나씩 붙인다
  for (int i = 0; i < oNodeList.Count; i++)
{
  //제목(title)을 위한 Row
       System.Web.UI.HtmlControls.HtmlTableRow oRow = new HtmlTableRow();
  System.Web.UI.HtmlControls.HtmlTableCell oTitleCell = new HtmlTableCell();
  string sTitle = oNodeList[i].ChildNodes[0].InnerText;

       //제목이 없을 경우를 위한 처리
       if (sTitle == null || sTitle.Length == 0)
  {
       sTitle = "제목없음";
  }
   

       //제목에다 link요소의 내용으로 링크를 건다.
      oTitleCell.InnerHtml =
       "<a target='_new' href='" + oNodeList[i].ChildNodes[1].InnerText + "'>" + sTitle + "</a>";
  oRow.Cells.Add(oTitleCell);
  oTable.Rows.Add(oRow);

       //상세 내용(Description)을 위한 Row
       System.Web.UI.HtmlControls.HtmlTableRow oRow2 = new HtmlTableRow();
  System.Web.UI.HtmlControls.HtmlTableCell oDescCell = new HtmlTableCell();
  oDescCell.InnerHtml = oNodeList[i].ChildNodes[2].InnerText;
  oRow2.Cells.Add(oDescCell);
  oTable.Rows.Add(oRow2);
}
//구성된 테이블을 페이지에 추가한다
  this.Page.Controls.Add(oTable);
}

실행한 화면이다.
내 별명인 kkongchi를 검색어로 검색을 해보았다.
사실은 페이징 부분을 추가하고, UI도 더 이쁘게 해야겠지만..


Posted by kkongchi
C# & VB.NET2006. 3. 28. 15:31

AES는 미국 정부에서 민감한 정보들을 암호화하는 데 사용되는 표준 암/복호화 알고리즘이다. 현재 업계 표준이고, 아직까지는 알려진 약점이 없는 가장 안전한 암/복호화 알고리즘이다. 최근에 일부 SI 프로젝트에서는 이 방식을 꼭 쓸 것을 요구하기도 한다.

1. 암호화

private static string EncryptString(string InputText, string Password)
{

  // Rihndael class를 선언하고, 초기화
  RijndaelManaged RijndaelCipher = new RijndaelManaged();

  // 입력받은 문자열을 바이트 배열로 변환
  byte[] PlainText = System.Text.Encoding.Unicode.GetBytes(InputText);

  // 딕셔너리 공격을 대비해서 키를 더 풀기 어렵게 만들기 위해서
  // Salt를 사용한다.
  byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());

  // PasswordDeriveBytes 클래스를 사용해서 SecretKey를 얻는다.
  PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);

  // Create a encryptor from the existing SecretKey bytes.
  // encryptor 객체를 SecretKey로부터 만든다.
  // Secret Key에는 32바이트
  // (Rijndael의 디폴트인 256bit가 바로 32바이트입니다)를 사용하고,
  // Initialization Vector로 16바이트
  // (역시 디폴트인 128비트가 바로 16바이트입니다)를 사용한다.
  ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

  // 메모리스트림 객체를 선언,초기화
  MemoryStream memoryStream = new MemoryStream();

  // CryptoStream객체를 암호화된 데이터를 쓰기 위한 용도로 선언
  CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);

  // 암호화 프로세스가 진행된다.
  cryptoStream.Write(PlainText, 0, PlainText.Length);
 
  // 암호화 종료
  cryptoStream.FlushFinalBlock();

  // 암호화된 데이터를 바이트 배열로 담는다.
  byte[] CipherBytes = memoryStream.ToArray();

  // 스트림 해제
  memoryStream.Close();
  cryptoStream.Close();       

  // 암호화된 데이터를 Base64 인코딩된 문자열로 변환한다.
  string EncryptedData = Convert.ToBase64String(CipherBytes);

  // 최종 결과를 리턴
  return EncryptedData;
}

2. 복호화

private static string DecryptString(string InputText, string Password)
{
  RijndaelManaged  RijndaelCipher = new RijndaelManaged();

  byte[] EncryptedData = Convert.FromBase64String(InputText);
  byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());       

  PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);

  // Decryptor 객체를 만든다.
  ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

  MemoryStream  memoryStream = new MemoryStream(EncryptedData);           

  // 데이터 읽기(복호화이므로) 용도로 cryptoStream객체를 선언, 초기화
  CryptoStream  cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);

  // 복호화된 데이터를 담을 바이트 배열을 선언한다.
  // 길이는 알 수 없지만, 일단 복호화되기 전의 데이터의 길이보다는
  // 길지 않을 것이기 때문에 그 길이로 선언한다.
  byte[] PlainText = new byte[EncryptedData.Length];       

  // 복호화 시작
  int DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);               

  memoryStream.Close();
  cryptoStream.Close();

  // 복호화된 데이터를 문자열로 바꾼다.
  string DecryptedData = Encoding.Unicode.GetString(PlainText, 0, DecryptedCount);

  // 최종 결과 리턴
  return DecryptedData;
}


참고: http://dotnet.org.za/deon/articles/2998.aspx
Posted by kkongchi
C# & VB.NET2006. 3. 28. 11:20

DataSet 에는 ReadXML이라는 메소드가 있어서,
파일에서는 바로 XML구조를 DataSet으로 읽어낼 수 있다.
하지만 문자열에서 읽는 것은 지원하지 않는다.
문자열을 DataSet으로 읽기 위해서는 MemoryStream 객체를 사용해서 읽은 후에 가능하다.


//데이터셋 선언
System.Data.DataSet dsXML = new DataSet();

//XML형태의 문자열
string strXML = "<result ><FILEDS>ACCOUNT;^~!ENTITY;^~!APP</FILEDS><RECORDCOUNT>0</RECORDCOUNT><DATA>;^~!;^~!</DATA></result>";

//문자열을 MemoryStream객체를 사용해서 읽기
System.IO.MemoryStream streamXML = new System.IO.MemoryStream(System.Text.Encoding.Default.GetBytes(strXML));

//Stream으로부터 DataSet을 읽는다
dsXML.ReadXml(streamXML);



아래는 XmlDocument로 읽는 방법


//XML형태의 문자열
string strXML = "<result ><FILEDS>ACCOUNT;^~!ENTITY;^~!APP</FILEDS><RECORDCOUNT>0</RECORDCOUNT><DATA>;^~!;^~!</DATA></result>";

//XmlDocument 객체 선언
System.Xml.XmlDocument xmldocXML = new System.Xml.XmlDocument();

//LoadXML 메소드 사용해서 XML 문자열 읽기
xmldocXML.LoadXml(strXML);

Posted by kkongchi
C# & VB.NET2006. 3. 25. 13:43
Split은 아주 많이 쓰이는 메소드 중에 하나이다. 대부분 "," 등의 Delimeter를 써서 여러 개의 데이터를 문자열로 이어 붙여서 DB에 넣어 두고는, 그걸 꺼내서 쓸 때 split 메소드를 사용해서 배열로 다시 쪼개서 사용하게 된다.

그런데, 아주 간혹 Delimeter가 한 글자가 아닐 때도 있을 수 있다. 복잡한 문장을 분석하고 싶을 때가 그런 경우가 된다. 또는 두 글자 이상의 문자열을 Delimeter로 써야 할 때도 있을 수 있다. (예를 들면 이미 각 문자열들에 "," 등의 character들이 포함되어 있어서 한 글자로 Delimeter를 쓰기가 애매한 경우가 있다.)

어제 나도 그런 경우가 생겨서 역시 Google의 도움을 받아서 어떤 사람이 만들어 놓은 함수를 하나 구했다.

원본은 여기 - http://community.sgdotnet.org/blogs/triplez/archive/2005/04/24/14627.aspx


C#

private string[] SplitByString(string testString, string split) {
  int offset = 0;
  int index = 0;
  int[] offsets = new int[testString.Length + 1]; 

  while(index < testString.Length) {
    int indexOf = testString.IndexOf(split, index);
    if ( indexOf != -1 )  {
       offsets[offset++] = indexOf;
       index = (indexOf + split.Length);
    } else {
       index = testString.Length;
    }
  }

  string[] final = new string[offset+1];
  if (offset == 0 ) {
    final[0] = testString;
  } else {
    offset--;
    final[0] = testString.Substring(0, offsets[0]);
    for(int i = 0; i < offset; i++) {
       final[i + 1] = testString.Substring(offsets[i] + split.Length, offsets[i+1] - offsets[i] - split.Length);
    }
    final[offset + 1] = testString.Substring(offsets[offset] + split.Length);
  }
  return final;
}


VB.NET

Function SplitByString(ByVal splitString As String, ByVal delimeter As String)
  Dim offset As Int16
  Dim index As Int16
  Dim offsets(splitString.Length) As Integer

  While index < splitString.Length
      Dim indexOf As Int16
      indexOf = splitString.IndexOf(delimeter, index)
      If indexOf <> -1 Then
          offsets(offset) = indexOf
          offset = offset + 1
          index = (indexOf + delimeter.Length)
      Else
          index = splitString.Length
      End If
  End While

  Dim final(offset) As String
  If offset = 0 Then
      final(0) = splitString
  Else
      offset = offset - 2
      final(0) = splitString.Substring(0, offsets(0))
      Dim i As Int16
      For i = 0 To offset
          final(i + 1) = splitString.Substring(offsets(i) + delimeter.Length, offsets(i + 1) - offsets(i) - delimeter.Length)
      Next
      final(offset + 2) = splitString.Substring(offsets(offset + 1) + delimeter.Length)
  End If

  Return final
End Function



원작자의 페이지에는 C# 으로 된 함수 뿐이지만, 필요했던 것이 VB.NET이어서 VB.NET으로 고쳤다. 그런데 VB.NET으로는 코딩해본 적이 거의 없어서, 일단 잘 실행되는 것 까지는 봤는데 어떤 버그가 있을지는 잘 모르겠다..^^;; 혹시 이 블로그 들르시는 VB.NET 고수 분들이 있다면 가르침을 좀 주시길....ㅎㅎ (배열 부분이 C#이랑 좀 달라서 애를 좀 먹었다)
Posted by kkongchi
C# & VB.NET2006. 3. 11. 22:55
물론 C#에서는 Base64 인코딩, 디코딩 API가 있지만,
공통 함수로 다음과 같이 만들고 쓰면 편하다.
두 줄이라도 공통화시키고, 또 string을 넘겨서 string을 받으니 직관적이기도 하다.

public static string Base64Encode(string src, System.Text.Encoding enc)
{
  byte[] arr = enc.GetBytes(src);
  return Convert.ToBase64String(arr);
}

public static string Base64Decode(string src, System.Text.Encoding enc)
{
  byte[] arr = Convert.FromBase64String(src);
  return enc.GetString(arr);
}  
Posted by kkongchi
C# & VB.NET2006. 3. 11. 22:48

private void WriteTempLog(string contents)
{
string strFileName = "c:\\Navigator.txt";
System.IO.FileStream oFS = null;
System.IO.StreamWriter oSW = null;
string strLogContents = "";


  try
{
  //파일스트림 객체 초기화
  oFS = new System.IO.FileStream(
   //파일 이름 지정
    strFileName,
   //파일이 있으면 열고, 없으면 만든다
    System.IO.FileMode.OpenOrCreate,
   //파일을 읽기,쓰기 모드로 연다
    System.IO.FileAccess.ReadWrite);


   //스트림라이터 객체 초기화
   oSW = new System.IO.StreamWriter(oFS);


   //마지막 부분을 찾는다.
   oSW.BaseStream.Seek(0, System.IO.SeekOrigin.End);


   strContents = contents;

   oSW.Write(strContents);


   //반드시 flush를 해야, 메모리에 있는 내용을 파일에 기록한다.
  //flush하지 않으면 파일을 잠그기 때문에 다른 프로세스가 이 파일에 접근할 수 없다
   oSW.Flush();
  oSW.Close();
}
catch(Exception ex)
{
  throw ex;
}
finally
{
  oSW = null;
  oFS = null;
}

Posted by kkongchi
C# & VB.NET2006. 3. 5. 17:56

C#에서는 try-catch-finally 구조를 사용해서 각 예외처리를 수행한다. 그런데 이 구조에서 예전에 제가 C#을 처음 익힐 때부터 약간 혼란스러웠던 것이 있다.


바로 Return 문이 어디에 위치해야 하는가이다...


MSDN 라이브러리의 try-catch-finally 구조에 대한 설명을 보자.

A common usage of catch and finally together is to obtain and use resources in a try block, deal with exceptional circumstances in a catch block, and release the resources in the finally block.

Catch finally같이 때의 일반적인 사용법은 try 블록에서 리소스를 얻어내서 사용하고, catch 블록에서는 예외적인 상황을 다루며, finally 블록에서리소스를 해제한다.



즉, return을 어디 두어야 하는 지는 어디에도 없다.

샘플도 교묘하게 void를 리턴 하는 함수를 만들어서 피해가고 있다.


두 가지 가설이 있을 수 있다.

첫 번째는 return은 메서드가 최종적으로 결과를 돌려주는 것이므로, finally 아래에 와야 한다.

두 번째는 try-catch-finally의 구조로 볼 때, return 문은 예외 처리 코드도 아니고 리소스 해제 코드도 아니기 때문에 try 내부에 오는 것이 맞다.

그래서 가지 방법으로 코드를 작성해 보았다.


//return문이 가장 마지막에 위치

public int ReturnInLastLine()

{

int i = 0;

PrivateOBJ obj = null;

try

{

obj = new PrivateOBJ();

i = obj.GetINT();

}

catch(Exception ex)

{

throw ex;

}

finally

{

obj = null;

}

return i;

}

//try블록 내부에 return이 위치

public int ReturnInTry()

{

int i = 0;

PrivateOBJ obj = null;

try

{

obj = new PrivateOBJ();

i = obj.GetINT();

           return i;

}

catch(Exception ex)

{

throw ex;

}

finally

{

obj = null;

}

}

그리고, 클래스를 컴파일한다음  .NET Reflector디스어셈블한 코드를 보았다.



결과는놀랍게도,

public int ReturnInLastLine()
{
int num1 = 0;
PrivateOBJ eobj1 = null;
try
{
eobj1 = new PrivateOBJ();
num1 = eobj1.GetINT();
}
catch (Exception exception1)
{
throw exception1;
}
finally
{
eobj1 = null;
}
return num1;
}

public int ReturnInTry()
{
int num2;
int num1 = 0;
PrivateOBJ eobj1 = null;
try
{
eobj1 = new PrivateOBJ();
num1 = eobj1.GetINT();

//여기 주의

//원 소스 코드에는 여기에 return이 있다. 그런데?
num2 = num1;
}
catch (Exception exception1)
{
throw exception1;
}
finally
{
eobj1 = null;
}

//여기에 리턴문이 있다.
return num2;
}


IL 코드도 이와 거의 유사하다고 보면 된다.

즉, return을 어느 위치에 두던지 간에 실제로 IL로 컴파일된 코드에서는 return이 가장 마지막에 위치한다는 것이다.

그래서 두 번째 try 내부에 리턴이 있는 경우를 보면 IL 코드는 내부적으로 (코드에는 없는) 변수를 하나
더 선언해서
거기에 값을 할당하고 그 변수를 최종적으로 리턴을 수행할 때 사용하는 것을 볼 수가 있다.



결론

1. 코드 상에서 return문이 어디에 있더라도, IL 코드 상에서는 가장 마지막 라인에 return문이 있게 된다. 결론적으로 마지막에 두는 것이 맞다는 것이다.

2. 코드에 Try 블록 혹은 catch 블록 혹은 여러 군데에 return을 위치시킬 수 있다. 심지어 if-else 문을 사용해서 각각 return하는 경우도 있다. (절대로 권장하지 않는 코딩방법!!) 그 경우 IL이 내부적으로 최종 리턴을 위해서 변수를 하나씩 더 할당한다. 이 값이 만약 매우 큰 데이터셋이라면? 메모리 누수의 원인이 될 수도 있을 듯 하다. 결과적으로 비효율적인 코드라는 것이고, 피해야 할 코딩이 되는 것이다.

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
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