Quick tip: Handy Scripts for Local Hyper-V Management


Here is a quick post with a small script that I find incredibly handy for managing my local Hyper-V machines (on windows 8).

It simply ensures what set of VMs are running at a given time – attach that to a shortcut on the desktop and it saves me 3 minutes every day; I find it useful.

Why? Quite often, I need to switch from one set of VMs to another for different tasks (VMWare term is “teams”) e.g. switching between SP2010 and SP2013 development. Sometimes just turn them off if I need the resources for something else.

Normally you just go into Hyper-V manager and start/stop the relevant VMs. Automating that was quite simple and painless – the download is here.

  1. I have one PowerShell script (SetRunningVMs.ps1) that handles the VM management and then a couple of batch files for executing that script with proper parameters. The script is:
    <#
    .SYNOPSIS
    This is a simple Powershell script that adjust what VMs are running on the local Hyper-V host.
    
    .DESCRIPTION
    This script will start/resume the requested VMs and suspend all other VMs to give you maximum power and make it easy to switch from one
    development task to another, i.e. switch teams.
    
    .EXAMPLE
    Make sure that only the dev1 and ad01 machines are running:
    ./SetRunningVMs.ps1 'dev1' 'ad01'
    
    Stop all VMs (no arguments)
    ./SetRunningVMs.ps1 
    
    .NOTES
    Requires admin rights to run. Start using admin shell or use one of the provided batch files.
    Pauses on error.
    
    .LINK
    
    http://soerennielsen.wordpress.com
    
    #>
    
    param( [Parameter(ValueFromRemainingArguments=$true)][string[]] $allowedVMs = @() )
    
    try{
        get-vm |? { $_.State -eq "Running" -and $allowedVMs -notcontains $_.Name } |% { Write "Saving $($_.Name)"; Save-VM $_.Name }
    
        get-vm |? { $_.State -ne "Running" -and $allowedVMs -contains $_.Name } |% { Write "Starting $($_.Name)"; Start-VM $_.Name }
    
        write "SetRunningVMs succesfully done"
    }
    catch{
        Write-Error "Oops, error:" $_
        pause
    }

    I assume that the PowerShell Hyper-V module is loaded; it has always been the case in my tests.

  2. I have a number of batch files for easily executing the script, one for turning off (suspend) all VMs, one for a SP2010 team and one for the SP2013 team. It’s a one-liner bat file that will work with both PowerShell 2 and 3, with or without UAC.

    To Start my SP2010 team (StartSP2010Team.bat):

    powershell -noprofile -command “&{ start-process powershell -ArgumentList ‘-noprofile -file %~dp0SetRunningVMs.ps1 \”AD01\” \”Dev1\”‘ -verb RunAs}”

    (where you replace the bold VM names above with your own)

    To start my SP2013 team (StartSP2013Team.bat)

    powershell -noprofile -command “&{ start-process powershell -ArgumentList ‘-noprofile -file %~dp0SetRunningVMs.ps1 \”AD02\” \”SP2013\”‘ -verb RunAs}”

    To stop all VMs

    powershell -noprofile -command “&{ start-process powershell -ArgumentList ‘-noprofile -file %~dp0\SetRunningVMs.ps1′ -verb RunAs}”

If you have UAC enabled (as I do) you will be prompted, otherwise it will just suspend/resume the relevant VMs.

It took about two hours to write the scripts, where the hardest part was getting the batch files properly in shape with escape characters and UAC.

You gotta love PowerShell ;-)

Supercharge your (Resource) Efficiency with Macros


This is part 4 of 4 in a series on how to improve the way we usually work with resource (resx) files.

I generally like to – and do – use resource files for all string constants that are shown to end-users, however I do feel that it is needlessly cumbersome, therefore these posts:

  1. A Good Way to Handle Multi Language Resource Files
  2. Verify that your Resource Labels Exists
  3. Find/Remove Obsolete Resource Labels
  4. Supercharge your (Resource) Efficiency with Macros (this one)

Generally these issues are generic to .NET and not specific to SharePoint, though that is where I’m spending my time writing this.

What is it again?

This is a macro to increase developer productivity. It is a topic that lies very close to my hearth and a healthy fraction of my posts are about automation and productivity. Every developer should really know the macro features especially the record/play shortcuts.

Working with resources (in SharePoint) is actually quite tedious – we write “$Resources:” a thousand times and occasionally cannot be bored and skip the chore.

This is simple a Visual Studio macro to improve that workflow, usage is:

1. You highlight a string

2. Press a shortcut (of your choice)

3. Write a name for the resource key to create(optionally use an existing if one exists with same value)

4. And you’re done.

It will then add the resource key to your existing resx file, it will type in “$Resources:….” as needed. If it’s an aspx/ascx file it will also throw in some “<%=” and “%>” tags.

(It works very well for xml files too.)

The Gory Detail

This is a VB macro script that took an inordinate amount of time to write mainly because the Visual Studio Macro object model (DTE) is one of the most hideous, awkward, APIs I’ve ever worked with. If there is one place the VS team could improve it would be here – the macro IDE is also tedious to work with.

I’m very certain that there are ways to make the code perform better (speed is fine) and look better (is it important?) – let me know your nuggets in the comments it’s always good to learn something new.

What you need to know is:

  1. It looks for a resx file with the same name as the target name of your project, i.e. the dll/wsp name
    • It only works on the culture independent resx file
    • It even adds a comment in the resource file as to where a key was first used J
  2. It works only for text editor windows
    • I have not found a way to make the selection work in the designer windows, specifically the feature designer would have been nice. This is annoying.

      The workaround is to simply choose to open the .feature file in the “XML (text) editor” (choose “Open with” in the file open dialog)

  3. You may need to customize the replacement pattern for cs and as?x files as it calls a simple utility method “ResourceLookup.SPGetLocalizedString” to translate the “$Resources:…” key (see code below)
  4. It handles quotes in/around the selection

At the moment it is only tested with VS2010 – I’m certain that changes need to be made for VS2013. In due time…

The resource lookup method I’m using is:

        public static string SPGetLocalizedString(string key)
        {
            if (!key.StartsWith("$Resources:"))
            {
                return key;
            }
            var split = key.TrimEnd(';').Remove(0, "$Resources:".Length).Split(',');

            if (split.Length != 2 || string.IsNullOrEmpty(split[1]))
            {
                return key;
            }

            return SPUtility.GetLocalizedString(key, split[0], (uint)System.Globalization.CultureInfo.CurrentUICulture.LCID);
        }

Download and Installation

It is simple:

  1. Download the Macro project here
  2. Dump it somewhere on your disk – the usual location is in “Documents\Visual Studio 2010\Projects\VSMacros80″
  3. Choose “Tools / Macros / Load Macro Project” and pick the DGMacros.vsmacros file
  4. Bind a keyboard shortcut for the text editor to the macro. Just write “dgm” in the search box and pick the “ReplaceStringWithResource” macro

  5. Have a try and perhaps a look at point 3 of the gory details above ;-)

Find/Remove Obsolete Resource Labels


This is part 3 of 4 in a series on how to improve the way we usually work with resource (resx) files. At least the way my team and I work with them.

I generally like to – and do – use resource files for all string constants that are shown to end-users, however I do feel that it is needlessly cumbersome, therefore these posts:

  1. A Good Way to Handle Multi Language Resource Files
  2. Verify that your Resource Labels Exists
  3. Find Obsolete Resource Labels (this one)
  4. Supercharge your (Resource) Efficiency with Macros

Generally these issues are generic to .NET and not specific to SharePoint, though that is where I’m spending my time writing this.

So – Near the End of the Project – are those Resource Entries Still in Use?

The issue at hand is that you have hundreds of source files of various flavors and they are sprinkled with references to a number of resource files. When code is refactored or just deleted what happens to old resource labels? Likely nothing at all.

Are you happy with a ton of useless resource entries no longer in active use? What if you had to translate it to a couple of languages?

Quite obviously this is no biggie code/quality wise, but still…

The answer is that you run the PowerShell script below, that’ll check – and optionally fix – it ;-)

The Script

I made a small script to check and remove the excess resource entries to slim down those resource files a bit.

The script will, given a starting location (i.e. the root folder for your solution)

  1. Go through every code file (to be safe every file, except a list of binary extensions) and look for resource labels of the form “$Resources:filename,label_key
  2. Search recursively for resx files
  3. For every one of those resx files it will look through the resource labels in use and flag those that it cannot find
  4. (Optionally) Do a “safemode” check where every file is searched for the resource label, i.e. necessary if you are using multiple/other resource lookup methods then the $Resource moniker
  5. (Optionally) If you choose you may remove them automatically but do make a dry run first to sanity check that you got the paths right and that you have all the source files to be searched

Usage:

    PS> & VerifyResxLabels.ps1 “path to solution dir” [-remove] [-safemode]

(Tip: Download the script to somewhere, write an ampersand (&) and then drag the ps1 file into the PowerShell window and then drag the solution folder to the window.)

You’ll definitely want to pipe the output to a file.

Limitations

There are obviously some limitations

  • It will not: Check out the resx files from source control (but it will show the file error in the output)
  • It will not: Respect commented out code – it’s simple pattern matching so commented out code will be treated as actual code (hardly an issue)
  • Safemode is very slow of necessity and will likely find false positives, i.e. it will play it safe and keep entries that exists in some files, even though the same label may be used in a completely different context
    • It’s an (O(n*m) algorithm, with number of files and number of labels) – My test with 1000 unique labels, 28 resx files and 2400 files it takes a night

Download the script here

Verify that your Resource Labels Exists


This is part 2 of 4 in a series on how to improve the way we usually work with resource (resx) files. At least the way my team and I work with them.

I generally like to – and do – use resource files for all string constants that are shown to end-users, however I do feel that it is needlessly cumbersome, therefore these posts:

  1. A Good Way to Handle Multi Language Resource Files
  2. Verify that your Resource Labels Exists (this one)
  3. Find Obsolete Resource Labels
  4. Supercharge your Resource Efficiency with Macros

Generally these issues are generic to .NET and not specific to SharePoint, though that is where I’m spending my time writing this.

So, are you sure that your Resource Labels Exists?

The issue at hand is that you have hundreds of source files of various flavors and they are springled with references to a number of resource files. Usually only one for each project/wsp though.

So how can you be sure that you don’t use one in your code that isn’t defined in your resource file?

As missing resource labels are just output verbose to the end user/application this can be a major issue.

The answer is that you run the PowerShell script below, that’ll check it ;-)

The Script

I made a small script to check for resource labels after a major code rewrite that had me change literally hundreds of labels.

The script will, given a starting location (i.e. the root folder for your solution)

  1. Search recursively for resx files and store their locations
  2. Go through every code file (.xml, .cs, .vb, .as*x, .webpart, .dwp, .feature) and look for resource labels of the form “$Resources:filename,label_key
  3. For every one of those resource keys it’ll open the corresponding resx file and check that the key is present and write a warning to the console if not

Obviously this takes a minute or two – in my current project with 8500 files (including everything) it takes about 1 minute to complete (a VM on a power laptop) which is completely acceptable as you don’t really need to run it that often.

Enterprising people may want to add it to the buildserver’s list of tests. I haven’t found the need or the time yet ;-)

Usage:

    PS> & VerifyResourceLabelsExists.ps1 “path to solution dir

(Tip: Download the script to somewhere, write an ampersand (&) and then drag the ps1 file into the PowerShell window and then drag the solution folder to the window.)

Sample output:

Searching for resx files
Searching for labels
Parsing resx files
Checking labels
Warning: Could not find $Resources:Delegate.XXX.XXX,ContentType_XXX_Description in file C:\Dev\TFS\xxxx\Elements.xml
Warning: Could not find $Resources:Delegate.XXX.XXX,ListDefinition_XXX_Heading in file C:\Dev\TFS\xxxx\Schema.xml
...
 

You’ll likely want to pipe the results to a file and then run through your source files to add the missing labels (see part 4, when I finish it).

What it does not do

There are obviously some limitations. It will not

  • Add the missing labels for you
  • It simply looks at files. If you have some files that are excluded from your project files they will be counted in regardless
  • It simply does pattern matching – code commented out is still included by the script
  • It always works of the default non-language specific resx file – the task of ensuring that all labels are defined in all languages is a fairly simple xml comparison for which tools exists
  • Handle default resource files, i.e. the case where you define a default resource file in your feature.xml files and then use the “$Resources:label_key” shorthand with no file name

Download the script here

A Good Way to Handle Multi Language Resource Files


If you are working with SharePoint you should also be using ressource (resx) files in your projects.

The problem is that SharePoint is quite annoying in the way it handles fallback to the default language resx when there is no culture specific version.

For instance in a Danish site it will look for MySolution.da-DK.resx and fallback to MySolution.resx if it isn’t o found.

Nice.

The Problem

However SharePoint will spam your ULS log with messages like:

04/20/2012 13:56:37.25     w3wp.exe (0x3758)     0x344C    SharePoint Foundation     General     b9y9    High     Failed to read resource file "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Resources\MySolution.da-DK.resx" from feature id "(null)".    5b6991c9-5b39-4c95-b895-ed282bc00034 
04/20/2012 13:56:37.25     w3wp.exe (0x3758)     0x344C    SharePoint Foundation     General     8e26    Medium     Failed to open the language resource keyfile MySolution.    5b6991c9-5b39-4c95-b895-ed282bc00034 
04/20/2012 13:56:37.25     w3wp.exe (0x3758)     0x2C94    SharePoint Foundation     General     b9y3    High     Failed to open the file 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Resources\MySolution.da-DK.resx'.    492a45e8-e416-4321-a83a-12f56c0341c1 
04/20/2012 13:56:37.25     w3wp.exe (0x3758)     0x2C94    SharePoint Foundation     General     b9y4    High     #20015: "" kan ikke åbnes: Filen eller mappen findes ikke.    492a45e8-e416-4321-a83a-12f56c0341c1 
04/20/2012 13:56:37.25     w3wp.exe (0x3758)     0x2C94    SharePoint Foundation     General     b9y4    High     (#2: "" kan ikke åbnes: Filen eller mappen findes ikke.)    492a45e8-e416-4321-a83a-12f56c0341c1 

And to make matters worse they are actually marked with “high” importance. In my mind this is a very normal way to code (for non-SharePoint projects) and should certainly not be marked with high importance. For now I am forced to look for the “unexpected” importance instead when troubleshooting.

The Simple Fix

There are a number of ways to correct this, I chose:

  1. Delete the duplicate localized version (MySolution.da-DK.resx) from source control
  2. Add a prebuild event to copy MySolution.resx to MySolution.da-DK.resx
    1. Write something like ‘copy /Y “$(ProjectDir)Resources\$(TargetName).resx” “$(ProjectDir)Resources\$(TargetName).da-DK.resx” ‘ (change to suit your needs and ensure quotes are not html mangled)
  3. Make sure to include MySolution.da-DK.resx in the project and mark it with “Build Action: Content”, “Copy to Output Directory: Do not copy”.
  4. Choose to exclude MySolution.da-DK.resx from Source Control in Visual Studio (File / Source Control / Exclude …)

    (otherwise Visual Studio will likely face write protected files)

All in all it should look somewhat like this:

Resx handling in the project

Other Ways

Other possible solutions would be to symbolic soft/hard link to the file (mklink.exe), however care should be taken as TFS really don’t like symbolic links.

The trick with exclusion from source control would likely work too, however a file copy just seemed like a simpler solution…

Another creative way would be to mess around with the packaging options it’s likely possible.

How to Make List Items Visible to Anonymous Users (in Search)


I had a funny little issue with showing list items from a custom list (with a custom view form) to anonymous users on a publishing site.

My good colleague Bernd Rickenberg insisted that I blogged the resolution since he had found quite a few post detailing the problem but no viable solutions ;-)

The Issue

You want to show a custom list to anonymous users. In our setting it was through search, your use case is likely different, but the issue remains the same with or without search.

Quite simply forms (List forms) are generally not accessible to anonymous users when you have the lockdown feature enabled (ViewFormPagesLockdown). It is a critical feature to have enabled otherwise you expose way too much information to SharePoint savvy users. Many of the solutions to this issue suggest turning it off.

It is fairly simple to test if you have this problem. Start Firefox, assuming that you have not enabled the NTLM auto login setting, and hit the …/DispForm.aspx page for a specific item. If you receive the login prompt as anonymous in Firefox and sail through when logged in this blog is for you.

If the ordinary publishing pages are also not viewable then this blog is not for you.

Note: Never use IE to test for anonymous access or not, I can’t count the number of times it has tricked consultants into thinking it works because they are tricked by the auto login feature while on the corporate network.

The Resolution

Is fairly simple.

The basics for search is that the list must be made searchable (it is by default) in the list settings, anonymous users must have access rights to the site and the lockdown feature should(!) be enabled.

What the lockdown feature does is that it changes the anonymous permission mask at the root site (which is inherited by all by default). The mask is basically the permission level assigned to all anonymous users and is similar to the normal permission sets – but is not editable in the UI.

The “View Application Pages” permission level is removed, see the image below on where to find it (for non-anonymous users):

Permission level settings page

Permission level settings page – not available for anonymous users

The best option, security wise, is to break the permission inheritance for your particular list and then add the “View Application Pages” permission to the anonymous users. Do not do that at the web level as you do not want to expose e.g. All site content etc.)

The Script

You need to run the following the PowerShell commands on one of your servers (replace url and list name):

$web = get-spweb "http://yoursiteurl/subweb/subsubweb" 
$list = $web.Lists["ListName"]
$list.BreakRoleInheritance($true)
$list.AnonymousPermMask = $list.AnonymousPermMask -bor ([int][Microsoft.SharePoint.SPBasePermissions]::ViewFormPages) #binary or adding the permissions
$list.Update()
 

(Note: Do be careful if copying directly from this page to PowerShell – you need to re-type the quotes as WordPress mangles them)

SharePoint Advanced Large Scale Deployment Scripting – “Features” (part 2 of 3)


I have been battling deployments for a while and finally decided to do something about it.

;-)

The challenge is to handle a dozen WSP packages on farms that host 20-50 web applications (or host header named site collections) to complete the deployments in a timely manner, ensure that the required features are uniformly activated every time while minimizing the human error element of the poor guy deploying through the night.

The deployment scripts require PowerShell v2 and are equally applicable to both SharePoint 2007 and 2010 – the need is roughly the same and the APIs are also largely unchanged. Some minor differences in service names are covered by the code.

To keep this post reasonable in length I’ve split the subject into three parts:

Part 1 is the main (powershell) deployment scripts primarily targeted at your test/QA/production deployments

Part 2 is the scripts and configuration for automatic large scale feature activations

Part 3 is about gold-plating the dev/test/QA deployment scenario where convenience to developers is prioritized while maintaining strict change control and records

Note: This took a long time to write and it will likely take you, dear reader, at least a few hours to implement in your environment.

If you have not done so already read “Part 1″ first and excuse me for a bit of duplicated text.

It’s all about the Features

This part is about features and managing their (de-)activations.

What you can do with this is:

  • Maintain a set of templates (“FeatureSets”) that defines what features should be activated on a given type of site – the scripts then ensures that they are properly activated
  • Set actions for features to be either activate, deactivate or reactivate through the configuration file
    • It safely handles web.config updates so that the scripts do not enter a race condition with the SharePoint timer service
  • Selectively override the default behavior and reactivate certain features when you need to

In other words you can ensure that your features are properly activated across sites and farms.

A note on reactivation is in order here. Reactivation is (force) deactivation and followed by activation which is particular useful for features that updates files in document library, e.g. masterpages. Some features require it when they have been updated but it is very rare that a feature always require reactivation.

Therefore I usually do not specify any features to always be reactivated in the configuration file, however if I know that we updated the masterpages I’ll update the batch file, or supply an additional one, where that feature is forced reactivated. The safe option of always reactivating is simply too slow if many files are deployed (or lengthy feature receivers) are involved.

The Configuration

The scripts work based on a configuration file that is shared between your dev, test, QA and production environments.

The procedure is:

  1. Identify all valid Sites/URLs in the local farm (i.e. always executed on one of the servers in the farm)
  2. For each site/URL go through all Feature sets and ensure activations, deactivations and reactivations required
    1. Keep track of reactivations so same feature is only reactivated once at each scope, i.e. overlap between FeatureSets are allowed as long as they specify the same action
    2. Report inconsistencies as errors, but do continue with the next features so that you can have the complete overview of all errors at the end of the run

A sample configuration file is (note: I just picked some more or less random WSPs from codeplex):

<?xml version="1.0" ?>
  <Config>
    <Sites>
      <!-- note: urls for all environments can be added, the ones found in local farm will be utilized -->
      <!-- DEV -->
      <Site url="http://localhost/">
        <FeatureSet name="BrandingAndCommon" />
        <FeatureSet name="Intranet" />
      </Site>
      <Site url="http://localhost:8080/">
        <FeatureSet name="BrandingAndCommon" />
        <FeatureSet name="MySite" />
      </Site>
      <Site url="http://localhost:2010">
        <FeatureSet name="CA" />
      </Site>
      <!-- TEST -->
      <Site url="http://test.intranet/">
        <FeatureSet name="BrandingAndCommon" />
        <FeatureSet name="Intranet" />
      </Site>
      ...
      <!-- PROD -->
      <Site url="http://intranet/">
        <FeatureSet name="BrandingAndCommon" />
        <FeatureSet name="Intranet" />
      </Site>
      ...
    </Sites>

    <FeatureSets>
      <FeatureSet name="BrandingAndCommon">
        <Solution name="AccessCheckerWebPart.wsp" />
        <Feature nameOrId="AccessCheckerSiteSettings" action="activate" ignoreerror="false" />
        <Feature nameOrId="AccessCheckerWebPart" action="activate" ignoreerror="false" />
        <Solution name="Dicks.Reminders.wsp" />
        <Feature nameOrId="DicksRemindersSettings" action="activate" ignoreerror="false" />
        <Feature nameOrId="DicksRemindersTimerJob" action="activate" ignoreerror="false" />
        <!-- Todo - all sorts of masterpages, css, js, etc. -->
      </FeatureSet>
      <FeatureSet name="Intranet">
        <Solution name="ContentTypeHierarchy.wsp" />
        <Feature nameOrId="ContentTypeHierarchy" action="activate" ignoreerror="false" />
      </FeatureSet>
      <FeatureSet name="MySite">
      </FeatureSet>
      <FeatureSet name="CA">
      </FeatureSet>
    </FeatureSets>

    <Solutions>
      <!-- list of all solutions and whatever params are required for their deployment -->
      <Solution name="AccessCheckerWebPart.wsp" allcontenturls="false" centraladmin="false" upgrade="false" resettimerservice="false" />
      <Solution name="ContentTypeHierarchy.wsp" allcontenturls="false" centraladmin="false" upgrade="false" resettimerservice="false" />
      <Solution name="Dicks.Reminders.wsp" allcontenturls="true" centraladmin="false" upgrade="false" resettimerservice="true" />
    </Solutions>
  </Config>

Where the interesting bits are that Sites contain a number of named FeatureSets. The FeatureSets are gathered in their own section (for reusability) and defines a number of solutions to be deployed and the features to be handled. It is good practice to list the solutions for the features that you are working on so you can be sure that the solution deployment matches your features. Do not spend time on noting all the SharePoint system features to be activated as they are normally handled just fine by the Site Definitions.

Each feature activation line looks like:

<Feature nameOrId=”AccessCheckerWebPart” action=”activate” ignoreerror=”false” />

Where nameOrId is either the guid (with or without braces, dashes etc.) or the name of the feature, i.e. the internal name in the WSP packages, not the display name. When possible I always opt for flexibility ;-)

The action attribute is either “activate”, “deactivate” or “reactivate”.

The ignoreerror is simply a boolean true/false switch that determines how the error should be logged if the feature fails to be activated. It is quite usable for the occasional inconsistencies between environments, e.g. if you are removing a feature then it might be present in production but no longer in the test environment. The script continues with next feature in case of errors regardless of this switch.

It is important to note that web scoped features are not supported here, “only” farm, web app or site scope is allowed.

The features are activated in the order that they are present in the config file.

The Scripts

There are two sections here:

  1. A number of SharePoint PowerShell scripts that include each other as needed
  2. A few batch files that start it all. I generally prefer to have some (parameter less) batch files that executes the PowerShell scripts with appropriate parameters

I have gold-plated the scripts quite a bit and created a small script library for my SharePoint related PowerShell.

The PowerShell scripts are too long to write in the post, they can be downloaded here. The list is (\SharePointLib):

*(Part 1) DeploySharePointSoluitions.ps1: Start the WSP deployments. Parse command line arguments of config file name and directory of WSP solutions

*EnsureFeatureActivation.ps1: Start the feature activation scripts (need command line arguments)

*(Part 3) QADeploymentProcess.ps1: Deployment process for dev, test and QA environments (need command line arguments)

SharePointDeploymentScripts.ps1: Main script that defines a large number of methods for deployment and activations.

SharePointHelper.ps1: Fairly simple SharePoint helper methods to get farm information

*RestartSharePointServices.ps1: Restart all SharePoint services on all servers in the local farm

Services.ps1: Non-SharePoint specific methods for handling services, e.g. restarts

Logging.ps1: Generic logging method. Note that there are options for setting different log levels, output files, etc.

The ones with an asterisk are the ones that you are supposed to execute – the others just defined methods for the “asterisk scripts”.

The batch files (same download) (root of zip download):

(Part 1) 01 Deploy Solutions.bat: Start the solution deployment. It will deploy all the WSP files dropped in “\SolutionsDropDir\” that are also specified in the “\DeploymentConfig.xml”:

02 Activate Features.bat: Works with the “\DeploymentConfig.xml” file and ensures that all features are activated.

In other words you’ll execute “02 Activate Features.bat” to ensure that all features are activated in your farm.

The important line in 02 Activate Features.bat file is

powershell.exe -File “SharePointLib\EnsureFeatureActivation.ps1″ “%config%” “” >>ActivateFeatures.log

And if you need to reactivate your branding features (masterpages) you can just copy the batch file and change the line to something like:

powershell.exe -File “SharePointLib\EnsureFeatureActivation.ps1″ “%config%” “BrandingMasterPages,BrandingCSS,BrandingPageLayouts” >>ReactivateFeatures.log

to force the three (made up) features “BrandingMasterPages”, “BrandingCSS” and “BrandingPageLayouts” to be reactivated.

By default you will get one log file from each batch file named after the operation, one log file with a timestamp and in case of any errors an additional error log with the same timestamp. In other words if the error log file is not created then no errors occurred.

Runtimes

The scripts are quite fast and the time to execute is determined by the time it takes to activate the features within SharePoint. Therefore if the script has nothing to do, i.e. all features are activated as they should, then it’s normally less than 1 minute to check everything and return.

What usually takes time is features with many files to be added to document libraries (branding) and features that modify the web.config as we wait for the timer job to complete (assuming that the API is used to do this).

Closing Notes

The scripts write quite a bit of logging that can be daunting (especially if you set it to verbose) but don’t worry – I rarely look at them anymore. Instead I look for the EnsureFeatureActivation_date_error_log. If it’s not there then no error occurred and no reason to look into the log files.

These scripts have been a huge benefit for our deployment in order to reduce the post-deployment errors and fixes. It is however also the first to be blamed for errors whenever some feature does not behave as intended (“the unghosted file is not change that must be the fault of the deployment scripts”) and it rarely is the source of the error.

They can be blamed for being a bit complicated though and that is a fair point. If you don’t understand what they do and how you shouldn’t use them.

If you make some brilliant changes then let me know so I can include it in my “official” version.

Please also leave credits in there so it’ll be possible for your successors to find the source and documentation.

Download

Grab the scripts here.

Note: Updated Aug 29 2011.

VMWare or Hyper-V for Virtualization?


On every project I work we use virtualized development machines. It is almost a requirement for SharePoint development and I would recommend it to all over physical servers, simply to keep matters (projects) separate and to avoid the inevitable pollution of any dev environment.

So the question always becomes which technology should I choose? VMWare or Hyper-V?

Traditionally I’ve always opted for VMWare as it sports more features and has less operating system requirements. I’ve used VMWare Server GSX, 1 and 2 and Workstation 4 till 7 (I try to avoid the Player). VMWare basically runs on everything (but requires some CPU support to virtualize 64 bit Guest OS) while (latest) Hyper-V requires Windows Server 2008 R2.

So I finally found some time to sit down and compare the two. Now there are a lot of variables here so I’ve cut it down to me being interested in getting the most out of the Virtual Machine in terms of performance of the Guest OS. I do not test how well it works for multiple servers, how it works for databases etc.

I compare VMWare Workstation to Hyper-V, one is a program the other a server like thingy. It might be an apples and oranges comparison however it is the choice I would usually have when working in SharePoint. Price does not matter to me – my time does.

Setup

I’ve recently reinstalled my desktop computer with Windows Server 2008 R2 x64 (SP1) and configured it to be usable as a desktop operating system. I’ve basically enabled all the features to make it look and behave almost as Windows 7 and giving me the additional option of having fun with Hyper-V.

I highly recommend looking Shinvas posts (part 1 and 2) for the how to – it is by far the better option virtualization or not.

Hardware

This is a modest PC a few years old:

CPU: E8400, 1 CPU, 2 Cores, 3 GHz

Mem: 1.111 GHz DDR3, 6 GB

Disk: Three 2 x Raid 0 (bad planning in HD buys resulted in three not one raid drive)

Software

Host is running Windows Server 2008 R2 x64 sp1.

I’ve enabled the Hyper-V role and configured it appropriately. After that I found that you cannot have both Hyper-V enabled and install/run VMWare workstation as they both come with their own version of a Hypervisor, though VMWare’s runs on top of the OS and Hyper-V the other way around. That can be solved with a dual boot configuration to the same system, one with Hyper-Vs Hypervisor (phew) enabled and one without (here).

VMWare is VMWare workstation 7.1.4.

For performance testing I used SiSoftware Sandra 2011 sp2c which should be well known and reliable. I’ve used HDTunePro for disk measurements though because Sandra was very unreliable for that (I don’t believe in x10 increase in speed just because the disk is now virtual).

Virtual Machines

I’ve unpacked an old favorite VM of mine originally made with VMWare Workstation that is a full SharePoint 2010 single server development box with SharePoint, SQL, Office and Visual Studio (though no AD). It includes VMWare tools.

I removed all snapshots and converted it to a Hyper-V VHD with VMHD to VHD (ancient tool that still works perfectly) and created a new VM for Hyper-V from that. Removed remnants of VMWare and installed the integration service components that come with Hyper-V. Also ensure that no differencing disk is in play.

The two VMs are therefore picture perfect identical and I’ve seen no issues due to the conversion at all.

I’ve executed a number of tests and on both VMWare and Hyper-V you’ll receive (by far) the best performance if you match the number (and type) of virtual CPUs with the physical numbers on the host. Therefore the VMs are configured to use 2 CPUs (Hyper-V: 2 CPUs, VMWare: 1 CPU two cores).

Results

We need some graphs! In a minute… J

To understand the following you need to understand that enabling Hyper-V installs the Hypervisor which will then slow down the host machine even when Hyper-V is not used. Your host will act as a kind of pseudo virtual machine.

Therefore I compare the following configurations:

  1. Base: Host with no hypervisor (i.e. Hyper-V disabled)
  2. Host with with hypervisor/Hyper-V
  3. Hyper-V Virtual Machine
  4. WMWare Virtual Machine, normal priority
  5. VMWare Virtual Machine, high priority

What is interesting is the performance numbers compared to the bare host and the goal is to get as close to 100% as possible.

What is measured? I’ve taken a cue from a benchmarking post at Capitalhead (excellent post!) and I’ve measured

  • “Processor Cryptography”, basically core CPU performance
  • “Processor Arithmetic” CPU performance for floating point calculations
  • “Memory Bandwidth”
  • “Disk” / “File System Performance” – to keep it simple just the average amount of data transferable is measured. Note: This measurement has been very hard to get a reliable figure for, so I’ve used both Sandra and HD Tune Pro.

Every measurement was repeated 3-5 times and averaged (took quite a while L).

The following graph is the sum of it all measured relatively to the base performance numbers, i.e. I do not consider the absolute numbers to be all that interesting:

There does not seem to be too much penalty on the host to have Hyper-V/hypervisor enabled only 6% in arithmetic. It’s somewhat better than Capitalhead, cause could be SP1, different hardware and measurement technique.

The Hyper-V VM performs consistently well in all categories, where VMWare lags a bit in the memory and arithmetic categories. Interesting the Hyper-V VM performs better than the host in arithmetic which is likely due to measurement inaccuracy.

VMWare priority seems to be of minor importance.

Conclusion

So the big question is what to choose.

From the performance test it is clear that the difference is really not that big. That means that no matter your choice it’ll work ;-) It also makes it a bit harder to choose.

Note that there are many variables and different hardware will likely have slightly different characteristics however I do believe the data is valid and representative.

Feature wise VMWare wins:

  • VMWare Workstation generally sports a lot more features than Hyper-V, the one I consider most important is the Snapshot trees that does nearly as developed in Hyper-V. Better networking support, shared folders, console drag and drop, ACE, unity, etc.
  • Hyper-V wins (in my mind) a bit on administration though I know that is because we’re comparing a server product with a workstation here, though the same conclusion is valid for the VMWare server as well (it definitely does not apply to any of their datacenter products). I’m a bit annoyed with the network support as it apparently does not support wireless network adaptors (ridiculous limitation that you need to use Internet Connection Sharing to get around). Once networking is running and you access the server through Remote Desktop the other stuff with drag and drop and shared folders does not matter.

Performance wise Hyper-V wins:

  • It is very impressive to only loose about 4% in performance (excluding the disk measurement) relative to the bare metal host – at the expense of the host
  • VMWare is naturally disadvantaged here as they do not have the option of penalizing the host and have to work on top of it. It simply is slower and the only way to remedy that is to install the full ESX server, which should have at least similar performance characteristics as the Hyper-V (at least of you only install Server 2008 Core)

For me I’ll choose Hyper-V from now on.

I like the performance and I can get around the feature limitations and I don’t care about Unity etc. That said I’ll likely continue to have a dual boot setup, just in case.

Automatic Fix of Pre Upgrade Issues (SharePoint 2007 to 2010)


Ever tried to run the PreUpgradeCheck command at your MOSS farm and received a frightening long list of issues that takes forever to solve manually?

If you are like me you refuse to do any manual work that takes more than 2 hours (and you’ll have to re-do it for every farm) – so I’ve tried to script all the required fixes. This is one of those posts that I’ve been working on for months so I hope you appreciate it – I’m a bit proud of the script at the end of the post.

The goal is to have a PowerShell (v1.0) script fix every one of those blocking issues you see in the PreUpgradeCheck report. On my own very messy (intentionally so!) farm with 40+ databases and site collections and a large number of solutions I’ve managed to fix all but the one about my operating system needing an upgrade to Server 2008. That one I’ll not work on ;-)

Going from:

To this:

Note: It will only work of you have installed SP2 and cumulative update from October 2009. At least. I recommend that you work of as new a version as possible.

WARNING

The script will remove invalid “stuff” from your sites so be absolutely sure that every solution that you care about is deployed to the farm – otherwise all features, files and webparts from missing solutions will be removed from the sites.

The script will also publish unpublished pages if they contain some of these invalid webparts.

I give you no warrenty – backup your farm first. I’m pretty sure I won’t mess it up though…

What it does

The script will check a number of things in your farm by working on the output of the “stsadm –o enumallwebs” command.

I use some direct SQL to get information out that is not possible through the API, but all modifications are done through the SharePoint 2007 API in a supported way only.

The script currently does 5 things:

Remove Invalid Webparts

(AKA: “The following web part(s) are referenced by the content, but they are not installed on the web server“)

This is the method I started with and by far the biggest timesaver.

It uses the “stsadm –o enumallwebs” to get a list of webparts that’s currently missing in your farm. They have been uninstalled at some point and are now those webpart with “Fatal Errors” on some of your pages. Some of the missing webparts are not even listed as failing with fatal errors (they have socalled “bad markup”) they are just listed on the page with and ID and no description (i.e. if you go to a given page and add “?contents=1″ to go to the webpart maintenance page).

Trouble is that there can be lots of these and there is no easy way to find all the pages.

This function will query the SQL for the pages where these webparts are (both the one with fatal errors and the ones with “bad markup”) and then remove them through the API. The offending pages will be published (if not already), whatever checkouts they may have been there is overridden, the webparts are removed and the page re-published.

It will take all pages not just the one in document libraries (i.e. those that came through features)

Note: I’m only handling the case of shared webparts I did not have any user specific webparts in my test farm so I’m uncertain how that will be handled.

Note2: I’ve copied the PublishListItem from some of Gary Lapointes excellent extentions and converted them to powershell. It seems that no one has been as thorough handling special cases as he.

Remove Orphaned Site Collections

(AKA: “Issue : Orphaned site collections“)

Site collections can get orphaned in a number of ways; the fix is simply to delete those.

You will not lose anything (new) as those sites were not accessible before anyway.

Remove Uninstalled/missing Features Activated at Web scope

Features that have been uninstalled at some point often linger in the content databases because they are still activated in some web or site. That activation is not deleted when the feature is removed though the feature will have no actual function anymore.

I wrote quite a bit on this a while ago.

The script will run through all those SPWeb’s and deactivate the offending features.

Note that I’m not crawling all webs in the site I only access those with missing features.

Remove Uninstalled/missing Features Activated at Site Collection Scope

(AKA: “The following feature(s) are referenced by the content, but they are not installed on the web server“)

Similarly features may be activated at site collection level and forgotten. In this case these features are not reported by the “stsadm –o enumallwebs” command and I have to run through every Site Collection in the farm to locate the features.

Remove Missing Setup Files

(AKA: “The following setup file(s) are referenced by the content, but they are not installed on the web server“)

After features have been uninstalled it is quite common that they forget to remove the files they installed on the farm. I suppose it’s just the way SharePoint works. If a feature installs a file in a document library somewhere changes are it will remain.

What are those files? Some examples are stuff in the style library, webpart gallery, master pages, page layouts, etc…

This method uses SQL to find where the missing files are still references and deletes them from the lists. It even deletes files that have been unghosted which could actually still be accessed because SharePoint has made a customized copy of it.

I’m still considering if it would be better to only remove the ones that are still ghosted.

Note: In my tests some page layouts could not be removed because they were still being referenced in the farm. That is clearly an error in my farm, however the script will not fix that. It really does require special handling by a human to decide what to do. I suppose it’s a good thing that they are not removed in this case as some things might otherwise break.

What it does not no

Out of scope of script:

  1. Fixing the OS version
  2. Fixing the database version

Sorry ;-)

How to Execute

First of all the script requires you to be site collection owner on every site collection, farm admin and have owner rights in every content and configuration database. Pretty much all you can get.

In the beginning of the script there is a few switches that you should know:

  • The logging level, set it to 3 to get lots of info: $verboseLevel = 3. Lower is less.
  • The “$whatif” ´switch. Set it to “$true” to have the script simulate a run but not change anything in your farm
  • The “$targetdb” that can limit the script to a single content database only. Blank equals all databases a name indicates one (note: Not the site name)

I’ve built in a lot of error handling and logging to let you know what’s going on.

Note that STSADM must be included in the path setting.

Recommended sequence of execution

Everything need to run on the SharePoint 2007 server and it must have (at least) PowerShell 1.0 installed.

  1. Backup all content databases. This is not optional. Easiest to use stsadm –o backup
  2. Use stsadm -o preupgradecheck
  3. Run script on one or all databases with the “whatif” statement set to true
  4. Check and recheck the output and verify that it looks correct to you.
    1. You may want to reduce the logging level a bit
  5. Run with $whatif set to $false, i.e. let it work!
    1. Depending on your confidence in me you can ask to work on only one database at a time
  6. Check the output!
    1. Errors and warnings will be written both to the output stream (what is piped down in your logfile) and on the screen
  7. Run preupgradecheck again and see the result J

Note to run the script use something like “powershell -file FixUpgradeIssues.ps1 >>fixupdateoutput.txt”, i.e. always pipe the output to a file that you can investigate later.

Runtime is about 5 minutes on my 40+ database test system so reasonably ok given the task.

I’ve been working on this script for a couple of months and have fixed a huge number of issues and funny edge cases; however I’ve likely missed a few. Let me know in the comments.

Good luck J

Download the Actual Script

All 850 lines of powershelling are not pretty in a blog post, so you can download it here.

[Updaet 25-12-2010: Now with correct file]

How to install a SharePoint 2010 Complete (Dev) Server without AD


This post details how you do install a SharePoint 2010 as a “complete” install without an AD, which is very useful to me as a development server (with or without Visual Studio).

This applies to both virtual and physical machines but I always work with VMs because traditionally SharePoint dev environments need to be re-installed once in a while and that’s easier with VMs.

Why would you want this?

  • A development server with all components is likely to resemble your test/QA/production environment a lot more than the alternative standalone install
  • A server with a local install of SharePoint with non-AD accounts can be run with or without an AD domain – you can even run the VM as a domain server disconnected from the actual domain e.g. at home or the commute
    • Alternative 1: Make your server an AD server but that changes all sorts of stuff with user management and will definitely not resemble any of your production servers
    • Alternative 2: Create two VMs one being the AD one being the actual development server connected on the same VLAN and waste a lot of resources for (almost) nothing.
  • To eliminate any need for rogue AD servers on your network that some develop accidently connected directly to the network and running DHCP, DNS etc. Don’t trust your developers or external consultants to care about your network!
  • I want a full SQL Server!

Why would you not want this?

  • This is not a supported development environment from Microsoft – they support installing a so-called standalone development environment without any of the frills. It’s easier and it’s officially supported. It’s even doable on Windows 7.
    • Why anyone would want to develop SharePoint on a Windows 7 machine is beyond me, the runtime environment for your code will always be a server 2008 so why not develop and test it directly on such a box? Surely you develop only in VMs so that you are able to create a clean dev environment easily once in a while…

How to

The procedure is fairly simple except for the final steps. Note that you can (and should) use whatever tools you can to help you out, I’ll point at the promising AutoSPInstaller at CodePlex.

Procedure:

  1. Create / install a Server 2008 (R2) 64 bit with
    1. Visual Studio 2010
    2. SQL Server 2008 (use a local user as service account)
    3. … and whatever other tools you are fond of …
    4. (Remember to sysprep/snapshot it at this stage)
  2. Install SharePoint 2010 with all prerequisites
    1. Scripted or not – do not run Config Wizard yet (It would result in “Local accounts should only be used in standalone mode” error)
  3. Create the farm by (trick #1)
    1. Start the SharePoint PowerShell
    2. Create a local service account
    3. Create a farm by running the “New-SPConfigurationDatabase” cmdlet and supply parameters for the service account, DB name, DB server and passphrase (thanks to Neil ‘The Doc’ Hodgkinson for that)
    4. After it finishes start the Config Wizard (interactive or not) and configure your server with all components
  4. Configure the farm services as you like
    1. I usually just use the wizard in Central Admin to configure all the Service Applications with some fairly useful values it works well enough
  5. Enterprise Search doesn’t work to fix it see below… (trick #2)

The Trouble with Search

Search will fail with a number of errors and in the search administration the Query Component will remain stuck in the initializing state:

The other bunch of event log errors etc. is listed at the end of this post for the benefit of Google.

As far as I can conjecture the problem is that the timer service is trying to setup a network share for every query component where the crawlers can dump their data. It is trying to setup that share with a domain account that happens to be a local user instead in this case and fails with either an “Access Denied” error or a “System.ArgumentException: The SDDL string contains an invalid sid or a sid that cannot be translated”.

The share name it’s trying to use is the same as the query role, i.e. “Guid-query-0″ pointing to (if using default locations) “C:\program files\Microsoft Office Servers\14.0\Data\Office Server\Applications” with change permissions for the “WSS_WPG” group.

Unfortunately it does not help to just create the share for it apparently the query components insist on waiting for the timer job to complete successfully. L

The Search Fix

The fix is fairly simple and almost completed by Gary Lapointe whom I owe great thanks for doing most of the hard work in his post on scripting the Enterprise Search installation and the comments below his post (thanks to Marco van Wieren).

The fix is simply to create and configure all the enterprise search components from PowerShell as it allows you to set a few more options, specifically the share name for the query components so that you are then allowed to create them yourself.

The script was originally made for configuring search components across an entire farm and therefore a bit more complicated than it strictly has to be. I left it in there while adding support for single server install as well. Gary’s script was made for beta 2 and I’ve fixed a few simple errors/typos, corrected the few API changes between beta 2 and RTM and finally added the share name support.

The script is quite long a not suitable for pasting into a blog – download instead.

The script needs a configuration file with something like this:

<Services>
    <EnterpriseSearchService ContactEmail="no-reply@SharePointDev1.com"
                             ConnectionTimeout="60"
                             AcknowledgementTimeout="60"
                             ProxyType="Default"
                             IgnoreSSLWarnings="false"
                             InternetIdentity="Mozilla/4.0 (compatible; MSIE 4.01; Windows NT; MS Search 6.0 Robot)"
                             IndexLocation="C:\Program Files\Microsoft Office Servers\14.0\Data\Office Server\Applications"
                             PerformanceLevel="PartlyReduced"
                             Account="localhost\saservice"
                             ShareName="SearchShare">

        <EnterpriseSearchServiceApplications>
            <EnterpriseSearchServiceApplication Name="Enterprise Search Service Application"
                                                DatabaseServer="localhost"
                                                DatabaseName="SharePoint_Search"
                                                FailoverDatabaseServer=""
                                                Partitioned="false"
                                                Partitions="1"
                                                SearchServiceApplicationType="Regular">
                <ApplicationPool Name="SharePoint Enterprise Search Application Pool" Account="localhost\saservice" />
                <CrawlServers>
                    <Server Name="localhost" />
                </CrawlServers>
                <QueryServers>
                    <Server Name="localhost" />
                </QueryServers>
                <SearchQueryAndSiteSettingsServers>
                    <Server Name="localhost" />
                </SearchQueryAndSiteSettingsServers>
                <AdminComponent>
                    <Server Name="localhost" />
                    <ApplicationPool Name="SharePoint Enterprise Search Application Pool" Account="localhost\saservice" />
                </AdminComponent>
                <Proxy Name="Enterprise Search Service Application Proxy" Partitioned="false">
                    <ProxyGroup Name="Default" />
                </Proxy>
            </EnterpriseSearchServiceApplication>
        </EnterpriseSearchServiceApplications>
    </EnterpriseSearchService>
</Services>

Remarks:

  • I replace “localhost” with the actual computer name in the script
  • The Share Name (here “SearchShare”) will be created by the script as well, so whatever you call it doesn’t matter
  • The config file shown can be reused on every machine provided that the local service account “saservice” has been created before

To continue and complete step 5 in the procedure above (sorry for the numbering wordpress is messing up the html):

  1. Start PowerShell shell (I will load the SharePoint snapin if it’s not a SharePoint Management Shell)
    1. Load the “SetupEnterpriseSearch.ps1″ script (just drag the file into the shell and execute) which will define the required functions
    2. Execute “Start-EnterpriseSearch “<path>\searchconfig.xml”"
    3. Wait for a few minutes and watch for errors
  2. Go to the Search Administration and verify that your new search topology works
    1. It should look something like this:

    2. If you configured search in step 4 you will have two
    3. If you have two you can safely go back to “Manage service applications” and delete the one named “Search Service Application 1″ (and associated databases) – the one created by the script is “Enterprise Search Service Application”
  3. Try it! Go to a local SharePoint site and search for something
    1. Before the search would return a server error 500 so anything else than that can be considered a success
    2. I like to add a few documents and have them show up in the search before I call it a success…

Caveats / Fast Search

Don’t know if it fair to call it a caveat however only the Enterprise Search is demonstrated here, the Fast Search behaves similarly in respect to the “share trouble” and will probably need the same fix as the enterprise search. I’ve not found the time or need to poke around with that just yet, but it should be doable in less than a day given the foundation above (for someone skilled in SharePoint and powershell).

Conclusions

It works; I’ll use it from now on :-)

… and I hope the nice chaps at AutoSPInstall will include this fix in their tool.

Scared of being in unsupported land?

  • It’s only your dev server and it did move a lot closer to production that the standalone dev machine option
  • It also protected your network from rogue AD servers that might potentially kill half your network if you are unlucky

So how well is this tested? Quite well for a single server install and not at all for a farm install (not by me at least). Trust it with the former and test it yourself if you need the latter.

Observed Errors

I got a lot of different errors, here they are for the benefit of Google.

Event log entry after completing the configuration wizard in Central Administration:

Log Name: Application
Source: Microsoft-SharePoint Products-SharePoint Server Search
Date: 11-06-2010 22:20:17
Event ID: 2579
Task Category: Administration
Level: Error
Keywords:
User: SHAREPOINTDEV1\saservice
Computer: SharePointDev1
Description:
Component a61ca0ca-194f-4cf0-bb5c-8ca998178935-query-0 of search application ‘Search Service Application’ has failed to execute transition sequence ‘initialize with empty catalog’ due to the following error: System.ArgumentException: The SDDL string contains an invalid sid or a sid that cannot be translated.
Parameter name: sddlForm
at System.Security.AccessControl.RawSecurityDescriptor.BinaryFormFromSddlForm(String sddlForm)
at System.Security.AccessControl.RawSecurityDescriptor..ctor(String sddlForm)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateShareSecurityDescriptor(String[] readNames, String[] changeNames, String[] fullControlNames, String& sddl)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateFileShare(String name, String description, String path)
at Microsoft.SharePoint.Administration.SPServer.CreateFileShare(String name, String description, String path)
at Microsoft.Office.Server.Search.Administration.QueryComponent.CreatePropagationShare(QueryComponent component)
at Microsoft.Office.Server.Search.Administration.QueryComponent.ExecuteCurrentStage(). It is now in state Uninitialized.
Event Xml:
<Event xmlns=”http://schemas.microsoft.com/win/2004/08/events/event“>
<System>
<Provider Name=”Microsoft-SharePoint Products-SharePoint Server Search” Guid=”{C8263AFE-83A5-448C-878C-1E5F5D1C4252}” />
<EventID>2579</EventID>
<Version>14</Version>
<Level>2</Level>
<Task>14</Task>
<Opcode>0</Opcode>
<Keywords>0×4000000000000000</Keywords>
<TimeCreated SystemTime=”2010-06-11T20:20:17.723875000Z” />
<EventRecordID>3926</EventRecordID>
<Correlation ActivityID=”{B1431F7E-1D0C-4CB7-B690-F0F016447FE4}” />
<Execution ProcessID=”956? ThreadID=”3484? />
<Channel>Application</Channel>
<Computer>SharePointDev1</Computer>
<Security UserID=”S-1-5-21-452889701-636363473-2591022535-1012? />
</System>
<EventData>
<Data Name=”string0?>a61ca0ca-194f-4cf0-bb5c-8ca998178935-query-0</Data>
<Data Name=”string1?>Search Service Application</Data>
<Data Name=”string2?>initialize with empty catalog</Data>
<Data Name=”string3?>System.ArgumentException: The SDDL string contains an invalid sid or a sid that cannot be translated.
Parameter name: sddlForm
at System.Security.AccessControl.RawSecurityDescriptor.BinaryFormFromSddlForm(String sddlForm)
at System.Security.AccessControl.RawSecurityDescriptor..ctor(String sddlForm)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateShareSecurityDescriptor(String[] readNames, String[] changeNames, String[] fullControlNames, String&amp; sddl)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateFileShare(String name, String description, String path)
at Microsoft.SharePoint.Administration.SPServer.CreateFileShare(String name, String description, String path)
at Microsoft.Office.Server.Search.Administration.QueryComponent.CreatePropagationShare(QueryComponent component)
at Microsoft.Office.Server.Search.Administration.QueryComponent.ExecuteCurrentStage()</Data>
<Data Name=”string4?>Uninitialized</Data>
</span
</EventData>
</Event>

And from the ULS log:

06/11/2010 22:20:17.72         OWSTIMER.EXE (0x03BC)         0x0D9C        SharePoint Server Search         Administration         fea9        Critical        Component a61ca0ca-194f-4cf0-bb5c-8ca998178935-query-0 of search application ‘Search Service Application’ has failed to execute transition sequence ‘initialize with empty catalog’ due to the following error: System.ArgumentException: The SDDL string contains an invalid sid or a sid that cannot be translated. Parameter name: sddlForm at System.Security.AccessControl.RawSecurityDescriptor.BinaryFormFromSddlForm(String sddlForm) at System.Security.AccessControl.RawSecurityDescriptor..ctor(String sddlForm) at Microsoft.SharePoint.Win32.SPNetApi32.CreateShareSecurityDescriptor(String[] readNames, String[] changeNames, String[] fullControlNames, String& sddl) at Microsoft.SharePoint.Win32.SPNetApi32.CreateFileShare(String name, String description, String path) at Microsoft.S…        b1431f7e-1d0c-4cb7-b690-f0f016447fe4
06/11/2010 22:20:17.72*        OWSTIMER.EXE (0x03BC)         0x0D9C        SharePoint Server Search         Administration         fea9        Critical        …harePoint.Administration.SPServer.CreateFileShare(String name, String description, String path) at Microsoft.Office.Server.Search.Administration.QueryComponent.CreatePropagationShare(QueryComponent component) at Microsoft.Office.Server.Search.Administration.QueryComponent.ExecuteCurrentStage(). It is now in state Uninitialized.        b1431f7e-1d0c-4cb7-b690-f0f016447fe4
06/11/2010 22:20:17.72         OWSTIMER.EXE (0x03BC)         0x0D9C        SharePoint Server         Unified Logging Service         2m1i        Verbose         Adding event 2579 (category: Administration, product: SharePoint Server Search) to spam monitoring list        b1431f7e-1d0c-4cb7-b690-f0f016447fe4
06/11/2010 22:20:17.72         OWSTIMER.EXE (0x03BC)         0x0D9C        SharePoint Server Search         Administration         djs2        Medium         SearchApi (): executing SetQueryComponent(d355048f-d4fa-4f31-88b0-342b5ed48e5c, null, null, null, null, Uninitialized, Uninitialized, null, -1, Failed, null, False, null, null, False, null)        b1431f7e-1d0c-4cb7-b690-f0f016447fe4

And another event log:

Log Name: Application
Source: Microsoft-SharePoint Products-SharePoint Foundation
Date: 12-06-2010 20:40:26
Event ID: 6398
Task Category: Timer
Level: Critical
Keywords:
User: SHAREPOINTDEV1\saservice
Computer: SharePointDev1
Description:
The Execute method of job definition Microsoft.Office.Server.Search.Administration.CrawlReportJobDefinition (ID 9529aace-a679-4fc9-ab8d-325780484cf0) threw an exception. More information is included below.
The search service is not able to connect to the machine that hosts the administration component. Verify that the administration component ’3147b99c-8f3a-41e9-a08b-296f930af877' in search application ‘Enterprise Search Service Application’ is in a good state and try again.
Event Xml:
<Event xmlns=”http://schemas.microsoft.com/win/2004/08/events/event“>
<System>
<Provider Name=”Microsoft-SharePoint Products-SharePoint Foundation” Guid=”{6FB7E0CD-52E7-47DD-997A-241563931FC2}” />
<EventID>6398</EventID>
<Version>14</Version>
<Level>1</Level>
<Task>12</Task>
<Opcode>0</Opcode>
<Keywords>0×4000000000000000</Keywords>
<TimeCreated SystemTime=”2010-06-12T18:40:26.553054700Z” />
<EventRecordID>4159</EventRecordID>
<Correlation ActivityID=”{6CED0041-2038-43E3-AB79-4DEFBB4216B3}” />
<Execution ProcessID=”1324? ThreadID=”1532? />
<Channel>Application</Channel>
<Computer>SharePointDev1</Computer>
<Security UserID=”S-1-5-21-452889701-636363473-2591022535-1012? />
</System>
<EventData>
<Data Name=”string0?>Microsoft.Office.Server.Search.Administration.CrawlReportJobDefinition</Data>
<Data Name=”string1?>9529aace-a679-4fc9-ab8d-325780484cf0</Data>
<Data Name=”string2?>The search service is not able to connect to the machine that hosts the administration component. Verify that the administration component ’3147b99c-8f3a-41e9-a08b-296f930af877' in search application ‘Enterprise Search Service Application’ is in a good state and try again.</Data>
</EventData>
</Event>

And one for foundation search:

Log Name:      Application
Source:        Microsoft-SharePoint Products-SharePoint Foundation
Date:          …
Event ID:      6398
Task Category: Timer
Level:         Critical
Keywords:
User:          …
Computer:      …
Description:
The Execute method of job definition Microsoft.Office.Server.Search.Administration.QueryTopologyActivationJobDefinition (ID de8eac2b-57db-4069-896d-747ae4fb35ed) threw an exception. More information is included below.
Topology activation was aborted because of System.ArgumentException: The SDDL string contains an invalid sid or a sid that cannot be translated.
Parameter name: sddlForm
at System.Security.AccessControl.RawSecurityDescriptor.BinaryFormFromSddlForm(String sddlForm)
at System.Security.AccessControl.RawSecurityDescriptor..ctor(String sddlForm)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateShareSecurityDescriptor(String[] readNames, String[] changeNames, String[] fullControlNames, String& sddl)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateFileShare(String name, String description, String path)
at Microsoft.SharePoint.Administration.SPServer.CreateFileShare(String name, String description, String path)
at Microsoft.Office.Server.Search.Administration.QueryComponent.CreatePropagationShare(QueryComponent component)
at Microsoft.Office.Server.Search.Administration.QueryComponent.ExecuteCurrentStage().
Event Xml:
<Event xmlns=”http://schemas.microsoft.com/win/2004/08/events/event“>
<System>
<Provider Name=”Microsoft-SharePoint Products-SharePoint Foundation” Guid=”{6fb7e0ce-52e7-47dd-997a-241563931fc2}” />
<EventID>6398</EventID>
<Version>14</Version>
<Level>1</Level>
<Task>12</Task>
<Opcode>0</Opcode>
<Keywords>0×4000000000000000</Keywords>
<EventRecordID>10895</EventRecordID>
<Correlation ActivityID=”{6E239D20-A2CD-45B4-AC87-4477A82558BB}” />
<Execution ProcessID=”2016? ThreadID=”2288? />
<Channel>Application</Channel>
<Computer>id1314</Computer>
<Security UserID=”S-1-5-21-30024279817-590149927-1659320300-1003? />
</System>
<EventData>
<Data Name=”string0?>Microsoft.Office.Server.Search.Administration.QueryTopologyActivationJobDefinition</Data>
<Data Name=”string1?>de8eac2b-57db-4069-896d-747ae4fb35ed</Data>
<Data Name=”string2?>Topology activation was aborted because of System.ArgumentException: The SDDL string contains an invalid sid or a sid that cannot be translated.
Parameter name: sddlForm
at System.Security.AccessControl.RawSecurityDescriptor.BinaryFormFromSddlForm(String sddlForm)
at System.Security.AccessControl.RawSecurityDescriptor..ctor(String sddlForm)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateShareSecurityDescriptor(String[] readNames, String[] changeNames, String[] fullControlNames, String&amp; sddl)
at Microsoft.SharePoint.Win32.SPNetApi32.CreateFileShare(String name, String description, String path)
at Microsoft.SharePoint.Administration.SPServer.CreateFileShare(String name, String description, String path)
at Microsoft.Office.Server.Search.Administration.QueryComponent.CreatePropagationShare(QueryComponent component)
at Microsoft.Office.Server.Search.Administration.QueryComponent.ExecuteCurrentStage().</Data>
</EventData>
</Event>

And finally from Gary’s blog (Marco van Wieren):

Component: 3b609311-67da-4df8-8c12-e597e9228dd3-crawl-0
Details:
The system cannot find the file specified. 0x80070002Propagation for search application 3b609311-67da-4df8-8c12-e597e9228dd3-crawl-0: failed to communicate with query server 3b609311-67da-4df8-8c12-e597e9228dd3-query-0.

Follow

Get every new post delivered to your Inbox.