windows2006. 4. 22. 16:17
 

Batch 파일에서 변수를 사용할때는 SET 명령을 사용한다.


set a_dir="c:\test"


변수를 사용할때에는 앞뒤로 %붙여주면 된다.


xcopy c:\hInstall.log %a_dir%\test2\

Posted by kkongchi
Software Engineering2006. 4. 8. 23:21

Foster open communications

열린커뮤니케이션을장려한다.


당연한 말일지도 모른다. 하지만 커뮤니케이션이 잘못되어서, 프로젝트가 위기에 빠지는 경우를 우리는 너무나 흔하게 본다. 실제로 많은 소규모 프로젝트들이 담당자들간의 간단한 대화에만 커뮤니케이션을 의존한다. 그런 경우, 마치 가족오락관의 어떤 게임처럼 한군데서 커뮤니케이션의 미스가 생기면 그게 눈덩이처럼 불어나면서, 돌이킬 수 없는 큰 문제로 발전하게 된다. 그리고 서로 책임 떠넘기기에 바빠진다.


위에서 언급한 사례들이 바로 닫힌 커뮤니케이션이다. 즉, 커뮤니케이션 자체는 이뤄졌지만 그 커뮤니케이션의 결과물들은 아무데도 없다. 단지 참여한 사람들의 기억 속에만 있다. 폐쇄적이고 닫혀 있어서 다른 사람들은 아무도 알 수가 없다. 열린 커뮤니케이션은 이런 것을 지양한다. 모든 커뮤니케이션은 기록되고 공개되어 있어서, 적절한 권한이 있다면 누구나 볼 수 있다. 그래서 현재 프로젝트의 상황을 투명하게 볼 수가 있다. 적어도 오른손이 하는 일을 왼손이 몰라서 문제가 생기지는 않는 것이다.



다른 원칙 보기

Foster open Communications (열린 커뮤니케이션을 장려한다)

Work toward a shared vision (비전을 공유하고, 그 비전을 목표로 작업한다)
Empower Team Members (팀 멤버들에게 많은 권한을 위임한다)
Establish clear accountability and shared responsibility (팀,개인의 의무를 분명히 하고, 동시에 책임을 모두가 공유해야 한다)
Focus on delivering business value(비즈니스 가치에 초점을 맞춰야 한다)
Stay agile, expect change (언제나 유연하게 변화에 대응할수 있도록 한다)
Invest in Quality (품질에 투자한다)
Learn From all Experiences(모든 경험으로부터 배운다)

Posted by kkongchi
Software Engineering2006. 4. 8. 23:19
 

MSF(Microsoft Solutions Framework) Microsoft에서 제안하는 Software 개발방법론이다. 실제로 Microsoft에서 동안 많은 소프트웨어를 개발하면서 겪어왔던 여러 교훈들이 녹아있는 훌륭한 방법론이다. (물론 제대로 적용되었을 얘기이다.) MSF다음 8가지를 기본 원칙으로 삼는다.


(* 이름을 클릭하면 각 원칙에 대해서 내가 코멘트한 포스트로 링크된다)

Foster open communications

열린 커뮤니케이션을 장려한다.


Work toward a shared vision

비전을 공유하고, 비전을 목표로 작업한다.


Empower team members

멤버들에게 많은 권한을 부여한다.


Establish clear accountability and shared responsibility

(개인)의무를 분명히 하고, 동시에 책임을 모두가 공유해야 한다.


Focus on delivering business value

비즈니스 가치에 초점을 맞춰야 한다.


Stay agile, expect change

언제나 유연하게 변화에 대응할있도록 한다.


Invest in quality

품질에 투자한다.


Learn from all experiences

모든 경험으로부터 배운다.

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
Team Foundation Server2006. 3. 25. 16:59

  • 반드시 SQL 2005 가 필요하다.
  • SQL 2005를 설치할 때에, Reporting Service와 Analysis Service를 꼭 설치해야 한다.
  • SQL 2005를 설치할 때에, SQL Browser 서비스가 자동실행되도록 해야 한다. 설치한 후에 관리도구의 서비스에 가서 자동으로 설정해도 된다.
  • Sharepoint Team Service 2.0 을 설치할때, 반드시 서버팜옵션으로 설치해야 한다.
    • 기존에 Sharepoint Team Service 1.0, 혹은 2.0이 Microsoft SQL Desktop Edition과 함께 설치되어있었다면, 기존 STS와 MSDE 둘 다 삭제해야 한다.
    • STS 설치후에, 기본 웹사이트를 STS를 사용하도록 확장해야 한다. FrontPage Extension은 쓰지 않도록 설정해야 한다.
    • 기본웹사이트가  STS로 확장되었다면, 아마 SQL Reporting Service 관련 웹 디렉토리가 정상적으로 동작하지 않을 것이다. 반드시 관련디렉토리(Reports, ReportServer)를  STS  중앙관리에서 제외경로로 설정해야 한다.
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
Sharepoint Portal Server2006. 3. 24. 17:57

회사에서 Microsoft Sharepoint Portal 서버를 설치하고, 사내 인트라넷 용도로 쓰고 있다. 그런데 서버의 이벤트 로그에 다음과 같은 에러가 계속해서 남는 것을 발견했다.

이벤트 형식: 경고
이벤트 원본: Microsoft SharePointPS Search Service
이벤트 범주: Gatherer
이벤트 ID: 3036
날짜: 2006-03-24
시간: 오후 5:30:03
사용자: N/A
컴퓨터: PORTAL
설명: 콘텐트 원본 <sps://portal.interdev.co.kr/site$$$people>을(를) 액세스할 수 없습니다.
컨텍스트:
http://portal.interdev.co.kr/ 응용 프로그램, Portal_Content 카탈로그
자세히: 액세스가 거부되었습니다. SharePoint 중앙 관리에 있는 기본 콘텐트 액세스 계정이 정확한 계정인지 확인하십시오. 또는 이 URL에 접근하기 위해서 적절한 탐색 계정을 지정해주는 규칙을 추가하십시오.   (0x80041205)

그런데, 기본 콘텐트 액세스 계정은 도메인의 administrator계정이었던지라, 액세스가 거부 되었다는 게 이해가 안 되는 상황이었다. 그래서 Google 검색을 해보니...

http://forums.isaserver.org/m_210038800/tm.htm


이 곳에서 답을 찾았다.


즉,


- don't use other ports then 80 and 443 on the webserver.
- don't use headertranslation
- use different ip-addresses on the webserver to make distinction between sites
- On the SSL-rule use linktranslation to transform the servername to the url-name

지금 에러가 나는 포탈 사이트의 경우, 기본 웹 사이트에 설치하지 않고,

제가 사이트를 새로 만들어서, 호스트 헤더 값으로(즉, portal.interdev.co.kr로 들어오는 경우만)

구분을 했었다. 그게 바로 문제의 원인이었던 것. 즉, 검색 정보를 모으는 Gatherer의 경우 서버의 로컬에서 내부적으로 HTTP요청을 보내서 사이트를 검색하게 되는 건데, 서버 내부에서는 당연히 portal.interdev.co.kr로 보내도 그 서버가 어디 있는지 알 수가 없기 때문에 이런 에러가 나게 되는 것이다.


혹시, Sharepoint Portal 서버에서 이런 에러가 나시는 분들은 참고하시기 바란다.

Posted by kkongchi
asp.net2006. 3. 18. 23:29

1. AJAX (Asynchronous Javascript And Xmlhttp)


Ajax(Asynchronous JavaScript and XML) 혹은 AJAX는 대화식 웹 어플리케이션의 제작을 위해 아래와 같은 조합을 이용하는 웹 개발 기법이다:
표현 정보를 위한 HTML (또는 XHTML) 과 CSS
동적인 화면 출력 및 표시 정보와의 상호작용을 위한 DOM, 자바스크립트
웹 서버와 비동기적으로 데이터를 교환하고 조작하기 위한 XML, XSLT, XMLHttpRequest
(Ajax 어플리케이션은 XML/XSLT 대신 미리 정의된 HTML 이나 일반 텍스트, JSON, JSON-RPC를 이용할 수 있다).
DHTML과 같이 Ajax는 자체가 하나의 특정한 기술을 말하는 것이 아니며, 함께 사용하는 기술의 묶음을 지칭하는 용어이다.
Ajax 어플리케이션은 실행을 위한 플랫폼으로 위에서 열거한 기술들을 지원하는 웹 브라우저를 이용한다. 이것을 지원하는 브라우저로는 모질라 파이어폭스, 인터넷 익스플로러, 오페라, 사파리 등이 있다.


2. Ajax 어플리케이션은 기존의 웹 어플리케이션과 무엇이 다른가


기존의 웹 어플리케이션


폼을 채우고 제출(submit)을 하면, 웹 서버로 요청을 보내도록 한다. 웹 서버는 전송된 내용에 따라서 새로운 웹 페이지를 작성하여 결과물을 되돌려준다.
이때 최초에 폼을 가지고 있던 사이트와 사용자가 이 폼을 채워 결과물로서 되돌려 받은 두 페이지 사이에 중복되는 HTML코드로 인해 많은 대역폭을 낭비하게 된다.
네이티브 어플리케이션과 비교할 때 복잡한 대화형 사용자 인터페이스를 작성하기가 어렵다.


Ajax 어플리케이션


필요한 데이터만을 주도록 웹 서버에 요청할 수 있다.
보통 SOAP나 XML 기반의 웹 서비스 언어를 사용하며, 웹 서버의 응답을 처리하기 위해 클라이언트 쪽에서 자바스크립트를 쓴다.
그 결과로 웹 브라우저와 웹 서버 사이의 교환되는 데이터량이 줄어들기 때문에 어플리케이션의 응답성이 좋아진다. 요청을 주는 수많은 컴퓨터에서 이 같은 일이 일어나기 때문에, 전체적인 웹 서버 처리량도 줄어들게 된다


3. AJAX.NET

http://ajax.schwarz-interactive.de/csharpsample/default.aspx
이 공통 라이브러리는 ASP.NET에서 작성한 메소드를 그 이름 그대로 자바스크립트에서 호출할 수 있게 해준다.(동기/비동기)


* 웹폼 메서드

[Ajax.AjaxMethod]
public string Test(string s)
{
string strReturn = s + " World";
return strReturn;
}

* 자바스크립트에서 바로 웹폼 메서드를 호출

function btn1_onclick()
{
  var response = WebForm1.Test(“Hello ");
  alert(response.value);
}


4. AJAX.NET 아키텍처


기존에는 XmlHttp를 통해서 웹 페이지 혹은 웹 서비스를 호출하는 함수를 만들어야 했는데, AJAX.NET은 이 라이브러리를 참조하고 AjaxMethod 어트리뷰트를 추가하면 그런 함수를 자동으로 렌더링시켜주게 된다.

5. AJAX.NET 사용법


Step1. ajax.dll 참조
Step2. 다음 내용을 Web.Config에 추가


<configuration>
<system.web>
  <httpHandlers>
  <add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax" />
  </httpHandlers>      ...
<system.web>
</configuration>


Step3. 페이지 로드에 다음을 추가


private void Page_Load(object sender, EventArgs e){
    Ajax.Utility.RegisterTypeForAjax(typeof(Index));     
    //...
  }


Step4. AjaxMethod를 작성하고, 스크립트에서 호출(위의 예제 참조)

Posted by kkongchi
javascript & HTML2006. 3. 11. 22:58
화면을 프레임으로 분할하는 것은,
사용자 편의성이나 네트워크 전송량을 줄이기 위해서 흔히들 쓰는 방법이다.

그런데 이렇게 프레임으로 분할했을 때,
상위 프레임의 요소를 자바 스크립트로 접근해야 할 때가 있다.

즉, 프레임셋을 구성하는 페이지의소스 중에서 id가 HiddenValue라는 요소가 있어서,
그 하위 프레임에서 그 값을 읽어서 사용해야 한다라고 가정을 하자.

이럴 때는 아래 코드처럼
window.parent.document를 사용해서 상위 프레임을 접근해야 한다.

function btnTest_onclick
{
  alert(window.parent.document.all.item("hdHiddenValue").value);
}

Posted by kkongchi