Adobe PDF x64 IFilter for MOSS 2007 Installation Tips

It has been a while since we installed the Adobe PDF IFilter for MOSS 2007 or Search Server 2008.  This is in part because Foxit Software (http://www.foxitsoftware.com) released a 64-bit PDF IFilter for SharePoint before Adobe did and because clients have been gravitating towards 64-bit SharePoint Server Farms for a while now.  In any case, I had to revisit the installation for a new client and came across a couple of things I thought would be good to share. 

 

First, the IFilter installation document found here:
http://www.adobe.com/special/acrobat/configuring_pdf_ifilter_for_ms_sharepoint_2007.pdf 

instructs you to verify that the PDF settings are correct in the registry.  Specifically, the value of this key:
\\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\12.0\Search\Setup\ContentIndexCommon\Filters\Extension\.pdf
should be {E8978DA6-047F-4E3D-9C78-CDBE46041603}.

The installation in this case supplied another GUID so I assumed it was correct and the documentation was outdated.  However, after the crawl executed it was clear something was wrong.  The crawl logs stated that although items were crawled, “the filtering process could not process this item.  This might be because you do not have the latest file filter for this type of item.  Install the corresponding filter”.

Tip:  Change the GUID in the .pdf registry setting to the GUID in the documentation.

After having done this, resetting the content indexes and restarting the crawl the PDF content was indexed as expected.

 

Second, in case you are looking for the 17x17 pdf icon that I think should be installed in the 12 hive TEMPLATE\IMAGES but isn’t, you can download it here:

http://www.adobe.com/misc/linking.html

Look for it near the bottom of the page.


Where is the SQL Server 2005/2008 Service Manager?

If you’ve worked with SQL Server prior to the 2005 release you’ve seen the Service Manager.  It was a taskbar tool that let you quickly stop and start SQL Server Instances and Services without having to load the SQL Server Enterprise Manager or the Services MMC.  Honestly, I hadn’t used it in ages but this morning I wanted to find and stop all SQL Server instances on a development server in order to save on memory usage and host a Virtual Machine.  At that point I remembered that it didn’t exist in the SQL Server 2005 or 2008 versions.

Fortunately, there is a replacement on CodePlex located here: http://sql2005srvcmngr.codeplex.com/


Fix for MOSS 2007 DisplayInAdmin and S2LeftNav_Administration Errors

One of our clients requested our assistance after MOSS a infrastructure update failed.  As a result, our client’s intranet site collection had now completely lost both its search box and the Search Center site was now hidden.  Although it was possible to navigate to the Search Center site through the “View All Site Content” link, an error occurred when displaying search results.  Of course, the error was a standard SharePoint error message that didn’t explain what was really happening.  In addition, the Farm’s Search Settings page in the Central Administration SSP also threw an “Unexpected Error”.

After changing the appropriate web.config files to reveal more information and recreating the errors it became clear what the errors were:

On the search results page the error was  System.IndexOutOfRangeException: DisplayInAdminUI.

DisplayInAdminUI Error

On the search settings the error was ‘S2LeftNav_Administration’ was not found.

image

 

After searching around it became apparent that the issue would either be resolved by re-running the SharePoint Configuration Wizard or by recreating the SSP.

I didn’t want to do the second so I gave the first a try and this *did* correct both errors.


Unable to load unit test - the assembly was not built with any known testing framework

Today, while working on some unit tests I encountered an issue I had not encountered before. After setting up a testing fixture and a base test(s) on a project, the test(s) failed to load in the NUnit GUI Test Runner.

 

An NUnit dialog stated:
Not a Test Assembly
The assembly was not built with any known testing framework

 

At first the thought was that the issue might be with the version of NUnit framework. Perhaps it was a mismatch with the GUI Runner version? This was not the case. This was a new install on a server that had never had the NUnit framework installed.

A second thought was that there might be an issue with the decorations of the unit test class but this was disproven when I opened the assembly using Reflector. The unit test class and test methods did exist in the assembly. And this was the assembly I was trying to open with the GUI Runner.  So why couldn't NUnit "see" the unit tests?

After speaking with a co-worker we realized that the issue was that there was a second assembly in the GAC that was causing the conflict. This project was part of a bigger solution and this solution installed the assembly into the GAC. It became clearer that the issue was the GAC version when I checked the Tools | Test Assemblies in the GUI Runner. There was indeed a reference (Path:) to the assembly in the GAC. After uninstalling the assembly from the GAC the GUI Runner was able to load the test(s).


SharePoint ErrorCode 0x81020014 on CAML Update

Recently while working on a client SharePoint project I encountered the following error code and message while executing a CAML update statement against a list:
<Results xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">
<Result ID=\"1,Update\">
    <ErrorCode>0x81020014</ErrorCode>
    <ErrorText>One or more field types are not installed properly. Go to the list settings page to delete these fields.</ErrorText>
<z:row ...  xmlns:z=\"#RowsetSchema\" /></Result>
</Results>
Frankly, the error message wasn't very helpful and I didn't see the issue right away but then I saw it -- I had used the wrong internal column name. The actual internal name in this case had a trailing 1 at the end of it. After using the correct name there was no need to "delete these fields" since the fields were indeed properly installed. It would have been more helpful if the message had said something like "the column you are trying updated doesn't exist", or "check your column names". Hopefully this helps someone else or perhaps just me in the future.

Helpful SharePoint Query String Parameters and JavaScript

Every so often I find it necessary to force a SharePoint web part page into edit or design mode using query string parameters. Originally posted on one of our internal development blogs, I decided to share this because it does come in handy from time to time. 

SharePoint Query String Parameters

Query String Parameter Values
DisplayMode Design or Edit
ToolPaneView 2
Mode Edit
ControlMode Edit
Contents 1

 

Helpful JavaScript

JavaScript:MSOLayout_ToggleLayoutMode()

JavaScript:MSOTlPn_ShowToolPane('2')

These come from Todd Bleeker’s blog: http://www.mindsharpblogs.com/todd/archive/2005/02/11/285.aspx


Creating New Contacts and Emails with SharePoint 2007 OWA web parts

One of the thing that has always bugged me about the SharePoint 2007 Outlook Web Access (OWA) web parts ever since I saw them was that that some of the web parts lack basic functionality and thus are inconsistent in their functionality.  The purpose of this post is to shed some light on what these web parts do or cannot do and give users an understanding of how to get around the lack of functionality.  Before I continue, I should remind readers that these OWA web parts are intended to be used in a My Site and that users of these web parts must have access to Outlook Web Access and know the OWA URL and account format to configure the web parts on their own.

My Inbox Web Part

It is great that a My Inbox web part can let me Reply to or Forward an email but what about creating a new email?  There isn’t a UI element for that in the web part.  Of course, if you know your secret keyboard keystrokes and you have the web part in focus you can create a new email with by using CTRL + N.  Most people don’t know this but note that if you don’t have the web part in focus you’ll likely end up with nothing or a new browser window.

My Inbox Context Menu

My Contacts Web Part

The My Contacts web part lets a user edit a contact and even use the web part to send an email or meeting request to an existing contact but what about creating a new contact?  There isn’t a UI element for that in the web part and I’m not aware of any secret key strokes.

My Contacts Context Menu 

My Tasks Web Part

The My Tasks web part unlike the My Inbox and My Contacts web part does have a mechanism for creating new tasks.  Type the task description in the box and hit the Enter key to submit it.

My Task Add New Task

The web part also allows the user also open, forward, mark complete or delete any task.

My Tasks Context Menu

My Calendar Web Part 

The My Calendar web part seems to be the mother of all MOSS 2007 OWA web parts.  This web part has a mechanism for creating new appointments and meeting requests and also creating a new email, contact or task.  It is where users will most easily find the “new” functionality missing in the other web parts.

My Calendar New Menu

Conclusion

The key to remember when using the MOSS 2007 OWA web parts is that the My Calendar web part is pivotal.  It needs to be used in combination with the My Inbox and My Contacts web parts in order to give users an easy (yet awkward) way to create emails and contacts with a simple mouse click.


Create a meta description control

This control produces a meta description element for use in the head element of a page, like this:

<meta name="Description" 
    content="Solien Technology is a Microsoft Gold Certified Partner 
    and Microsoft Managed Partner in Southern California." />

The .net framework’s System.Web.UI.HtmlControls.HtmlMeta control renders as a meta tag, and by using Microsoft.SharePoint.WebControls.FormComponent as our base class we gain access to the current SharePoint item.

namespace Solien.SharePoint
{
    /// <summary>
    /// Adds a meta description tag based on the contents of the specified field
    /// </summary>
    public class MetaDescription : Microsoft.SharePoint.WebControls.FormComponent
    {
        private const string fieldNameDefault = "Description";
        /// <summary>
        /// Field to use for description tag's content. Default value is "Description"
        /// </summary>
        [System.ComponentModel.DefaultValue(fieldNameDefault)]
        public string FieldName
        {
            get
            {
                object o = ViewState["FieldName"];
                if (o == null) return fieldNameDefault;
                return (string)o;
            }
            set { ViewState["FieldName"] = value; }
        }

        protected override void OnPreRender(System.EventArgs e)
        {
            base.OnPreRender(e);

            if (Item != null
                && Item.Fields.ContainsField(FieldName)
                && Item[FieldName] != null
                && !(string.IsNullOrEmpty(Item[FieldName].ToString())))
            {
                System.Web.UI.HtmlControls.HtmlMeta meta =
                    new System.Web.UI.HtmlControls.HtmlMeta();
                meta.Name = "Description";
                meta.Content = Item[FieldName].ToString();
                Controls.Add(meta);
            }
        }
    }
}

Note that the FieldName property has a default value of “Description” since that’s the most common usage. Adding the control to a page layout is simple:

<SolienSharePointControls:MetaDescription runat=server />

No matter what your next project’s description is, we’re here to help with application development and SharePoint consulting.


Build a control to show the first non-blank field

Here’s a control that shows the first non-blank SharePoint field. I created it for Solien’s web site when I added the PageTitle field. By using this control, if content authors leave the PageTitle field blank the contents of the Title field are shown instead.

By inheriting from Microsoft.SharePoint.WebControls.FormComponent we gain access to the Item property.

using System.ComponentModel;
using System.Web.UI.WebControls;

namespace Solien.SharePoint
{
    /// <summary>
    /// Given a list of fields, displays the first field that has content.
    /// </summary>
    public class CoalescingFieldControl : Microsoft.SharePoint.WebControls.FormComponent
    {
        /// <summary>
        /// Fields to search for content. Fields are searched in order.
        /// </summary>
        [TypeConverter(typeof(StringArrayConverter))]
        public string[] FieldNames
        {
            get
            {
                object o = ViewState["FieldNames"];
                if (o == null)
                    return new string[0];
                return (string[])o;
            }
            set { ViewState["FieldNames"] = value; }
        }

        protected override void OnPreRender(System.EventArgs e)
        {
            base.OnPreRender(e);

            if (Item != null)
            {
                foreach (string key in FieldNames)
                {
                    if (Item.Fields.ContainsField(key)
                        && Item[key] != null
                        && !string.IsNullOrEmpty(Item[key].ToString()))
                    {
                        this.Controls.Add(new System.Web.UI.LiteralControl(
                            Item[key].ToString()));
                        break;
                    }
                }
            }
        }
    }
}

Because we check that Item.Fields.ContainsField, no exception will be thrown if a field in FieldNames doesn’t exist for the current item.

Here’s how the control is used on a page template:

<%@ Register Tagprefix="SolienSharePointControls" Namespace="Solien.SharePoint "
    Assembly="[...]" %>

[…]

<SolienSharePointControls:CoalescingFieldControl id="HomePageTitleInHeader"
    FieldNames="PageTitle,Title" runat="server"/>

If you’ve got a SharePoint implementation or asp.net development project you’d like help with, have your people talk to our people.


SharePoint Development for Beginners: Adding a field to a page layout

Here’s how to add a new field to an existing page layout in Microsoft Office SharePoint Server 2007.

Our current page layout uses the Title field both for the HTML title element shown browser’s title bar and for the header shown in the content. We want to separate these so that the HTML title can be different.

We’ll be modifying the SolienInnerPage.aspx and SolienInnerPageNoLeftNav.aspx page layouts. Here’s an outline of the work we’ll need to do:

  1. Find the associated content type for the page layout
  2. Add a new site column on the content type
  3. Set the column ordering on the content type
  4. Add the field to the page layout
  5. Add content to the new field
  6. Test that the new field’s content is shown on the page layout

1. Find the associated content type for the page layout

image

Both layouts use the Solien Page content type. We’ll add the new column there.

2. Add a new site column on the content type

image

Below the list of existing columns, click “Add from new site column”

image

Set the Column Name and select a group for the column.

image image

Enter a description for the new column.

image

We want to update content types inheriting from this type so that existing items will have the new column available.

image

Once we click OK, the site column is added.

3. Set the column ordering on the content type

On the Solien Page content type, we’ve clicked “Column Order.”

image

We can now set the column order for the new PageTitle column.

4. Add the field to the page layout

Currently our page layout uses the Title field for the HTML title element. We’ll modify it to use the new PageTitle field instead.

First we need to grab a copy of the page layout. In the master page gallery, find the page layout, then select Send To –> Download a Copy.

image

Here’s how the Title field is currently used.

<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">

            <SharePointWebControls:FieldValue id="HomePageTitleInHeader" FieldName="Title"

                        runat="server" />

</asp:Content>

Instead, we want to use the PageTitle field.

<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">

            <SharePointWebControls:FieldValue id="HomePageTitleInHeader" FieldName="PageTitle"

                        runat="server" />

</asp:Content>

After saving our changes, we’ll upload the new version of the page layout. In the master page gallery, choose Upload –> Upload Document.

image

We’ll overwrite the existing file.

image

Here’s what we see after the page layout is uploaded. There aren’t any property changes needed, so we’ll click “Check In.”

image

5. Add content to the new field

Now that the column has been added to the content type, we can add content on pages that use this page layout.

image

6. Test that the new field’s content is shown on the page layout

It works! Previously the Title field was used,

image

but now the PageTitle field is used instead.

image

 

Want help with your SharePoint implementation, or just need a quick consultation to get things rolling? We’re here to help.