MOSS MVP

I've moved my blog to http://blog.falchionconsulting.com!. Please update your links. This blog is no longer in use--you can find all posts and comments at my new blog; I will no longer be posting to this site and comments have been disabled.

Monday, August 13, 2007

Set Available Site Templates

One of the common tasks that administrators will need to perform across various site collections upon initial deployment is to set which site templates (and page layouts) are available for creating subsites and pages. You can do this via the Site Collection Site Settings page (Site Settings -> Page Layout and Site Template Settings). If you need to script it like I did then you'll need to get a PublishingWeb object (via the static PublishingWeb.GetPublishingWeb() method which takes an SPWeb object as an argument) and then call the SetAvailableCrossLanguageWebTemplates() method and the SetAvailableWebTemplates() depending on whether you are setting a cross language (language neutral) template or a language specific template.

Enumerating the list of templates is just as easy - you simply call the GetAvailableWebTemplates() method or the GetAvailableCrossLanguageWebTemplates() method. One of the challenges I had was in determining exactly how Microsoft handles the setting of templates as it's not entirely as obvious as I indicate above due to the fact that a template name can be associated as a cross language template or a language specific template and it's not always clear how it's currently set. I did a lot of digging through Microsoft's code and I believe that I've got it all figured out.

The commands below allow you to enumerate the list of current available and installed templates (helpful for getting the real template names so that you can then call the add and remove commands) as well as add and remove available templates.

1. gl-enuminstalledsitetemplates

The code to enumerate the list of installed templates is extremely simple. We create a new SPSite object passing in the URL of the Site Collection and then we use an SPWeb object to get the list of installed languages which we will iterate through. Then, for each installed language we get the list of web templates and custom web templates by calling the SPSite objects GetWebTemplates() and GetCustomWebTemplates() methods, passing in the locale ID (LCID) we retrieved from the SPWeb.RegionalSettings.InstaleldLanguages.SPLanguage object:

   1: string url = keyValues["url"];
   2:  
   3: using (SPSite site = new SPSite(url))
   4: {
   5:     using (SPWeb web = site.OpenWeb())
   6:     {
   7:  
   8:         foreach (SPLanguage lang in web.RegionalSettings.InstalledLanguages)
   9:         {
  10:             foreach (SPWebTemplate template in site.GetWebTemplates((uint)lang.LCID))
  11:             {
  12:                 output += template.Name + " = " + template.Title + " (" + lang.LCID + ")\r\n";
  13:             }
  14:             foreach (SPWebTemplate template in site.GetCustomWebTemplates((uint)lang.LCID))
  15:             {
  16:                 output += template.Name + " = " + template.Title + " (Custom)(" + lang.LCID + ")\r\n";
  17:             }
  18:         }
  19:     }
  20: }

The syntax of the resultant command can be seen below:

C:\>stsadm -help gl-enuminstalledsitetemplates

stsadm -o gl-enuminstalledsitetemplates

Returns the list of site templates installed for the given site collection.

Parameters:
        -url <site collection url>

Here’s an example of how to enumerate the list of installed templates for a site collection:

stsadm –o gl-enuminstalledsitetemplates –url "http://intranet/"

The results of executing this command can be seen below (your results may be different):

GLOBAL#0 = Global template (1033)
STS#0 = Team Site (1033)
STS#1 = Blank Site (1033)
STS#2 = Document Workspace (1033)
MPS#0 = Basic Meeting Workspace (1033)
MPS#1 = Blank Meeting Workspace (1033)
MPS#2 = Decision Meeting Workspace (1033)
MPS#3 = Social Meeting Workspace (1033)
MPS#4 = Multipage Meeting Workspace (1033)
CENTRALADMIN#0 = Central Admin Site (1033)
WIKI#0 = Wiki Site (1033)
BLOG#0 = Blog (1033)
BDR#0 = Document Center (1033)
OFFILE#0 = Records Center (1033)
OFFILE#1 = Records Center (1033)
OSRV#0 = Shared Services Administration Site (1033)
SPS#0 = SharePoint Portal Server Site (1033)
SPSPERS#0 = SharePoint Portal Server Personal Space (1033)
SPSMSITE#0 = Personalization Site (1033)
SPSTOC#0 = Contents area Template (1033)
SPSTOPIC#0 = Topic area template (1033)
SPSNEWS#0 = News Site (1033)
CMSPUBLISHING#0 = Publishing Site (1033)
BLANKINTERNET#0 = Publishing Site (1033)
BLANKINTERNET#1 = Press Releases Site (1033)
BLANKINTERNET#2 = Publishing Site with Workflow (1033)
SPSNHOME#0 = News Site (1033)
SPSSITES#0 = Site Directory (1033)
SPSCOMMU#0 = Community area template (1033)
SPSREPORTCENTER#0 = Report Center (1033)
SPSPORTAL#0 = Collaboration Portal (1033)
SRCHCEN#0 = Search Center with Tabs (1033)
PROFILES#0 = Profiles (1033)
BLANKINTERNETCONTAINER#0 = Publishing Portal (1033)
SPSMSITEHOST#0 = My Site Host (1033)
SRCHCENTERLITE#0 = Search Center (1033)
SRCHCENTERLITE#1 = Search Center (1033)
SPSBWEB#0 = SharePoint Portal Server BucketWeb Template (1033)

2. gl-enumavailablesitetemplates

The code to enumerate the list of available templates is almost identical to that needed to enumerate installed templates. The only real difference is that instead of getting the collection from the SPSite object you'll be getting it from a PublishingWeb object (not that there is no way to get a list of cross languange installed templates - this one of those things that threw me off - when you install the template it appears to be language specific but you can then make it available as a cross language template):

   1: string url = keyValues["url"];
   2: using (SPSite site = new SPSite(url))
   3: {
   4:     using (SPWeb web = site.OpenWeb())
   5:     {
   6:         PublishingWeb pubweb = PublishingWeb.GetPublishingWeb(web);
   7:  
   8:         //System.Diagnostics.Debugger.Launch();
   9:         foreach (SPWebTemplate template in pubweb.GetAvailableCrossLanguageWebTemplates())
  10:         {
  11:             output += template.Name + " = " + template.Title + " (All)\r\n";
  12:         }
  13:         foreach (SPLanguage lang in web.RegionalSettings.InstalledLanguages)
  14:         {
  15:             foreach (SPWebTemplate template in pubweb.GetAvailableWebTemplates((uint)lang.LCID))
  16:             {
  17:                 output += template.Name + " = " + template.Title + " (" + lang.LCID + ")\r\n";
  18:             }
  19:         }
  20:     }
  21: }

The syntax of the resultant command can be seen below:

C:\>stsadm -help gl-enumavailablesitetemplates

stsadm -o gl-enumavailablesitetemplates

Returns the list of site templates available for the given site collection.

Parameters:
        -url <site collection url>

Here’s an example of how to enumerate the list of available templates for a site collection:

stsadm –o gl-enumavailablesitetemplates –url "http://intranet/"

The results of executing this command can be seen below (your results may be different):

WIKI#0 = Wiki Site (All)
BLANKINTERNET#2 = Publishing Site with Workflow (All)
SPSREPORTCENTER#0 = Report Center (All)
SPSNHOME#0 = News Site (All)
CMSPUBLISHING#0 = Publishing Site (All)
BDR#0 = Document Center (All)
SPSSITES#0 = Site Directory (All)
STS#1 = Blank Site (All)
STS#0 = Team Site (All)
SRCHCEN#0 = Search Center with Tabs (All)
WIKI#0 = Wiki Site (1033)
BLANKINTERNET#2 = Publishing Site with Workflow (1033)
SPSREPORTCENTER#0 = Report Center (1033)
SPSNHOME#0 = News Site (1033)
CMSPUBLISHING#0 = Publishing Site (1033)
BDR#0 = Document Center (1033)
SPSSITES#0 = Site Directory (1033)
STS#1 = Blank Site (1033)
STS#0 = Team Site (1033)
SRCHCEN#0 = Search Center with Tabs (1033)

Note that the reason why some sites appear to be listed twice but only show up once in the web tool is because behind the scenes Microsoft is removing the duplicate (it knows that WIKI#0 is listed as a cross language template and it's locale is 1033 so don't show the locale specific entry if we're already showing as a language neutral template. I chose to not do this filtering so you could see everything that's going on - it wouldn't take much effort to change the code so that it list each item on one line and merely flags the fact that it's listed as cross language and what the specific locale is.

3. gl-addavailablesitetemplate

To add to the list of available templates we simply get a collection of currently available templates and then add to that collection. We then call SetAvailableCrossLanguageWebTemplates() or SetAvailableWebTemplates() passing in the modified collection. The method you call depends on whether the template is a language neutral template or not. The syntax of the resultant command can be seen below:

C:\>stsadm -help gl-addavailablesitetemplate

stsadm -o gl-addavailablesitetemplate

Adds a site template to the list of available templates for the given site collection.

Parameters:
        -url <site collection url>
        -template <template name>
        [-lcid <locale id>]
        [-resetallsubsites]

Here’s an example of how to add a template to the list of available templates for a site collection:

stsadm –o gl-addavailablesitetemplate –url "http://intranet/" -template "WIKI#0" -lcid 1033 -resetallsubsites

4. gl-removeavailablesitetemplate

Removing a template is similar to adding a template but instead of adding to the SPWebTemplateCollection object you're going to remove from it. The syntax of the resultant command can be seen below:

C:\>stsadm -help gl-removeavailablesitetemplate

stsadm -o gl-removeavailablesitetemplate

Removes a site template from the list of available templates for the given site collection.

Parameters:
        -url <site collection url>
        -template <template name>
        [-lcid <locale id>]
        [-resetallsubsites]

Here’s an example of how to remove a template from the list of available templates for a site collection:

stsadm –o gl-removeavailablesitetemplate –url "http://intranet/" -template "WIKI#0" -lcid 1033 -resetallsubsites

15 comments:

Anonymous said...

Will this work only on MOSS or also on Windows SharePoint Services 3.0?

Gary Lapointe said...

All of my testing has been done using MOSS but this particular command "should" work with WSS.

Anonymous said...

Is there a command that enumerates which site templates are being used or not used?

Gary Lapointe said...

Nothing that I'm aware of.

Julien said...

Hello Gary,

I tried to use gl-removeavailablesitetemplate on a web and a site collection without, then with -lcid parameter but both failed. The template (WIKI#0) is installed and available. Without -lcid parameter, the command returns "Template is not assigned.". With -lcid 1033 parameter, it returns "The system cannot find the file specified. (Exception from HRESULT: 0x80070002)" and the site become buggy: on the _layouts/newsbweb.aspx page, all the templates are gone! Do you have any idea of the problem? Thanks a lot.

Julien

Gary Lapointe said...

Use the gl-enuminstalledsitetemplates command to see what is currently there - if you can, post the results for that template.

Chad said...

Hey Gary, I also had the same issue "The system cannot find the file specified. (Exception from HRESULT: 0x80070002".

Now when I try to enumberate that site collections available templates I get "Operation completed successfully", but no listing of available templates.

I tried doing an iisreset and then re-running the command,but still nothing.

chandra said...

Hi,

I follow your steps to list out the site templates available and then tried removing one site template and restart the IIS.

1. tsadm –o gl-enuminstalledsitetemplates -url
2. It list out the site templates available.
3. I wanted remove this site template "_GLOBAL_#0 = DP Workspace (1033)"
3. i tried the remove command "stsadm –o gl-removeavailablesitetemplate –url "http:/intranet/" -template "_GLOBAL_#0" -lcid 1033 -resetallsubsites"
4. It shows operation completed
5. I restarted the IIS
6. Open the sharepoint home page
7. Click Site Action - Create Site
8. it throws an error as "File or arguments not valid for site template '|0'"
9. Now I am lost and not able to put it back to the previous working condition. I check again via stsadm to show the list of available site templates and i can still see the template is still shown as available. But now I cant create a site from sharepoint.
Is there anything I had done wrong here please. Is there any solution to solve the error. Thank you very much

Regards,
chandra

Gary Lapointe said...

You don't want to remove the global template - it's a hidden template and users can't create sites off it (it's used as a sort of marker as most every other template is effectively based on it - not really but that's the net result).

Gary Lapointe said...

Oh, forgot to address how to fix - did you try running my stsadm command to add it back?

chandra said...

Hi,

Yes I did tried to add the site template back again "stsadm –o gl-addavailablesitetemplate –url "http://intranet/" -template "_GLOBAL_#0" -lcid 1033 -resetallsubsites"
It gives this error "File or arguments not valid for site template '|0'"

Please advice. Thank you

regards,
chandra

chandra said...

Hi,
Yes I did try your stsadm command to put back the site template again but it shows an error.The error is "File or arguments not valid for site template '|0'". Its the same error when i tried to create a site from the Site Action.

In the list of site templates displayed via the stsadm it shows a few site templates as this:
"
_GLOBAL_#1 = DP ProjectWorkspace (1033)
_GLOBAL_#3 = DP ProjectWorkspaceV1 (1033)
_GLOBAL_#0 = DP Workspace (1033)
_GLOBAL_#2 = Issue_List (1033)
"
As you can see that i have these few workspace site templates and was trying to remote the "_GLOBAL_#0" template which is not in use.
All these workspace template is was created for Project Server (PWA) which are also used for Sharepoint as well. I am not sure if these have anything to cause this.

Thank you very much

regards,
chandra

Gary Lapointe said...

I'm not sure what's going on then. I'd look at it myself but unfortunately I don't have a 2007 machine available right now as I've just rebuilt my laptop and only have a 2010 machine running. There is probably a way to fix it but at the moment I just don't know without being able to reproduce it.

chandra said...

Hi Gary,
Thanks for the respone. Appreciate it very much. If you would like to take a look at my machine, we can have a remote session which i can sent to via mail. I have also sent Microsoft this error to see if they have any idea on this which yet to receive any reply. I am googling to see if there is any workaround which can allow the users to be able to create site for time being.

Thank you and regards
chandra

Jeff said...

Hi Gary - Any word on how to "reset" and make ALL templates available? I am trying to do this in C# with WSS object model but getting stuck. Thank you!