Tuesday, March 23, 2010

Steps to Clear SharePoint Configuration Cache

1. On all Servers in the farm, stop the Windows SharePoint Services Timer service (OWSTIMER.EXE). To do this go to the Services Console, right click on Windows SharePoint Services Timer service and click stop.

2. After this go the SharePoint Server running Indexing Server and navigate to “System Drive\Documents and Settings\All Users\Application Data\Microsoft\SharePoint\Config\GUID” in case of Windows Server 2003 or “System Drive\ProgramData\Microsoft\SharePoint\Config\GUID” in Windows Sever 2008.

3. In the folder there is single “cache.ini” & rest all are XML files. Delete all the XML files except for the “Cache.ini file”, make sure you do not delete the “cache.ini”. This is very important, do not even delete the whole GUID folder too, this is also very important. I repeat do not delete the GUID folder or the cache.ini file!

4. Now open the “cache.ini” file and note down the number. Clear the number and type in 1.

5. Click save and close the “Cache.ini” file.

6. Now start the Windows SharePoint Services Timer Service on the Indexing Server from the services console.

7. Now, you will see all XML files being generated again.
Open the Cache.ini and you will see same the number, as you noted down before.

8. Now repeat steps 2-8 on all queries servers followed by application/web servers.

Thursday, March 18, 2010

Custom code to get the list of site collection administrators for all the site collections in SharePoint server farm

Alright we have changed our idea of giving "Administrator" level access to all the site collections to the outsourced team. Instead we decided to deliver them an Excel document with the URL and site collection administrators for each site collection. In fact, all the outsourced team members have access to their own team site. So we are going to upload this Excel document to their team site.As usual, I wrote C# console application to achieve this.Note:1. This code assumes that you have all the site collections created under "sites/"2. This is a console application so you have to use it the way you use stsadm command.3. This code will output a text file with comma separated values when you run it as follows,SCAdmin.exe -url http://sharepoint.domain.com > SCAdmins.txt4. Finally you can import SCAdmin.txt file to an Excel document with ","(comma) selected as separator for creating a new column.5. SCAdmin.txt file should look like this,http://sharepoint.domain.com/sites/SC1, domain\spadmin;http://sharepoint.domain.com/sites/SC1, domain\spadmin; domain\user2; domain\user3http://sharepoint.domain.com/sites/SC1, domain\user4; domain\user5;http://sharepoint.domain.com/sites/SC1, domain\spadmin; domain\user6http://sharepoint.domain.com/sites/SC1, domain\user7;..........................................................6. When you import SCAdmin.txt to an Excel document by selecting "," (comma) as the separator, it will place URL in first column and site collection administrators in second column.Disclaimer: Please test this code in test environment before you use it. I will not be responsible the outcome of this code.Here is the code,using System;using System.Collections;using System.Collections.Generic;using System.Text;using Microsoft.SharePoint;using Microsoft.SharePoint.Administration;using Microsoft.SharePoint.StsAdmin;namespace SCAdmins{ class SCAdminsClass { static void Main(string[] args) { SCAdminsClass sc = new SCAdminsClass(); sc.getSiteCollectionAdministrators(args); } private void getSiteCollectionAdministrators(string[] args) { try { string mode = ""; string virtualserver = ""; // get command line arguments if ((args.Length == 0) (args.Length == 1 && (args[0] == "-?" args[0] == "-help"))) { displayOutput("", mode); displayOutput("SCAdmin.exe -url VirtualServerURL [-quiet]", mode); displayOutput("", mode); displayOutput(" -url VirtualServerURL: Full URL of virtual server starting with http://", mode); return; } // loop through command line arguments for (int i = 0; i < args.Length; i++) { if (args[i] == "-url") { virtualserver = args[i + 1]; i++; // make sure url parameter starts with http: if (!virtualserver.StartsWith("http:")) { throw new ArgumentOutOfRangeException("url parameter should start with http://"); } } else if (args[i] == "-quiet") { mode = "quiet"; continue; } else { displayOutput(String.Format("Unrecognized switch {0}", args[i]), mode); return; } } // connect to web application on virtualserver SPWebApplication webApp = SPWebApplication.Lookup(new Uri(virtualserver)); // create site collections object for web application SPSiteCollection siteCollections = webApp.Sites; string SCUrl = ""; int SCCount = 0; SPSite site = null; SPWeb web = null; string admins = ""; // loop through site collections foreach (SPSite siteCollection in siteCollections) { site = new SPSite(siteCollection.Url); web = site.OpenWeb(); SCUrl = siteCollection.Url; if (SCUrl.Contains("sites")) { SCCount++; SPUserCollection users = web.Users; foreach (SPUser user in users) { if (user.IsSiteAdmin) { admins = admins+user.LoginName+"; "; } } Console.WriteLine(SCUrl + ", " + admins); } admins = ""; } //Console.WriteLine("Total Site Collection: " + SCCount); } catch (Exception e) { Console.WriteLine(e.Message); } } private void displayOutput(string text, string mode) { if (mode != "quiet") { Console.WriteLine(text); } } }}

Site Storage WebPart

For SharePoint site Administrators it could be important to view the storage of a SiteCollection (and subsites). However, SharePoint sites are often hosted by a external hosting and administrators have no access to the Central Administration. I wrote the following WebPart which summarizes the storage of a SiteCollection and the SubSites of this SiteCollection. Since there's no property for getting the Site Size I make recursively use of the Folder Size of a SPWeb.



public class SiteUsageWebPart : System.Web.UI.WebControls.WebParts.WebPart{ public SiteUsageWebPart() {
}
private SPSite siteCollection; private SPWeb site; private SPWebCollection sites;
protected override void CreateChildControls() { siteCollection = SPContext.Current.Site; site = SPContext.Current.Web; sites = siteCollection.RootWeb.Webs; }
private long GetWebSize(SPWeb web) { long total = 0;
foreach (SPFolder folder in web.Folders) { total += GetFolderSize(folder); }
foreach (SPWeb subweb in web.Webs) { total += GetWebSize(subweb); subweb.Dispose(); }
return total; }
private long GetFolderSize(SPFolder folder) { long folderSize = 0;
foreach (SPFile file in folder.Files) { folderSize += file.Length; }
foreach (SPFolder subfolder in folder.SubFolders) { folderSize += GetFolderSize(subfolder); }
return folderSize; }
private double ConvertBytesToMegabytes(long bytes) { return (bytes / 1024f) / 1024f; }
protected override void Render(HtmlTextWriter writer) { writer.WriteLine(""); // Size of the Rootweb writer.WriteLine(""); writer.Write(""); writer.Write(""); writer.WriteLine(""); writer.WriteLine("");
foreach (SPWeb subSite in sites) { writer.WriteLine(""); writer.Write(""); writer.Write(""); writer.WriteLine(""); writer.WriteLine(""); //SPListCollection lists = subSite.Lists;
//foreach (SPList list in lists) //{ // writer.Write(SPEncode.HtmlEncode(list.Title) // e.g. you can also summarize list sizes //} } // Total Size of SiteCollection writer.WriteLine(""); writer.WriteLine(""); writer.Write(""); writer.Write(""); writer.WriteLine(""); writer.WriteLine("");
writer.WriteLine("
" + SPEncode.HtmlEncode(siteCollection.RootWeb.Title) + " (RootWeb)" + siteCollection.RootWeb.Url + "" + SPEncode.HtmlEncode(ConvertBytesToMegabytes(GetWebSize(siteCollection.RootWeb)).ToString("0.00")) + " MB
" + SPEncode.HtmlEncode(subSite.Title) + "" + subSite.Url + "" + SPEncode.HtmlEncode(ConvertBytesToMegabytes(GetWebSize(subSite)).ToString("0.00")) + " MB
---------------
Total size of sitecollection " + siteCollection.Url + "" + SPEncode.HtmlEncode(ConvertBytesToMegabytes(siteCollection.Usage.Storage).ToString("0.00")) + " MB
"); }}

Friday, March 12, 2010

‘Access Denied’ when activating the ‘Server Publishing Infrastructure’

I recently had to activate the publishing infrastucture on a WSS v3 Teamsite. This had always worked before, but now I was getting ‘Access Denied’ when activating the ‘Server Publishing Infrastructure’.

This was due to my change in devlopment procedure. I always used to create development farms using Administrator for everything, but scince I found problems with feature activation I am developing using the Microsoft Guidelines for MOSS accounts. This means the AppPool account has limited permissions.

To solve the ‘Access Denied’ problem you need to elevate the permissions of the AppPool of the web application on which you are trying to activate the Publishing Infrastructure feature.

One way to achieve this is to temporarily change the AppPool of the web application…

1. Open IIS Admin.
2. Location the Web Site for your WSS web application.
3. Goto to the properties and select the ‘Home Directory’ tab.
4. Change the AppPool to be the same as Central Administration.
5. IISRESET
6. Activate the Publishing Infrastructure feature on your site.
7. Change to AppPool back to the original.
8. IISRESET.

This should allow you to enable the feature and use the publishing features within MOSS.

Wednesday, March 10, 2010

Unable to modify navigation - Add heading/link

Issue Description:
When I Try to modify Navigation in a site and add a heading, this is not working. When pushing OK, there is nor error messages appearing, but the heading is not showing up.

Solution Description:

Use Following Command to Fix the issue:

use Content Database Name

INSERT INTO [NavNodes] ([SiteId] ,[WebId] ,[Eid] ,[EidParent] ,[NumChildren] ,[RankChild] ,[ElementType] ,[Url] ,[DocId] ,[Name] ,[DateLastModified] ,[NodeMetainfo] , [NonNavPage] ,[NavSequence] ,[ChildOfSequence])

SELECT DISTINCT SiteId, WebId ,1002 ,0 ,0 ,1 ,1 ,'' ,NULL ,'SharePoint Top Navbar' ,getdate() ,NULL ,0 ,1 ,0
FROM NavNodes
WHERE WebId NOT IN (
SELECT WebId
FROM NavNodes
WHERE Eid = 1002)