Welcome

Giving back to the community...

Please contact me (Michael Hamilton) at this link, if you would like to have a blog setup. NOTE: Please include your full contact information (Name, City/State, Phone and Email address).

Syndication

Blog Stats

Bloggers (posts, last update)

Latest Posts

Cleaning up a Basic WSS (Windows SharePoint Services) v3 uninstall. Removing SQL Server embedded #SSEE database setup

Cleaning up a Basic WSS (Windows SharePoint Services) v3 uninstall. Removing SQL Server embedded #SSEE database setup - this has proven a pain for a lot of our clients, as well as some of our developers that are not familiar with the goings on of WSS v3. and a Basic installation.

 

INSTALLATION

When you install WSS v3 - by default - and most of us love defaults - it blazes right through and does a BASIC installation/configuration.

BASIC

Under this installation - WSS creates NOT a well known documented and easily discernable MSDE flavor of SQL Server - in all the right places like \%PROGRAMFILES%\Microsoft SQL Server\blah blah blah...

Nope... It creates a hybrid of sorts - Microsoft Embedded SQL Server - nested under the OS folder. Neat...

FARM INSTALLATIONS / INSTALLATIONS using a separate SQL Server

The key to getting WSS to work on a remote SQL Server - major requirement in most all organizations, is to be aware that you need to do a COMPLETE installation - for a Farm - and when you run PSCONFIG after the install - you'll have the option to select a <domainName>\<instanceName>...

 

UNINSTALL WSS V3 - COMPLETE

Just running PSCONFIG and removing your configuration - then uninstalling WSS - does NOT solve your problem here. The real problem is that MSFT SQL Server Embedded (#SSEE) is still installed - and EVERYTIME you run the setup bits for WSS ??? It's reverting back to this database - w/no obvious way to get around it.

So, if you do not need the embedded version - and after you have uninstalled WSS V3 - do the following:

 

REMOTE #SSEE Embedded SQL Server

1. Start Registry Editor, and then locate the following registry key:              HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

2. Do an Edit/Find on Microsoft SQL 2005 embedded Edition

3. When you see a display name that matches the name, copy the value of the Key named “UninstallString”

4. Start-->Run-->CMD - opens a command prompt

5. Issue the following MSI - copying in your GUID and ensuring to complete the whole string.

6. - For example: MsiExec.exe /X{BDD79957-5801-4A2D-B09E-852E7FA64D01} CALLERID=OCSETUP.EXE

7. Confirm the removal - then bounce the box when you're done.

 

When you come back to install WSS v3 - do a Complete install - not a basic...

posted @ 7/11/2008 9:49 AM by Michael J. Hamilton, Sr.

FAST Search for SharePoint Server 2007 / Microsoft (MSFT) Acquires FAST Search

FAST Search for SharePoint Server 2007 / Microsoft (MSFT) Acquires FAST Search

The following links are provided to give you 1) more background on what this acquisition means, and 2) how to leverage it immediately in Microsoft SharePoint Server 2007 (MOSS).

http://www.microsoft.com/presspass/press/2008/jan08/01-08FastSearchPR.mspx

http://blogs.msdn.com/enterprisesearch/archive/2008/01/08/microsoft-announces-offer-to-acquire-fast-search-transfer.aspx

http://blogs.msdn.com/sharepoint/archive/2008/06/20/announcing-sharepoint-web-parts-for-fast-esp.aspx

 

A firm believe that there is nothing new under the sun, this does not surprise me. I see this as a serious enhancement to an already formidable foray into this space by MSFT.

Regards...

posted @ 6/24/2008 5:48 AM by Michael J. Hamilton, Sr.

SharePoint Products and Technologies (PSCONFIG) - MOSS 2007 - Setup - The Account is invalid. The account must be a local account or global domain account.

During a normal setup of a medium farm configuration for MOSS, when running the SharePoint Products and Technologies (PSCONFIG) wizard - I would receive the error, "The account is invalid. The account must be a local account or global domain account."

Having deployed several dozen MOSS farms by now, I was perplexed after spending an hour checking and triple checking the service account (a least privileged domain-level account). All appeared to be just fine.

The server I was installing on was a member server of the domain, and when checking the properties of the server, it was listed properly as <serverName>.domainName.suffixName

So, what was going on?

Googling the issue turned up nothing; TechNet turned up nothing. I was stumped.

I deleted the user account on the PDC and re-created it - no joy.

Then I did some other digging... The NIC in this machine had an issue not long ago. Specifically, when it was joined to the domain - there was a different NIC in the computer that failed not long ago. Alas... The MAC address/machineName were foobarred in Active Directory. All appeared well on the surface. Until I tried a simple little test; login to the host as a domain account :) I quickly got the message that the domain was not available or that my machine name was not registered in the PDC.

After finding this - it was a quick fix - unjoin the domain, bounce the host, re-join the domain - and all is well.

Hopefully this will save someone some time.

posted @ 5/24/2008 11:28 PM by Michael J. Hamilton, Sr.

Access Denied - Folder Permissions as Administrator in Windows XP

I recently setup a Windows XP Pro virtual machine w/Virtual PC 2008. So... I'm the only user account on the host - Administrator - and life should be grand.

While working on a specific project for a client, I copied to my VM C: drive a copy of the solution from a network share at the client site.

After some work - a couple days later - I needed to overwrite the local virtual machine copy with a refresh from the client site.

I continued to get the Access Denied when trying to replace files.

Okay... No biggy - I'm administrator - so I elect to DELETE the folder locally - I get the same error.

So... I open Windows Explorer (Start-->Run-->Explorer [Enter]) and browse to that folder. I select the folder - Right-Click-->Properties, and to my surprise, there is no Security tab. Mmmm Gotta love these mysteries.

By default, with Windows XP Pro SP2/SP3 - the Security tab is turned off.

To turn this on - open Windows Explorer, select Tools-->Options- you should see a screen like the following:

image

Click on the VIEW tab here...

Scroll all the way down and uncheck the Use Simple... blah blah blah

image

 

Hope that helps...

posted @ 5/19/2008 10:57 AM by Michael J. Hamilton, Sr.

It's not just MOSS - It's MOSStastic!

Okay, so I've run that one in the ground so much the past couple years, you're tired of hearing it, right? WRONG. We've only just begun...

Read the latest about Microsoft Office products here - MOSS is still in the early stages.

For some really useful quick links - check out Mark Grimes' blog - and many thanks for the links Mark.

I have received a host of pings regarding older postings on Directory Services, ASP.Net, BizTalk and more - and I will be posting some new source/solutions for Directory Services on my technical blog here.

As much as I love Microsoft myself, Dan Woolston had one of the best posts I've seen this year - here! Dan is a noted author and technical contributor in ASP.Net, AJAX and BizTalk - to mention a few - but this link was great!

Some technical footnotes:

  • Windows XP Professional SP3 is now out.
  • PowerShell is getting a GUI - what took you so long!?!?!?
  • InfoPath Forms Services Expense Reporting - excellent reference for doing Forms Services outside of MOSS. The only other recommendation I could add is to check out offerings from business process management solutions stacks like BlueSprings' BPM Suite - they have the full-scale version, and one specific for SharePoint as well.
  • Windows Essential Business Server 2008 - it has taken a long time, and I am really pleased with the progress and integration of the MSFT business solutions releasing this year.
  • Finally, some tidbits from Scripting Guy! - always worth a glance now and then.

We're still looking to launch MOSStastic! mid-to end July '08 - and just some of the features include:

  • Automated creation of site collection - create your own first site collection, and start down the path of building out a full-fledged Internet facing site.
  • AJAX enabled wizards for User and Site Collection management - we take the best of the Central Administration features and attempt to provide your quick how-to wizards that will help you
    • Define your IIS/Site collection/definition
    • Setup user accounts / access permissions to your site collection
    • Edit / Set permission sets and create/manage groups for your site
    • and much more...
  • Full support for SharePoint Designer 2007, including a video walk-through on customizing your master pages w/custom CSS and UI elements.
  • How to create custom web parts and deploy those for a site collection, site-level, or as a custom Feature for your site.
  • Video training support on advanced Features, Event Handlers and Site Definitions - step-by-step walk-through support to give you insight and guidance on best practices for custom development of your solutions.
  • Much more...

A lot of people have worked hard to help make this possible, and I am grateful to everyone for the support.

Looking to get a hosting provider for a WSS, ASP.Net or DotNetNuke portal? Check out Dot Net Haven for some of the best, most competitive hosting solutions available.

On that note - I'm outta here - today is my best friend's birthday (translate wife!) and I have no business blogging more tonight!!!

posted @ 5/15/2008 11:03 PM by Michael J. Hamilton, Sr.

The 'Microsoft.Jet.OLEDB.4.0' provider is not registered on the local machine - Running Vista x64 / Vista 64bit / 64bit

I ran into this problem while trying to model some demo code for an ASP.Net application.

I'm running Vista Enterprise x64 and Visual Studio x64 2008.

When I tried to create a new web application in VS 2008 and browse it, I'd get the above error. The fix was to change the application pool to run in 32 bit.

Right-Click on My Computer --> Manage

Expand Services and Applications

Select Internet Information Services, then local Application Pools under Connections.

 

image

Right click on DefaultAppPool, Advanced Settings, and set the 32bit mode to True:

image

Hopefully this will be useful to others out there.

 

MikeH... Another Geek in Need...

posted @ 4/13/2008 7:40 AM by Michael J. Hamilton, Sr.

DNS Snafus - Recursion - and Hosting Sites

My first hand at a lightweight training session.

Click and play the video below...

to review the 4 minute video and please let me know what you think. Was the video/audio stream okay? What things do we need to work on? Etc Etc Etc.

posted @ 1/17/2008 5:56 AM by Michael J. Hamilton, Sr.

Windows Mobile Device Center and sync problems with the Verizon / HTC VX6800 SmartPhone

Windows Mobile Device Center and sync problems with the Verizon / HTC VX6800 SmartPhone

I was able to sort out most of the setup on this neat new phone - but for the life of me I could not get Windows Mobile Device Center to detect it.

The phone comes with Windows Mobile 6, and you would think all would go smooth insofar as the sync to your Windows Vista setup.

Alas - there is an update I found that magically resolved the issue - it's Windows Mobile Device Center 6.1 update - specifically for SmartPhones/PDA's running Mobile 6

http://www.microsoft.com/windowsmobile/devicecenter.mspx

Scroll down and select your language - go through the Genuine Advantage Validation of your OS - and the rest will magically fall right into place (PS - make sure your phone is connected - syncs right up).

HTH's someone else that's spent the last couple hours trying to sort this out.

posted @ 1/12/2008 1:35 PM by Michael J. Hamilton, Sr.

Browser Support for Microsoft Office SharePoint Server (MOSS) 2007

Browser Support for Microsoft Office SharePoint Server (MOSS) 2007

MSFT provides a decent review of the stated compatibility here.

The feature specific list deserves special attention.

posted @ 1/10/2008 9:44 AM by Michael J. Hamilton, Sr.

How to change a user's password in Active Directory with Directory Services and C#

How to change a user's password in Active Directory with Directory Services and C#

 

Below is a code snippet that I hope will be helpful. There are some obvious assumptions made - that the user has experience coding in Directory Services and C# - let me know if you would like more info.

 

private const string GETUSERID_QUERY = "(|(&(objectClass=user)(samAccountName={0}))(&(objectClass=contact)(displayName={0})))";

  

public bool ChangePassword(string rootDSE, string userName, string newPassword)
    {
        // Here, the rootDSE is already set, so is the user's name and their desired new password.
        // We'll call a sub that will resolve the user's name to their ID in AD and invoke the change password on that userID
        // You can do something as simple as DirectoryEntry root = new DirectoryEntry() - that'll return your root to you...
        // User name is the same as Context.User.Identity.Name - their loginID (please forgive any typoes - I'm not using a dev env for this)...

        using(DirectoryEntry userEntry = GetUserByLoginID(root, username))
        {
            try
            {
                userEntry.Invoke("SetPassword", new object[] { newPassword });
                userEntry.Invoke("SetInfo"); // It's possible you might not even need this call...

                userEntry.CommitChanges();

            }
            catch(System.Reflection.TargetInvocationException err)
            {
                throw new PasswordPolicyException(comError.Message,comError);       /// Assuming you have a method to handle this...
            }
        }
    }

    private DirectoryEntry GetUserByLoginID(string rootDSE, string userID)
    {
        using (DirectoryEntry searchRoot = new DirectoryEntry(rootDSE))
        {
            using (DirectorySearcher searcher = new DirectorySearcher(searchRoot, String.Format(GETUSERID_QUERY, userID)))
            {
                SearchResult searchResult = searcher.FindOne();
                if (searchResult==null)
                    return null;
                else
                    return searchResult.GetDirectoryEntry();
            }
        }
    }

posted @ 12/25/2007 7:08 PM by Michael J. Hamilton, Sr.

Toolbars - Status bars - Estimated Copy Time - And Beyond

Toolbars - status bars - estimated copy time - and beyond.

Trust me, if you're writing an installation program, you want to pay particular attention to the status bar and the time remaining to finish the setup.

For example, to copy roughly 15GB to an external USB 2.0 hard drive - that has about 300GB of free space - the following status bar is not a little disconcerting:

image

I'll be the first to admit - Vista rocks! and it really does.

But 125 years to finish copying 15GB? Dude, I honestly believe there are better things to do :)

In all, it actually took almost 3 hours to complete this backup. Don't ask me why it was estimating 125+ years initially.

But for those who have NOT seen this - I thought you'd get a real kick out of it.

posted @ 12/15/2007 3:19 PM by Michael J. Hamilton, Sr.

Not all things Windows!

Not all things Windows! - Indeed.

I pulled out an older Sony notebook - PIII / 800Mhz - but it has a half gig of RAM in it and I thought it'd be a great one to leave around the house (translate - wireless) for anyone that needs a handy computer.

I receive the MSDN DVD's - like many of us do - and the latest XP / SP2 disc I had was November 2007. Cool beans - I'll just boot that and load it.

Well... You'll get a chuckle out of this one.

This may be a November 2007 release (and here it's only December 2007) - but when I ran for updates? It first downloaded the Genuine Advantage program - then 92 more updates!!!! NINETY-TWO - OUTRAGREOUS.

I guess XP won't be supported much longer either!

posted @ 12/14/2007 9:09 PM by Michael J. Hamilton, Sr.

The SQL Server System Configuration Checker cannot be executed due to WMI configuration...

The SQL Server System Configuration Checker cannot be executed due to WMI configuration on the machine <machineName> Error: 21475000034 (0x80004002)

SPECIAL NOTE: Please read this entire post before attempting any of the options that I describe - things are not all that they seem. The final solution did require re-loading the OS. It came down to my opening the UAC and then installing AIM. No matter what I did after that - WMI would hose up if I was trying to install anything like SQL Server, BizTalk Server - you name it. Sorry for the lengthy post - but I suspected someone else would learn from this.

If you receive the above error - when trying to install SQL Server 2005 Developer, Standard, or Enterprise, on a Vista workstation...

image

You have probably read this thread - http://sqljunkies.com/Forums/ShowPost.aspx?PostID=85

Further - MSDN here - http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=131970&SiteID=1

HOWEVER

Is the Registry setting set to zero for the UAC on Vista? I thought this may be the issue as I leave it turned off - and I found many posts online regarding how WMI can be affected when you turn this off - some setup applications will fail without any real error message or event entry regarding why it failed. So I turned UAC back on:

 

I use REGEDIT and edit HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System - and set EnableLUA to '0'

image

ADDITIONAL SETTINGS

  • I also found the following information provided by Product Support Services for another person running into a similar issue:
  • 1. Add network service account to administrators group.
  • 2. Add authenticated users to following registry keys: * HKCR\CLSID\{73E709EA-5D93-4B2E-BBB0-99B7938DA9E4} * HKCR\CLSID\{7C857801-7381-11CF-884D-00AA004B2E24} * HKLM\Software\Microsoft\WBEM\CIMOM

This person gave the local\Authenticated Users group Full Control on these registry keys...

The first registry key is the Launch permission on the WMI Provider Subsystem:

image

The second registry key is the access to wbemsvc.dll:

image

The third key deals with much more - and I suspect is the crux of the solution:

image

Nonetheless, I followed the instructions:

NOTE regarding Authenticated Users: If your workstation/notebook is connected to a domain - you will need domain Administrator permissions to change the add user to the Local Machine when you are adding the Authenticated Users to these registry keys - you cannot add a domain scoped Authenticated Users to the keys - only for the local machine.

FINDINGS

The above did not work for me on this Vista Ultimate host. I found additional PSS support tickets with the following:

  • Also you can try running the following from a command prompt :
  • Mofcomp.exe %windir%\system32\wbem\cimwin32.mof
  • Regsvr32 %windir%\system32\wbem\wbemupgd.dll
  • Regsvr32 %windir%\system32\wbemwbemsvc.dll

image

The second regsvr32 entry for wbemupgd.dll returned an error for me that the DLL did not exist.

 

Alas - my problem continues to persist.

The following is a snippet from my installed programs - of special notice is that I have Visual Studio 2005 Tools for Applications SDK February 2007 installed.

image

 

On the following link - http://download.microsoft.com/download/2/b/5/2b5e5d37-9b17-423d-bc8f-b11ecd4195b4/ReadmeSQL2005SP2.htm - I found - down at 5.5.1 Scripting Incompatible with Microsoft Windows Vista the blurb about VSTA installing something that appears to be the culprit.

Uninstalling VSTA - did not solve the problem.

Extensive review of online MSDN Forums, and even some PSS tickets on Connect.MSFT - etc - for SQL Server - convey that the problem is much more nefarious than anything I've turned up thus far - and that WMI is the root of the issue - and my guess is - something has become corrupt w/WMI.

I've run the WMI Diags 2.0 utility from MSFT - and it showed 16 succinct errors where MOF (Managed Object Format) files were not being restored / instantiated successfully. Alas - my woes are just beginning...

WMI and the Art of Zen

I found the following instructions at - http://searchwincomputing.techtarget.com/tip/0,289483,sid68_gci1160143,00.html

  • 1. At the command line, type net stop winmgmt. You may get a warning that other services need to be stopped as well; type Y and continue.
  • 2. Open Explorer and go to the folder called %SystemRoot%\System32\WBEM\Repository.
  • 3. Delete that folder and everything in it.
  • 4. Reboot the system normally.
  • 5. On the next login, open a command prompt and type the following commands in this order:
    winmgmt /clearadap
    winmgmt /kill
    winmgmt /unregserver
    winmgmt /regserver
    winmgmt /resyncperf
  • This procedure will force the WINMGMT service to re-register itself as well, although, if WMI is damaged, re-registering can be a problem. If this approach does not work, an in-place upgrade (i.e., a reinstall) might be required.

FINAL ANALYSES

I was not able, under any circumstances - to get any of the foregoing to work for me. I wound up reloading the notebook from scratch. Sorry I could not provide you an easy work-around.

posted @ 12/14/2007 8:02 PM by Michael J. Hamilton, Sr.

Microsoft SharePoint Office Server (MOSS) 2007 B2TR and RTM - Deprecated TopNavFlyouts master page and other deprecated components that break your master page after applying these upgrades

Between beta 2 and beta 2 TR/RTM - a number of things changed in the MOSS master pages/CSS - and the odds are that if you have custom master pages in B2, and especially if you customized the TopNavFlyouts or LeftNavFlyouts master pages - after applying TR or RTM - you'll find that your master page is broke - and the site will not come up. Do not despair - help is close at hand!!! A number of things changed in B2TR and followed into RTM. We can make some minor customizations to your current master page (TopNavFlyouts in this example) that will get it back up and running.

After applying the upgrade - ensure that you have a updated copy of the SharePoint Designer (SPD). Open your site, and fetch the master page in question (TopNavFlyouts in this example).

Get there where we can render the page...

First, search for <PublishingNavigation:PortalSiteMapDataSource> - the control with id=DataMapDS. Once you find this, replace the TrimNonCurrentHeadings="true" property with TrimNonCurrentTypes="Heading".

Second, search for and replace

<SharePoint:ScriptLink language="javascript" name="core.js" runat="server"/>

<SharePoint:ScriptLink language="javascript" name="ows.js" runat="server" />

with

<SharePoint:ScriptLink language="javascript" name="init.js" runat="server"/>

If you try saving right now? You might see:

If this does not render - it is a prompt stating that you need to add a new placeholder for the Robots meta tag - go ahead and click Yes.

Third, You can click Yes above, or add the following just after the <meta> tags in your master page - <SharePoint:RobotsMetaTag runat="server"></SharePoint:RobotsMetaTag>

NOTE: This must be added after the <meta> tags, and before the </head> end tag.

 

There is a snafu now - which you would notice if you tried rendering now - with the toolbar rendering where we want it. Do the following:

Fouth, locate the class="mainContainer" line. Add id="MSO_ContentDiv" runat="server" in this line. The corrected line should look like:

<div class="mainContainer" id="MSO_ContentDiv" runat="server">

Fifth, search for the following in your master page:

 

<div class="search">
<asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">
<SPSWC:RightBodySectionSearchBox id="SearchBox" TextBeforeDropDown="" TextBeforeTextBox="<%$Resources:cms,masterpages_searchbox_label%>" TextBoxWidth="100" GoImageUrl="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow.jpg %>"
GoImageUrlRTL="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow_RTL.jpg %>" SearchResultPageURL="<% $SPUrl:~sitecollection/SearchResults.aspx %>" DropDownMode = HideScopeDD FrameType="None" runat="server" WebPart="true" __WebPartId="{7872FDA4-AEF7-4DB0-8C99-648EE4441DC8}"/>
</asp:ContentPlaceHolder>
</div>

We want to replace the <SPSWC... /> area with the following:

<SPSWC:SearchBoxEx id="SearchBox" RegisterStyles="false" TextBeforeDropDown="" TextBeforeTextBox="<%$Resources:cms,masterpages_searchbox_label%>" TextBoxWidth="100"
GoImageUrl="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow.jpg %>"
GoImageUrlRTL="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow_RTL.jpg %>"
GoImageActiveUrl="<% SPUrl:~sitecollection/Style Library/Images/Search_Arrow.jpg %>"
GoImageActiveUrlRTL="<% SPUrl:~sitecollection/Style Library/Images/Search_Arrow_RTL.jpg %>" UseSiteDefaults="true" DropDownMode = "HideScopeDD" SuppressWebPartChrome="true" runat="server" />

The finished line should match:

<div class="search">
<asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">
<SPSWC:SearchBoxEx id="SearchBox" RegisterStyles="false" TextBeforeDropDown="" TextBeforeTextBox="<%$Resources:cms,masterpages_searchbox_label%>" TextBoxWidth="100"
GoImageUrl="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow.jpg %>"
GoImageUrlRTL="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow_RTL.jpg %>"
GoImageActiveUrl="<% SPUrl:~sitecollection/Style Library/Images/Search_Arrow.jpg %>"
GoImageActiveUrlRTL="<% SPUrl:~sitecollection/Style Library/Images/Search_Arrow_RTL.jpg %>" UseSiteDefaults="true" DropDownMode = "HideScopeDD" SuppressWebPartChrome="true" runat="server" />
</asp:ContentPlaceHolder>
</div>

Almost done..

Sixth, we need to make some changes to your CSS. In our case, we often override the TopNavFlyouts.css object with one of our own. Whichever the case is for you, you'll need to make the following replacements in your primary CSS for the search control:

 

.search
{
margin:6px 2px 20px 2px;
}
.search .ms-sbcell .ms-sbplain
{
margin-right:2px;
margin-left:2px;
border:1px #555555 solid;
height:14px;
}
.search .ms-sbcell
{
border:none;
font-weight:normal;
font-size:8pt;
color: #3A4663;
padding:0px;
}
.search .ms-sbgo
{
background:none;
}

This involves adding the 'margin: 6px, etc.' line to your existing .Search class, and adding the other 3 new classes.

Now - one more thing. The TopNavFlyouts.master is a given master page in the Internet Presence Web Site site definition - but it has been deprecated. With that said, we need to make a couple more changes - so our Publishing Portal (or other custom) site definition can see the master page.

1) Browse the site in question that you have the TopNavFlyouts master page in.

2) Site Actions-->Manage Content and Structure

3) Select the Master Page Gallery on the left.

4) Locate your TopNavFlyouts.master on the right side

5) Hover over and get your drop down menu - click and Check Out the master page - if it is not already

6) Hover over again, click and Edit Properties

7) On the Edit Item - Master Page Gallery: TopNavFlyouts screen, notice the Content Type is set to Master Page. Drop this down and change it to Publishing Master Page.

8) Notice now that a Hidden Page attribute/property just appeared at the bottom of the properties screen. Un-check that - we do not want it hidden.

9) Click OK

10) Publish the new page.

That's it!!!

You may have other modifications to make - but this should get your page to where it renders and is compliant with new MOSS controls.

Enjoy :)

posted @ 12/8/2007 10:31 AM by Michael J. Hamilton, Sr.

Microsoft Office SharePoint Server 2007 – Custom Chrome / Branding

Microsoft Office SharePoint Server 2007 – Custom Chrome / Branding

PREFACE

If the graphics snapshots do not paste over in this document (to the blog) please feel free to email me, including an email address for yourself, and I will send you this final draft, in MS Word format, including all graphics/screenshots.

REVIEW

After deploying MOSS and my first site collection, obviously the first thing I want to know is how can I customize the look and feel?

Thus begins my journey down Chrome Lane and my first of a multi-part series on customizing the look and feel of WSS v3 / MOSS 2007 sites (v3 bits / sites).

As you have no doubt read and heard several times, v3 sites leverage the .Net 2.x Framework and implement master / content pages. Whether you are new to, or seasoned with this approach, I hope the following provides some insight into the ways you can customize your v3 sites.

Foremost, this approach is a simplified example of customizing and the approach is 1 of many you can take. This approach is not exhaustive and certainly not applicable to all v3 deployments. Please allow me to explain…

MOSS provides many feature-rich templates for each optional site collection you can deploy under a web application (a web application is an IIS web application, and previously referred to as a virtual server in v2 days). If you deploy a Team Site, or Internet Presence Site, each of these provides the developer a set of templates that can be used / customized further for that site collection. It is important to note here that the actual templates provided are different from 1 site collection to another. Why is this important? For this presentation, the customization that we are going to do will be specific to the master page provided for the template of the site type. More specifically, if you deploy a Blank Site or a Internet Presence Site, the templates for the master pages will be different, and you will have to understand these differences to apply this approach to each of the different sites. Let’s get started and you will see what I mean.

CHROME LANE

We are going to deploy a web application and 1 site collection for that web application. Here we will work with the My Company Site, and the site collection is an Internet Presence Web Site template-base.

As we proceed I will reveal the out-of-the-box templates and setup derived from publishing this site template.

I could proceed on the predicate that you can create a web application and the site collection for that web application – but I’ll walk through this piece by piece. Please forgive the lengthy posting and the many screen shots – I simply want to try and be as thorough as possible.

ASSUMPTIONS

MOSS 2007 is installed and configured on your server. Further, you have configured the services that should be running on this server. If you are not familiar with these, please review the following screenshot and ensure that you have at least these services running (you get to this screen by opening the Central Administrator and clicking the server name under Farm Topology.

Farm Topology

Ensure that your services are started – as indicated in the above figure.

Finally, we are going to customize our site by placing a banner object in the titleArea (we’ll get into this when we open the SharePoint Designer and begin to customize the template), and we are going to customize the toolbar. To do these things we have created custom graphics – 1 for the banner display, and 1 for the toolbar – which is a small GIF image, 40px high that we’ll repeat-x across the toolbar space – basically overriding the default out-of-the-box GIF used by SharePoint.

We will begin by creating our web application on a specified port on this server.

THE FUN BEGINS!

Launch the SharePoint Central Administrator. Click on Application Management.

Under SharePoint Web Application Management choose the first option Create or extend Web application.

On the next screen click Create a new Web Application.

In the IIS Web Site section, fill in the Description field with My Company Site, and for the Port set it to 10000.

In the Security Configuration section, set the Allow Anonymous: to Yes.

In the Application Pool section, set the Create new Application Pool / Application Pool Name to MyCompanySite.

Under Select a security account for this application pool, select Configurable and enter the User name and password fields appropriately. I used the Administrator account.

You can accept the rest of the default properties, scroll the page to the bottom, and click OK. This may take up to several minutes to create the web application.

When the web application is created, you will see a screen similar to the following:

Web Application

We want to click the first link Create a new Windows SharePoint Service web collection.

The Web Application will be on the machineName:port we created it on.

For the Title and Description enter My Company Site.

Under Web Site Address change the radio button from the default of Create site under this URL: (URL Name) to the 2nd option Create site at this URL: (URL path:) and leave the (root) path. (I will go into this in more detail in another post.)

For this exercise, under Primary and Secondary Site Collection Administrator enter the Administrator account.

Under Template Selection select Internet Presence Web Site and click OK.

It may take several minutes for the site collection to be created. Once it is complete let’s browse to our new site root. We do this by browsing to http://machineName:10000 – where machineName is the name of the server you have installed MOSS on. If all went well and you have browsed to the new site, your screen should be similar to the following:

Publishing Portal Site

If you select the top-right Site Actions drop-down, and select Edit Page you will see a template that provides a Page Image and two Summary Links content panes, as well as three webpart zones. This page is derived from the WelcomeSplash.aspx. I can confirm this by selecting Site ActionsàManage Content and Structure and then selecting Pages in the left treeview. On the right I’ll see a default.aspx and to the far-right, you’ll see the template it derived from. We are not going to get into modifying templates in this posting, but I wanted to help you understand some of the out-of-the-box aspects and how your template was created by default.

I want to review one more thing before we begin. SharePoint also uses a default master page and set of style sheets for this site. To see what the default master page is, select Site ActionsàSite SettingsàModify All Site Settings.

Under Look and Feel click Site Master Page Settings.

Under Site Master Page notice that our master page is TopNavFlyOuts.master. We will do some customization here to implement our custom look and feel. Scroll this page down and notice under Alternate CSS URL there is a style sheet referenced called Blue.css. We are going to be replacing this as well.

Out-of-the-box, the Blue.css is an empty file that we can edit and use to override some of the classes that drive the master page TopNavFlyouts.master (Top Nav). Top Nav has a style sheet called TopNavFlyouts.css that is used when the master page is rendered.

For now, select Site ActionsàManage Content and Structure. In the left treeview, expand Style Library, then en-us, finally, select Core Styles. Your screen should look similar to the following:

Style Library

Notice that we have some out-of-the-box style sheets, and one of these is TopNavFlyouts. What is important to understand is that we have to create a new style sheet, in this Core Styles library so we can override some of the classes in the Top Nav style sheet.

We do not want to edit the Top Nav style sheet directly, but rather, create our own style sheet and override the classes that we’ll need to implement our customizations. Also, we’ll create a couple new classes in our style sheet that will handle the banner and default background images / colors.

For this exercise, I created a my.css text file with the following in it:

CSS Top Nav

This has my color for the main background, and my banner properties. The three graphics that I will be using are for the banner, toolbar, and the toolbar hover/selected images.

We’ll include a custom footer in this setup and that’s why I have the my–spacerX and my–footer classes included.

My banner is 785px by 200px, and my toolbar images are 4px by 40px each. These are shown below:

Company Logo

Tool Bar GIF my-toolbar.gif

Toolbar Hover - Selectedmy-toolbar-hoverselected.gif

Each of these graphics and my my.css style sheet need to be uploaded to SharePoint before we can begin to customize our Top Nav master page.

To do this, back in SharePoint under Site Content and Structure with Core Styles still selected on the left, in the right pane, click NewàItem to upload our style sheet.

On the Upload Document: Style Library page, click Browse to browse to where you saved your my.css object. Once you have selected your file, click OK and you should see a screen similar to the following:

Upload to Style Library

Here we enter a Title for our style sheet, and click Check In. You will be returned to the Core Styles and you’ll notice our new style sheet in the library.

Style Library - Core Styles

Notice in the above image, under Style Library there is an Images folder. There is also one under the en-us folder. We want to select the one that’s actually under Style Library, not en-us. Once selected, we need to select New-->Item and here we are going to upload multiple items – our banner and two toolbar objects.

When you get to the Upload Document: Style Library screen, below the Name textbox for the image, you’ll see a link for Upload Multiple Files… - click this to browse for the banner and toolbar objects.

Style Library - Document Upload

Once these are selected, click OK to begin the upload process. You will be prompted to confirm the upload and you will want to click Continue.

Once the upload is completed you will be returned to the Site Content and Structure-->Style Library-->Images view. You want to scroll down and find our three new images, and click the box to the left of each image to select them. Once selected, select Actions from the menu, and select Check In (be sure to select Publish Major Version as well).

When prompted for comments about the check-in, enter My Company SIte Images and click OK.

Once this is done, in the upper-left area of your screen click My Company Site to return to the root site.

We are now ready to being our customization of the master page and override the classes from the Top Nav style sheet.

To perform these next steps you will need the SharePoint Designer 2007 installed.

Launch SharePoint Designer (SPD) and select FileàOpen Site, then type in the URL for our new site (http://<machineName>:10000).

You should see a screen similar to the following once you are connected to the site with SPD:

SharePoint Designer - Base Site

In SPD, under Folder list expand _catalogs, then masterpage, and locate and double-click on TopNavFlyouts.aspx. When prompted to Check Out the object, click Yes and continue.

If this is the first time you have worked on this site with SPD you will be restricted from editing code at first. Do the following to resolve this:

From the menu bar select SiteàContributor Settings and you will see a dialog like the following:

SPD Author Settings

In the upper Manage Contributor Groups region, select Content Authors (Default) and click Modify.

You should see a screen like the following:

SPD Author Settings - Allow

From here click / enable Allow unrestricted use of SharePoint Designer and click OK. Click OK again to return to SPD with full editing capabilities.

When you return the SPD the Web Site tab is rendered. Click on the TopNavFlyouts.aspx tab to render that page. In the lower region of your designer form you’ll see Design Split Code. Click on Split and you should see something similar to the following:

TopNavFlyout Master Page

We want to load our custom my.css style sheet, and the TopNavFlyouts style sheet now too. In the Folder list browse down to Style Libraryàen-us (Style Library)àCore Styles (Style Library). Double-Click our my.css object. When prompted to check-out the item, click Yes. Now double-click the TopNavFlyouts.css, but when prompted to check-out, click No.

OVERRIDING STYLES

The TopNavFlyouts.css library is used for the TopNavFlyouts.aspx master page – which you have probably already assumed. For this example, we will want to override some of the classes in this style sheet. And to do this, we copy and paste those classes into our my.css object. Yes, we can certainly get more involved and complex in our chroming / customization – but for this walk-through I am trying to keep this pretty simple / straight-forward. Soon you will see where our my.css object gets configured in SharePoint and you will understand why I took this approach.

Remember, our image is 200px high by 785px wide. By default, the Top Nav area renders by percentage, and at 100%. We will need to change this so that our screen aligns with our banner. Again, this is for this customization only – and you can play with this in a number of different ways, depending on your customization and whether or not you are introducing custom graphics or navigation.

For now, locate, and copy / paste the following classes from TopNavFlyouts.css to our my.css:

.body

.master

.search td

.search

.topNavContainer

.topNavItem

.topNavItem a

.topNavSelected a

.topNavHover a

.topNavFlyouts

.topNavFlyOutsItem

.topNavFlyOutsItem a

.topNavFlyOutsHover

You should now have a my.css object that contains the following – before any customizations have been implemented:

.my-mainbackground

{

background-color: #B4BC97;

background-image: url(../images/blog-background.jpg);

}

.my-mainbanner

{

background-image: url(../images/blog-header.jpg);

background-color: #768365;

height: 200px;

border: 0px;

}

.my-spacer5

{

height: 5px;

}

.my-spacer10

{

height: 10px;

}

.my-footer

{

background-color: #B4BC97;

height: 15px;

border: 0px;

text-align: center;

font-family: Verdana;

font-size: 11px;

font-style: italic;

font-weight: normal;

color: #ffffff;

}

.body

{

background-color:#596E9E;

height:100%;

margin:0px;

}

.master

{

width:950px;

margin-left:auto;

margin-right:auto;

height:100%;

background-color:#FFFFFF;

}

.search td

{

font-family:tahoma;

font-size: 8pt;

color: #3A4663;

}

.topNavContainer

{

background-image:url("../../images/bl_Navbar_Gd_Default.jpg");

background-repeat:repeat-x;

height:40px;

}

.topNav

{

*position:relative;

*top:-1px;

}

.topNavItem

{

background-image: url('../../Images/bl_Navbar_Splitter.jpg');

background-repeat:no-repeat;

background-position:top right;

font-family: tahoma;

font-size: 8pt;

color: #294C7A;

}

.topNavItem a

{

display:block;

padding:8px 5px 0px 5px;

height:32px;

}

.topNavSelected a

{

background-image: url('../../Images/bl_Navbar_Gd_Hover.jpg');

background-repeat:repeat-x;

background-position:top right;

color: #EFF4FA;

}

.topNavHover a

{

color:#FFFFFF;

background-image: url('../../Images/bl_Navbar_Gd_Hover.jpg');

background-repeat:repeat-x;

background-position:top right;

}

SHOW ME THE CHROME!!!

Now the fun begins!

We’ll step through the change for each class, and then we’ll modify a few things in our master page and step back and see how things render.

1) .body, and .master – Change color to #B4BC97

2) .search td – change Color to #3A4663.

3) .search – Remove top:-2px; altogether.

4) .topNavContainer – change background-image: to ‘../../my-toolbar.gif’

5) .topNavItem a – Change padding to 12px 5px 0px 5px, and change the height to 40px.

6) .topNavSelected a – Change the background-image URL to ../../Images/my-toolbar-hoverselected.gif'.

7) .topNavHover a – Change the background-image URL to ../../Images/my-toolbar-hoverselected.gif'.

APPLY THE STYLE SHEET

Before we proceed, let’s apply our custom style sheet to the site collection so we can see our progress thus far.

To do this, select Site ActionsàSite SettingsàModify All Site Settings.

Under Look and Feel select Site Master Page Settings.

Scroll down to Alternate CSS URL and ensure that the following is entered:

/Style Library/en-us/Core Styles/my.css

Click OK to apply the setting.

MASTER PAGE CUSTOMIZATION

We are now ready to do the final modifications to our master page.

Locate the line just below the beginning of the <body> tag that looks like

<table cellpadding=”0” cellspacing=”0” class=”master”>

Just below this replace the class reference of shadowLeft with my-background

Your screen should look similar too:

TopNavFlyout - Change ShadowLeft

TIP – It’s important to remember that this walk-through deals with a specific template and as you venture into the area of chroming and customization, you will not do everything the same.

FINAL STEPS

Just below our my-background, within the table def. that includes masterContent, change the width to 785 and add an align statement like the following:

  • Modify the table def. below this line to include align=”center” width=”785”

See below:

The highlighted areas include the changed content:

TopNavFlyout - Change masterContent

Now, we need to remove the Title Area icon, and class, and insert our banner. Scroll down in the code view and locate the topArea class. Look at the snapshot below – you want to select the two lines below the topArea and delete those. Then we’re going to replace the top area class:

TopNavFlyout - Change topArea

Now, change the topArea class reference to my-header the name of the class which defines our new banner. The following reflects these changes:

topArea Class Change

Now, scroll down to where the table definition and class reference for the topNavContainer are. Just below this is the reference to topNavRoundLeft, and below that is a table definition with only a valign attribute setting. Here we want to change the attribute to valign=”center”, and add an align=”left” in table definition. (This is necessary because we added the align=”center” earlier in our changes, and we’ll need to address the navigation, breadcrumb, and left navigation text being left justified vs. centered.)

Next, scroll down to the <div class=”breadcrumb”> statement, and add align=”left” at the end of “breadcrumb”.

The following screenshots show these latest changes.

Breadcrumb Change...

Breadcrumb Changed...

Now, locate the table def. just above the div class=”mainContainer” line, and change the width from 100% to 785.

In the line with class=”mainContainer” add a align=”left” to this line (just after the “mainContent” part.

Finally, locate the table def. just below this that includes the class reference for shadowRight and replace shadowRight with my-background. Save your changes.

Your screen should reflect changes similar to that shown below:

TopNavFlyout - ShadowRight change

Finally, let’s add a custom footer to our page. Just below the </tr> and just before the final </table> tags, insert the following code:

<!-- Custom Footer... -->

<tr>

<td colspan="3" class="my-background">

<table width="100%">

<tr><td class="my-spacer10"></td></tr>

<tr><td class="my-footer">Copyright (C) 2006 – My Company Site</td></tr>

<tr><td class="my-spacer10"></td></tr>

</table>

</td>

</tr>

Save the TopNavFlyOuts.master page. Once this is saved, right-click on the master page in the Folder List in Designer, and select Check-In.

When the check in dialog appears, be sure to select Publish Major Version. You should see something similar to the following:

Check-in changes

Click OK to check-in and publish a major version (otherwise you will not see your changes immediately).

Next you should see a dialog like the following:

Change Notice to Publish

Click YES to proceed.

You will get to the Master Page Gallery (MPG) for your site, and see a screen similar to the following:

Master Page Gallery

Hover over the Top Nav page that is in Pending status, and select Approve/reject. When you get to the approval page, you will want to ensure you click Approve before submitting. You should have a screen similar to the following:

Approval Process

Click OK to finalize this process.

If all has gone well, your home page should be similar to the following:

Show changes...

This concludes a basic chroming / customization approach. Yes, there are certainly more robust things that can be done – and hopefully this opens the door for some ideas!

NOTES

If something is not rendering properly, it is usually because something is not checked in and published fully. This will become a nuance you’ll get used to quickly J.

I am pasting the following graphics and complete source code to help you just in case you need them. The graphics are our images (4 total) that we used for the main banner, toolbar, toolbar-hoverselected, and finally, the background.

The source is the my.css first, followed by the complete topnavflyouts.master XSL code-behind (if such a thing is a valid way to state it).

GRAPHICS

Main Banner

Header Logo

Background

Header Shim

Toolbar

Toolbar Color

Toolbar – hoverselected

Toolbar hover - selected

MY.CSS

.my-background

{

background-color: #B4BC97;

background-image: url(../images/my-background.jpg);

}

.my-header

{

background-image: url(../../images/my-header.jpg);

background-color: #768365;

height: 200px;

border: 0px;

}

.my-topmenu

{

background-image: url('../../images/my-toolbar.gif');

background-color: #f9da5d;

height: 40px;

boarder: 0px;

text-align: left;

vertical-align: top;

padding-top: 10px;

padding-bottom: 5px;

padding-left: 10px;

padding-right: 10px;

font-family: Verdana;

font-size: 11px;

font-style: normal;

font-weight: bold;

text-decoration: none;

color: #ffffff;

}

.my-spacer5

{

height: 5px;

}

.my-spacer10

{

height: 10px;

}

.my-footer

{

background-color: #B4BC97;

height: 15px;

border: 0px;

text-align: center;

font-family: Verdana;

font-size: 11px;

font-style: italic;

font-weight: normal;

color: #ffffff;

}

.body

{

background-color:#B4BC97;

height:100%;

margin:0px;

}

.master

{

width:950px;

margin-left:auto;

margin-right:auto;

height:100%;

background-color:#B4BC97;

}

.search td

{

font-family:tahoma;

font-size: 8pt;

color: #3A4663;

}

.search

{

float:right;

font-size: 8pt;

margin-left:5px;

margin-right: 0px;

position:relative;

}

.topNavContainer

{

background-image:url("../../images/my-toolbar.gif");

background-repeat:repeat-x;

height:40px;

}

.topNav

{

*position:relative;

*top:-1px;

}

.topNavItem

{

background-image: url('../../Images/bl_Navbar_Splitter.jpg');

background-repeat:no-repeat;

background-position:top right;

font-family: tahoma;

font-size: 8pt;

color: #294C7A;

}

.topNavItem a

{

display:block;

padding:12px 5px 0px 5px;

height:40px;

}

.topNavSelected a

{

background-image: url('../../Images/my-toolbar-hoverselected.gif');

background-repeat:repeat-x;

background-position:top right;

color: #EFF4FA;

}

.topNavHover a

{

color:#FFFFFF;

background-image: url('../../Images/my-toolbar-hoverselected.gif');

background-repeat:repeat-x;

background-position:top right;

}

TOPNAVFLYOUTS.master

<%@ Master language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@ Import Namespace="Microsoft.SharePoint" %>

<%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register TagPrefix="wssuc" TagName="Welcome" src="~/_controltemplates/Welcome.ascx" %>

<%@ Register TagPrefix="PublishingVariations" TagName="VariationsLabelMenu" src="~/_controltemplates/VariationsLabelMenu.ascx" %>

<%@ Register Tagprefix="PublishingConsole" TagName="Console" src="~/_controltemplates/PublishingConsole.ascx" %>

<%@ Register TagPrefix="PublishingSiteAction" TagName="SiteActionMenu" src="~/_controltemplates/PublishingActionMenu.ascx" %>

<html dir="ltr" runat="server" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">

<head runat="server">

<META name="WebPartPageExpansion" content="full">

<meta name="GENERATOR" content="Microsoft SharePoint" />

<meta http-equiv="Content-Type" content="text/html" />

<meta http-equiv="Expires" content="0" />

<title id="onetidTitle">

<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>

</title>

<Sharepoint:CssLink runat="server"/>

<!--Styles used for positioning, font and spacing definitions-->

<SharePoint:CssRegistration name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/TopNavFlyouts.css %>" runat="server"/>

<SharePoint:CssRegistration name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/controls.css %>" runat="server"/>

<SharePoint:ScriptLink language="javascript" name="core.js" runat="server"/>

<SharePoint:ScriptLink language="javascript" name="ows.js" runat="server"/>

<!--Placeholder for additional overrides-->

<asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server"/>

</head>

<body class="body" onload="javascript:_spBodyOnLoadWrapper();">

<WebPartPages:SPWebPartManager runat="server"/>

<form runat="server" onsubmit="return _spFormOnSubmitWrapper();">

<table cellpadding="0" cellspacing="0" class="master">

<tr>

<td height="100%" class="my-background" />

<td valign="top">

<table cellpadding="0" cellspacing="0" align="center" width="785" class="masterContent">

<tr>

<PublishingWebControls:AuthoringContainer id="authoringcontrols" runat="server">

<td colspan="2" width="100%" class="authoringRegion">

<span class="siteActionMenu">

<PublishingSiteAction:SiteActionMenu runat="server" />

</span>

<div class="sharepointLogin">

<!--Authentication for Authors only-->

<table cellpadding="0" cellspacing="0" >

<tr>

<td><SharePoint:DelegateControl ControlId="GlobalSiteLink1" Scope="Farm" runat="server"/></td>

<td><SharePoint:DelegateControl ControlId="GlobalSiteLink2" Scope="Farm" runat="server"/></td>

<td><wssuc:Welcome id="explitLogout" runat="server"/></td>

</tr>

</table>

</div>

<div class="console">

<PublishingConsole:Console runat="server" />

</div>

</td>

</PublishingWebControls:AuthoringContainer>

</tr>

<tr>

<td colspan="2" >

<table cellpadding="0" cellspacing="0" width="100%">

<tr>

<td colspan="4" class="my-header">

<PublishingNavigation:PortalSiteMapDataSource ID="SiteMapDataSourceRoot" Runat="server"

SiteMapProvider="CombinedNavSiteMapProvider" EnableViewState="true"

StartFromCurrentNode="true" StartingNodeOffset="0" ShowStartingNode="true"/>

<div class="topLinkBar">

<div class="topLink">

<PublishingVariations:VariationsLabelMenu id="labelmenu1" runat="server"/>

</div>

<PublishingWebControls:AuthoringContainer id="VisibleToReaders" DisplayAudience="ReadersOnly" runat="server">

<div class="login">

<asp:ContentPlaceHolder id="PlaceHolderLogin" runat="server">

<!--End user login for forms authentication-->

<asp:LoginStatus id="formsAuthLogin" LoginText="<%$Resources:cms,masterpages_logincontrol_label%>" LogoutText="<%$Resources:cms,masterpages_logoutcontrol_label%>" LogoutAction="RedirectToLoginPage" runat="server"/>

</asp:ContentPlaceHolder>

</div>

</PublishingWebControls:AuthoringContainer>

</div>

</td>

</tr>

<tr class="topNavContainer">

<td class="topNavRoundLeft" />

<td valign="top" align="left">

<SharePoint:AspMenu ID="GlobalNav" Runat="server" DataSourceID="SiteMapDataSource1"

Orientation="Horizontal" StaticDisplayLevels="1" MaximumDynamicDisplayLevels="1"

StaticSubMenuIndent="0" DynamicHorizontalOffset="0" DynamicVerticalOffset="-8"

StaticEnableDefaultPopOutImage="false" ItemWrap="false" SkipLinkText="<%$Resources:cms,masterpages_skiplinktext%>" CssClass="topNav">

<StaticMenuItemStyle CssClass="topNavItem" ItemSpacing="0"/>

<StaticSelectedStyle CssClass="topNavSelected" ItemSpacing="0"/>

<StaticHoverStyle CssClass="topNavHover"/>

<DynamicMenuStyle CssClass="topNavFlyOuts" />

<DynamicMenuItemStyle CssClass="topNavFlyOutsItem" />

<DynamicHoverStyle CssClass="topNavFlyOutsHover"/>

</SharePoint:AspMenu>

<PublishingNavigation:PortalSiteMapDataSource ID="siteMapDataSource1" Runat="server"

SiteMapProvider="GlobalNavSiteMapProvider" EnableViewState="true"

StartFromCurrentNode="true" StartingNodeOffset="0" ShowStartingNode="false">

</PublishingNavigation:PortalSiteMapDataSource>

</td>

<td>

<div class="search">

<asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">

<SPSWC:RightBodySectionSearchBox id="SearchBox" TextBeforeDropDown="" TextBeforeTextBox="<%$Resources:cms,masterpages_searchbox_label%>" TextBoxWidth="100" GoImageUrl="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow.jpg %>"

GoImageUrlRTL="<% $SPUrl:~sitecollection/Style Library/Images/Search_Arrow_RTL.jpg %>" SearchResultPageURL="<% $SPUrl:~sitecollection/SearchResults.aspx %>" DropDownMode = HideScopeDD FrameType="None" runat="server"/>

</asp:ContentPlaceHolder>

</div>

</td>

<td class="topNavRoundRight" />

</tr>

</table>

</td>

<tr>

<td colspan="2">

<asp:ContentPlaceHolder id="PlaceHolderTitleBreadcrumb" runat="server">

<div class="breadcrumb" align="left">

<asp:SiteMapPath ID="siteMapPath" Runat="server" SiteMapProvider="CurrentNavSiteMapProvider" RenderCurrentNodeAsLink="false" cssclass="breadcrumb" CurrentNodeStyle-CssClass="breadcrumbCurrent"/>

</div>

</asp:ContentPlaceHolder>

</td>

</tr>

<tr>

<asp:ContentPlaceHolder id="PlaceHolderLeftNavBar" runat="server">

<td valign="top">

<!-- Current Navigation -->

<SharePoint:AspMenu runat="server" datasourceID="SiteMapDS" orientation="Vertical"

StaticDisplayLevels="2" MaximumDynamicDisplayLevels="0" StaticSubMenuIndent="1" ItemWrap="true" AccessKey="3" CssClass="leftNav" SkipLinkText="<%$Resources:cms,masterpages_skiplinktext%>">

<LevelMenuItemStyles>

<asp:MenuItemStyle CssClass="leftNav1" />

<asp:MenuItemStyle CssClass="leftNav2" />

<asp:MenuItemStyle CssClass="leftNav3" />

</LevelMenuItemStyles>

<StaticHoverStyle CssClass="leftNavHover"/>

<StaticSelectedStyle CssClass="leftNavSelected"/>

<DynamicMenuStyle CssClass="leftNavFlyOuts" />

<DynamicMenuItemStyle CssClass="leftNavFlyOutsItem"/>

<DynamicHoverStyle CssClass="leftNavFlyOutsHover"/>

</SharePoint:AspMenu>

<PublishingNavigation:PortalSiteMapDataSource ID="SiteMapDS" Runat="server"

SiteMapProvider="CurrentNavSiteMapProvider" EnableViewState="true"

StartFromCurrentNode="true" StartingNodeOffset="0" TrimNonCurrentHeadings="true" ShowStartingNode="false">

</PublishingNavigation:PortalSiteMapDataSource>

<div class="leftNavSpacer"/>

</td>

</asp:ContentPlaceHolder>

<td width="785" valign="top">

<div class="mainContainer">

<div class="pageTitle">

<asp:ContentPlaceHolder id="PlaceHolderPageTitleInTitleArea" runat="server" />

</div>

<div class="mainContent" align="left">

<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server" />

</div>

</div>

</td>

</tr>

</table>

</td>

<td height="100%" class="my-background" />

</tr>

<!-- Custom Footer... -->

<tr>

<td colspan="3" class="my-background">

<table width="100%">

<tr><td class="my-spacer10"></td></tr>

<tr><td class="my-footer">Copyright (C) 2006 – My Company Site</td></tr>

<tr><td class="my-spacer10"></td></tr>

</table>

</td>

</tr>

</table>

<asp:panel visible="false" runat="server">

<asp:ContentPlaceHolder ID="PlaceHolderPageImage" runat="server" />

<asp:ContentPlaceHolder ID="PlaceHolderBodyLeftBorder" runat="server" />

<asp:ContentPlaceHolder ID="PlaceHolderNavSpacer" runat="server" />

<asp:ContentPlaceHolder ID="PlaceHolderTitleLeftBorder" runat="server" />

<asp:ContentPlaceHolder ID="PlaceHolderTitleAreaSeparator" runat="server" />

<asp:ContentPlaceHolder ID="OSSConsole" runat="server" />

<asp:ContentPlaceHolder ID="PlaceHolderMiniConsole" runat="server" />

<asp:ContentPlaceHolder id="PlaceHolderCalendarNavigator" runat ="server" />

<asp:ContentPlaceHolder id="PlaceHolderLeftActions" runat ="server" />

<asp:ContentPlaceHolder id="PlaceHolderPageDescription" runat ="server" />

<asp:ContentPlaceHolder id="PlaceHolderBodyAreaClass" runat ="server" />

<asp:ContentPlaceHolder id="PlaceHolderTitleAreaClass" runat ="server" />

</asp:panel>

</form>

</body>

</html>

posted @ 12/8/2007 10:21 AM by Michael J. Hamilton, Sr.

.Net Directory Services Programming - C# - Part 3

.Net Directory Services Programming – C# - Part 3

 

Topics

DirectorySearcher – the other critical class in the DirectoryServices namespace.

 

 

Review

Because a lot of your Directory Services (DS) development will involve querying DS for data, it makes sense that this is a powerful class offered in the namespace, and below are some of the features:

 

  • DirectorySearcher – Performs the initial queries against AD
  • SearchResult – A single object reference from a search performed by DirectorySearcher
  • ResultPropertyCollection – A collection of properties of the SearchResult instance
  • ResultPropertyValueCollection – The values of properties in a SearchResult instance.
  • SearchResultCollection – Basically a collection of SearchResult instances returned from a query by DirectorySearcher
  • SortOption – Allows a means to sort a result set.

 

We have briefly touched on DS by introducing some basic DirectoryEntry information and a couple simple examples, and we have introduced some basic properties and examples on how to interact with those.

 

I have not taken a lot of time to review a directory structure – basically assuming that you should have some of this understanding already. As I delve into the next lesson, this assumption holds fast. If you have any issues or are dealing with something that I am not elaborating enough on, please feel free to email me directly at (mikeh AT thedataworks.net) and I will respond as quickly as I can. Please forgive the notation there – but we all are familiar with the latest in SPAM bots and whatnot.

 

Show me the Money!!!

Or at least the code. Lets get started…

 

Parent – Child Relationships

DirectoryEntry objects (DE’s) can be a root object in AD, or an object within another – hence, a child object of another. We reviewed in Part 1 a few of the common references to object types (CN, OU, DC). These are the most prevalent you will deal with.

 

DC is the root level context. OU’s can be off the root, or a child of other OU’s and even Containers. CN’s can be off the root, within OU’s and often are found within Containers.

 

A word about Containers and Security

When planning your DS application, keep this in mind: Containers are non-secure objects! Let me explain. AD security is multi-faceted, yes, but the real security is managed using Group Policy (something we are not going to review here).

 

Containers are basically folders in your directory tree. AD comes with a couple by default. If you promote a server and check your directory tree, you’ll find a Users, a Built-In, and a couple other folders off the root tree (or context/server name) object. These are not OU’s – they are containers.

 

Group Policy (GP) cannot be applied to a Container object in AD. You can apply GP to objects within Containers – depending on what those objects are – but not the Container itself. This is important because a lot of administration can be simplified by applying the GP to the entire Container. So if not the Container, then what? Organizational Units – OU’s. Alas, OU’s are going to be your preferred folder or container (for lack of a better way to put it) for object storage.

 

Basic Searches

In Part 1 we introduced a server name and basic OU’s. To re-cap that:

 

Server: developer.hamilton.com

OU=Accounts – off the root of developer.hamilton.com

OU=Developers – within the OU=Accounts

CN=Mike Hamilton – within the OU=Developers

 

Within the OU=Accounts I might also create service accounts – basic user accounts that are used to run services such as IIS Application Pools, SQL Server, or other server / service applications. I might also have OU’s that represent other departments that pertain to development: BA’s for the Business Analyst, QA’s, etc. You can nest OU’s and accounts in just about any way you want to. NOTE: In AD – if you have not already – you will run into one of the inherent limitations of the AD Users & Computers (dsa.msc) snap-in: It can only display the first 2,000 objects within a Container or OU. So if you anticipate a large volume of users for a system you are designing, keep this in mind. You will want to present 1) a more suitable customized user interface piece for administration of this DS, or 2) design your object hierarchy so that users are more spread out within the DS. I will touch base on this topic in a later Part and introduce a couple ideas for addressing this limitation.

 

DirectorySearcher and the SearchResult

When using the DirectorySearcher class, you have the FindOne() and FindAll() methods that build your result set. As they infer, one finds one occurrence, the other finds all occurrences.

 

Let’s say I had more than one Mike on my team, and I wanted to find all entries that began with Mike?

 

DirectoryEntry rootEntry = new DirectoryEntry();                // Binds root context

// Now find every CN that has Mike at the beginning of the name…

DirectorySearcher searcherResults = new DirectorySearcher(rootEntry,”(CN=Mike*)”);

 

This is a simple example, and the result set will be one or more object references that begin with Mike. Notice that I did a bind on the root of the DS. I could have narrowed the focus of the search to only the developer’s OU by doing the following:

 

DirectoryEntry developersEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/OU=Accounts,OU=Developers,DC=developer,DC=hamilton,DC=com”);

 

This would return an entry object where the parent would be the OU=Developers, and not the default root of the DS tree.

 

Lets say my DS was structured like the following:

 

developer.hamilton.com à root of the DS

            OU=Accounts à First OU of accounts of users.

                        OU=Developers à Key development personnel

                        OU=Bas à Business Analyst

                        OU=QA à Quality Assurance / Test personnel

                        OU=Users à General users on this server.

 

Now, we want to find all users that are in the Users OU, not returning the developers or other personnel within the directory. That’s pretty straight forward.

 

DirectoryEntry developersEntry = new DirectoryEntry(“LDAP://developer.hamilton.com/OU=Accounts,OU=Users,DC=developer,DC=hamilton,DC=com”);

 

// Now return all users in this OU…

DirectorySearcher searcherResults = new DirectorySearcher(rootEntry,”(CN= *)”);

 

As you get more familiar with DS programming, you will find there are other ways to accomplish the same result – I am simply trying to open those doors for you.

 

It is important that you understand how to narrow your search filter in this way because you will find it greatly improves the performance of your application when you know where to search for content and you keep your search filter narrowly defined. For example, if I have 15,000 employees, they would very likely be grouped in AD by their department, and possibly further grouped by sub-departments. I would want to know this information beforehand so I can plan my DS application to be as efficient as possible. I would not want to search the rootDSE each time for a given employee or group of employees, if I know the departments those employees are in.

 

More on the Search Filter

The filter is a LDAP string that allows you to search for objects based on specific criteria. You will also use relational operators to better refine your search. The following list those operators:

 

=                      Equal to

~=                    Is approximately equal to (or like)

<=                    Less than or equal to

>=                    Greater than or equal to

 

NOTE: You cannot use ‘<’ or ‘>’ individually in LDAP – you must use the notation <= or >=.

 

The * character works as a wildcard in your search, as in the example above we searched for CN=Mike* or CN=* - in this case, get all Canonical (common) Names beginning with Mike, or get all names period (respectively).

 

To find all users with a surname of Hamilton you would use

 

(sn = Hamilton)

 

To find all users where the email ends in @hamilton.com

 

(&(objectCategory = person) (objectClass = user) (mail = *@hamilton.com))

 

Notice the Polish notation used here – the operator comes before the condition. LDAP uses this notation in the Filter. The above example would be more familiar possibly as

 

(objectCategory = person) AND (objectClass = user) AND (mail = *@hamilton.com)

 

The following are allowed logical operators:

 

&         AND

|           OR

!           NOT

 

You set the filter for a search using the DirectorySearcher.Filter property. The following code will create a binding to the root context, and return everything from the root down:

 

DirectoryEntry rootEntry = new DirectoryEntry();                // Binds root context

DirectorySearcher rootSearcher = new DirectorySearcher(rootEntry);

 

Let’s say we have a binding to the rootDSE as above, but only want to return all users with a surname of Hamilton? Change the DirectorySearcher to the following:

 

DirectorySearcher rootSearcher = new DirectorySearcher(“(sn=Hamilton)”);

 

You can either pass the DirectoryEntry object, or you can specify a filter in this fashion when creating a DirectorySearcher instance.

 

Loading Specific Properties

By default, when you create a DirectorySearcher instance, you return all properties for that binding (which can be a lot of data if you