MOSS 2007에서 아래와 같은 형태로 구성 시 위의 이벤트 로그가 계속 쌓이게 된다.

1. Root 사이트가 게시 사이트 형태인 경우 ( 공동 작업 포탈이든, 게시 사이트 든..)
2. Root 사이트에 하위 Application으로 사이트를 추가하여 구성한 경우.
   ( 보통 가상 디렉터리 만들 때, 기능 옵션에 실행을 체크하여 넣으면 "기어" 표시가 생기면서
     하위 응용 프로그램으로 구성되는 경우 )
보낸 사람 ForBlog2
위와 같은 형태에 있을 때 가상 디렉터리 이하의 특정 리소스(JS 파일이든, ASPX 파일이든)에 접근하다가, 아래와 같은 이벤트로그를 뿜어댄다.
Event Type:    Error
Event Source:    Office SharePoint Server
Event Category:    게시 캐시
Event ID:    5785
Date:        2009-02-25
Time:        오전 10:57:07
User:        N/A
Computer:    KYOKO
Description:
출력 캐싱에 대한 게시 사용자 지정 문자열 처리기에 연결할 수 없습니다. IIS 인스턴스 ID는 '1986061912'이고 URL은 'http://www.knoie.com/virtualdir1/Images/presence/presence_off.gif'입니다.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

위의 내용을 이곳 저곳을 기웃 거리다가 한 Technet 의 토론 내용 중 하나의 쓰레드에 눈이 가서 훝어 본 결과 단 한줄로 해결 되었다.

해당 가상 디렉터리는 자체적인 응용 프로그램 쓰레드를 갖기 때문에, 보통 web.config를 별도로 구성하는 경우가 많다. 만일 없다면 기본 web.config를 만들어서 구성하신 뒤, module 부분에 추가하면 된다.

<httpModules>
      <remove name="PublishingHttpModule" />
       <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <!--<remove name="ApplicationMasterPage" />-->
</httpModules>
web.config 에서 httpModules로 찾아서 해당하는 섹션이 보이면 굵게 보이는 저 한 줄을 넣어주면 된다.
나머지는 그대로 두면 된다. 만일 httpModules라는 섹션이 없다면, System.web 섹션을 찾아서 그 안에 다음과 같이 추가하면 된다.

<system.web>
     <httpModules>
          <remove name="PublishingHttpModule" />     
     </httpModules>
 .......
<system.web>

요는  PublishingHttpModule 이라는 Module을 없애면 된다.
728x90

MOSS의 기능 중(WSS의 상위 제품) 게시라는 기능이 있다.
Publish 라고 하며, ASPX 페이지 자체를 보관할 수 있고, 다양한 마스터를
미리 얹어 놓고, 변경해줄 수 있는 진정한 포탈을 위한 사이트라고 보면 된다.

이렇게 구성된 사이트에서 시작페이지와 마스터페이지를 프로그램 상으로 변경하는
방법을 소개한다.

1. 시작 페이지 변경 방법.

보통 시작페이지 설정은 사이트 설정 페이지 내에서 시작페이지 변경에 들어가,
설정하려는 페이지의 URL을 넣어서 처리하곤 했다. 그런데, 프로그램 상에서는
어떻게 처리해야 되는지 전혀 나와있지 않아 조금 곤란했다.
같은회사에 있는 녀석이 이 내용을 찾았는데, 그 내용을 정리하면 아래와 같다.

SPFolder forder = web.RootFolder;
forder.WelcomePage = "Pages/MyStartPage.aspx";
forder.Update();

저 Pages라는 내용이 있는데, 게시 사이트를 만들게 되면 자동으로 생성되는 ASPX 저장용 SPList이다. 이 SPList 상에 저 페이지를 넣어주면 된다. 해당 SPList 에 파일 넣는 방법은 아래와 같다.

FileStream chgstartFile = new FileStream(this.MapPath("/_layouts/MyStartPage.aspx"), FileMode.Open)
SPFolder forder = web.RootFolder;
web.Files.Add("MyStartPage.aspx", chgstartFile.OpenBinary(), true);
folder.Update();
chgstartFile.Close();

일단 Pages 라는 List에 잘 들어가면 한큐에 끝난다.( 사이트 생성용 ONET.XML에서도 처리할 수 있다고 한다. )

 

2. 마스터 변경 방법

이 방법이 제일 쉽다. 일단, 위의 파일 업로드하는 로직을 이용하여, /_catalogs/masterpage/ 라는 SPList에 변경할 마스터 파일을 업로드 해준다.

그리고 난 뒤 아래의 로직을 실행하면 된다.

web.MasterUrl = "/_catalogs/masterpage/MyMaster.master";
web.Update();

일단 web의 Root 폴더와 web 자체의 Update 해야 하므로, 최소한 모든 권한을 가진 사용자여야만 사용가능한 명령이다.

728x90

WSS/MOSS 들고 다양한 사이트에 가다보면, 마스터를 심각하게 뜯어버려, "사이트 작업" 이라는 버튼이 없어졌을 때 발생하는 문제가 종종 있다.

그 중, 페이지 편집이라는 버튼이 없어진 경우가 그 경우이다.

사이트 작업 버튼이 있을 때는 간단하게 되었는데, 없어지면 웹파트 추가건 뭐건
아무것도 안된다. 이럴때.... 이렇게 한다.

페이지 편집을 시도할 페이지에서 주소 창에 아래의 내용을 입력한다.

javascript:MSOLayout_ChangeLayoutMode(false)

그러면 자동적으로 페이지 편집 모드로 들어가게 된다.

아주 간단한 팁.

728x90
보통 우리가 SQL 형식으로 데이터를 조회할 때 SELECT를 사용한다. 이 중 특정 조건에 해당하는 값을 가져올때 다양한 방식으로 표현하게 되는데, 만일 아래와 같이 작성했다고 하자.

SELECT * FROM splist WHERE id>10

저렇게 되면 splist 안의 데이터 중 id가 10보다 큰 모든 값을 들고 온다. 아마도 이 바닥(IT, 프로그래머들이 가득찬....)에서 위와 같이 코드를 짜게 되면 별거 아니면 상관 없지만, ERP 같은 대규모 DB 로 구성된 솔루션을 사용 중이라면 욕 진탕 얻어 먹을 것이다.
특별한 경우가 아닌 경우 보통 아래와 같은 스타일로 SELECT를 하라고 할 것이다.

SELECT [id],[name],[address] FROM splist WHERE id>10

그러면 최소한 id는 10 이상인 것 중에 id, name, address 만 해당하는 값만 쭉 가져오게 된다.

자... 그럼 이제 SPList에서 SPQuery를 이용할 때를 살펴보자.

보통 SPQeury라는 객체를 사용하는 것은 SPList 내에 특정 데이터를 가져올 때 사용하기 위한 부분이다. 그래서 그 SPQuery안에 있는 Query라는 속성 값 내에 <WHERE></WHERE>  라는 형식의 검색 조건을 넣어 처리하곤 한다.

만일 아래와 같이 코드를 짰다면... 어떻게 될까?

SPList list = web.GetList("/Lists/PresidenSchedule1");

SPQuery query = new SPQuery();
query.Query = "<Where><DateRangesOverlap><FieldRef Name=\"EventDate\" />
<FieldRef Name=\"EndDate\" /><FieldRef Name=\"RecurrenceID\" />
<Value Type=\"DateTime\"><Now  /></Value>
</DateRangesOverlap>
</Where><OrderBy>
<FieldRef Name=\"EventDate\" /></OrderBy>";
query.CalendarDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day);
query.RowLimit = 10;
query.RecurrenceOrderBy = true;
query.ExpandRecurrence = true;

 SPListItemCollection items = list.GetItems(query);


저 코드가 바로 SELECT * FROM ~ WHERE ~ 스타일인 코드이다.
그렇다면 이 SPQuery에서는 어떻게 특정 Field만 가져오게 할까?

방법은 간단하다. SPQuery의 ViewFields를 설정하면 된다.
StringBuilder sbFields = new StringBuilder();
sbFields.Append("<FieldRef Name=\"EventDate\" />");
sbFields.Append("<FieldRef Name=\"EndDate\" />");
sbFields.Append("<FieldRef Name=\"ID\" />");
sbFields.Append("<FieldRef Name=\"Title\" />");
sbFields.Append("<FieldRef Name=\"RecurrenceID\"  />");
sbFields.Append("<FieldRef Name=\"fAllDayEvent\" />");
sbFields.Append("<FieldRef Name=\"fRecurrence\" />");
query.ViewFields = sbFields.ToString();

즉 GetItems 를 실행하기 전에 SPQuery 안에 저렇게 ViewField들을 정의해주면 간단하게 끝난다.

물론 자체적으로  Sharepoint가 Cache로 가지고 있어서, 어느정도는 후후 되지만, 그래도 깔삼하게 필요한 것만 가져오는게 좋지 않을까?




728x90

사실 이 부분에 대한 글은 외국 사이트들에 많이 소개 되어 있다.
그러나, 정작 사용하려 하면 헷갈리게 구성되어 있어 이기회에 정리하도록 한다.

이전에 사용해 왔고 계속 진행해온 방법이 아래와 같은 방법이다.


<a href="javascript:" onclick="IMNImageOnClick();return false;" class="ms-imnlink">

<img title="" alt="No presence information" name="imnmark" border="0" valign="middle" height="12" width="12" src="/_layouts/images/blank.gif" sip="administrator@trainsbydave.com" id="imn0,type=smtp" >

</a>


즉 저 내용 중 SIP 라는 항목에 실제 OC 에 필요한 SIP를 넣어서 처리하곤 했다.

그런데, 간혹 위와 같이 표기하면 Presence 정보가 제대로 표시되지 않거나(SIP가 잘못된 것 처럼 아예 표시 조차 안되는 경우), 2개 씩 나오는 경우가 있다.

이에 MOSS에서 제공하는 스크립트를 가만히 뜯어 보았다. MOSS에서 제공하는 자바스크립트는 두가지 인데, 하나는 /_layouts/{LCID_CODE}/init.js 고 다른 하나는 /_layouts/{LCID_CODE}/ows.js 이다. ( LCID_CODE란 언어별 코드로 한국어면 1043 일 것이다. )

그 자바스크립트를 가만히 보게 되면 위와 같은 형태의 코로는 도무지 제대로 찾지 못하는 구조일 수 밖에 없다. ( 도리어 표시되는게 무척이나 신기한 구조다. )

예전 WSS v2 에서는 아래와 같이 구성되어 있었다.

<img border="0" height="12" width="12" src="http://portal.blackbladesystems.com/_layouts/images/blank.gif" onload="IMNRC('erosenfeld@blackbladesystems.com')" id="imn0" >

그래서 해당 Img가 Load될때 IMNRC라는 자바스크립트가 실행되면서 동작했는데, WSS v3 부터는 ProcessImn() 이라는 함수를 부르면 알아서 찾아 처리하는 것이다.

아무것도 없는데 알아서 처리할리는 없고, 실제 자바스크립트에서 찾는 방법을 간단하게 서술하면 아래와 같다.

1. name="imnmark" 라는 이름을 가진 element를 모두 검색한다.

2. 검색한 element가 span이라고 가정하고, OC의 active X에 이벤트를 연결한다.

3. 이벤트에서는 active X의 presence가 변경될 때 마다, 해당하는 이미지로 변경할 수 있도록한다. 이 때 이미지 id는 span에서 제공한다.

혹시 이 Presence 정보에 골머리를 싸아보신 분은 헉.... 이라는 한마디를 할 것이다. 저 1,3 번이 바로 OC Presence 정보의 함정인 것이였다.

먼저 아래와 같은 구조가 되어야 한다는 것이다.

<span id="{고유ID-1}" name="imnmark" >
  <img id="{고유ID-1}" src="blank.gif" >
</span>

서두에 전달드렸던 태그와는 전혀 생뚱맞지 않은가?

즉 <a> <img> </a> 형태가 아닌 <span><img></span>이되어야 한다는 것이다.

그런데, 여기서 잠깐!. 저 ID가 무척 웃기는 구조이다. 정말이지 고유 ID가 되어야 정확한 이미지 변경이 가능하다.만일 모든 Presence 정보의 ID를 맨 위의 코드 처럼 id="imn0,type=smtp"  라고 쓰면 한개의 이미지만 그럴싸하게 나오고 나머지에서는 제대로 표시도 안된다.

그렇다면, 저 ID는 어떻게 뽑을까?

물론 한 페이지에 이 Presence 정보를 뽑는 곳이 딱 한개의 웹파트에서 모두 표시된다면 문제가 없다. 그 안에서 int nIndex = 0; 한다음에 뺑뺑이 돌면서 ID를 만들면 된다. id="imn0,type=smtp" , id="imn1,type=smtp", id="imn2,type=smtp", id="imn3,type=smtp"... 이런 식으로 표시만 되면 된다.

그런데.. 만일 멀티 웹파트 인경우에는 어떻게 해야 할까?

사실 이것 때문에 조금 고민했다.  웹 구성요소(웹 컨트롤, 웹 파트 등)에서 모두 공유해서 쓸만한 변수라는게 있을까? 웹 컨트롤 내에 백개의 변수를 정해줘바야 다른 웹 컨트롤이나 웹 파트에서 접근도 못할 뿐더러, 이미 접근할 때에는 그 객체는 Render 하고 끝났을 테니깐...

그러다가, 이렇게 생각을 조금 다르게 바라보자,  웹페이지에서도 나름대로 공용 변수를 하나 세울 수 있었다.

바로 HttpContext.Current.Cache라는 것이였다.

즉 저 안에는 Key 값을 정해준뒤, object 형태의 값을 넣을 수 있는데, 바로 그 점에 착안한 것이다.

즉 Presence 정보를 표시하는 모든 웹 구성요소들은  아래와 같은 캐쉬를 꼭 읽도록 한다.

object val = HttpContext.Current.Cache["PRESENCE_COUNT"];

만일 val이 null 이라면 새로 값을 넣고, 그렇지 않으면 그 값을 사용한다.

presence 정보를 쭉 나열한 뒤, 전체 인덱스가 변했다면, 이젠 그 값을 Set 해준다. 이 때 만료시간은 2~3초로 잡아주면 끝날 것이다.

아래의 코드를 참고하도록 한다.

static public string GetPresenceInfoHtml(string sSipAddress)
{
      string CacheName = CACHE_PRESENCE_COUNT_PREFIX +   UserData.GetCurrentUserId();
       int nCount = 0;
       object val = CacheHelper.GetCache(CacheName);
       if (val != null)
       {
            nCount = (int)val;
            nCount++;
        }

        string sId = "imn" + nCount.ToString() + ",type=smtp";
        StringBuilder sbContent = new StringBuilder();
        sbContent.Append("<span name=\"imnmark\" ShowOfflinePawn=\"true\" id=\"" + sId + "\" sip=\"" + sSipAddress + "\">");
         sbContent.Append("<img border=\"0\" id=\"" + sId + "\" valign=\"middle\" height=\"12\" width=\"12\" src=\"/_layouts/images/blank.gif\" onload=\"IMNRC('" + sSipAddress + "');\" sipaddr=\"" + sSipAddress + "\" />");
         sbContent.Append("</span>");
        CacheHelper.SetCache(CacheName, DateTime.Now.AddSeconds(5), nCount);

         return sbContent.ToString();
}


( 위의 코드 중 CacheHelper.SetCache와 GetCache는 신경 쓰지 않도록 한다. HttpContext.Current.Cache를 쉽게 사용할 수 있도록 구성한 함수 들이다. )


* 주의! : Presence를 표시하는 Html 부분을 AJAX 기법으로 동적으로 추가되도록 구성하지는 말자. <div> 안에 innerHTML 같은 것으로 해당 부분의 Html을 넣거나 빼게 되면 그 안의 값은 getElementById 혹은 getElementByName 등의 함수로 찾지 못하는 경우가 발생한다. 가급적 HTML은 미리 인쇄될 수 있도록 구성해야 한다.

728x90

21세기 초, MS 운영체제에서 대거 수많은 보안 문제들이 대두되었다.
특히 MS Windows 2000. 과거 불안하게 동작되었던 운영체제의 기반을 싹다 갈아 엎고 만들어서 인지, 안정적으로 돌아가는 운영체제라는 희대의 찬사와 함께, MS를 운영체제 회사로 자리매기게 해주었다. 그러나, 보안 문제가 심각하게 대두되면서 보다 강력하게 보안문제를 해결하기 위해 Windows 2003에서는 그에 따른 철저한 계정 정책을 만들었다.

초기에는 모든 서비스들은 Local System이라는 계정으로 동작해서, 모든 자원을 주무르도록 하였으나, Windows 2003에서는 Local Service와 Network Service라는 계정을 제공하여, 제한적인 권한을 주어 제한 내에서 동작할 경우 ( 특정 폴더나, NIC 등의 단순한 자원 접근 시 ) 가급적 이 제한 계정에서 동작하도록 강력하게 권장한다.

그런데, AD에 Join되어 있는 MOSS Farm에서 이런 제한적인 Local 계정으로 접속하였을 때 문제가 없을까 라는 의문이 생겼다. 금일 고객사에 방문하여 고객사가 안고 있는 문제를 분석하는 도중에 발견하게 되었는데, 그 쪽에서는 MS Exchagne의 Federation 기능 - 인증 대리자 역할. 즉 Exchange에 접속할 때 사용되는 Credention(아이디와 패스워드로 인증된 결과물)의 생성이 필요 없이, MOSS로그인 사용자와 Exchange 사용자가 같다라고 표현 해줄 수 있는 일종의 대리자 - 을 활성화 하기 위해 MOSS의 웹 응용 프로그램 실행 계정을 Network Service계정으로 했다고 한다.
그런데, Network Service라는 것은 로컬 계정이기 때문에( http://msdn.microsoft.com/en-us/library/ms684272(VS.85).aspx) IIS를 통해 AD에서 자원을 가져올 수 없다. 그런데 이 설정 방법은 MOSS에 대한 기술 지원을 한 MS의 한 엔지니어가 권장한 방법이라고 말씀하셨다. 도무지 이해가 안되서 되묻기도 했지만....일단 현재 파악해야 하는 문제와는 별개라고 판단되어 대충 얼버무리고 함구하고 나오긴 했으나, 의문감이 배가 되고 있다.

금일 테스트 결과에 따라서 나오겠지만, 현재로는 아마도... 이상하다고 생각된다.

과연 어느쪽이 옳은 걸까?

* Update : 2008 / 05 / 14
SSP ( 공유 서비스 제공자 : Shared Service Provider )를 만들려면 NetworkService 계정으로 만들어진 웹 응용 프로그램은 안된다. 반드시 AD에 접근 가능한 계정이여야 만들어진다.

728x90

근래 MS에서 제시한 서버 제품 군 중 나름대로 이슈가 된 제품으로 MOSS 2007이라고 있다. MOSS 란, Microsoft Office Server System의 약자로 Office 제품군을 엮어주는 서버 제품군의 총칭을 의미한다.  DOC, XLS, PPT 등등 다양한 오피스 파일들에서 부터 공유 서비스를 제공하는 Grove 까지 그 영역은 한도 없이 넓다.

그런데, 현재 대부분이 드라이브 걸고 있는 MOSS의 영역은 포털 솔루션으로써 다루어지는게 현실이다. 한국 MS에서도 대부분의 고객들에게 포털의 성격을 강조하고 있고, 또한 고객들도 그렇게 받아들이고 있다. 그러다 보니, 점점 고객들은 Naver를 기대하고 기대한 만큼 설치 운영 후 그대로 실망을 갖게 된다. 포털이 갖는 각종 자료의 수집이나 정리, 그 외에도 수많은 기능들, 아름다운 화면 어느것 하나 제대로 부합되는 건 없다. ( 있어도, 기능이 약하거나, 많은 수정 작업을 수행해야 할지 모른다. )

그런데, 눈을 돌려서 포털로써의 MOSS가 아닌 문서 관리 및 협업용 솔루션 MOSS로 포커스를 맞추어 보면, 이것 처럼 정확한 시점으로 제작된 것은 없다고 생각된다.

일예로, 만일 사무실 내에 각종 MS Office 제품군들을 이용한 파일들이 난무한다고 하자.
그  중 회계 업무를 수행하는데, 엑셀 파일을 관리부 직원과 회계부 직원 그리고 회계부 과장이 동시에 쓴다고 가정하자. 물론 이 훌륭한 엑셀에서는 파일 공유 사용기능이 있어, 네트워크 공유로 동시에 열어 쓸 수 있다.

여기서 관리부 직원이 실수로 회계부 직원이 작업 중이던 워크시트를 날렸다고 하자.
이랬을 때 취하는 행동. 회계부 과장이 "뭔가 작업할 때 꼭 백업해서 다른 이름으로 저장해 놓으라고 했지!!!!!" 막 뭐라 할 것이다. 그러나 이미 엎질러진 물. 돌아가기엔 먼길을 가버린 후다.

이를 MOSS 에서 저장을 하고, 버전 관리를 켜게 되면, 해당 파일을 편집할 때 마다, 저장 할 때  마다 해당 파일에 대한 버전을 계속 업을 해주어 자동 버전 백업을 해주게 된다. 그렇다면, 저장된 시점을 찾아 해당 파일을 복구해주면 위의 사태를 해결할 수 있을 것이다.

또 하나, 만일 회계부 직원, 관리부 직원 여러명이 회계 사무실에 보내야 할 중요한 엑셀 파일을 작성한다고 할 때, 그 문서를 작성하기 위한 일정이나, 작업들을 계획 할 때, 이리저리 사람들이 왔다 갔다 하면서 구두로 해결하거나, 회의실 하나 차지해서 함께 모여 합숙 분위기로 작성을 한다.

이를 MOSS에서 사용할 때 해당 문서에 대한 작업 사이트를 만들면, 그 안에 해당 문서를 중심으로한 팀 사이트가 만들어지면서, 일정이나, 작업 목록등을 사용할 수 있고, 또한 이 사이트 내에 접근할 사용자들을 정의해서 외부 사람은 접근하지 못하게 만들 수 도 있다. 최종적으로 모든 작성이 완료되면, 실제 원본 위치에 다시 게시해주게 된다.

사실 들춰보면 MOSS의 숨겨진 기능이나 장점들이 무척 많다.
그러나 문제는 고객의 생각은 언제는 기존 웹 시스템으로 굳어져 버려, 간단하게 해결되길 원한다. 그렇게 굳어진 생각을 다양한 사례를 들어 조금 다른 길로 가더라도, 더욱 편리하고 효율적으로 갈 수 있다면 조금은 마음을 열어주지 않을까?

답답한 마음에 한번 끄적여본다.

728x90

MOSS 2007에서 사이트 내 마스터 페이지를 추가/삭제/편집 하는 페이지가 있다.

사용자 삽입 이미지
일반적인 설정으로 모든 권한을 Administrators 그룹에 속한 계정에게 주고,
그 계정으로 로그인 하면 모든 페이지를 접근 할 수 있으며, 지금 말하려는
마스터 페이지 및 페이지 레이아웃 안의 설정 페이지에도 들어갈 수 있다.

그러나 Form 인증과 같은 전혀 다른 Login을 하거나 Administrators 그룹내의 계정이 아니면,
저 안의 페이지에 접근 할 수 없다.
심지어 사이트의 소유자 권한을 가지고 있어도 불가하다.

이 안에 들어가려면, 사이트의 모음(Site Collection)의 관리자에 등록되어 있어야 한다.
여기에 등록하려면, 최소한 SharePoint 3.0 중앙관리에 들어가야 가능하다.
사용자 삽입 이미지

중앙관리에 들어가 응용 프로그램 관리SharePoint 사이트 관리 목록 중 사이트 모음 관리자를 선택하면 된다.























모음 관리자에서 자신이 원하는 계정을 하나 추가하면 된다.
보통 사이트를 처음에 만들때 정한 계정이 들어가 있는데, Form 인증으로 중간에 설정시에는 안들어가 있는 경우가 많다. 그러므로 여기서 추가해주는 것이다.
사용자 삽입 이미지
위의 그림에서 처름 보조 사이트 모음 관리자 같이 윈도우 인증 계정이 아니는 Form 인증과 같은 별도 인증 계정을 저런 식으로 등록해주어야 저 계정으로 완벽한 사이트 관리를 수행할 수 있다.

현재까지 사이트 관리에서 안되는 부분은 이 마스터 페이지 등록/삭제/편집 페이지 뿐인데,
가급적 저런식으로 등록하여 준비해 놓는 것이 좋다.

728x90

+ Recent posts

728x90