사이트 템플릿 만들기

 

1.     Site Action / Create Site 클릭하면, New SharePoint Site 라는 화면이 나타난다.

 

2.     Template Selection / Select a template 탭 추가

 

 

-      C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\(LCID)\XML WEBTEMP.XML를 해당 폴더에 Copy 하여 파일명을 WEBTEMP*****.XML로 변경한다. (, 파일명을 임의로 정하면 되지 않는다. 예를 들면, WEBTEMPSKT.XML)

 

-      복사한 WEBTEMPSKT.XML를 수정하는데, 예제를 통해 설명하자면,

 

<?xml version="1.0" encoding="utf-8"?>

<!-- _lcid="1033" _version="12.0.4518" _dal="1" -->

<!-- _LocalBinding -->

<Templates xmlns:ows="Microsoft SharePoint">

<Template Name="SampleTemplate" ID="10001">

<Configuration ID="0" Title="Global Avenue Community" Hidden="FALSE" ImageUrl="/_layouts/images/stsprev.png"

Description="A site for teams to quickly organize, author, and share information. It provides a document library, and lists for managing announcements, calendar items, tasks, and discussions.(SKT Global Avenue Community Site)"

                           DisplayCategory="SKT" >

                          </Configuration>

            </Template>

</Templates>

 

<Template>

Name : Site Template 이름 (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates 밑에 사이트 템플릿을 만들 폴더 이름)

ID : Site Template ID인데, 임의로 지정(10000번 이상으로 지정하는 게 좋다고 한다.)

 

<Configuration>

ID : Configuration IDSite Template 만들 때 중요한 ID값이므로, 기억하는 게 좋다.

Title : 위 그림에서 보면 탭 안에 있는 템플릿 명을 나타낸다.

Hidden : 템플릿 탭을 보여줄지 여부를 체크한다.

ImageUrl : 우측 이미지 URL 주소를 나타낸다.

Description : 이미지 아래 설명 부분을 나타낸다.

DisplayCategory : 탭 버튼에 들어가는 텍스트를 나타낸다.(상단그림에서 빨간색 부분)

 

 

-      Site Template 폴더 생성

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates\sts를 해당 폴더에 Copy 한다. 그 폴더 명은 WEBTEMPSKT.XML에서 정의한 Template Name으로 변경한다.

 

-      Site Template Onet.xml 수정

 

<?xml version="1.0" encoding="utf-8"?>

<Project Title="$Resources:onet_TeamWebSite;" Revision="2" ListDir="$Resources:core,lists_Folder;" xmlns:ows="Microsoft SharePoint">

<!-- _locID@Title="camlidonet1" _locComment="{StringCategory=HTX}" -->

<NavBars>…

<ListTemplates>…

<DocumentTemplates>…

<Configurations>…

<Modules>…

</Project>

            

             보통 수정해야 할 부분이 Configurations Modules 부분이다.

            

 

<Configurations>

<Configuration ID="0" Name="Default" MasterUrl="_catalogs/masterpage/GAComm.master">

<Lists>

<List FeatureId="00BFEA71-E717-4E80-AA17-D0C71B360101" Type="101" Title="Shared Documents" Url="doc" QuickLaunchUrl="doc/Forms/AllItems.aspx" />

<List FeatureId="00BFEA71-EC85-4903-972D-EBE475780106" Type="106" Title="$Resources:core,calendarList;" Url="$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;" QuickLaunchUrl="$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;/Calendar.aspx" EmailAlias="$Resources:core,calendar_EmailAlias;" />

<List FeatureId="00BFEA71-52D4-45B3-B544-B1C71B620109" Type="109" Title="Picture library" Url="picture" QuickLaunchUrl="picture/Forms/AllItems.aspx" />

                  </Lists>

                  <Modules>

                      <Module Name="Default" />

                      <Module Name="CustomMasterPage" />

                  </Modules>

                  <SiteFeatures>

                      <!-- BasicWebParts Feature -->

                      <Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />

                      <!-- Three-state Workflow Feature -->

                      <Feature ID="FDE5D850-671E-4143-950A-87B473922DC7" />

                  </SiteFeatures>

                  <WebFeatures>

                      <Feature ID="00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5" />

             <!-- TeamCollab Feature -->

                      <Feature ID="F41CC668-37E5-4743-B4A8-74D1DB3FD8A4" />

                      <!-- MobilityRedirect -->

<!-- 응답형 게시판 -->

                      <Feature ID="EE4DB430-EB44-4696-9E03-F6D70DFC144C" />

                      <!-- 사이트생성후 처리 -->

                      <Feature ID="A4DFAAF2-D2D0-45a2-8AC6-011B9E6B2088" />

                  </WebFeatures>

              </Configuration>

         </Configurations>

 

l  <Configuration> 설명

여기서 중요한 사항 중 하나가 WEbTEMP***.XML 에서 정의한 Configuration ID 값과 Site Template 에서 정의한 Configuration ID 값이 같아야 한다. MasterUrl은 해당 Url에 있는 file를 마스터로 등록한다.

 

Lists : 리스트 찍는 부분으로 FeatureId 는 리스트템플릿의 FeatureId, Type는 리스트 Type 번호

                 Title 는 리스트 이름, Url는 리스트 Url

Modules : 웹파트 추가, 마스터 페이지 파일 등록 등등 작업하는 곳

SiteFeatures : 사이트 모음 기능을 나타내며, Feature ID를 등록시, 기능 활성화 된다.

WebFeatures  : 사이트 기능으로 ID 등록시, 기능 활성화 된다.

 

 

         <Modules>

<Module Name="CustomMasterPage" List="116" Url="_catalogs/masterpage" RootWebOnly="FALSE">

                  <File Url="GAComm.master" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />

              </Module>

              <Module Name="Default" Url="" Path="">

                  <File Url="default.aspx" NavBarHome="True">

<View List="$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;" BaseViewID="0" RecurrenceRowset="TRUE" WebPartZoneID="Left" WebPartOrder="2" />

<AllUsersWebPart WebPartZoneID="Right" WebPartOrder="0">

                   <![CDATA[

                      <webParts>

                           <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">

                           <metaData>

<type name="SKT.TWorkplace.SPS.GlobalAvenue.WebParts.CommImage, SKT.TWorkplace.SPS.GlobalAvenue.WebParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=388b774ba96c947e" />

                           <importErrorMessage>Cannot import this Web Part.</importErrorMessage>

                           </metaData>

                           <data>

                           <properties>

                                    <property name="AllowClose" type="bool">True</property>

                                   <property name="Width" type="string" />

                                   <property name="AllowMinimize" type="bool">True</property>

                                    <property name="AllowConnect" type="bool">True</property>

                                   <property name="ChromeType" type="chrometype">None</property>

                                   <property name="TitleIconImageUrl" type="string" />

                                   <property name="Description" type="string" />

                                   <property name="Hidden" type="bool">False</property>

                                   <property name="TitleUrl" type="string" />

                                   <property name="AllowEdit" type="bool">True</property>

                                   <property name="Height" type="string" />

<property name="MissingAssembly" type="string">Cannot import this Web Part.</property>

                                    <property name="HelpUrl" type="string" />

                                   <property name="Title" type="string">Community Image</property>

                                   <property name="CatalogIconImageUrl" type="string" />

                                   <property name="Direction" type="direction">NotSet</property>

<property name="ChromeState" type="chromestate">Normal</property>

                                   <property name="AllowZoneChange" type="bool">True</property>

                                   <property name="AllowHide" type="bool">True</property>

                                   <property name="HelpMode" type="helpmode">Modeless</property>

                                   <property name="ExportMode" type="exportmode">All</property>

                           </properties>

                           </data>

                           </webPart>

                      </webParts>

                      ]]>

</AllUsersWebPart>

                  </File>

</Module>

         </Modules>

 

l  <Modules> 설명

<Configuration><Modules><Module Name=””>에서 정의한 Name과 동일하여야 한다.(Configuration 아래 Modules는 구성하는것이고, 실제 작업은 여기 Modules에서 한다고 생각하면 된다.)

        

<Module Name="CustomMasterPage" List="116" Url="_catalogs/masterpage" RootWebOnly="FALSE">

              <File Url="GAComm.master" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />

</Module>

 

사이트 템플릿을 만든 폴더 (, C:\Program Files\Common Files\Microsoft Shared\web se

rver extensions\12\TEMPLATE\SiteTemplates\SKTTemplate) 아래 있는 마스터 페이지를 마스터 페이지 갤러리에 등록하는 부분이다.

 

<Module Name="Default" Url="" Path="">

             <File Url="default.aspx" NavBarHome="True">

<View List="$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;" BaseViewID="0" RecurrenceRowset="TRUE" WebPartZoneID="Left" WebPartOrder="2" />

<AllUsersWebPart WebPartZoneID="Right" WebPartOrder="0">…….

      

default.aspx 레이아웃(웹파트존) 정의 된 페이지로, 그 파일에 웹파트를 추가하는 부분이다. WebPartZoneID 는 웹파트존의 위치, WebPartOrder 웹파트의 순서를 나타낸다.

 

<AllUsersWebPart WebPartZoneID="Right" WebPartOrder="0">

<![CDATA[

...*******************************************

]]>

</AllUsersWebPart>

 

커스텀 웹파트는 ********** 부분에 웹파트 속성 정보(xml 형식)을 작성하면 된다.

웹파트 속성은 아래 그림과 같이 내보내기를 하면 해당 파일에 xml형식로 되어 있다.

 

  • SharePoint Search 테스트 시나리오
  1. 아래 그림과 같이 인코딩 형식을 유니코드(UTF-8) 형식으로 저장한 eml 파일과

    한국어(EUC-KR) 형식으로 저장한 eml 파일이 있습니다.   

 

  1. 위 2가지 형태로 저장한 eml 파일을 Document Library에 업로드합니다.

    (Document Library 뿐만 아니라 그 외 Custom List의 Attachment에 업로드 후 테스트 결과 동일하였음. => 리스트 상관 없음)

     

  2. 중앙 관리 사이트(SSP-검색관리)에 크롤링 작업을 한 후, 해당 문서에 대해 검색을 해보면 아래 이미지와 같이

    한글이 깨지는 현상이 일어납니다. (아래 검색 결과 페이지의 첫 번째 문서는 UTF-8 인코딩 형식으로 저장된 문서입니다.)

 

  • 크롤링 로그 확인
  1. 중앙 관리 사이트(SSP-검색관리)에 크롤링 로그를 확인하여 보면, 해당 문서에 대해서 크롤링 작업 상태 유형은 성공으로 되었으나,

    아래와 같이 "The document contains invalid utf-8 encoded characters" 라는 메시지가 나와 있습니다.

  2. 해당 메시지가 나온 문서에 대해서는 검색 시 한글이 깨져 표시 됩니다.

    현재 이 유니코드(UTF-8)파일이 아닌 문서에 대한 크롤링 문제 해결 방안을 찾고 있습니다.
아래는 FullTextSqlQuery를 이용하고,
검색 범위를 지정하여 해당 범위안에 있는 아이템을 검색하는 소스이다.


string strQuery = string.Empty;
string strkeyword = "Microsoft";

ServerContext context = ServerContext.Current;
FullTextSqlQuery kQuery = new FullTextSqlQuery(context);

strQuery = "SELECT Title, HitHighlightedSummary, Write, ContentClass, Department, IsDocument, Path, Author, Size, SiteTItle FROM Scope() WHERE \"scope\" = 'Search' AND FREETEXT(defaultproperties, '" + strkeyword + "')";
    //Search는 중앙 관리에서 생성한 검색 범위명
    
kQuery.QueryText = strQuery;
kQuery.ResultTypes = ResultType.RelevantResults;
kQuery.StartRow = 0;
kQuery.RowLimit = 50;
kQuery.EnableStemming = true;
kQuery.TrimDuplicates = true;
kQuery.HighlightedSentenceCount = 3;
kQuery.Culture = CultureInfo.CurrentCulture;
kQuery.KeywordInclusion = KeywordInclusion.AllKeywords;
kQuery.Timeout = 60000;
kQuery.AuthenticationType = QueryAuthenticationType.NtAuthenticatedQuery;

ResultTableCollection resultTbls = kQuery.Execute();
if ((int)ResultType.RelevantResults != 0)
{
       ResultTable tblResult = resultTbls[ResultType.RelevantResults];

       DataTable resultDataTable = new DataTable();
       resultDataTable.Load(tblResult, LoadOption.OverwriteChanges);

       gvSearchResult.DataSource = resultDataTable;
       gvSearchResult.DataBind();
}

특정 문서 라이브러리에 대한 리스트 아이템에 대해서 검색하도록 검색 범위를 지정한 후,
해당 문서 라이브러리에 여러 문서를 업로드한다. (이때, 많은 문서를 손쉽게 업로드 하기 위해 원도우 탐색기를 이용하여 업로드 하였다.)
그리고, 크로링 작업을 완료 한 후, 검색을 해보았다.
그런데 이때 위 소스에 Author 부분에 아이템의 작성자가 아닌, 이상한 값들이 있는것을 발견!!!

테스트 해 본 결과!!
원도우 탐색기를 열때, 기존의 인증(시스템 계정)이 물려 있었다.
쿠키 및 캐시 때문인가 싶어 지우고도 다시 해보았으나, 처음에 물려있던 인증창이 한번 물리면 안풀린다
(어떻게 해야 풀리는지 찾지는 못함. 단, 어느정도 시간 지나면 풀림)

우선 일차적인 문제는 시스템 계정 인증 문제였으나,
왜 Author에 시스템 계정으로 나오지 않고, 다른 이름이 나오는가 의문을 갖게 되어 찾아본 결과..

시스템 계정 인증으로 Office를 업로드 한 문서를 검색할 경우, 
해당 Office 문서의 만든이로 Author에 등록되어 나온다는 것을 알았다.
그리고 Office 문서가 아닌 이미지와 같은 파일은 시스템 계정으로 나온다.

인증 문제로 인해 다시 삽질을 하지 말자는 바램으로 정리 해보았다.

I am having several problems configuring incoming e-mail.  I have consulted Steve Smith's paper from Combined Knowledge on the topic (www.combined-knowledge.com/Downloads%202007.htm), but am still having problems.  I think they may be related so I am including them in a single post.

I am running MOSS 2007 SP1 (slipstreamed installation) with two WFE, one APP, and one DB server.  Service accounts are setup for least privilege.  The WFE servers have the SMTP service installed.  The services (Windows SharePoint Services Incoming E-Mail) are running on each WFE, as indicated from the Services on Server page in CA.

Problem #1:

When I " Enable sites on this server to receive e-mail " in automatic mode I immediately get two errors in the APP server Application event log once every minute:
-------
Event ID: 6872
A critical error occurred while processing the incoming e-mail drop folder . The error was: Value cannot be null.
Parameter name: path.

and

Event ID: 6398
The Execute method of job definition Microsoft.SharePoint.Administration.SPIncomingEmailJobDefinition (ID b8197cdb-92a2-4554-b3a4-46a89887878a) threw an exception. More information is included below.

Value cannot be null.
Parameter name: path
-------
I switched to advanced mode and entered the drop folder path "c:\inetpub\mailroot\drop" and the error continues.

I checked the permissions of the drop folders (there are two, one on each server since there are two WFEs that are load balanced) WSS_ADMIN_WPG and WSS_WPG had their permissions set.  I granted the CA service account full control over the drop folder, the errors continue.


Problem #2:
With incoming e-mail enabled (and generating the error above) I attempt to e-mail enable a document library.  After submitting the setting I get a non-descript error:
-------
Error
Error in the application.
Troubleshoot issues with Windows SharePoint Services.
-------

I suspect this error is because an entry cannot be made into the AD OU designated to hold


Problem #3:
As a test I sent an e-mail to the MOSS address, @sp.company.com (name changed to obscure my employer).  The e-mail bounced back and a warning was logged on the WFE server.

The System warning:
-------
Event ID: 4000
Message delivery to the remote domain 'sp.company.com' failed for the following reason: Unable to deliver the message because the destination address was misconfigured as a mail loop.

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

The bounced back message:
-------
Delivery has failed to these recipients or distribution lists:

thisisatest@sp.company.com
The recipient's e-mail system can't process this message at this time. Microsoft Exchange will not try to redeliver this message for you. Please try resending this message later, or provide the following diagnostic text to your system administrator.
-------

I'm still troubleshooting and will post any updates to the thread

 

  • 구성 요소
    1. WSS 3.0 / MOSS Server
    2. SPTimer Service
    3. SMTP Service
    4. Active Directory management service
    5. AD의 특정 OU에 대해서 충분한 권한이 있는 사용자 계정(최소:읽기 권한 이상)

 

  • 받는 전자 메일에 대한 소개
    1. List와 Library에 E-mail 메시지와 첨부 파일을 저장할 수 있다.
    2. 사용자의 SharePoint Document Library에 문서를 업로드 할 수 있다.
    3. List와 Library에 특정 E-mail 주소를 가질 수 있다.

 

  • SMTP 구성

    서버구성

    1. 비록 우리는 Exchange Server가 있지만, SharePoint Farm의 Web Front End Server에 SMTP 서비스를 설치해야 한다. SMTP 구성 요소를 SharePoint Server에 설치하였다면, SharePoint Timer Service에서 E-mail과 첨부파일을 가져올 것이다.
    2. SharePoint Server에 SMTP 서비스를 설치했을 때, SMTP 서비스 가상 서버에서 새로운 도메인이 생성될 것이다. 수동으로 구성할 필요는 없지만, 진행에 앞서, 몇 가지 검사 할 게 있다.
    3. 실행 > inetmgr(인터넷 정보 관리자) 명령어를 입력 > 기본 SMTP 가상 서버 > 도메인 > 도메인명(이후 가정하에 진행:MOSS.com) > 속성창을 연다. SharePoint Timer Service에서 가져갈 E-mail이 저장되어 있는 C:\Inetpub\mailroot\Drop(기본 위치) 폴더 위치로 지정 되어 있는지, 드롭 디렉토리를 확인한다. SharePoint Timer Service에서 해당 폴더를 매일 5분(기본) 체크할 것이다. 그리고 C:\Inetpub\mailroot\Drop 폴더에 보안 수준을 체크하며, WSS_ADMIN_WPG 로컬 그룹에 모든 권한이 부여한다.

    1. SMTP 가상 서버 등록 정보 설정
  • 속성 페이지에 액세스 탭을 선택한 후, 액세스와 릴레이에 대해 IP를 추가한다.
     
  • SMTP 서버 IP 와 Exchange 서버 IP 주소에 대해 허가됨을 추가한다.

클라이언트 구성

  1. E-mail 클라이언트와 클라이언트 컴퓨터는 모든 Windows 운영 체제 중인 MS Outlook 또는 Outlook Express으로 SharePoint 목록에 E-mail 보낼 있다.
  2. Outlook Express 실행 > 계정 추가

    표시 이름 입력

    전자 메일 주소 입력

    받는 메일 서버 유형 POP3 선택

    받는 메일 서버와 보내는 메일 서버 입력 (예: MOSS.com)

    계정 이름 및 암호 입력

    NOTE

    POP3 서버 접속 실패할 수 있는데, Sharepoint Server에 POP3 서비스가 아닌 유일한 SMTP 서버를 구성하였기에, 이를 무시해도 좋다. 받는 전자 메일 SMTP 서버 구성에는 충분하다.

     

테스트

Outlook Express를 열어 메일을 작성한 후 보내면 드롭 디렉토리에 .eml파일이 저장되는 것을 볼 수 있다.

  • 받는 전자 메일 사용 : 예
  • 설정 모드 : 자동
  • 디렉토리 관리 서비스 : 아니오
  • 받는 전자 메일 서버 표시 주소 : Moss.com
  • 안전한 전자 메일 서버 : 모든 전자 메일 서버에서 오는 메일 수락

 

리스트 설정

  1. Sharepoint 사이트에 리스트(공지사항으로 진행)를 생성한다.
  • 라이브러리 형태에 따라 설정 부분이 조금씩 달라진다.
  1. 리스트 설정에 받는 전자 메일 설정을 한다.
  • 받는 전자 메일 사용 : 예
  • E-mail 주소 입력
  • 전자 메일 첨부 파일 저장 여부 : 예
  • 원본 전자 메일 저장 여부 : 예
  • 전자 메일로 모임 초대 여부 : 예
  • 전자 메일 보안 정책 : 모든 보낸 사람의 전자 메일 메시지 수락

테스트

  1. 첨부 파일과 함께 이메일 발송(예:test@moss.com)한다.
  2. 드롭 디렉토리에 .eml 파일이 생성된 것을 확인한다.
  3. Sharepoint 타이머 서비스에서 .eml를 가져가며, 리스트에 저장한다.
  • Exchange Server 구성
    1. Exchange 관리 콘솔 > 조직 구성 > 허브 전송
    2. SMTP에 대한 송신 커넥터를 추가한다.
  • 송신 커넥터명 입력, 송신 커넥터에 저장할 용도 선택

  • 주소 공간 입력(SMTP 주소입력 => 예:moss.com)
  • 모든 하위 도메인 포함 체크

  • 네크워크 설정

    다음 스마트 호스트를 통해 메일 라우팅 선택

    스마트 호스트 추가한다.(MOSS 서버 IP주소:SMTP)

  • 스마트 호스트 인증 설정 구성 (없음 선택)

  • 원본 선택 후, 새 커넥터를 생성한다.

  1. 고급 SharePoint 구성
    1. 소개
  • Active Directory 및 Sharepoint 서비스 계정에 대한 권한을 위임 제어 옵션을 이용하여 새로운 조직 구성 단위를 만들어 관리한다.
  1. AD에 새로운 OU를 만든다.
  2. 중앙 관리 사이트 > 작업 > 받는 전자 메일 설정

    (http://ServerName:Port/Admin/IncomingEmail.aspx)

  3. 테스트는 기존 위 방식과 같으나, 체크할 항목이 하나 있다.
  • AD에서 OU를 체크하는데, 받는 전자 메일에 설정한 메일 주소가 연락처에 추가된 것을 볼 수 있다.

 

 

원본 http://blogs.msdn.com/selvagan/archive/2008/01/26/incoming-email-configuration-moss.aspx


CAML Query로 Date 및 Time 를 쿼리할 때가 있다.
U2U CAML tool 이용할 경우, 지원이 되지 않아,
쿼리문에 IncludeTimeValue=\"TRUE\" 를 추가하면 된다.

 System.Text.StringBuilder QueryBuilder = new System.Text.StringBuilder();
QueryBuilder.Append(""); 
QueryBuilder.Append("  "); 
QueryBuilder.Append("    "); 
QueryBuilder.Append("    " + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now.AddDays(10)) + ""); 
QueryBuilder.Append("  "); 
QueryBuilder.Append("");

몇일전에 워크플로 진행 상태에 따른 아이템에 대한 권한 변경을 이벤트리시버를 통해
변경되도록 개발 진행한적이 있다.

이와 같이 MOSS를 개발하게 되면, 권한 변경을 프로그램상으로 개발해야 하는 경우가 많을 것이다.
그래서 이번 기회에 리스트 아이템에 대한 권한 변경 모듈을 정리해 보려 한다.

아래 소스는 작성자에게는 기본 참가 그룹이 아닌 사용 수준 정의를 추가한 참가 그룹(특정 권한 뺌)을,
특정 관리자 그룹에게는 모든 권한을 부여하는 소스이다.
            SPPrincipal spPrincipal = null;
            SPRoleAssignment spRoleAssignment = null;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite spSite = new SPSite(properties.WebUrl))
                using (SPWeb spWeb = spSite.OpenWeb())
                {
                    spWeb.AllowUnsafeUpdates = true;

                    SPList spList = spWeb.Lists[properties.ListId];
                    SPListItem spListItem = spList.Items.GetItemById(properties.ListItemId);

                    try
                    {
                        // 사용 권한 수준 정의 (관리자, 참가 권한)
                        SPRoleDefinition spAdminRoleDef = spListItem.Web.RoleDefinitions.GetByType(SPRoleType.Administrator);
                        SPRoleDefinition spConRoleDef = spListItem.Web.RoleDefinitions[strContributorRoleDefName];

                        // #1. 권한 상속 여부 체크
                        if (!spListItem.HasUniqueRoleAssignments)
                        {
                            // 권한 상속을 푼다.
                            spListItem.BreakRoleInheritance(false);
                        }

                        // #2. 작성자 권한 부여
                        int authorSiteID = int.Parse(spListItem[SPBuiltInFieldId.Author].ToString().Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries)[0]);
                        SPUser spAuthorUser = spListItem.Web.AllUsers.GetByID(authorSiteID);

                        spPrincipal = spAuthorUser as SPPrincipal;
                        spRoleAssignment = new SPRoleAssignment(spPrincipal);
                        spRoleAssignment.RoleDefinitionBindings.Add(spConRoleDef);
                        spListItem.RoleAssignments.Add(spRoleAssignment);


                        // #3. 관리자 그룹 권한 부여

                        // 관리자 그룹에 대해 관리 권한을 정의한다.
                        SPGroup spAdminGroup = spListItem.Web.Groups[strManageGroupName];
                        spPrincipal = spAdminGroup as SPPrincipal;

                        try
                        {
                            // 해당 SPPrincipal 에 대해 만족하는 RoleAssignment이 없을 경우, 바로 Exception 발생
                            spRoleAssignment = spListItem.RoleAssignments.GetAssignmentByPrincipal(spPrincipal);
                        }
                        catch { spRoleAssignment = null; }

                        // 관리 그룹에 대해 관리 권한이 부여되어 있지 않거나, 그룹추가가 안되어 있을 경우
                        if (spRoleAssignment == null || (spRoleAssignment != null && !spRoleAssignment.RoleDefinitionBindings.Contains(spAdminRoleDef)))
                        {
                            spRoleAssignment = new SPRoleAssignment(spPrincipal);
                            spRoleAssignment.RoleDefinitionBindings.Add(spAdminRoleDef);
                            spListItem.RoleAssignments.Add(spRoleAssignment);
                        }
                    }
                    catch (Exception ex)
                    {
                        this.LogWrite("UpdateAuthorRole의 ItemAdded 이벤트 실행중 오류가 발생하였습니다.", ex.Message);
                        spListItem.ResetRoleInheritance();
                    }

                    spListItem.SystemUpdate(false);

                    spWeb.Update();
                    spWeb.AllowUnsafeUpdates = false;
                }
            });

After Service Pack 1 and the inherent security improvements that had been implemented you may find yourself having issues with SharePoint Designer workflows kicking off automatically.  One way that we have found around that issue is setting workflows in a list / library that you know will have that issue to manual start only and register a custom event handler on that list for ItemAdded or ItemUpdated to manually kick off the workflow through code.

 

That in itself is a nice workaround, but what if you wanted to kick off a workflow using another users context, but you don’t want to store credentials or any other pesky security information in your code?

 

In this specific scenario we created a workflow service account that we wanted to use to kick the workflow off on a form library where items were being submitted through InfoPath Forms Services (and because these workflows were creating, updating, and looking inside other lists that we needed to set security we only needed to do it for this one service account).  Here is a bunch of code:

 

//Set variables from web.configstring _workflowUser = ConfigurationSettings.AppSettings["WorkflowUser"]; //Example:DOMAIN\Administratorstring _workflowName = ConfigurationSettings.AppSettings["WorkflowName"]; //Example:Master Workflowstring _formsLibrary = ConfigurationSettings.AppSettings["FormsLibrary"]; //Example:Request LibrarySPSecurity.RunWithElevatedPrivileges(delegate(){     //Setting variables to use under workflow service account     string userName = properties.UserLoginName;     int itemID = properties.ListItemId;     SPWeb parentWeb = properties.OpenWeb();     SPList parentList = parentWeb.Lists[_formsLibrary];     string targetUrl = parentWeb.Url;     SPUser workflowUser = parentWeb.AllUsers[_workflowUser];     //Open site as workflow service account     SPSite site = new SPSite(targetUrl, workflowUser.UserToken);     site.AllowUnsafeUpdates = true;     //Open web as workflow service account     SPWeb web = site.OpenWeb();     web.AllowUnsafeUpdates = true;     //Get Item object as workflow service account     SPList formsLibrary = web.Lists[_formsLibrary];     SPListItem item = formsLibrary.GetItemById(itemID);     //Getting workflow information     SPWorkflowAssociation workflowTemplate = formsLibrary.WorkflowAssociations.GetAssociationByName(_workflowName, System.Globalization.CultureInfo.CurrentCulture);     //Getting workflow Manager to start workflow     SPWorkflowManager mgr = site.WorkflowManager;     //Starting workflow as service account     mgr.StartWorkflow(item, workflowTemplate, workflowTemplate.AssociationData);     web.Dispose();     site.Dispose();     parentWeb.Dispose();});

 

First off I’m getting my variables from my web.config appSettings, you could just as easily set these in a property bag on an SPSite or SPWeb object.  After that, I start running the next few lines in the context of the application pool so that I know I have access for everything I need to populate other variables I will need down the road.  The fun part comes when I open the SPSite site object using the workflowUser.UserToken object.  After that all items that I use the parent site object to obtain is opened up as that workflowUser

Best Practices
다음 과 같이 소스는 메모리를 많이 사용한다고 한다.
그리고 IIS 에서의 리사이클 주기를 짧게 하여 성능 상의 문제를 일으킨다고 한다.
public void GetNavigationInfo()
{
   SPWeb oSPWeb = SPContext.Web;

   // .. Get information oSPWeb for navigation .. 
   foreach(SPWeb oSubWeb in oSPWeb.GetSubWebsForCurrentUser())
   {
      // .. Add subweb information for navigation .. 
    }
}

아래와 같이 Dispose 를 권장한다.
public void GetNavigationInfo()
{
   SPWeb oSPWeb = SPContext.Web;
   foreach(SPWeb oSubWeb in oSPWeb.GetSubWebsForCurrentUser()))
   {
      // .. Add subweb information for navigation ..
      oSubWeb.Dispose();
   }
}
캐쉬 데이타를 사용할 경우에는 Lock 을 하자 아래의 소스 처럼 캐쉬 데이터를 사용할 경우 동 시간대의 접속 자들은 같은 오브젝트에 같은 데이터를 업데이트를 하려고 한다. 이 경우 캐쉬데이타의 깨짐 현상이 일어 날수 있다고 한다.
public void CacheData()
{
   SPListItemCollection oListItems;
   oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
   
   if(oListItems == null)
   {
      oListItems = DoQueryToReturnItems();
      Cache.Add("ListItemCacheName", oListItems, ..);
   }
}
이 현상을 방지 하기 위해서 다음과 같은 locking 처리가 필요하다.
public void CacheData()
{
   DataTable oDataTable;
   SPListItemCollection oListItems;

   lock(this)
   {
      oDataTable = (DataTable)Cache["ListItemCacheName"];
      if(oDataTable == null)
      {
         oListItems = DoQueryToReturnItems();
         oDataTable = oListItems.GetDataTable();
         Cache.Add("ListItemCacheName", oDataTable, ..);
      }
   }
}


워크플로에 대한 구글링을 하다, MS에서 워크플로에 대한 설명을 정리한 문서를 발견하였다.

크게 3분류로

1. WWF(Windows Workflow Foundation)에 대한 설명
2. WSS(Windows SharePoint Service)에 Workflow 접목
3. Office Sharepoint Server 2007에 Workflow 접목

에 대한 설명이 되어 있다.


SharetPoint 리스트에 워크플로 상태 값을 쿼리 하기 위해,
UI상에 보이는 승인됨, 진행 중 과 같은 값으로 쿼리를 날렸으나,
제대로 값이 나오지 않을 것이다.

워크플로 상태 값을 쿼리 하기 위해서는, 워크플로 상태 코드 값으로 쿼리하면 된다.
아래는 워크플로 상태 코드 값들이다.

진행중(In Progress) : 2
승인됨(Approved) : 16
거절됨(Rejected) : 17
취소됨(Canceled) : 4
에러발생함(Error Occured) : 3


MOSS 권한을 보면 아래와 같은 그림처럼 
모든 권한, 디자인, 계층 구조 관리, 승인, 참가, 읽기 ....등등 
각 사용 권한 수준에 특정 권한이 기본적으로 부여되어 있다.



여기서 필자가 말하려고 하는 것은 특정 권한만이 부여된 사용 권한 수준이 필요 할 경우
그 사용 권한 수준을 어떻게 추가하는지 정리한 항목이다.

우선 관리자(Administrator) 계정으로 로그인하여 사이트 설정에 사용자 및 그룹을 선택하고,
좌측 메뉴의 사이트 사용 권한 항목을 선택한다.
그러면 아래와 같은 화면이 나타날 것이다.



해당 화면에서 폼 메뉴에 설정이라는 항목을 클릭하면 
아래와 같이 사용 권한 수준이 있으며 선택한다.
 


자, 이제부터는 사용 권한 수준 설정 부분이니 잘 보도록 하자.
위 순서대로 잘 진행했다면 아래와 같은 화면이 나타난다.


사용 권한 수준 추가에 대한 페이지 화면이 나타나며,
이름 및 설명 그리고 사용 권한을 부여한 후, 하단의 만들기 버튼을 클릭하면
사용 권한 수준 추가는 끝이 난다.



특정 사용 권한 수준에 대해 복사하고 싶을 경우
사용 권한 수준 화면(바로 위에 위 이미지)에서 사용 권한 수준 이름을 클릭하면
해당 사용 권한 수준 설정이 나타날 것이며,
맨 하단에 보면 사용 권한 수준 복사라는 항목을 클릭하면 된다.


+ Recent posts