Saturday, February 21, 2009

Event ID : 6398 - WSS (IndexingScheduleJobDefinition - Access Denied)

It’s been three days I have been struggling with rectifying an insane error which keeps popping up in Windows Event Viewer under application category. I checked everything starting from permission settings on DCOM Component Services (OSearch) to recreating entire index and resetting all crawl rules and scopes, even creating new SSP. Steps as suggested in some Microsoft TechNet Posts are specified in my previous post, which did not help in full resolution of the issue. Following were the two errors which were giving me lot pain while setting up the environment. 

 Event ID 10016 and Event ID 6398

For resolution steps for Event 10016 click here.

Event ID 6398Windows SharePoint Services 3    Error  Timer  6398   N/A   WIN2K3R2EE    "The Execute method of job definition Microsoft.Office.Server.Search.Administration.IndexingScheduleJobDefinition (ID b991a523-c9a3-402d-878c-31e7fa8b04b2) threw an exception. More information is included below.

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"

Root Cause Analysis:

Upon visiting following path: Central Administration > Operations > Timer Job Status I saw one of the job was failing each time. 

Indexing Schedule Manager on WIN2K3R2EE Failed 2/20/2009 6:00 PM  

Once Indexing Schedule Manager Timer Job was deactivated, alerts stopped coming. Upon reactivating, alerts appeared again. This seemed to be the culprit.

Next, I checked Central Administration > Operations > Services on Server > Windows SharePoint Services Search Service Settings where I found Service Account was running under predefined "Network Service".

Under service account comments it said: "The search service account must not be a built-in account in order to access the database. Examples of built-in accounts are Local Service and Network Service."

Final point to take note of it, error states it’s a Windows SharePoint Services 3 Timer Error. I went ahead WSS Timer Service at Start > Administrative Tools > Services

As one can see in the the above figure Windows SharePoint Service Timer is running as Network Service and error showed as "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"

Solution:

Following are the steps which helped me in resolving this issue.

1) Create new user account "X" (ensure accounts X have admin level privledges)

2) Associate account "X" with

i)  Central Administration > Operations > Services on Server > Windows SharePoint Services Search Service

ii )Start > Administrative Tools > Services > Windows SharePoint Service Timer

This did the trick. Am not seeing any 6398 alerts any more.

Cheers

Friday, February 20, 2009

Event ID 10016 and Event ID 6398

Recently, I am working on to build a SharePoint environment for my team. This is a brand new environment. So I created the AD accounts and did all those steps, account delegation stuff. Created the sites/site collections following our build docs. Everything was working out fine to a point where things started falling apart. I narrowed down the problem to following errors, which I dug up from windows application event viewer.
  • Event ID 10016 : Local Activation permission for the COM Server application with CLSID {61738644-F196-11D0-9953-00C04FD919C1}
  • Event ID 6398: The Execute method of job definition Microsoft.Office.Server.Search.Administration.IndexingScheduleJobDefinition

Solutions -

Event ID 10016 :

To prevent the event ID error messages from being logged in the System log, use the Component Services snap-in to enable the Local Activation permission to the IIS Wamreg Admin Service for the domain user account that you specified as the Windows SharePoint Services 3.0 service account. To do this, follow these steps:
1. Click Start, click Run, type dcomcnfg in the Open box, and then click OK.
2. Expand Component Services, expand Computers, expand My Computer, and then click DCOM Config.
3. Right-click IIS WAMREG admin Service, and then click Properties.
4. Click the Security tab.
5. Under Launch and Activation Permissions, click Edit.
6. In the Launch Permission dialog box, click Add.
7. In the Select Users, Computers, or Groups dialog box, type the domain user account that you specified as the Windows SharePoint Services 3.0 service account, click Check Names, and then click OK.
8. In the Permissions for UserName list, click to select the Allow check box that is next to Local Activation, and then click OK two times.

Event ID 6398: Still working on Solution (Following steps solved partial problem):

1. Open Start Menu > Administrative Tools > Component Services Tool
2. Drill Down and Expand DCOM Config
3. Navigate to the OSearch, Right Click Properties
4. Select the Security Tab
5. Add the Network Service Account to Local and Activation Permissions
6. Add the Network Service Account to Access Permissions
7. Restart the Office SharePoint Server Search Service from Start Menu > Administrative Tools > Services Tool
-------------------------------

I have found the solution to Error 6398. Please refer to my post here.

Monday, January 19, 2009

Requirements for SharePoint VPC or VM

Hi All,

My apologies for being away so long, did not get much time to update my blog regularly. Anyhow, now as am back, I will keep you updated on stuff happening at my end in SharePoint World.

Let's talk a little about what can get us up and running to do development on SharePoint 2007. There are two possible options.

1.     Use a common development environment.

2.     Use a personal development environment as a VM.

1. In scenario where a common development environment is used, it raises more problems than solving (purely based on my experience, others may differ). Many issues come in when one is debugging the code. By default Windows Server 2003 allow three people to log in at same time.

  • In a scenario, Developer 1 had enabled debugging on WebApp1 and other connected people are also accessing same WebApp (i.e. WebApp1), their request will not be executed untill Developer 1 terminates the debugging process. 
  • Another scenario will be, as Developers mostly put DLL's in GAC which are either required by a webpart or feature, if in a case multiple developers are working on same DLL then there might be a conflict.

Personally, I prefer the second option i.e. use personal VM for development later on for builds/WSP's common development environment can be used.

2. Lets discuss what we need to get ourselves up and running for development by creating a personal VM.

  • Create a Virtual Image for dedicated SharePoint development purposes
  • Install and Configure Windows SharePoint Services 3.0 (WSS)/Microsoft Office SharePoint Server 2007 (MOSS) on a server operating system (Windows Server 2003 or Windows Server 2008) for development purposes

To develop SharePoint solutions it is recommended to create a virtual machine image with the following minimum software and hardware requirements.

Hardware Requirements

·                 PC with a processor speed of at least 2.5 GHz

·                 RAM capacity of 2 GB minimum

·                 4 GB recommended

·                 Disk space up to 2 GB for installation minimum, 5 GB or more minimum for data

·                 Network connectivity and Internet access

Software Requirements

Licensed

Free

·                 Virtual PC 2007 (http://www.microsoft.com/downloads/details.aspx?FamilyId=04D26402-3199-48A3-AFA2-2DC0B40A73B6) or Virtual Server 2005 R2 SP1 (http://technet.microsoft.com/en-nz/bb738033(en-us).aspx) or Hyper-V

·                 Microsoft .Net Framework 2.0

·                 Microsoft .Net Framework 3.0

·                 Visual Studio 2005 Extensions for Windows SharePoint Services 1.1 (http://www.microsoft.com/downloads/details.aspx?familyid=3E1DCCCD-1CCA-433A-BB4D-97B96BF7AB63&displaylang=en)

·                 Windows SharePoint Services 3.0 with SP1

·                 MOSS SDK (http://go.microsoft.com/?linkid=7934513)

·                 WSS SDK (http://msdn2.microsoft.com/library/ms441339)

·                 Additional information is available at the WSS Developer Centre (http://msdn2.microsoft.com/en-us/sharepoint/default.aspx)


Cheers,

Saturday, November 15, 2008

SharePoint: Best Practices

"Several of the Windows SharePoint Services objects, primarily the SPSite class and SPWeb class objects, are created as managed objects. However, these objects use unmanaged code and memory to perform the majority of their work. The managed part of the object is small; the unmanaged part of the object is much larger. Because the smaller managed part of the object does not put memory pressure on the garbage collector, the garbage collector does not release the object from memory in a timely manner. The object's use of a large amount of unmanaged memory can cause some of the unusual behaviors described earlier. Calling applications that work with IDisposable objects in Windows SharePoint Services must dispose of the objects when the applications finish using them. You should not rely on the garbage collector to release them from memory automatically." - MSDN [Scott Harris - Microsoft Corporation, Mike Ammerlaan - Microsoft Corporation : November 2006]

Best techniques:
- Dispose method
- using clause
- try, catch, and finally blocks

The SPSite.RootWeb property and SPWeb.ParentWeb property create new objects and assign them to a local member variable. So don't forget to dispose them to.

[code]
String str; using(SPSite oSPSite = new SPSite("http://server")) {    using(SPWeb oRootWeb = oSPSite.RootWeb)    {       str = oRootWeb.Title;       str = oRootWeb.Url;    … additional processing on RootWeb …     } }
[/code]

SPSiteCollection Class

This section describes the methods, properties, or operators in the SPSiteCollection object that require the returned SPSite object to be closed after access.

SPSiteCollection.Add Method

The SPSiteCollection.Add method creates and returns a new SPSite object. You should dispose of any SPSite object returned from the SPSiteCollection.Addmethod.

Must visit URL's:

Monday, October 20, 2008

SharePoint: Creating Timer Jobs

Its been quiet some time since my last post. Been hectic at work lately, finally some relief. Today, I want to discuss how to create timer jobs in SharePoint.  A timer job is a schedule of when to run a service by using the SharePoint Timer service.
SharePoint Service Timer service is a service that runs other services according to schedules specified in timer jobs. Many features in MOSS/Windows SharePoint Services 3.0 rely on timer jobs to run services according to a schedule.

Lets break down entire process into simpler steps. 
Step 1. Timer Job Development
Step 2. Timer Job Deployement Methodology
Step 3. Enable Timer Job

Step 1. Timer Job Development
The first thing you need to do is create a class that inherits from the Microsoft.SharePoint.Administration.SPJobDefinition class.

Let's look into WSS object model.  [Click on the image to enlarge]


To implement this class, one needs to create a few constructors and override the Execute() method. 

[code]
namespace sandeep {
 public class MyJob: SPJobDefinition{

public MyJob(): base(){
}

public MyJob(string jobName, SPService service, SPServer server, SPJobLockType targetType)
: base (jobName, service, server, targetType) {
}

public MyJob(string jobName, SPWebApplication webApplication)
: base (jobName, webApplication, null, SPJobLockType.ContentDatabase) {
this.Title = "My SharePoint Task Job";
}

public override void Execute () {
// your business logic goes here
}
}
}
[/code]

Step 2. Timer Job Deployement Methodology
MSDN suggests, that the best way to deploy a timer job is to wrap it as a feature. On feature activated and deactivating events we can write code to add/delete timer job in context of current web/site.

Take a look at the code below:-
[code]
namespace sandeep {
class FeatureToEnableJob: SPFeatureReceiver {
const string TASK_LOGGER_JOB_NAME = "My Custom Job Name";

public override void FeatureInstalled (SPFeatureReceiverProperties properties) {
}
 
public override void FeatureUninstalling (SPFeatureReceiverProperties properties) {
}

public override void FeatureActivated (SPFeatureReceiverProperties properties) {
SPSite site = properties.Feature.Parent as SPSite;

// make sure the job isn't already registered
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions) {
if (job.Name == TASK_LOGGER_JOB_NAME)
job.Delete();
}

// install the job
MyJob job = new MyJob(TASK_LOGGER_JOB_NAME, site.WebApplication);

SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 120;
schedule.Interval = 5;
job.Schedule = schedule;

job.Update();
}

public override void FeatureDeactivating (SPFeatureReceiverProperties properties) {
SPSite site = properties.Feature.Parent as SPSite;

// delete the job
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions) {
if (job.Name == TASK_LOGGER_JOB_NAME)
job.Delete();
}
}
}
}
[/code]

Step 3. Enable Timer Job
Once we have timer job wrapped as feature, either one can go for manual feature deployement process or go the WSP way (better approach)

Manual Way:
  • Deploy the strongly named assembly to the GAC.
  • Reset IIS (required for SharePoint to "see" the new timer job in the GAC).
  • Specify the receiver class and assembly in feature.xml that contains the event receivers.
  • Install the feature using stsadm.
  • Activate the feature using stsadm or settings.aspx.
WSP Way:
Please refer to my past post for this. 

cheers,

Monday, October 13, 2008

SharePoint: Creating a Web Part with a Custom Tool Part

Today, I want to talk on, how to add multiple toolparts in a webpart property window. In one of my earlier post, I did mention a quick and dirty way as how one can add simple textbox in webpart property window without needing any toolparts for that matter. But when it comes to implementing reusable/pluggable collection of controls, using toolparts is best possible option. 
Now, the question is, how can one easily implement toolparts in custom or default SharePoint Webparts. I think, the best way to approach this problem is to dig into SharePoint object model. Please refer the image below:

WebPart class exposes an overridable method "GetToolParts" which returns an array of references to the new ToolPart objects that will be displayed in the property pane of the Web Part. The ToolPart objects are rendered by the tool pane in the order listed in the array. 
Following is a sample code for creating a toolpart:
[code]
  public class SampleToolPart : Microsoft.SharePoint.WebPartPages.ToolPart
    {
        // First, override the CreateChildControls method. This is where we create the controls. 
        protected override void CreateChildControls()
        {
            // create a panel that will hold all of our controls 
            Panel toolPartPanel = new Panel();            
           
            // create the actual control 
            DropDownList sampleDropDown1 = new DropDownList();
            sampleDropDown1.ID = "sampleDropDown1";
            sampleDropDown1.Items.Add("Item 1");
            sampleDropDown1.Items.Add("Item 2");
            sampleDropDown1.Items.Add("Item 3");

            toolPartPanel.Controls.Add(sampleDropDown1);            

            // finally add the panel to the controls collection of the tool part 
            Controls.Add(toolPartPanel);

            base.CreateChildControls();
        }

        // Next, override the ApplyChanges method. 
        // This method is where we will persist the values that the user selects. 
        public override void ApplyChanges()
        {
            // get the parent webpart 
            SampleWebPart parentWebPart = (SampleWebPart)this.ParentToolPane.SelectedWebPart;

            // loop thru this control's controls until we find the ones that we need to persist. 
            RetrievePropertyValues(this.Controls, parentWebPart);
        }

        // Recursive function that tries to locate the values set in the toolpart 
        private void RetrievePropertyValues(ControlCollection controls, SampleWebPart parentWebPart)
        {
            foreach (Control ctl in controls)
            {
                RetrievePropertyValue(ctl, parentWebPart);

                if (ctl.HasControls())
                {
                    RetrievePropertyValues(ctl.Controls, parentWebPart);
                }
            }
        }

        // Method for retrieving the values set by the user. 
        private void RetrievePropertyValue(Control ctl, SampleWebPart parentWebPart)
        {
            if (ctl is DropDownList)
            {
                if (ctl.ID.Equals("sampleDropDown1"))
                {
                    DropDownList drp = (DropDownList)ctl;
                    if (drp.SelectedItem.Value != "")
                    {
                        parentWebPart.myProperty = drp.SelectedItem.Value;
                    }
                }
            }
        }
    }
[/code]
All this toolpart would do is:
  • add dropdown box in webpart properties window
  • on applying changes, it assigns selected value from dropdown box to public property of base webpart class
Lets see out to add this custom toolpart in webpart's toolpart collection. To do this, we override the GetToolParts() method and place our new tool part in the ToolPart array. Take a look at the code below:
[code]
      public class SampleWebPart : Microsoft.SharePoint.WebPartPages.WebPart
    {
        private string _property1 = "Default Value";

        public SampleWebPart()
        {
            this.ExportMode = WebPartExportMode.All;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Label lbl = new Label();
            lbl.ID = "toolpart_webpart_lbl1";
            lbl.Text = _property1;
            Controls.Add(lbl);
        }

        public string myProperty
        {
            get
            {
                return _property1;
            }
            set
            {
                _property1 = value;
            }
        }        

        public override ToolPart[] GetToolParts()
        {
            // resize the tool part array 
            ToolPart[] toolparts = new ToolPart[3];
            // instantiate the standard SharePopint tool part 
            WebPartToolPart wptp = new WebPartToolPart();
            // instantiate the custom property toolpart if needed. 
            // this object is what renders our regular properties. 
            CustomPropertyToolPart custom = new CustomPropertyToolPart();
            // instantiate and add our tool part to the array. 
            // tool parts will render in the order they are added to this array. 
            toolparts[0] = new SampleToolPart();
            toolparts[1] = custom;
            toolparts[2] = wptp;
            return toolparts;
        }
    }
[/code]

WebPart Added On Page:
[before updation]

[after updation]

Hope this helped.

cheers