SharePointRoot


Leave a comment

Add User to Lync using C# (Enable-CSUser Powershell)

The current project I’m working on has a web-based application that manages user provisioning – add/edit/delete – to Active Directory, Microsoft Exchange and Lync (previously OCS).

The way to provision a user within Lync is via Powershell – lots of bingoogle’ing tells that you can use the Enable-CsUser command – this is what I need to do via Powershell :

Enable-csUser -identity AccountName -RegistrarPool lyncPoola.FQDN -SipAddressType EmailAddress

So – how do you do it via C# ??   

There doesn’t seem to be many people who have been able to do this – judging by the Q&A via StackOverflow.

My choice of solution was to define a “web service” project – and can thus have this running *ON* the same server as Lync – thereby running ‘locally’ if needed.

(1) Include the DLL for Powershell

  • Install the Powershell SDK – and then grab the DLL and include in your project  
  • System.Management.Automation.dll

(2) Add the using statements :

  • using System.Management.Automation;
  • using System.Management.Automation.Runspaces;
  • using Microsoft.PowerShell;
  • IMPORTANT – for some reason, this doesn’t work in Visual Studio 2008 – so use Visual Studio 2010 instead.

(3) Open A PowerShell RunSpace

Need to import the “module” for PowerShell Lync commands – just like an “Import-Module” command.

  • InitialSessionState iss = InitialSessionState.CreateDefault();
  • iss.AuthorizationManager = new AuthorizationManager("MyShellId");  
  • iss.ImportPSModule(new string[] { "Lync" });
  • Runspace powerShellRunspace = RunspaceFactory.CreateRunspace(iss);
  • powerShellRunspace.Open();

*** You might get an error like this :

"File C:\Program Files\Common Files\Microsoft Lync Server 2010\Modules\Lync\startup.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details

The answer I found was to include the line above with the “AuthorizationManager” – this one line of “awesome (!)” was thanks to Nivot Ink.

This essentially ‘bypasses’ the ExecutionPolicy checks – proceed with caution !

(4) Do the PowerShell Command

This uses the PowerShell RunSpace which has been initiated with the “Lync” module.

The code then defines the “Command” – ie. Enable-CsUser.

The AddParameter is then like the Params for any method – like a Stored Procedure (SQL) – or something like that.   

Prepare your key/value parameters – and then ‘fire’ using the “Invoke” command.

The results are returned as a “PSObject” collection – so just save these to a StringBuilder to return.

  • StringBuilder stringBuilder = new StringBuilder();
  • using (PowerShell powershell = PowerShell.Create())
  • {
  • powershell.Runspace = powerShellRunspace;
  • powershell.AddCommand("Enable-CsUser");
  • powershell.AddParameter("Identity", samName);
  • powershell.AddParameter("RegistrarPool", “lyncPoola.FQDN”);
  • powershell.AddParameter("SipAddressType", "EmailAddress");
  • Collection<PSObject> results = powershell.Invoke();
  • foreach (PSObject obj in results)
  • {
  • stringBuilder.AppendLine(obj.ToString());
  • }
  • powerShellRunspace.Close();
  • }
  • return stringBuilder.ToString()

(5) Do a Happy Dance !!

This was fairly tricky to get working – took me a day or so to get the bits aligned.

Other considerations :

  • Need to run the code as a user with Lync admin permission
  • Need to run the code from a server/machine that is “on the domain”

Here’s a full set of the source code that I used :

image

Let know if this helped you – as it was a good challenge to crack !

Smile


Leave a comment

Change MySites Landing Page (SharePoint 2010)

Within SharePoint 2010, the right-hand context menu includes a link for a user to navigate to their “MySite” – assuming the User Profiles Service – and MySiteHost is configured and working, etc.

There are a few pieces to the MySite – the ‘shared area (host)’ – and then the MySite’s themselves – one for each user.    The user area is actually a different site collection – that’s just the way MySites work.

When the user clicks “My Site” – the default place to go is the landing place for the “My Site Host” Site Collection.

image

It follows that this is simply another type of Site Collection – a very special Site Collection – but none-the-less, there’s a landing page – and you can CHANGE it.

This can be done via POWERSHELL – to one of the pages within the Site Collection.   This is thus the “welcome page” for the Site Collection.

Here’s the pages you can choose from :

  • default.aspx
  • person.aspx
  • organizationview.aspx
  • personcontent.aspx
  • tagprofile.aspx

 

The steps to do this are :

  • Get the site for the MySiteHost
  • Get the RootFolder
  • Set the Welcome Page
  • Update

 

Here’s the actual CODE (PowerShell)…

  • $site = Get-SPSite http://server/mysitehost/
  • $web = $site.RootWeb
  • $folder = $web.RootFolder
  • $folder.WelcomePage = "personcontent.aspx"
  • $folder.update()
  • $web.update()
  • $web.Dispose()
  • $site.Dispose()

In the following screen shot, I’ve update to “PERSONCONTENT.ASPX”.   This shows the MySite with the tab for ‘Content’ already open.  

The user can then navigate to their MySite directly – as shown.

image

Easy, eh !?

Hope you can use this cool tip.

Smile


1 Comment

Nintex Workflow Error (Update XML)

Within a Nintex Workflow, you might have seen this error :

The workflow could not update the item, possibly because one or more columns for the item require a different type of information.

I’ve been experiencing this during the development of a workflow – and it was happening as the workflow was about to do a Flexi Task.

BUT – the problem is actually happening earlier – and it’s related to the UPDATE XML activity.

InfoPath Forms – Update XML

When using an InfoPath form, it’s very easy to update the settings and values within a form, by the Update XML action to essentially ‘poke’ a value back into the InfoPath Form.

As below, you determine the XPath from within your InfoPath Form :

image

And – use the Update XML action within Nintex Workflow :

image

There is also the Query XML activity, to READ values – based on an XPath statement.

SharePoint List Columns – Update Item

Another useful step within the Nintex Workflow set of activities is ‘Update Item’ in which you can change the values of a SharePoint list column – for any fields that have been set as a promoted property.

Eg.  When publishing the form from InfoPath :

image

Within the Update Item, you choose the column, and the value to set :

image

Conflicting Updates – Great Scott !!

Here’s where the problem arises.

If/when you have a combination of these types of update – ie. UPDATE XML *and* UPDATE ITEM – you might run into the issue as detailed above.

The workflow could not update the item, possibly because one or more columns for the item require a different type of information.

This is a little misleading, and can be confusing until you understand how Nintex Workflow operates.

How The Flow Works

When the steps of a workflow are executed, any updates to the form, such as Security and Updates are not processed ‘immediately’.  

Instead, they are essentially batched up for processing at a pause-point.

By the term ‘pause-point’ – I’m meaning an activity when it’s awaiting a response from a user – or when the workflow stops to take a breath in processing – such as :

  • Flexi Task
  • Wait For Item Update
  • Change State
  • Pause For…
  • Pause Until…

It follows that there can be a mis-match of batch activities – and the QUERY XML and ITEM UPDATE don’t seem to play very well together.

You can almost understand this – one is an XML update via one API set, and the other is a SharePoint SPItem update – and if you consider versioning, and ‘concurrency’ – it’s a murky scenario.

The Solution

Introduce a pause-point !

More specifically, include a step that does a “Commit Pending Changes” within the workflow.

This will pause operations, and wait for the changes to be flushed back to the item (InfoPath Form).

 

image

 

Alternative Solution

My preference for designing workflows is to rely on the “Update XML” activities for updating values within the InfoPath Form – as opposed to “Update Item”.

If you can choose ONE of these approaches – and not BOTH – then you’ll further reduce the potential for problems.

Hope that might have assisted someone out there – happy workflow’ing…!

Smile


2 Comments

SharePoint Users Can’t Rename Documents – Access Denied

A recent client had a requirement that certain users were NOT allowed to delete files – but that they would be able to add, edit, etc.

The solution that was put in place involved the following steps :

  • Create a new user role – Contribute Without Delete (within SharePoint)
  • Copy the “Contribute” role
  • Un-check the ability to Delete
  • Add users to this role/group – within SharePoint

This solution works well – and people can’t delete – there is no ‘icon’ on the Ribbon or Context Menu.

BUT – and this is where the problem arises – people are getting errors.

  • User-A is within Contribute Without Delete
  • Uploads a document to a library
  • Metadata screen is shown

image

  • User changes the document name (or via Edit Properties)
  • Click OK – and BOOM – Access Denied !
  • This problem does NOT occur for other users – only those within the Contribute Without Delete role/group.

image

WHY ??

When a file is renamed in SharePoint, it is actually DELETED and ADDED with the new name.

As such, any users who do not have ‘delete’ permissions will get an Access Denied error – as shown.

This is the same as the Windows File System – within Windows Explorer – ie. consistent behaviour.

HOW TO SOLVE ??

Quite simply, the best approach is to NOT use the Contribute Without Delete role/group.

The discussion I’ve had with some colleagues has some merit :

  • If a person is able to upload/edit, why NOT allow Delete
  • If they accidentally delete, it goes into their own Recycle Bin
  • If they empty it, it goes into the Site Collection Recycle Bin
  • If a person should not be able to delete a file, perhaps have an area where they have READ ONLY permission – and can’t do any edits, ie. no renaming, etc.

It’s certainly an interesting scenario, eh ?

Rename = Delete + Add

I’ll have to talk it over with my client – and work out what they want to do !


Leave a comment

SharePoint People Picker Columns (via Powershell)

With a SharePoint list, the “People Picker” column can be a little tricky to deal with – as it’s an “object” – not just a string value.

A colleague was trying to retrieve the “AccountName” for a People Picker field – with a Powershell script – in order to update another column/list.

Here’s the full code segment :

$web = Get-SPWeb -identity "http://server/site&quot;
$lib = $web.Lists["PeoplePhotos"]
foreach ($photo in $lib.Items) {
    $user = $photo["CompanyPerson"]
    $userObj = New-Object Microsoft.SharePoint.SPFieldUserValue($web, $user)
    $accountName = $userObj.User.UserLogin
    $accountName.substring($accountName.IndexOf("\")+1)
}

Line-By-Line Explanation 

The tricky part is to make sure to use the SPFieldUserValue object – ie. ‘cast’ to the this object type – and can then get the SPUser object – and any of it’s properties.

(1) Get the web site object

(2) Get the SharePoint list

  • $lib = $web.Lists["PeoplePhotos"]

(3) Go through each item in the list – and get the field/value

  • foreach ($photo in $lib.Items) {

(4) Get the field/value – column called “CompanyPerson”

              • $user = $photo["CompanyPerson"]

(5) Convert to be a user object – ie. SPFieldUserValue

              • $userObj = New-Object Microsoft.SharePoint.SPFieldUserValue($web, $user)

(6) Get the AccountName – will be the format of “DOMAIN\user”

              • $accountName = $userObj.User.UserLogin

(7) Get the “user” part – ie. drop off the DOMAIN\ prefix

              • $accountName.substring($accountName.IndexOf("\")+1

(8) End the loop

  • }

 

Hope that helps – you have to do the same approach within C#/VB.NET – this is just “Powershell’ed”…

Smile

 

Further references :

MSDN : SPFieldUserValue Constructor (SPWeb, String)

MSDN : SPFieldUserValue.User Property

MSDN : SPUser Members


Leave a comment

Format DateTime in JavaScript (using jQuery !!)

During some recent project work using jQuery and REST, I was needing to format the current date/time – and use as a filter for a REST query.

eg. From a given site/library, get the most recent 5 items – but only for the last week

http://server/_vti_bin/ListData.svc/library?$select=Id,Path,Name,Title,Modified&$top=5&$orderby=Modified desc&$filter=(Modified ge datetime’2012-10-31T00:00:00′)

It follows that I need to do a “math” function to subtract 7 days from the current date – and THEN – format into the date for the REST query string param.

The first bit was easy :

  • var d = new Date();
  • d.setDate(d.getDate() – 7);

This would mean I now have a date object with “one week ago”.

But – then – how to FORMAT it ??   

Working with the DATE object in JavaScript is a little clunky – to say the least !

From what I could find – the best way was to do this :

  • var curr_date = d.getDate();
  • var curr_month = d.getMonth();
  • curr_month++;   // need to add 1 – as it’s zero based !
  • var curr_year = d.getFullYear();
  • var formattedDate = curr_date + "-" + curr_month + "-" + curr_year);

See more about this approach :

http://www.elated.com/articles/working-with-dates/

This is an overly complex approach – and what happens if my month needs to be zero prefix ?

Eg.   14/09/2012 – instead of 14/9/2012 – or maybe 1/12/2012, or 01/12/2012.

WTF !!?     Sad smile

jQuery to Save The Day !

As I’m working with some jQuery components, and the jQuery UI is also referenced along the way, I can make sure of the “DatePicker” component – to do date-formatting – EASY !!

So – my revised code is :

  • var d = new Date();
  • d.setDate(d.getDate() – 7);
  • var formattedDateTime = $.datepicker.formatDate(‘yy-mm-ddT00:00:00′, d);

 

You could even have a DATEFORMAT for the current date in ONE line – this is soooo much simpler – and much more powerful – and almost akin to a C#/VB.NET formatting approach.

  • var formattedDateTime = $.datepicker.formatDate(‘yy-mm-dd’, new Date());

 

Here’s a few jQuery’ised DateTime Format functions – AWESOME !

$.datepicker.formatDate([FORMAT], new Date());

dd/mm/yy 01/09/2012
d/m/y 1/9/12
d-M-y 1-Sep-12
d-MM-yy 1-September-2012

 

Have a look at the jQuery doco for some more examples – and how-to.

Unfortunately, it doesn’t extend to TIME formatting – doh…!

Hopefully that helps someone out there – and avoids the clunky old-school JavaScript approach. 

It certainly saved ME !    

Viva la jQuery !

Smile with tongue out


1 Comment

The form has been closed – go back to library

When using InfoPath forms, and Nintex workflow, there are a few ways to view the InfoPath form.  You can either :

  1. Open the form by clicking on the link within the form library – and do save/submit, etc – and you’re redirected back to the form library
  2. Click on a link as generated by an Email (item URL within Nintex) – and do save/submit – and you get “Form was closed” – annoying ??!?

image

My recent customer was asking if they could auto-direct back to the Forms Library after saving the form – so I did some checking of the URL’s.

When you click on the form as in #1 above – this is the URL :

http://server/site/_layouts/FormServer.aspx?XmlLocation=/site/FormLib/FormName.xml&ClientInstalled=true&Source=https%3A%2F%2Fserver%2Fsite%2FFormLib%2Fdefault%2Easpx&DefaultItemOpen=1

BUT – when clicking the email link – as generated by Nintex Workflow (using the “Item URL” variable) – you get this :

http://server/site/_layouts/FormServer.aspx?XmlLocation=/site/FormLib/FormName.xml&OpenIn=browser

Notice anything missing ??

The basic problem is that one of the ‘QueryString’ values is missing – ie. the “SOURCE” list.    This is a ‘url-encoded’ name-of-page-to-redirect-back-to.

So – to solve the problem at hand – I did the following :

  • Within Nintex Workflow, create a variable called FormUrl (as opposed to ItemUrl)
  • Add a Build String activity (at the start)
  • Include the “ItemUrl” – and then…
  • &Source=https%3A%2F%2Fserver%2Fsite%2FFormLib%2Fdefault%2Easpx
  • Store the value into “FormUrl”
  • Whenever needing to send the URL in an email – just use my custom variable (FormUrl) – not ItemUrl.

Keep in mind that you need to change the “Source” url – depending on the library name and/or site – OR – you could re-direct back to the home page for the intranet after completed.

That works nicely – and people don’t get the dud “Form has been closed” screen after saving & submitting – when viewing the form via Email Link (ItemUrl).

Smile

Follow

Get every new post delivered to your Inbox.

Join 26 other followers