Sep 26
SQL Reporting Services Subscriptions Not Firing Event Receivers

I recently build an event receiver for a document library that takes files added to a document library and republishes them to a different web application based on some custom rules.  On a side note I used an event receiver and not the Drop Off Folder or a second SQL Reporting Services Subscription because it didn't appear as though you could he Content Organizer Rules or subscriptions are sophisticated enough to publish to alternate web applications.

Anyways the event receiver was simple enough, and in testing when a document is added or updated, it was replicated to the correction location on the second web application perfectly.  After deploying the event receiver I noticed that when my subscriptions ran and published the files to the document library the event receiver didn't appear to fire, and the files were not replicated to the secondary location.  I went back to my development environment and set up a similar subscription, set a breakpoint in the event receiver, and attached my debugger to SharePoint and waited for the breakpoint to get hit.  Nothing!
I had to think about this for a bit and then realized that the subscriptions might run in a different service context.  Sure enough they do, in the SQL Reporting Services context.  So I attached the debugger to this process and the breakpoint was hit.  My problem was 2 fold.  First my code was using appSettings from the web.config to get a configurable variable for the second web applications URL.  Because the code was getting executed in the context of SQL Reporting Service, appSettings was referring to the ReportingServicesService.exe.config appSettings and not my web applications web.config appSettings where I had deployed the settings.  Secondly, I had use the SharePointLogger, part of the SharePoint Guidance Library to log errors to the ULS logs.  Again because the code was executed in the context of Reporting Services, the service account that was used didn't have permission to write to the ULS logs so I wasn't seeing these errors in the logs.
A quick background on why the code is getting executed in the Reporting Services context and not SharePoint.  Reporting Services is using the SharePoint API to publish the files.  Specifically Reporting Services is using the API call, SPFileCollection.Add() to add the file to the document library.  Internally in this method, the logic would need to check to see if there's any event receivers on this list, and if so call the event receiver, either synchronously or asynchronously depending on the event in question.  This is why the event receiver code needs to be generic enough that it can be run from any application that has the ability to call the SharePoint API, and also means event receiver code in DLL's need to be GAC deployed.

Aug 03
Microsoft Mouse Without Borders

In my role as a software developer and system administrator I've elected to haul around a laptop with me, specifically the Dell M6500 Mobile Workstation, so I have the versatility to work from where ever I happen to be when problems arise or creativity hits me. At both work and home I have a docking stations connected to monitors and keyboards so that I can easily dock my laptop and use it just like a regular computer. At home though, I also have a personal computer that I use for whatever, gaming, downloading, etc... but when I come home I remove my USB dongle for my keyboard and mouse from my desktop to my docking station and manually switch one of the inputs on my monitor. Now I know I could just go out and buy a KVM switch for $20 from where ever and problem solved, but most KVM's only support a single monitor, and the ones that support dual and triple monitors become costly and I've always been looking for something more elegant. Last night I found it.

Behold Microsoft Mouse without Borders. Developed by Microsoft employee Troung Do as part of the Microsoft Garage Projects essentially the software allows you to use one keyboard across multiple machines. What's great about this is now I can have one monitor allocated to each machine, but use the resources of both.

The beauty of a product like this though will quickly expand quickly opens possibilities for me though. The most promising is that my laptop only supports dual monitors. I'd love to have a third monitor, or maybe more if possible, and have tried the external USB video adapters but they often have problems displaying VM's without crashing or appear choppy. Now I can setup an additional desktop in my office, add more monitors to my setup, and use all of them seamlessly. I could even setup a test workstation that runs different environments like IE 6, 7 and 8 for testing changes before moving them to production. I currently use VM's to test this, which I would probably keep doing, but having a monitor with each browser would be awesome.

Anyways check it out. I should point out this is a Windows only solution, so if you're looking to interface between different OS' check out Synergy.

 

 

Jun 06
Word Automation Services - The file could not be converted - Error 65543

​So in my recent escapades with SharePoint 2010 I've been trying to play with the new Word Automation Services.  Microsoft was so kind to release a demo feature receiver that shows how you can quite easily use the new service to convert Microsoft Word documents to PDF documents when a document is added to a document library, but using that as a starting point you can theoritically convert them whenever you want tyou can easily adapt the sample to convert whenever and wherever you like in your custom SharePoint applications.

Now for the life of me I couldn't get this to work.  The event receiver would fire, everything looked great, no error messages in the Event Viewer or in the ULS logs, so I assumed I'd just have to wait, and wait, and wait some more.  But alas nothing was happening.  It appeared as though the Word Automation Services was just not working. 

So it was time to breakout LINQPad.  For those not familiar with LINQPad, it's a great asset for any developers toolbox that allows you to quickly execute .NET code.  I especially like this tool when trying to test out snippets of code against SharePoint that aren't working and I'm making lots of changes, as opposed to having to build and compile my code, deploy it to SharePoint, activate the features, and then run it everytime I make a change, LINQPad allows me to just run the code.  Anyways enough about LINQPad.

So using LINQPad I ported the event receiver code from Microsoft over, and I found another chunk of code that allows you to monitor the conversion status of the job.  Here's the code I used to convert the file, and monitor the status of the job.

 

// Create the site context
using (SPSite site = new SPSite(siteUrl))
{
	//Variables used by the sample code.
	ConversionJobSettings jobSettings;
	ConversionJob pdfConversion;
	string wordFile;
	string pdfFile;
	
	// Get the site context
	SPServiceContext context = SPServiceContext.GetContext(site);
	
	// Create the conversion job using the settings.
	var wordAutomationProxy = (WordServiceApplicationProxy)context.GetDefaultProxy(typeof(WordServiceApplicationProxy));
	
	// Initialize the conversion settings.
	jobSettings = new ConversionJobSettings();
	jobSettings.OutputFormat = SaveFormat.PDF;
		
	pdfConversion = new  ConversionJob (wordAutomationProxy, jobSettings);
	
	// Set the credentials to use when running the conversion job.
	pdfConversion.UserToken = site.RootWeb.CurrentUser.UserToken;
		
	// Set the file names to use for the source Word document
	// and the destination PDF document.
	wordFile = inputFileUrl;
	pdfFile = outputFileUrl;
	
	// Add the file conversion to the conversion job.
	pdfConversion.AddFile(wordFile, pdfFile);
	
	// Add the conversion job to the Word Automation Services 
	// conversion job queue. The conversion does not occur
	// immediately but is processed during the next run of
	// the document conversion job.
	pdfConversion.Start();
	
	Console.WriteLine("Conversion job started");
	ConversionJobStatus status = new ConversionJobStatus(wordAutomationProxy, pdfConversion.JobId, null);

	Console.WriteLine("Number of documents in conversion job: {0}", status.Count);

	while (true)
	{
		Thread.Sleep(5000);
		status = new ConversionJobStatus(wordAutomationProxy, pdfConversion.JobId, null);
		if (status.Count == status.Succeeded + status.Failed)
		{
			Console.WriteLine("Completed, Successful: {0}, Failed: {1}",
				status.Succeeded, status.Failed);
			ReadOnlyCollection failedItems =
				status.GetItems(ItemTypes.Failed);
			foreach (var failedItem in failedItems)
			{
				Console.WriteLine("Failed item: Name:{0}", failedItem.InputFile);
				failedItem.ErrorMessage.Dump();
				failedItem.ErrorCode.Dump();
			}
				
			break;
		}
		
		Console.WriteLine("In progress, Successful: {0}, Failed: {1}", 
			status.Succeeded, status.Failed);
	}
}

So after running this I got the following error message:

"The file could not be converted; it may be corrupt or otherwise invalid (the conversion process failed). Please try opening the file in Microsoft Word, resaving it, and then resubmitting the file for conversion. If this does not resolve the issue, contact your system administrator."

Error Code: 65543

So off to the internet to find out what this error code means, and if you're here, you probably found very little aside from the actual error message that the error code corresponds too, or vice versa.  So after several hours of reading through various information regarding permissions on accounts, databases, and sites, I finally stumbled upon a blog post by Jonation Beckett at nintex blogs.  He had mentioned that after SP1 was released, the Word Automation Service had been set to run in Sandboxed mode.  What does that mean, and why would Microsoft change it, I don't know, but I'd love to find out.  So he proposed disabling this by running the following PowerShell commands:

 

$sp = Get-SPServiceApplication | where {$_.TypeName.Equals("Word Automation Services")}  

$sp.DisableSandbox = $true 

$sp.Update()

So I tried this, but still nothing, and still the same error message when I re-ran the code.  But more so out of sheer anger than for any other reason I restarted the SharePoint Timer Service and issues an IISRESET command to see if cycling these would maybe pick up the changes made to the Word Automation Service.  ALAS, it did, and it worked, my first document was converted successfully.  Hopefully this will help someone else out, and if you have any insights as to why the Word Automation Service was changed to run in Sandboxed mode, please let me know.

**You can find the source code for the Microsoft Event Receiver here:

http://msdn.microsoft.com/en-us/library/ff181518.aspx

 

Mar 14
Configure Managed Accounts - Object reference not set to an instance of an object

​So while I was trying to configure a managed service account in SharePoint 2010 today I came across the error "object reference not set to an instance of an object" when I tried accessing the Configure Managed Accounts page (/_admin/ManagedAccounts.aspx).  After some research it turns out that the likely culprit here is enabling the automatic password reset on an account that is running in an Active Directory Environment that is set for Pre-Windows 2000 Compatible Access.  The automatic password reset feature is only available if your Active Directory environment is running is 2008 mode.

To resolve the error you need to open up the SharePoint Management Console (Powershell) and run the following command against your Farm Account.

$farmAccount = Get-SPManagedAccount domain\loginname
$farmAccount.AutomaticChange= $false
$farmAccountt.Update()

Jan 20
Getting a SPUser object in SharePoint
using (SPWeb web = new SPSite(SPContext.Current.Web.Url).RootWeb)
{
	SPUser user = web.EnsureUser("loginName");
}
Nov 30
Programatically Disabling Content Approval on a Page Library
private void DisableContentApproval(SPWeb web)
{
    SPList pagesLibrary = web.GetList("Pages");

    if (pagesLibrary != null)
    {
        pagesLibrary.EnableModeration = false;
        pagesLibrary.Update();
    }

    foreach (SPWeb subWeb in web.Webs)
    {
        DisableContentApproval(subWeb);
    }
}
Sep 30
Office 365 Blog – Word Cannot Register Your Account

When using the "Launch Blog Program to Post" feature in my Office 365 SharePoint Blog I encountered the following error in Microsoft Word.

Word cannot register your account.

To resolve this I needed to do things.

  1. Download the Desktop Extensions for Office 365. Office 365 uses a custom authentication mechanism which Word by default doesn't support. Installing the Desktop Extensions enables this support. You can download the extensions from your Office 365 Portal under the downloads section.
  2. After running the Desktop Extensions in your Start Menu you'll have a new shortcut for the Office 365 Portal. Open it.
  3. Under Team Site, select "Word" to create a new Word document.
  4. This will open a new window where you give the file a name. Provide a name and press "OK".
  5. The document will now open in Office Web Apps, but in the ribbon there will be an option to "Open in Word", select it.
  6. You'll now be asked by Microsoft Word to sign into Office 365. Sign in using your credentials.
  7. Now that you've signed in you can just close the document, and go back to your blog and select "Launch blog program to post"
  8. SharePoint will prompt you to enter the "New SharePoint Blog Account" information, just press OK.

You should now be able to post without any problems.

Sep 30
Fixing the Windows 7 Slow Logon – Waiting for the User Profile Service

Since moving to Windows 7 my work laptop has constantly been plagued with a slow logon when I'm not physically connected to my work network. The entire point of having a laptop is so that I don't need to be physically connected at my work desk all the time. Recently I've grown extremely tired of this so I started investigating.

So what's happening?

When I start up my machine I am presented with the login screen. Upon logging in it says Welcome, then switches to "Waiting for the User Profile Service" from anywhere between 60 and 90 seconds. I've read for most people it takes even longer, but I'm assuming the shorter delay on mine is due to the beefed up hardware I'm using. So the first thing I tried was checking out the Event Viewer for any indication in the logs that something was going wrong. I noticed a few information messages regarding Forefront and MOM not being able to connect to their respective proxies, but that makes sense considering the network hasn't been initialized yet, but no error messages. I also noticed the following message:

The winlogon notification subscriber <Profiles> took 67 second(s) to handle the notification event (Logon).

But this just confirmed what I already knew.

The Solution

Let's get to the point. After countless trial and error procedures including disabling service after service, startup programs, enabling verbose logging, and even going as far as creating new Organization Units in Active Directory with no Group Policies, I finally discovered the Holy Grail.

  1. Run > gpedit.msc
  2. Navigate to Computer Configuration > Administrative Templates > System > User Profiles
  3. Edit the policy "Set maximum wait time for the network if a user has a roaming user profile or remote home directory" to "Enabled" and set the value Wait for network for maximum (seconds) to 0.
  4. Press OK and close the Local Group Policy Editor.
  5. Run > cmd.exe
  6. Run gpupdate /force

Voila, restart now and enjoy.

One caveat though… As I mentioned earlier my computer was on a corporate domain. To run gpupdate /force you need to have a connection to your corporate domain controller. I was able to achieve this away from the office by connecting through our VPN connection. If you can't connect to the DC some fellow bloggers have indicated restarting twice will put the local policy into effect, but you may have to wait until the next time you're in the office to update your policy.

Sep 23
Deleting All Items From A List

​Often when you're developing or testing out a new feature you need a way to quickly purge all items from a list.  If you're only working with a handfull of list items, iterating through the list one item at a time may work sufficiently for you, but if you're working with a list containing several thousand or possibly tens of thousands of items you'll quickly discover that you need a more efficient method for this.  SharePoint allows for you to submit batch jobs for processing.  Here's a quick example for batch deleting all the items in the list.

using (SPSite site = new SPSite(SITEURL))
{
	using (SPWeb web = site.OpenWeb())
	{
		var list = web.Lists[LISTNAME];
		
		StringBuilder sbDelete = new StringBuilder();
		sbDelete.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		sbDelete.Append("<Batch>");
		
		string command = "<Method><SetList Scope=\"Request\">" + list.ID + 
				 	"</SetList><SetVar Name=\"ID\">{0}</SetVar>" +
				 	"<SetVar Name=\"Cmd\">Delete</SetVar></Method>";

		foreach (SPListItem item in list.Items)
		{ 
			sbDelete.Append(string.Format(command, item.ID.ToString()));
		}
		
		sbDelete.Append("</Batch>");
		
		web.ProcessBatchData(sbDelete.ToString());
		
		web.RecycleBin.DeleteAll();
	}
}

 

Sep 01
Creating Sites in SharePoint 2010 Using PowerShell

Creating new SharePoint sites and site collections using PowerShell is extremely easy in SharePoint 2010. Just follow these few quick steps:

  1. Launch the SharePoint 2010 Management Shell
  2. Get a listing of all the site templates

    Get-SPWebTemplate


  3. Select the template you want to instantiate

    $template = Get-SPWebTemplate "[TEMPLATENAME]"


  4. Create the new site

    New-SPSite –URL [URL] –owneralias domain\username –template $template

And that's all there is too it.

References:

TechNet

1 - 10Next

 ‭(Hidden)‬ Blog Tools

 About this blog

About this blog
I was in a hurry to move my site from my previous hosting provider so I'm still in the process of branding this blog to match the rest of my site. It's not that branding a SharePoint Blog is hard, or wait yes that's exactly why it's talking me so long.  Anyways check back soon for updates or subscribe to updates via the RSS feed at the bottom of the page.  ENJOY!!