Monday
Dec172012

Nintex Workflow - using all Regex options in your actions

 

Nintex Workflows supports a Regular Expression action.  This action has a very simple configurable UI with only the "Ignore case" option.

But there are a number of other very interesting Regex Options that you may want to use in your pattern.  This blog article is about how to enable them, and what sort of patterns you might use them for.

 

Regular Expression Options

Making an educated guess that the Nintex workflows uses the standard .NET Regular Expression (System.Text.RegularExpressions.Regex) rather than implementing their own regex engine.  Here's a list of the Regular Expression Options supported in the .NET Framework.

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

  • i = IgnoreCase (this option is available in the Nintex action)
  • m = Multiline, if enabled, ^ and $ matches beginning and end of each line, rather than the whole block of text
  • s = Singleline, if enabled, . (period) matches all characters including newline (\n), by default, the period character only matches [^\n] (any character except the newline).
  • n = ExplicitCapture, don't capture groups
  • x = IgnorePatternWhitespace, ignore unescaped whitespace, and allow inline # comments

 

Using Regex Options within a pattern group

.NET allows you to use regular expressions with special options within a pattern group.  To do this, the pattern is:

  • (?imnsx-imnsx:pattern)

You can read up about it here: http://msdn.microsoft.com/en-us/library/bs2twtah.aspx#group_options

Lets see some examples.

 

Using the multiline option

Example, given this block of text:

Dear John,

Thanks for the email.

/footer

We want to extract the line that has the word "thanks".

We can use this expression:

  • (?m:^.*thanks.*$)
  • multiline match of any line that contains the word thanks.  Match from beginning of line ^ to end of line $.

image

The results in the workflow:

image

 

Using the singleline option

Example, given this block of text:

Dear John,

Thanks for the email.

/footer

We want to capture everything before the /footer.

  • ^(?s:.*)(?=/footer)
  • use singleline option, match any character (including line breaks).  Use a positive look-ahead match on /footer, but don't actually include it in the pattern match result.

image

The results in the workflow:

image

Wednesday
Dec052012

Removing HomeGroup icon from Windows 8 desktop

This morning, I found a HomeGroup icon in my Windows 8 Deskotp.  I'm not actually sure what happened and how it appeared.  I am pretty sure it wasn't there last night.

To remove it, but not remove it from Explorer, search for "desktop icons"

image

 

I toggle the selection for "Network" on, then off again.

image

OK, and the HomeGroup icon has disappeared from the desktop.

Wednesday
Nov282012

How to create your Windows 8 Start Button with PowerShell

Before I go on, I have to say I find the Start Menu unnecessary.  There are already many ways to get to your Start Screen:

  • Throw mouse to lower-left corner (with the mouse)
  • Press the Windows key (on your keyboard)
  • Swipe in from the left edge (touch screen)
  • Press the Start button (any device with a hardware start button)

 

That said, Windows is still about choice.  And here's how you can add your own "Start Menu Button"

  1. Create a shortcut.
  2. Type in this:
    powershell.exe -Command "Add-Type -AssemblyName System.Windows.Forms; [Windows.Forms.SendKeys]::SendWait('^({ESC})')"

    (all in one line)
    This sends the Windows key (CTRL-ESC) via Powershell.
    image
  3. Configure the shortcut to run minimized
    image
  4. Change the Icon, I select this icon from the bootux.dll file %SystemRoot%\System32\bootux.dll) 
    image
    (All the icons are white, select them to see what they look like) 
  5. Drag the shortcut and pin it to the task bar, on the far left.
    image
  6. Now you have that familiar Start menu button back.  Click it and you'll get the Start Screen to pop up. 
    image

 

Notes

  • Does not appear to work in Windows RT, but if you have a Surface just hit that start hardware button
Monday
Oct292012

SharePoint Saturday Sydney 2012

Thank you all for attending SharePoint Saturday, giving up your time.  Sydney marks the last of the 6 SharePoint Saturdays that I've had the privilege to present in this year, ticking off:

The best part of SharePoint Saturday is just meeting talking to the enthusiastic SharePoint fans and hear what people are doing out there.  Honestly, not many people are that crazy to give up a sunny Saturday to learn about SharePoint - you guys are amazing.

The worst part is the travel. 

 

Sydney SharePoint User Group

I was honestly surprised almost everybody already know about the Sydney SharePoint User Group.  We meet monthly in the CBD between 6-7pm on the 3rd Tuesday of the Month.  We actually start at 5:30pm to eat up all the pizza first, and for the guys that don't need to head home right away, join us at the pub and geek out.

Sign up here so you can see what topic is coming up next month:

 

Golf Course

The User Group gave away a Miniature Golf Course during the event.

The Miniature Book of Miniature Golf

If you didn't manage to win one, but is still interested in it, it's here:

 

Downloads

Thursday
Sep272012

InfoPath form load rules and loading event order

 

A strange gotcha in InfoPath concerning which event runs first.

  • Create an InfoPath form, with a field.
  • Create a Form Load rule, that sets this field to 1.
  • Add code behind, and create a Form_Loading event, that sets the same field to 2.

 

In InfoPath rich client form / debugging

  • The result number is 2

In InfoPath browser form

  • The result number is 1

 

Keep this order in mind if you use both Form Load rules as well as Form_Loading event.

Thursday
Sep272012

SharePoint Saturday Canberra 2012

I had the pleasure of presenting REST services and AJAX at Canberra again.  It was a fun and sunny day that started at 4am in the morning, and packing a sleeping mr4 into the car and drive down.  Mr4 and my wife went to see the Cockington Miniature Gardens for the day, leaving me to geek out with fellow crazy SharePoint Saturday-ers.

As promised, there are a number of links:

 

Some of the comparisons I've made in the talk:

  • In SharePoint 2013, Microsoft wants you to use the services to talk to SharePoint, either via the Client Object Model, or via JavaScript and REST.  They also provide a whole lot of service endpoints for you to use:
    • /_vti_bin/listdata.svc
    • /_vti_bin/*.asmx
    • /_api/
  • In SharePoint 2010, you don't have nearly as many service end points, nor all the capabilities, but you can build custom services (which BTW, will still work in 2013).  So if you want to future-proof your solutions it is good to start thinking about implementing services and keeping the Javascript UI tier separate from the underlying services.
  • In the SharePoint 2013 Azure Workflow model, you can't deploy workflow actions.  But you are given an out of the box action that will let you call web services.  So building custom services is still a good way going forward to implement functionality that you can then reuse.
  • Re-use everywhere:
    • InfoPath
    • Workflow Web Request action
    • JavaScript AJAX
Tuesday
Sep252012

SharePoint - showing Contacts in People Search results

 

Scenario:

  • You have a working and functioning People Search page, and it's used to show information (and lovely photos) of your employees and acting as a very capable office phone book.
  • HR now wants to add more people to the list, people that, for some reason (may be they are kiosk workers, or external contractors), don't have an Active Directory account.  The phantom people.

Solution:

  • Create a standard SharePoint Contacts list
  • Include this list as part of the People search scope
  • Configure Search Metadata Properties to bring across the correct Site Columns, ultimately, showing both Real users and Contacts from Contact List in the same People Search results.

 

Create a contact list

image

 

The Contact list doesn't come with a Contact Photo by default, we should add one

 

 

Configuring Search

  • Create a new Search Scope "Humans"

    image
  • Add rules, in addition to the rule to include People, which is "contentclass = urn:content-class:SPSPeople"
    Add rule to also include Folder = http://server/Lists/Contacts

    image
  • You'll need to do a full crawl, which will pick up the Contact list, this will also pick up a crawled property for Contact_x0020_Photo
  • Then update the Scopes

 

Configure Search Page

 

  • Configure the Search Page
    • Change People Search Core Results webpart:
    • Scope: humans
    • Use Location Visualization: untick
    • Append Text To Query: scope:humans 
      (this allows your search results to show the first 20 people always, even when no query is specified)

 

Your search results should begin to show something, but it's not right:

image

  • Some fields are mapped automatically, here, the Job Title, Company, WorkPhone and Email fields have come across.  We're missing two significant ones

 

Configure Search Metadata Properties

 

  • Fix PreferredName

    image

    Add both "ows_FullName(Text) and ows_Full_x0020_Name(Text)
    Tick "Include values from all crawled properties mapped
  • PictureUrl

    image

    Add ows_Contact_x0020_Photo(Text)
    Tick Include values from all crawled properties mapped
  • Full crawl again.

 

The End result

 

image

 

Real users and Contact list entries displayed together in the search results!

Friday
Sep072012

XML deserialization - cannot have child contents to be deserialized as an object

Element MyValue from namespace http://schemas.datacontract.org/2004/07/Services cannot have child contents to be deserialized as an object. Please use XmlNode[] to deserialize this pattern of XML.

 

I was playing with DataContractSerializer, and getting this strange error when performing de-serialization (turning XML back into an object of type MyClass).

[DataContract]
public class MyClass
{
    [DataMember]
    public string MyName;

    [DataMember]
    public object MyValue;
}

 

The error message actually is pretty clear about what the issue is, but English is a sucky language.  Let me highlight what the error message is really saying:

Element MyValue from namespace http://schemas.datacontract.org/2004/07/Services cannot have child contents to be deserialized as an object. Please use XmlNode[] to deserialize this pattern of XML.

Read it again:

Element MyValue cannot be deserialized as an object.

 

The deserializer was actually talking about the fact that it can't turn <MyValue>1</MyValue> back into an object of the type Object.

If you change your DataContract to

[DataContract]
public class MyClass
{
    [DataMember]
    public string MyName;

    [DataMember]
    public string MyValue;
}

 

Then the deserializer will be happy.

Thursday
Aug302012

InfoPath 2013 uses new Online Pictures instead of Clip Art

 

The InfoPath 2013 Preview doesn't really have many new features.  But this one little one made me smile.

image

In InfoPath 2013, the Clip Art ribbon is replaced with Online Pictures.

image

For those of you wondering what was there before, in InfoPath 2010 it looked like this.  Yes it's that little button that we never used.

This dialog appears when you click it.

image

 

Searching for a victim's face...

image

 

image

 

A few things would make this even more awesome:

  • Add my commonly used Clip Arts to my skydrive, and link it up.  This probably works already, except my Office 2013 Preview isn't hooked up to my normal Microsoft Account.
  • Allow additional websites, I find iconfinder.com to be extremely good.
  • Or allow URL to be used directly in the dialog.
Wednesday
Aug222012

SharePoint - The object has been updated by another user since it was last fetched - while updating Site Columns

This is the second time I've been bitten by this error.

Exception:

The object has been updated by another user since it was last fetched

 

And both times I had forgotten why, and then panicked, then searched online, found articles talking about this, and figured it all out, only to recall in the last minute...

Hey, wait a minute, this happened before.

The story begins as soon as you are trying to update your site columns.  Either via the web UI, or via code, or via PowerShell.  And then you hit this error.

The cause:

This is most likely because you've created the site column using an invalid Schema XML, in particular, you've embedded the version field in the <Field> definition.

<Field Type="Text" DisplayName="OrganisationName" Required="FALSE" EnforceUniqueValues="FALSE" Indexed="FALSE" MaxLength="255" ID="{guid-xxx}" StaticName="OrganisationName" Name="OrganisationName" Version="1" ></Field>

 

The Version attribute could have got in via a number of means, but most likely you exported the existing Schema from somewhere and it got embedded.

 

My explanation:

When you update a site column, SharePoint expects that the version number of this site column object increments after the update.  But because you are updating the site column via Schema and forcing the version to be fixed all the time, that number doesn't increment.  SharePoint now thinks there's something really wrong.

 

The Fix:

Remove the Version attribute from the Field definition, and then redeploy that definition to the server.

<Field Type="Text" DisplayName="OrganisationName" Required="FALSE" EnforceUniqueValues="FALSE" Indexed="FALSE" MaxLength="255" ID="{guid-xxx}" StaticName="OrganisationName" Name="OrganisationName" ></Field>