Sunday, 29 August 2010

Moving files in Visual Studio and the SharePointProjectItem.spdata file

While mucking around the CKS:Development Tools Edition Visual Studio 2010 extension for SharePoint, I inadvertently created a new master page from the Starter Master Page (CKSDev) template in an existing VS module:

Module-CKSDev-MasterPage

Neither VS nor SharePoint seemed to object to this arrangement—likely because the module in question was otherwise empty—but, as an experiment, I decided to move the CKS:Dev master page SPI into the project (and the top-level MasterPages module) nonetheless, making the nested CKS:Dev container obsolete.

This wasn't a good idea because subsequent attempts to build the package failed with the error "Could not find the file 'c:\…PageLayouts\StarterMasterPage1.master". Omg, what to do and why is trying to find these files in the project root?! I briefly pined for the good ol' .ddf file from 2007 days and then slapped some sense back into myself.

To begin fixing the problem, I first had to click the Show All Files button in the Solution Explorer window to reveal the SharePointProjectItem.spdata file in the root-level module (note the CKS:Dev inner master page module has its own .spdata file, which is empty after the move):

SharePointProjectItem_spdata

This is an XML file and its structure is quite basic; I'd describe it as a mini project file for the module in question as it lists the source files in the module along with their targets, and types.

Interestingly, the Source values specified all started with "..\" but inspecting a similar file from an un-modified module simply listed each file names; I assume Visual Studio helped out during the move to add this additional path information.

Removing the "..\" prefix fixed the problem and suggested to me the SharePoingProjectItem.spdata file may prove fragile during project refactoring. Sure enough, moving the files back to their original home added a spurious MasterPages\ prefix to each file and wreaked havoc all over again.

Moral of the story: manually edit the SharePointProjectItem.data file as required but beware Visual Studio may "fix" any of your changes.

One other thing to note: when I moved my files around, Visual Studio reset the properties on some of them. Most notably, Elements.xml file reverted to a Deployment Type of ElementFile instead of ElementManifest and the Build Action was set to Content. Modifying these properties also added the parent directory prefixes back to my .spdata file. Perhaps removing files from one location and adding them them back through the Add –> Existing Item… dialog is a safer way to approach this long-term if VS is going to continue meddling with things.

And just to add to the joy, one final bit of fun: a page layout added to the module in question was deploying fine; for the sake of producing the screenshot above, I excluded it from the solution, which also removed it from the files listed below the MasterPages module in the visual feature designer. While I assumed the feature designer would automatically update itself when I added the layout back to the module, I was wrong: the designer refused to update to reflect the inclusion of the page layout until I restarted Visual Studio! If this is a VS 2010 bug, it'll be one of several I've already filed with MS! Viva SP1!!!

If you found this post helpful, please support my advertisers.

Thursday, 19 August 2010

Setting the Visible property on a webpart throws

Using myWebPart.Visible = false and getting this?

The Visible property cannot be set on Web Part 'your_web_part'. It can only be set on a standalone Web Part.

Use myWebPart.Hidden = true instead.

If you found this post helpful, please support my advertisers:

Wednesday, 18 August 2010

Must Have Windows Server 2008 R2 Hyper-V Hotfixes

Now there's a damning blog post title!

In brief, I've had a few issues since installing Windows Server 2008 R2 and adding the Hyper-V Role on my Dell Precision M6500 Core i7 laptop (if you've landed on this post and you don't care about laptops--i.e. you're an admin--don't stop reading now as this post will likely apply to you too). This post is meant to be a running log of problems and their resolutions while we await the next service pack, I suppose.

Problem #1: Blue Screen of Death/random reboots

Resolution:

KB975530: Stop error message on a Windows Server 2008 R2-based computer that has the Hyper-V role installed and that uses one or more Intel CPUs that are code-named Nehalem: "0x00000101 - CLOCK_WATCHDOG_TIMEOUT"

Symptoms, event log entries, and whatnot: Unexpected freezes, BSODs and reboots during periods of high network activity.

  • Event ID 219, The driver \Driver\WUDFRd failed to load for the device USB\VID_0A5C&PID_5800&MI_01\7&66de6c9&0&0001.
  • Event ID 41, The system has rebooted without cleanly shutting down first. This error could be caused if the system stopped responding, crashed, or lost power unexpectedly.
  • Event ID 4, Broadcom NetXtreme 57xx Gigabit Controller: The network link is down.  Check to make sure the network cable is properly connected.
  • Event ID 1001, The computer has rebooted from a bugcheck.  The bugcheck was: 0x00000101 (0x0000000000000019, 0x0000000000000000, 0xfffff880020ce180, 0x0000000000000003). A dump was saved in: C:\Windows\MEMORY.DMP. Report Id: 043010-31168-01.

Apparently this issue is caused by an Intel erratum affecting Nehalem-based processors (i.e. Xeon 5500, Core i7-800, and Core i5-700 series).

Problem #2: Guest VMs freeze, lost connection

Resolution:

None of this worked for me but changing my host power settings from Balanced to High performance did. In theory you should be able to revert to Balanced after installing and the above.

You may also want to investigate turning off TCP offloading.

Symptoms, event log entries, and whatnot: Hyper-V console freezes in some virtual machines but not others (the only one affected in my case was an XP VM upgraded from Virtual PC 2007 SP1), Hyper-V manager reports the Heartbeat as "Lost connection".

  • Event ID 5: The miniport 'Microsoft Virtual Machine Bus Network Adapter #3' hung.

...followed by...

  • Event ID 4: The miniport 'Microsoft Virtual Machine Bus Network Adapter #3' reset.

For additional information about this problem, definitely check out http://social.technet.microsoft.com/Forums/en-US/windowsserver2008r2virtualization/thread/0408a28d-6ab8-4c85-8773-4bc42c2df40b

More to come? Hopefully not! ;-)

If you found this post helpful, please support my advertisers:

Thursday, 12 August 2010

Configuring the People Picker and No exact match was found

SharePoint's people picker is generally one of those things that just kind of works—and fairly well no less. There's a gotcha to that statement however: the people picker works well when the the SharePoint farm exists in the same domain as the users you want to match against, or exists in a second domain where a two-way trust has been established with the first domain.

SharePoint-People-Picker

If your SharePoint web frontends exist in another domain with a one-way trust, you've got some extra work to do. This is the case with our dev setup and DMZ setup: our dev VMs are joined to the dev domain which trusts the corporate domain and our production servers are similarly joined to a web domain that also trusts the corporate domain. Both trusts are one-way.

I'll simplify what needs to be done by stating you simply need to tell SharePoint which forests or domains house the users you're after and provide an account from that domain.

Firstly you'll need to provide a key that will be used to encrypt any passwords you plug in during the next step. Run this on every WFE where "key" is a string of your choosing:

STSADM.exe -o setapppassword -password key

Next, set the peoplepicker-searchadforests property:

STSADM.exe -o setproperty-propertyname peoplepicker-searchadforests -propertyvalue <Valid list of forests or domains> -url <URL of the Web application>

where <Valid list of forests or domains> might look like this:

"domain:mydomain.com,mydomain\myuser,mypassword"

Supply the URL of the web application you want to configure (and note you don't need to set this for Central Admin, set it for a specific web application). Multiple domains and forests can be listed if necessary.

For more information, check out these resources:

 
If you found this post helpful, please support my advertisers:

Tuesday, 10 August 2010

Data Compare crashes Visual Studio 2010

Although I'd previously noticed the Data Compare and Schema Compare options on the Data menu in Visual Studio, until today I didn't have a good reason to see what they can do.

Note I'm running VS Ultimate; if you can't see it, I'm not certain in which editions of the product this menu makes an appearance. SQL Server Management Studio 2008 doesn't seem to have a comparable tool that I'm aware of—which seems odd—but please comment if you know something I don't.

So here's the situation: two copies of the same database, one that's been moved to a different server and both of which have data changes. Your mission: find and fix the differences.

Open VS, Data –> Data Compare –> New Data Comparison…

CRASH!

Luckily I was able to work around this problem (feature?) by re-opening VS, Data –> Transact-SQL Editor –> New Query Connection, connecting to any ol' database (or optionally just cancelling out of the connection window) and then launching the compare wizard again.

I'm not sure what this does since you specify a database connection in the compare wizard anyway and cancelling the connection window or closing the new query window after opening the Transact-SQL Editor connection makes the problem go away. I've logged a bug with Microsoft connect.

Update 6 Sept 2010: MSFTConnect just got in touch to tell me this is likely related to the Solution Navigator extension in the Productivity Power Tools. Disabling apparently fixes the problem and the problem should be fixed this month.

If you found this post helpful, please support my advertisers:

Monday, 2 August 2010

Enable Fusion Assembly Binding Logging

The WRN: Assembly binding logging is turned off message is annoying but assembly binding logging can be extremely helpful when you need to know how .NET is (or isn't) locating the assemblies you've referenced. The message is annoying because, if you're like me, you never have logging enabled and the registry key cited is a bit unusual:

To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.

What does the exclamation mark mean? Presumably EnableLog is a DWORD in the Fusion key but it's all a bit unclear for my liking. Once you've set this DWORD, you need to figure out what to do next and for many people that will likely involve firing up the Fusion Log Viewer fuslogvw.exe or the Windows/.NET SDK. But then what?

Gary Kindel was kind enough to post the following details in response to a related Stack Overflow question:

Add the following values to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion

DWORD ForceLog set value to 1
DWORD LogFailures set value to 1
DWORD LogResourceBinds set value to 1
String LogPath set value to folder for logs ie) C:\FusionLog\

Make sure you include the backslash after the folder name. I also found an IISRESET was necessary in a web context.

Since I wanted to enable this logging in an environment without Visual Studio or the Windows SDK installed, the above option was clean and lightweight. Log files were dumped to the expected location in .html format and it was then a case of locating the assembly I was interested in… and, oh yeah, fixing the problem ;-) The issue was also detailed in the ASP.NET error message returned by IIS.

Advanced geeks: because Fusion logging supposedly affects performance, you might want to create a reg file/batch script to toggle logging on and off. Here's a starting point—put this into a file called EnableFusionLogging.reg and double-click to run it:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion]
"ForceLog"=dword:00000001
"LogFailures"=dword:00000001
"LogResourceBinds"=dword:00000001
"LogPath"="C:\\Temp\\FusionLog\\"

I actually call this from a batch script which also resets IIS and I have a mirror reg file that disables logging.

If you found this post helpful, please support my advertisers:

Sunday, 1 August 2010

Windows Licensing Details

Windows will report licensing details if you run the following from an elevated console window:

slmgr.vbs /dlv

The Windows Script Host popup will shortly tell you which edition of Windows you're running, which licensing channel you fall under (retail, OEM, volume), your activation ID, license status, rearm counts, and KMS details.

Wednesday, 28 July 2010

Visual Studio 2010 Remote Debugger Location

You'll find the VS 2010 remote debugger a similar location to that of the 2005/2008 debuggers:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Remote Debugger

Note VS2010 is still a 32-bit app so if you're running a 64-bit OS, you'll need to be looking in the Program Files (x86) directory. The debugger itself comes in both x86 and x64 flavours.

To install, I normally just copy the relevant architecture folder to the remote server. Run msvsmon.exe and assuming you're otherwise setup for remote debugging, it should be same as previous versions of Visual Studio!

Ps. You can also download the remote debugger from Microsoft.
Pps. I normally add msvsmon to the Windows Startup folder so it starts whenever I boot my remote dev environment (I've found I previously had to log on to the server, however, and two users can't run the monitor simultaneously on the same server). Apparently the 2010 monitor can be run as a service—not sure if this was the case for previous versions.

Friday, 23 July 2010

PublishingPageLayout doesn't point to current web application

In the past, we've developed a habit of "birthing" new SharePoint sites in a UAT environment for initial setup and stabilisation before the big move to the production farm; during major site renovations—like the recent www.westernaustralia.com rebrand—we'll implement a quasi-freeze on production (emergency edits only) and conversely pull the content down to UAT for overhaul. At the end of the day, we're moving SharePoint content between farms on a fairly regular basis.

Prior to the release of the April 2009 Cumulative Update packages, Microsoft didn't support moving content databases between farms because "MOSS often stores absolute URLs to the Page Layout in the properties of a Publishing Page." With the April Cu that changes but of course the times they a change too and we've abandoned the stsadm backup/restore commands in favour of restoring SQL Server backups and running the stsadm deletecontentdb/addcontentdb commands (it's not only more reliable but many times faster…).

Until yesterday none of the above was causing us any problems. In fact, we'd even become complacent about it all.

So finding out one of our content editors was unable to publish a page due to a previously unseen exception was not something that would have led us to review the way we handle content databases. After checking out some pages for editing, an attempt to publish the page was met with the following exception:

ArgumentException 
Value does not fall within the expected range.

    Stack trace:    at Microsoft.SharePoint.Library.SPRequestInternalClass.GetMetadataForUrl(String bstrUrl, Int32 METADATAFLAGS, Guid& pgListId, Int32& plItemId, Int32& plType, Object& pvarFileOrFolder)
   at Microsoft.SharePoint.Library.SPRequest.GetMetadataForUrl(String bstrUrl, Int32 METADATAFLAGS, Guid& pgListId, Int32& plItemId, Int32& plType, Object& pvarFileOrFolder)
   at Microsoft.SharePoint.SPWeb.GetMetadataForUrl(String relUrl, Int32 mondoProcHint, Guid& listId, Int32& itemId, Int32& typeOfObject, Object& fileOrFolder)
   at Microsoft.SharePoint.SPWeb.GetFileOrFolderObject(String strUrl)
   at Microsoft.SharePoint.Publishing.CommonUtilities.GetFileFromUrl(String url, SPWeb web)
   at Microsoft.SharePoint.Publishing.PublishingPage.get_Layout()
   at Microsoft.SharePoint.Publishing.PublishingPage.GetEffectivePageCacheProfileId(Boolean anonUserProfile)
   at Microsoft.SharePoint.Publishing.PublishingPage.GetEffectiveAnonymousPageCacheProfileId()
   at Microsoft.SharePoint.Publishing.CachedPage..ctor(PublishingPage page, SPListItem altItem, String id, String parentId, String title, String url, String description, CachedObjectFactory factory, List`1& fieldInfo, Boolean datesInUtc)
   at Microsoft.SharePoint.Publishing.CachedPage.CreateCachedPage(PublishingPage page, SPListItem altItem, CachedObjectFactory factory, List`1& fieldInfo, Boolean datesInUtc)
   at Microsoft.SharePoint.Publishing.CachedPage.CreateCachedPage(PublishingPage page, CachedObjectFactory factory, List`1& fieldInfo, Boolean datesInUtc)
   at Microsoft.SharePoint.Publishing.CachedListItem.CreateCachedListItem(SPListItem item, SPListItem alternateItem, Boolean parentIsWeb, CachedObjectFactory factory, List`1& fieldInfo, Boolean datesInUtc)
   at Microsoft.SharePoint.Publishing.CachedObjectFactory.CreateObject(SPListItem listItem, List`1& fieldInfo, Boolean datesInUtc)
   at Microsoft.SharePoint.Publishing.CachedObjectFactory.CreateObject(PublishingPage page, Boolean datesInUtc)
   at Microsoft.SharePoint.Publishing.CachedObjectFactory.GetPageForCurrentItem()
   at Microsoft.SharePoint.Publishing.TemplateRedirectionPage.ComputeRedirectionVirtualPath(TemplateRedirectionPage basePage)
   at Microsoft.SharePoint.Publishing.Internal.CmsVirtualPathProvider.CombineVirtualPaths(String basePath, String relativePath)
   at System.Web.Hosting.VirtualPathProvider.CombineVirtualPaths(VirtualPath basePath, VirtualPath relativePath)
   at System.Web.UI.DependencyParser.AddDependency(VirtualPath virtualPath)
   at System.Web.UI.DependencyParser.ProcessDirective(String directiveName, IDictionary directive)
   at System.Web.UI.PageDependencyParser.ProcessDirective(String directiveName, IDictionary directive)
   at System.Web.UI.DependencyParser.ParseString(String text)
   at System.Web.UI.DependencyParser.ParseFile(String physicalPath, VirtualPath virtualPath)
   at System.Web.UI.DependencyParser.GetVirtualPathDependencies()
   at Microsoft.SharePoint.ApplicationRuntime.SPVirtualFile.CalculateFileDependencies(HttpContext context, SPRequestModuleData basicRequestData, ICollection& directDependencies, ICollection& childDependencies)
   at Microsoft.SharePoint.ApplicationRuntime.SPDatabaseFile.EnsureDependencies(HttpContext context, SPRequestModuleData requestData)
   at Microsoft.SharePoint.ApplicationRuntime.SPDatabaseFile.EnsureCacheKeyAndViewStateHash(HttpContext context, SPRequestModuleData requestData)
   at Microsoft.SharePoint.ApplicationRuntime.SPDatabaseFile.GetVirtualPathProviderCacheKey(HttpContext context, SPRequestModuleData requestData)
   at Microsoft.SharePoint.ApplicationRuntime.SPVirtualFile.GetVirtualPathProviderCacheKey(String virtualPath)
   at Microsoft.SharePoint.ApplicationRuntime.SPVirtualPathProvider.GetCacheKey(String virtualPath)
   at Microsoft.SharePoint.Publishing.Internal.CmsVirtualPathProvider.GetCacheKey(String virtualPath)
   at System.Web.Compilation.BuildManager.GetCacheKeyFromVirtualPath(VirtualPath virtualPath, Boolean& keyFromVPP)
   at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile)
   at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile)
   at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean noAssert)
   at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp, Boolean noAssert)
   at System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath)
   at System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig)
   at System.Web.HttpApplication.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Which of course means nothing.

Before long the guys stumbled across one of Stefan Goßner's brilliant posts, which suggests MOSS doesn't update all absolute page layout URLs on each publishing page object when content is shifted between farms; of cours, with the April 2009 CU installed and doing things via backup/restore or import/export, we may have avoided this issue.

You can see the exact problem by examining a page in SharePoint Manager: locate a page in the Pages library, expand the page node to reveal its Properties node, and expand the Properties node so you can inspect the PublishingPageLayout node. This screenshot is from my development environment, a server named dev-moss-mh5 and the wa.com web application configured to run on port 180—so obviously the http://edit.uat.westernaustralia.com value is incorrect:

SPM 2007 Publishin Page Properties

Interestingly, this problem was only affecting the production edit site… for whatever reason, my dev environment was unaffected. However, running Stefan's FixPageLayout code corrected the problem in production. The application runs through every page in every subsite and fixes the PublishingPageLayout property where required (in addition to reporting any other page instance/layout/master page issues). 

Update: Just remembered from a while back Gary Lapointe also has an stsadm command to fix this problem:

http://stsadm.blogspot.com/2007/08/fix-publishing-pages-page-layout-url.html

Thursday, 22 July 2010

Subsites, the Pages lists and 302 Redirects in an anonymous environment

Our network admin recently noticed some unusual errors in the proxy logs: www.rottnestisland.com/en/pages was failing to redirect to the default page. Fiddlering the request revealed a 401 response was being returned by SharePoint and friends.

Naturally our first inclination was to scratch our heads and wonder why such a thing would occur; at first glance both /en and /en/pages share many similarities with regular IIS directories; shouldn't SharePoint just go looking for the default page?!? After all, a request for /en is successfully 302 Redirected to /en/pages/home.aspx and the authenticated site also redirects the /en/pages request.

In the above case, home.aspx is the default page as configured in the Pages list and it is published along with its master page and other supporting resources (in fact the page loads without issue when requested directly).

Our anonymous setup isn't out of the ordinary: a read/write web app running in the default security zone is extended to a second read-only web app running in the internet zone with anonymous access enabled. Most annoyingly, we've got some URL rewriting tricks going on with www.westernaustralia.com so that site (which runs in the same farm as Rottnest) does redirect the /pages directory, as does its sister web site, www.tourism.wa.gov.au… the latter of which should have no tricks applied!

Until this point we assumed those of us in the naughty developer team had broken something on the Rottnest site and those of its sibling sites running the same code base. When I spun up a sanity web app in my dev machine, however, I found I could reproduce the problem in that environment with no customisations applied.

From one point of view this all makes sense: subsites will 302 Redirect to the default page in the Pages library and behave in the "normal IIS way"; the Pages library, being a list, should not do the same and does not—it's not a site. While plausible, this argument falls down when everything just works in the authenticated site.

No deeper understanding or solution to this one as yet…