Tag Archives: MimbolovePowershell

Writing PowerShell Modules That Interact With Various SDK Assemblies

Written by Tao Yang

Over the last few months, there have been few occasions that I needed to develop PowerShell scripts needed to leverage SDK DLLs from various products such as OpsMgr 2012 R2, SCSM 2012 R2 and SharePoint Client Component SDK.

In order to be able to leverage these SDK DLLs, it is obvious that prior to running the scripts, these DLLs must be installed on the computers where the scripts are going to be executed. However, this may not always be possible, for example:

  • Version Conflicts (i.e. OpsMgr): The OpsMgr SDK DLLs are installed into computer’s Global Assembly Cache (GAC) as part of the installation for the Management Server, Operations Console or the Web Console. However, you cannot install any components from multiple OpsMgr versions on the same computer (i.e. Operations console from OpsMgr 2012 and 2007).
  • Not being able to install or copy SDK DLLs (i.e. Azure Automation): If the script is a runbook in Azure Automation, you will not be able to pre-install the SDK assemblies on the runbook servers.

 

In order to be able to overcome these constraints, I have developed a little trick: developing a simple PowerShell module, placing the required DLLs in the PS module folder and use a function in the module to load the DLLs from the PS Module base folder. I’ll now explain how to develop such PS module. I’ll use the custom module I’ve created for the Service Manager 2012 R2 SDK last week as an example. In this example, I named my customised module “SMSDK”.

01. Firstly, create a module folder and then create a new PowerShell module manifest using “New-ModuleManifest” cmdlet.

02. Copy the  required SDK DLLs into the PowerShell Module Folder. The module folder would also contain the manifest file (.psd1) and a module script file (.psm1).

SNAGHTML12c34a9

03. Create a function to load the DLLs. In the “SMSDK” module that I’ve written, the function looks like this:

As you can see, In this function, I have hardcoded the DLL file names, assembly version and public key token. The script will try to load the assemblies (with the specific names, version and public key token) from the Global Assembly Cache first (line 32). If the assemblies are not located in the GAC, it will load the assemblies from the DLLs located in the PS Module folder (line 38).

The key to this PS function is, you must firstly identify the assemblies version and public key token. There are 2 ways to can do this:

  • Using the PowerShell GAC module on a machine where the assemblies have already been loaded into the Global Assembly Cache (i.e. in my example, the Service Manager management server):

image

  • Load the assemblies from the DLLs and then get the assemblies details from the current app domain:

image

Note: although you can load the assemblies from the GAC without specifying the version number, in this scenario, you MUST specify the version to ensure the correct version is loaded. It happened to me before when I developed a script that uses OpsMgr SDK, it worked on most of the computers but one computer. It took me a while to find out because the computer had both OpsMgr and Service Manager SDKs loaded in the GAC, the wrong assembly was loaded because I didn’t not specify the version number in the script.

Now, Once the Import SDK function is finalised, you may call it from scripts or other module functions. For example, in my “SMSDK” module, I’ve also created a function to establish connection to the Service Manager management group, called Connect-SMManagementGroup. This function calls the Import SDK (Import-SMSDK) function to load assemblies before connecting to the Service Manager management group:

For your reference, You can download the sample module (SMSDK) HERE. However, the SDK DLLs are not included in this zip file. For Service Manager, you can find these DLLs from the Service Manager 2012 R2 Management Server, in the <SCSM Management Server Install Dir>\SDK Binaries folder and manually copy them to the PS module folder:

image

Lastly, this blog is purely based on my recent experiences. Other than the Service Manager module that I’ve used in this post, I’ve also used this technique in few of my previous work, i.e. the “SharePointSDK” module and the upcoming “OpsMgrExtended” module that will soon be published (You can check out the preview from HERE and HERE). I’d like to hear your thoughts, so please feel free to email me if you’d like to discuss further.

A SMA Integration Module For SharePoint List Operations

Written by Tao Yang

Background

Many Microsoft System Center Orchestrator and Service Management Automation (SMA) users may agree with me, that these two automation platform does not have feature rich end user portals natively. Although System Center Service Manager can be used as a user portal for triggering SCORCH/SMA runbooks, Microsoft SharePoint is also a very good candidate for this purpose.

Integrating SharePoint with Orchestrator and SMA is not something new, many people have done this already. i.e.

System Center Universe America 2014 – Orchestrating Daily Tasks Like a Pro (by Pete Zerger and Anders Bengtsson)

Service Management Automation and SharePoint (by Christian Booth and Ryan Andorfer)

In my opinion, SharePoint (especially SharePoint lists) provides a quick and easy way to setup a web based end user portal for orchestration runbooks. I have also blogged my experiences in the past:

My Experience Manipulating MDT Database Using SMA, SCORCH and SharePoint

SMA Runbook: Update A SharePoint 2013 List Item

To me, not only I am using SharePoint 2013 in my lab; SharePoint Online from my Office 365 subscription, I also have no choice but using SharePoint 2010 in real life.

In my opinion, it is complicated to write SMA runbooks to interact with SharePoint (Using SharePoint web based APIs), not to mention the different versions of SharePoint also dictates how the runbook should be written. It is easier to use Orchestrator as a middle man in between SMA and SharePoint so we can use Orchestrator’s SharePoint integration pack.

Earlier this month, I was developing solutions to use SMA and Azure Automation to create OpsMgr Management Packs catalog on SharePoint 2013 / SharePoint Online sites. I have blogged the 2 solutions here:

On-Premise Solution (SMA + SharePoint 2013)

Cloud Based Solution (Azure Automation + SharePoint Online)

As I mentioned in the previous posts, I had to write a separate SMA module to be used in Azure Automation to interact with SharePoint Online because SharePoint Online sites require a different type of credential (SharePointOnlineCredential) that the PowerShell cmdlet Invoke-RESTMethod does not support. I called that module SharePointOnline back in the previous post and it utilises assemblies from the SharePoint Client Component SDK. I think the SharePoint people also refer to this SDK as Client-Side Object Model (CSOM)

After the MP catalogs posts were published, I have decided to spend a bit more time on the SharePoint Client Component SDK and see if it can help me simplify the activities between SMA and SharePoint. I was really happy to find out, the SharePoint Client Component SDK works for SharePoint 2013, SharePoint Online and SharePoint 2010 (limited). So I have decided to update and extend the original module, making it a generic module for all 3 flavours of SharePoint.

After couple of weeks of coding and testing, I’m pleased to announce the new module is now ready to be released. I have renamed this module to SharePointSDK (Sorry I’m not really creative with names Smile with tongue out).

 

SharePointSDK Module Introduction

The SharePointSDK module contains the following functions:

image

CRUD Operations for SharePoint List items:

Function Description Compatible SharePoint Version
Add-SPListItem Add an item to a SharePoint list 2010, 2013 and SP Online
Get-SPListFields Get all fields of a SharePoint list 2010, 2013 and SP Online
Get-SPListItem Get all list items of a SharePoint list or a specific item by specifying the List Item ID 2010, 2013 and SP Online
Remove-SPListItem Delete an item from a SharePoint list 2010, 2013 and SP Online
Update-SPListItem Update one or more field values of a SharePoint list item 2010, 2013 and SP Online

The functions listed above are the core functionalities this module provides. it provides simplified ways to manipulate SharePoint list items (Create, Read, Update, Delete).

Miscellaneous Functions

Function Description Compatible SharePoint Version
Import-SPClientSDK Load SharePoint Client Component SDK DLLs 2010, 2013 and SP Online
New-SPCredential Based on the type of SharePoint site (On-Prem vs SP Online), create an appropriate credential object to authenticate to the Sharepoint site. 2010, 2013 and SP Online
Get-SPServerVersion Get SharePoint server version 2010, 2013 and SP Online

These functions are called by other functions in the modules. It is unlikely that runbook authors will need to use them directly.

SharePoint List Attachments Operations

Function Description Compatible SharePoint Version
Add-SPListItemAttachment Add an attachment to a SharePoint list item 2013 and SP Online
Get-SPListItemAttachments Download all attached files from a SharePoint list item 2013 and SP Online
Remove-SPListItemAttachment Delete an attached file (based on file name) from a SharePoint list item 2013 and SP Online

As the names suggest, these functions can be used to manage attachments for SharePoint list items.

I’d like to point out  that the Add-SPListItemAttachment function not only support uploading an existing file to the SharePoint list item. it can also be used to create an attachment file directly using a byte array. This function can be used in 3 scenarios:

  • Uploading an existing file from the file system
  • Directly creating a text based file with some contents as a list item attachment.
  • Read the content of an existing binary (or text)  file, save it as a attachment with a different name

 

Configuration Requirements

Download and Prepare the module

The module zip file should consist the following 5 files:

image

  • Microsoft.SharePoint.Client.dll – One of required DLLs from the SDK
  • Microsoft.SharePoint.Client.Runtime.dll – One of required DLLs from the SDK
  • SharePointSDK.psd1 – Module Manifest file
  • SharePointSDK.psm1 – PowerShell module file
  • SharePointSDK-Automation.json – SMA Integration Module Meta File (where the connection asset is defined).

Download SharePointSDK Module

Note:

The zip file you’ve downloaded from the link above DOES NOT contain the 2 DLL files. I am not sure if Microsoft is OK with me distributing their software / intellectual properties. So, just to cover myself, you will need to download the SDK (64-bit version) from Microsoft directly (https://www.microsoft.com/en-us/download/details.aspx?id=35585), install it on a 64-bit computer, and copy above mentioned 2 DLLs into the SharePointOnline module folder.

Once the SDK is installed, you can find these 2 files in “C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\” folder.

Once the DLLs are placed into the folder, zip the SharePointSDK folder to SharePointSDK.zip file again, and the integration module is ready.

image

Import Module

Once the DLLs are zipped into the module zip file, import the module into SMA by using the Import Module button under Assets tab

image

Create a Connection object to the SharePoint site

After the module has been successfully, a connection to SharePoint Site must be created. The Connection type is “SharePointSDK”

image

The following fields must be filled out:

  • Name: Name of the connection.
  • SharePointSiteURL: URL to your sharepoint site
  • UserName : a User who should be part of the site members role (members group have contribute access).
    • If the site is a SharePoint Onine site, this username MUST be in the email address format. (i.e. yourname@yourcompany.com). I believe this account must be an account created in the Office 365 subscription. I have tried using an outlook.com account (added as a SharePoint site member), it didn’t work.
    • When connecting to a On-Prem SharePoint site, you can use the Domain\UserName format (As shown in the screenshot below)
  • Password: Password for the username you’ve specified.
  • IsSharePointOnlineSite: Boolean field (TRUE or FALSE), specify if it is a SharePoint Online site.

i.e. the connection to a SharePoint site in my lab:

image

Sample Runbooks

In order to better demonstrate this module, I have also created 10 sample runbooks:

image

Download Sample runbooks

I’ll now go through each sample runbook.

Runbook: Sample-SPNewUserRequestList

This sample runbook creates a brand new dummy new users requests list on your SharePoint site. The list created by this runbook will then be used by other sample runbooks (for demonstration purposes).

This runbook is expecting 2 input parameters:

  • ListName: The Display Name that you’d like to name the new users requests list (i.e. New Users OnBoarding Requests).
  • SPConnection: The name of the SharePointSDK connection that you’ve created previously (i.e. Based on the connection I’ve created in my lab as shown previously, it is “RequestsSPSite”

image

This runbook creates a list with the following fields:

image

Runbook: Sample-SPGetListFields

This runbook demonstrates how to retrieve all the fields of a particular list.

image

Runbook: Sample-SPAddListItem

This runbook adds an item to the New Users Requests list the previous runbook created. It also demonstrates how to create a text file attachment directly to the list item (without having the need for an existing file on the file system).

It is expecting the following inputs:

  • Title (New users title, i.e. Mr. Dr. Ms, etc)
  • FirstName (New user’s first name)
  • LastName (New user’s last name)
  • Gender (New user’s Gender: Male / Female)
  • UserName (New user’s user vname)
  • AttachmentFileName (file name of the text based attachment)
  • TextAttachmentContent (content of the text file attachment)
  • NewUserListName (display name of the new users requests list. i.e. New Users OnBoarding Requests)
  • SPConnection (The name of the SharePointSDK connection that you’ve created previously (i.e. Based on the connection I’ve created in my lab as shown previously, it is “RequestsSPSite”)

i.e.

image

The list item is created on SharePoint:

SNAGHTML1d5a6df8

Attachment content:

image

Runbook: Sample-SPUpdateListItem

This runbook can be used to update fields of an existing list item on the New Users Requests list.

Runbook: Sample-SPGetAllListItems

This runbook can be used to retrieve ALL items from a list. Each list item are presented as a hash table.

image

Runbook: Sample-SPGetListItem

This runbook can be used to retrieve a single item from a list.

image

Runbook: Sample-SPDeleteListItem

This runbook deletes a single list item by specifying the List Item ID.

Runbook: Sample-SPAddListItemAttachment

This runbook demonstrates 2 scenarios:

  • Directly attaching a file to a list item
  • attach and rename a file to a list item

image

image

Runbook: Sample-SPDeleteListItemAttachments

This runbook demonstrates how to delete an attachment from a list item (by specifying the file name).

Runbook: Sample-SPDownloadListItemAttachments

This runbook demonstrates how to download all files attached to a list item:

image

Files downloaded to the destination folder:

image

Benefit of Using the SharePointSDK Module

Using as a Regular PowerShell Module

As we all know, SMA modules are simply PowerShell modules (sometimes with optional SMA module meta file .json for creating connections). Although this module is primarily written for SMA, it can also be used in other environments such as a regular PowerShell module or in Azure Automation. When using it as a normal PowerShell module, instead of passing the SMA connection name into the functions inside the module, you may provide each individual value separately (Username, password, SharePoint Site URL, IsSharePointOnlineSite).

Simplified scripts to interact with SharePoint

When using this module, most of the operations around the list item only takes very few lines of code.

i.e. Retrieving a list item:

Using PowerShell:

Using PowerShell Workflow (in SMA):

If you use SharePoint 2013’s REST API, the script will be much longer than what I’ve shown above.

Same Code for Different SharePoint Versions

The SharePoint REST API has been updated in SharePoint 2013. Therefore, if we are to use the REST API, the code for Share Point 2013 would look different than SharePoint 2010. Additionally, when throwing SharePoint Online into the mix, as I mentioned previously, it requires different type of credential for authentication, it further complicates the situation if we are to use the REST API. This makes our scripts and runbooks less generic.

By using this SharePointSDK module, I am able to use the same runbooks on SharePoint 2010, 2013 and SharePoint Online sites.

Limitations

During testing, I noticed the 3 attachments related functions in the SharePointSDK module would not work on SharePoint 2010 sites. These functions are:

  • Add-SPListItemAttachment
  • Remove-SPListItemAttachment
  • Get-SPListItemAttachments

After a bit of research, looks like it is a known issue. I didn’t think it too much a big deal because all the core functions (CRUD operations for the list items) work with SharePoint 2010. Therefore, in these 3 functions, I’ve coded a validation step to exit if the SharePoint Server version is below version 15 (SharePoint 2013):

image

Conclusion

If you are using SMA and SharePoint together, I strongly recommend you to download this module and the sample runbooks and give it a try. If you have a look at the sample runbooks, I’m sure you will realise how easy it is to write PowerShell code interacting with SharePoint.

In case you didn’t see the download links, you can download them here:

Download SharePointSDK Module

Download Sample Runbooks

Lastly, I’m not a SharePoint specialist. If you believe I’ve made any mistakes in my code, or there is room for improvement, I’d like to hear from you. Please feel free to drop me an email Smile.

Using Royal TS for PowerShell Remote Sessions

Written by Tao Yang

Background

I have used many Remote Desktop applications in the past. I have to say Royal TS is the one that I like the most! Recently, I showed it to one of my colleagues, after a bit of playing around, he purchased a license for himself too.

Today, my colleague asked me if I knew that Royal TS is also able to run external commands, and he thought it’s pretty cool that he’s able to launch PowerShell in the Royal TS window. Then I thought, if you can run PowerShell in Royal TS, we should be able to establish PS remote sessions in Royal TS too. Within 10 minutes, we managed to create few connections in Royal TS like these:

SNAGHTML1c209a8d

SNAGHTMLa497d178

image

SNAGHTML1c2e5543

In this post, I’ll go through the steps I took to set them up.

Connections to Individual Servers

To create a connection to an individual server,

01. Choose add->External Application:

image

02. Enter the following Details:

Display Name: The name of the server you want to connect to.

Command: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Arguments: -NoExit -Command “Enter-PSSession $CustomField1$”

Working Directory: C:\Windows\System32\WindowsPowerShell\v1.0

On the icon button next to the display name, choose “Use Application Icon” if you want to.

image

image

03. Choose a Credential if you want to connect using an alternative credential

SNAGHTML1c5136c4

If you choose to use an alternative credential,  you must also tick “Use Credentials” box under Advanced tab:

image

04. Enter the remote server name in Custom Field 1:

image

Note: in the arguments field from step 01, I’ve used a Royal TS variable $CustomField1$ as the name of the computer in the Enter-PSSession command. It is more user friendly to use the Custom Field for the computer name, rather than modifying the argument string for each connection that you wish to create.

Create An Ad-Hoc Connection

You can also create a connection in Royal TS for Ad-Hoc connections. In this scenario, you will need to enter the remote computer that you wish to connect to:

image

After the the computer name has been entered, the connection is then established:

image

To create this connection in Royal TS, instead of using the Custom Field 1 for the computer name, I’ve added an additional PowerShell command in the Arguments:

Arguments: -NoExit -Command “$Computer = Read-Host ‘Please enter the Computer Name'; Enter-PSSession $Computer”

image

The Custom Field 1 is no longer required in this scenario. Everything else is the same as the previous sample (for individual computers).

Other Considerations

Maximised PowerShell Window

You may have noticed from the screenshots above, that the PowerShell windows are perfectly fitted in the Royal TS frame. this is because I am also using a customised PS Module that I’ve written in the past to resize the PoewerShell window. Without this module, the PowerShell console would not automatically fit into the Royal TS frame:

image VS image

If you like your console looks like the left one rather than one on the right, please follow the instruction below.

01. Download the PSConsole Module and place it under C:\windows\system32\WindowsPowerShell\v1.0\Modules

image

02. Modify the “All Users Current Host” profile from a normal PowerShell window (NOT within PowerShell ISE). If you are not sure if this profile has been created, run the command below:

image

After the profile is created, open it in notepad (in PowerShell window, type: Notepad $Profile.AllUsersCurrentHost) and add 2 lines of code:

image

After saving the changes, next time when you initiate a connection in Royal TS, the console will automatically maximise to use all the usable space.

Note: Because most likely you will be using an alternative (privileged credential) for these PS remote sessions. therefore the resize console commands cannot be placed into the default profile (current user current host). It must be placed into an All users profile. And also because the resize command only works in a normal PowerShell console (not in PowerShell ISE), therefore the only profile that you can use is the “All Users Current Host” profile from the normal PowerShell console.

Alternatively, if you do not wish to make changes to the All Users Current host profile, you can also add the above mentioned lines into the Royal TS connection arguments field:

i.e.

Arguments: -NoExit -Command “import-module psconsole; resize -max; Enter-PSSession $CustomField1$”

image

Duplicating Royal TS Connections

If you want to create multiple connections, all you need to do is to create the first one manually, and then duplicate it multiple times:

image

When duplicating connections, the only fields you need to change are the Display Name and CustomField1.

WinRM configuration

Needless to say, WinRM must be enabled and properly configured for PS remoting to work. this is a pre-requisite. I won’t go through how to configure WinRM here. Someone actually wrote a whole book on this topic.

Conclusion

I’d like to thank Stefan Koell (blog, twitter), the Royal TS developer (and also my fellow SCCDM MVP) for such an awesome tool. This is now probably THE most used application on all my computers Smile.

If you haven’t tried Royal TS out, please give it a try. Other than the obvious Windows version, there are also a Mac version, an iOS version and an Android version.

A Simplified Way to Send Emails and Mobile Push Notifications in SMA

Written by Tao Yang

Background

For those who knows me, I’m an OpsMgr guy. I spend a lot of time in OpsMgr and I am very used to the way OpsMgr sends notifications (using notification channels and subscribers).

In OpsMgr, I like the idea of saving the SMTP configuration and notification recipients’ contact details into the system so everyone who has got enough privilege can use these configurations (when configuring alert subscriptions).

Over the last few months, I have spent a lot of time on SMA (Service Management Automation). As I started building more and more runbooks and integration modules, I really miss the simple way of sending notifications in OpsMgr. Although there is a built-in PowerShell cmdlet for sending emails (Send-MailMessage), it requires a lot of input parameters, and the runbook author needs to have all the SMTP information available. I thought it would be nice if I could save SMTP settings as connection objects (similar to notification channels in OpsMgr), and recipients’ contact details (email and mobile device push notification services’ api keys) also as connection objects (similar to subscribers in OpsMgr).

To achieve my goals, I have created 2 SMA Integration modules:

Module Name Connection Type Name PowerShell Functions
SendEmail SMTPServerConnection Send-Email
SendPushNotification SMAAddressBook Send-MobilePushNotification

SendEmail Module

This module defines a connection type where can be used to save all SMTP related information:

  • SMTP Server address
  • Port
  • Authentication Method (Anonymous, Integrate or Credential)
  • User name
  • Password
  • Sender Name
  • Sender Address
  • UseSSL (Boolean)

SNAGHTML1ba0bfc7

image

SNAGHTML1ba1992f

This module also provides a PowerShell function called “Send-Email”. Since when retrieving an automation connection in SMA, a hash table is returned, Not only you can pass individual SMTP parameters into the Send-Email function, you can also simply pass the SMA connection object that you have retrieved using “Get-AutomationConnection” cmdlet. for more information, please refer to the help topic of this function, and the sample runbook below.

SendPushNotification Module

This module provides a connection type called SMAAddressBook. It can be used like an address book to store recipient’s contact details:

  • Display Name
  • Email Address (optional)
  • NotifiyMyAndroid API Key (optional, encrypted)
  • Prawl (iOS push notification) API Key (optional, encrypted)
  • NotifyMyWndowsPhone API Key (optional, encrypted)

image

SNAGHTML1bb2b9d4

This module also provides a PowerShell function called Send-MobilePushNotification. It can be used to send push notification to either Prawl, NotifyMyAndroid or NotifyMyWindowsPhone.

Sample Runbook

As you can see from this sample, the runbook author does not need to know the SMTP server information (including login credentials), nor the contact details of the recipient. The runbook can simply pass the SMTP connection object (PowerShell Hash Table) into the Send-Email function.

After I executed this runbook, I received the notification via both Email and Android push notification:

SNAGHTML1bb9521f

image

Download

Please download from the download link below. Once downloaded, please import the zip files below into SMA:

image

Download Link

Related Posts

OpsMgr Alerts Push Notification to iOS (And Android, And Windows Phone) Devices

Authoring Integration Modules for SMA

Conclusion

As shown in the sample above, once the SMTP details are saved in SMTP connection objects, and recipients’ contact details are saved as SMAAddressBook connections, it is really simple to utilise the functions provided by these 2 modules to send notifications.

Also, I’d like to point out I had to create 2 integration modules instead of 1 because I need to create 2 kinds of connections. Having said that, these 2 modules do not depend on each other and can be used separately too.

As many people referring to SMA modules and runbooks as Lego pieces, I will definitely to share more and more my Lego pieces as they’ve been developed. In the meantime, please feel free to contact me if you have questions or suggestions.

Using PowerShell and OpsMgr SDK to Get and Set Management Group Default settings

Written by Tao Yang

Over the last couple of days, I have written few additional functions in the OpsMgrSDK PowerShell / SMA module that I’ve been working on over the last few months. Two of these functions are:

  • Get-MGDefaultSettings – Get ALL default settings of an OpsMgr 2012 (R2) management group
  • Set-MGDefaultSetting – Set any particular MG default setting

Since I haven’t seen anything similar to these on the net before, although they will be part of the module when I release it to the public later, I thought they are pretty cool and I’ll publish the code here now.

Get-MGDefaultSettings

This function returns an arraylist which contains ALL the default settings of the management group.

Usage:

$DefaultSettings = Get-MGDefaultSettings -SDK “OpsMgrMS01″ –verbose

image

As you can see, this function retrieves ALL default settings of a management group. It returns the following properties:

  • SettingFullName: The full name of the assembly type of the setting. This is required when using the Set-MGDefaultSetting function to set the value.
  • SettingName: The name of the assembly type of the setting. consider it as the setting category
  • FieldName: The actual name of the setting. It is required when using the Set-MGDefaultSetting function.
  • Value: The current default value of the setting.
  • AllowOverride: When it’s true, this value can be overridden to a particular instance (differ from the default value).

If you want to retrieve a particular setting, you can always use pipe (“|”) and where-object to filter to the particular setting:

image

 

Set-MGDefaultSetting

Usage:

Set-MGDefaultSetting -SDK “OpsMgrMS01″ -SettingType Microsoft.EnterpriseManagement.Administration.Settings+ManagementGroup+AlertResolution -FieldName AlertAutoResolveDays -Value 3 –verbose

image

I think these two functions are particularly useful when managing multiple management groups. they can be used in automation products such as SC Orchestrator and SMA, to synchronise settings among multiple management groups (i.e. Test vs Dev vs Prod).

PowerShell Script to Add MP References to Unsealed Management Packs

Written by Tao Yang

Background

Few months ago, I have written a script to remove obsolete MP references from unsealed management packs and have also built this into the OpsMgr Self Maintenance MP. Last week, I needed to write a script to do the opposite: creating obsolete MP references in unsealed MPs.

In the past, some of the MPs I have released had issues with creating overrides in the OpsMgr operational console. i.e. the OpsMgr 2012 Self Maintenance MP and the ConfigMgr 2012 Client MP. Both of them have one thing in common: the phrase “2012” is a part of the MP namespace, and if someone tries to create an override for these MPs in the operational console, he / she will get an “Alias atribute is invalid” error:

image

When I was testing the latest release ConfigMgr 2012 Client MP (version 1.2.0.0) last week, I also got this error when assigning a RunAs account to the RunAs profile defined in the MP – because the assignment is basically a Secure Reference Override, and a MP reference to the ConfigMgr 2012 Client Library MP needs to be created in the Microsoft.SystemCenter.SecureReferenceOverride MP.

Although we can easily workaround this issue by exporting the unsealed MP, add the MP reference in by manually editing the XML, I thought I’ll write a PowerShell script to do this to make everyone’s life easier.

Script

To make it a bit easier for the users, this PowerShell function CAN ONLY be used on a OpsMgr management server.

Usage Example:

Add-MPRef -ReferenceMPName “ConfigMgr.2012.Client.Library” -Alias “C2CL” -UnsealedMPName “Microsoft.SystemCenter.SecureReferenceOverride” –Verbose

Conclusion

By using this script, we can pick the alias name that we prefer. Although this script is already included in the ConfigMgr 2012 Client MP package, I’d also like to share this script on this blog. For me, it’s a rare scenario that I had to do this, but I hope this can also help someone out there.

SMA Runbook: Update A SharePoint 2013 List Item

Written by Tao Yang

Background

This blog hasn’t been too active lately. I’ve been spending a lot of time learning the new member in System Center family: Service Management Automation.

Yesterday, I needed a SMA runbook to update SharePoint 2013 list items, I found a sample from a blog post by Christian Booth, which contains a SMA runbook written by Ryan Andorfer, a System Center Cloud and Datacenter MVP.  Looks Ryan’s code was written for SharePoint 2010, which does not work for SharePoint 2013 because the SharePoint REST API has been updated. So I have spent some time, learned a bit more about SharePoint 2013’s REST API, and developed a new runbook for SharePoint 2013 based on Ryan’s code.

PowerShell Code

Here’s the finished work:

Unlike Ryan’s code, which also monitors the SP list, my runbook ONLY updates a specific list item.

Pre-Requisite and Parameters

Prior to using this runbook, you will need to save a credential in SMA which has  access to the SharePoint site

SNAGHTML7ebadf0

The runbook is expecting the following parameters:

SharePointSiteURL: The URL to the sharepoint site. i.e. http://SharepointServer/Sites/DemoSite

SavedCredentialName: name of the saved credential to connect to SharePoint site

ListName: Name of the list. i.e. “Test List”

ListItemID: the ID for the list item that the runbook is going to update

PropertyName: the field / property of the item that is going to be updated.

PropertyValue: the new value that is going to be set to the list item property.

Note: The list Item ID is the reference number for the item within the list. If you point the mouse cursor to the item, you will find the list item ID in the URL.

SNAGHTML90254b7

Putting it into Test:

To test, I’ve created a new list as shown in the above screenshot, I have kicked off the runbook with the the following parameters:

image

image

Here’s the result:

SNAGHTML8fd5d4a

SNAGHTML8fed515

Using It Together With Orchestrator SharePoint IP

Since this SMA runbook requires the List Item ID to locate the specific list item, when you design your solution, you will need to find a way to retrieve this parameter prior to calling this runbook.

If you are also using SC Orchestrator and have deployed the SharePoint IP, you can use the “Monitor List Items” activity, and the List Item ID is published by this activity:

image

Conclusion

Although I’m still a newbie when comes to SMA, it got me really excited. Before its time, when I design Orchestrator runbooks, I often ended up just write the entire solution in PowerShell and then chopped up my PowerShell scripts into many “Run .Net Script” activities. I thought, wouldn’t it be nice if there is an automation engine that only uses PowerShell? Well, looks like SMA is the solution. I wish I have started using it sooner.

If you are like me and want to learn more about this product, i highly recommend you to read the Service Management Automation Whitepaper (currently version 1.0.4) from my fellow SCCDM MVP Michael Rueefli. I have read it page by page like a bible!

How to Create a PowerShell Console Profile Baseline for the Entire Environment

Written by Tao Yang

Background

Often when I’m working in my lab, I get frustrated because the code in PowerShell profiles varies between different computers and user accounts. And your user profile is also different between the normal PowerShell command console and PowerShell ISE. I wanted to be able to create a baseline for the PowerShell profiles across all computers and all users, no matter which PowerShell console is being used (normal command console vs PowerShell ISE).

For example, I would like to achieve the following when I start any 64 bit PowerShell consoles on any computers in my lab under any user accounts:

This is what I want the consoles to look like:

SNAGHTML65445bb.png

image.png

Although I can manually copy the code into the profiles for each of my user accounts and enable roaming profile for  these users, I don’t want to take this approach because it’s too manual and I am not a big fan of roaming profiles.

Instructions

My approach is incredibly simple, all I had to do is to create a simple script and deployed it as a normal software package  using ConfigMgr. I’ll now go through the steps.

All Users All Hosts Profile

Firstly, there are actually not one (1), but six (6) different PowerShell profiles (I have to admit, I didn’t know this until now Smile with tongue out). This article from the Scripting Guy explained it very well. Based on this article, I have identified that I need to work on the All Users All Hosts profile. Because I want the code to run regardless which user account am I using, and no matter whether I’m using the normal command console or PowerShell ISE.

Pre-Requisite

As I mentioned previously, because I want to use the PSConsole module I have developed earlier, I need to make sure this module is deployed to all computers in my lab. To do so, I have created a simple msi to copy the module to the PowerShell Module’s folder and deployed it to all the computers using ConfigMgr. I won’t go through how I created the msi here.

Code Inside the All Users All Hosts profile

The All Users All Hosts profile is located at $PsHome\profile.ps1

image

Here’s the code I’ve added to this profile:

if (Get-module -name PSConsole -List)
{
Import-Module PSConsole
}

$host.UI.RawUI.BackgroundColor = "Black"
$host.UI.RawUI.ForegroundColor = "Green"
$host.UI.RawUI.WindowTitle = $host.UI.RawUI.WindowTitle + "  - Tao Yang Test Lab"
If ($psISE)
{
$psISE.Options.ConsolePaneBackgroundColor = "Black"
} else {
Resize-Console -max -ErrorAction SilentlyContinue
}
set-location C:\
Clear-Host

Note: The $psISE variable only exists in the PowerShell ISE environment, therefore I’m using it to identify which console am I currently in and used an IF… Else… statement to control what’s getting executed within PowerShell ISE and normal PowerShell console.

Script To create All Users All Hosts Profile

Next, I have created a PowerShell script to create the All Users All Hosts profile:

#=====================================================================
# Script Name:        CreateAllUsersAllHostsProfile.ps1
# DATE:               03/08/2014
# Version:            1.0
# COMMENT:            - Script to create All users All hosts PS profile
#=====================================================================

$ProfilePath = $profile.AllUsersAllHosts

#Create the profile if doesn't exist
If (!(test-path $ProfilePath))
{
New-Item -Path $ProfilePath -ItemType file -Force
}

#content of the profile script
$ProfileContent = @&quot;
if (Get-module -name PSConsole -List)
{
Import-Module PSConsole
}

<code>$host.UI.RawUI.BackgroundColor = &quot;Black&quot;
</code>$host.UI.RawUI.ForegroundColor = &quot;Green&quot;
<code>$host.UI.RawUI.WindowTitle = </code>$host.UI.RawUI.WindowTitle + &quot;  - Tao Yang Test Lab&quot;
If (<code>$psISE)
{
</code>$psISE.Options.ConsolePaneBackgroundColor = &quot;Black&quot;
} else {
Resize-Console -max -ErrorAction SilentlyContinue
}
set-location C:\
Clear-Host
&quot;@
#write contents to the profile
if (test-path $ProfilePath)
{
Set-Content -Path $ProfilePath -Value $ProfileContent -Force
} else {
Write-Error &quot;All Users All Hosts PS Profile does not exist and this script failed to create it.&quot;
}

As you can see, I have stored the content in a multi-line string variable. The only thing to pay attention to is that I have to add the PowerShell escape character backtick (`)  in front of each variable (dollar sign $).

This script will overwrite the profile if already exists, so it will make sure the profile is consistent across all computers.

Deploy the Profile Creation Script Using ConfigMgr

In SCCM, I have created a Package with one program for this script:

image

Command Line: %windir%\Sysnative\WindowsPowerShell\v1.0\Powershell.exe .\CreateAllUsersAllHostsProfile.ps1

Note: I’m using ConfigMgr 2012 R2 in my lab, although the ConfigMgr client seems to be 64-bit, this command will still be executed under 32-bit environment. Therefore I have to use “Sysnative” instead of “System32” to overcome 32-bit redirection in 64-bit OS.

I created a re-occurring deployment for this program:

image

I’ve set it to run it once a day at 8:00am and always rerun.

Conclusion

This is an example on how we can standardise the baseline of PowerShell consoles within the environment. Individual users will still be able to add the users specific stuff in different profiles.

For example, on one of my computers, I have added one line to the default Current User Current Host profile:

image

In the All Users All Hosts profile, I have set the location to C:\, but in the Current User Current Host profile, I’ve set the location to “C:\Scripts\Backup Script”. The result is, when I started the console, the location is set to “C:\Scripts\Backup Script”. Obviously the Current User Current Host profile was executed after the All Users All Hosts profile. Therefore we can use the All Users All Hosts profile as a baseline and using Current User Current Host profile as a delta Smile.

OpsMgr 2012: A Trick to Drive Another Contextual Widget From PowerShell Grid Widget

Written by Tao Yang

PowerShell Grid widget and PowerShell Web Browser Widget were released as part of OpsMgr 2012 SP1 UR6 and R2 UR2. To me, these two widgets have opened a window of opportunities, because by using PowerShell, it allows OpsMgr 2012 users to customise and present the data exactly the way they wanted on dashboards.

Since it has been released, many people have share their work. Recently, Microsoft has started a new repository for the PowerShell widgets in TechNet Gallery.

The best article for the PowerShell Grid Widget that I have seen so far is from Oleg Kapustin’s blog: SCOM Powershell Grid Widget for Mere Mortals. In Oleg’s article (and seems to be a common practice), for each item that to be listed by the PowerShell Grid Widget, a unique Id is assigned to it (an auto incremented number):

image

Today, I want to share a small trick with you, something I’ve only picked up couple of days ago when I was writing the Location History dashboard for the 3rd part of my Location, Location, Location series. This is what the dashboard looks like:

SNAGHTML52cdecf

On this dashboard, users suppose to make their way from section 1 (state widget) to section 2 (PowerShell Grid Widget) and finally to section 3 (PowerShell Web Browser Widget). The PowerShell script in section 2 retrieves particular events generated by the object from section 1 using OpsMgr cmdlets, then display the data on this customised list. This script is listed below:

Param($globalSelectedItems)

$i = 1
foreach ($globalSelectedItem in $globalSelectedItems)
{
 $MonitoringObjectID = $globalSelectedItem["Id"]
 $MG = Get-SCOMManagementGroup
 $globalSelectedItemInstance = Get-SCOMClassInstance -Id $MonitoringObjectID
 $Computername = $globalSelectedItemInstance.DisplayName
 $strInstnaceCriteria = "FullName='Microsoft.Windows.Computer:$Computername'"
 $InstanceCriteria = New-Object Microsoft.EnterpriseManagement.Monitoring.MonitoringObjectGenericCriteria($strInstnaceCriteria)
 $Instance = $MG.GetMonitoringObjects($InstanceCriteria)[0]
 $Events = Get-SCOMEvent -instance $Instance -EventId 10001 -EventSource "LocationMonitoring" | Where-Object {$_.Parameters[1] -eq 4} |Sort-Object TimeAdded -Descending | Select -First 50
 foreach ($Event in $Events)
 {
 $EventID = $Event.Id.Tostring()
 $LocalTime = $Event.Parameters[0]
 $LocationStatus = $Event.Parameters[1]
 $Latitude = $Event.Parameters[2]
 $Longitude = $Event.Parameters[3]
 $Altitude = $Event.Parameters[4]
 $ErrorRadius = $Event.Parameters[5].trimend(".")
 
 $dataObject = $ScriptContext.CreateInstance("xsd://foo!bar/baz")
 $dataObject["Id"]=$EventID
 $dataObject["No"]=$i
 $dataObject["LocalTime"]=$LocalTime
 $dataObject["Latitude"]=$Latitude
 $dataObject["Longitude"]=$Longitude
 $dataObject["Altitude"]=$Altitude
 $dataObject["ErrorRadius (Metres)"]=$ErrorRadius
 $ScriptContext.ReturnCollection.Add($dataObject)
 $i++
 } 
}

 

Because I need to drive the contextual PowerShell Web Browser widget (section 3) from the PowerShell Grid Widget (section 2), the script used in section 3 needs to locate the exact event selected in section 2. As per Oleg’s article, based on his experiment, the only property passed between widgets is the “Id” property (of the data object). therefore, instead of using an auto increment number as the value for “Id” property as demonstrated in the previous screenshot from Oleg’s blog, I assigned the actual event Id as the data object Id so script in section 3 can use the event ID to retrieve data from the particular event.

From Section 2:

image

From Section 3:

image

Conclusion

Please keep in mind, the only property (and its value) for $globalselectedItems that travels between contextual widgets is “Id” property. if you want to drive another contextual widget based on the data passed from a PowerShell Grid Widget, please make sure you use the actual Id of the OpsMgr object (monitoring object, class, event, alert, etc…) so the next widget can use this Id to retrieve the object from OpsMgr.

PowerShell Script: Remove Obsolete References from Unsealed OpsMgr Management Packs

Written by Tao Yang

Background

Last month, in TechEd North America, Cameron Fuller demonstrated a PowerShell script to search and remove obsolete MP references from an unsealed management pack. The script was written by Cameron’s colleague Matthew Dowst. You can watch Cameron’s presentation here and get the script here.

After TechEd, Cameron emailed me and suggest me to add this script into my OpsMgr Self Maintenance management pack. So before I built this functionality into the Self Maintenance MP, I have written a similar stand-alone script as a proof-of-concept.

Script Highlights:

The differences between my version and Matthew Dowst version are:

  • No need to export and re-import unsealed management packs: My script directly reads and updates MP contents using SCOM SDK. therefore unsealed MPs don’t need to be exported and re-imported.
  • Scan through all unsealed MPs: My script go through all unsealed MPs rather than individual XML files.
  • Option to backup MPs before changes are made: the script accept parameters to backup original unsealed MPs before any changes are made.
  • Option to increase MP version or keep version the same: Users can choose whether the MP version should be increased.
  • Allow test run (-WhatIf): Users can use –WhatIf switch to test run the script before changes are made.
  • MP Verify: the script verifies the MP before and after changes. if MP verify fails (including pre-existing errors), no changes will be made to the particular MP.
  • Allow Users to customize a “white list” for common MPs: When obsolete references are detected for the “common management packs” defined in the CommonMPs.XML (placed in the same folder as the script), these references will be ignored. This is because these common management packs are referenced in many out-of-box unsealed management packs by default. Additionally, since it is very unlikely these management packs will ever be deleted from the management group, therefore it should not be an issue when they are referenced in other management packs. Users can manually add / remove MPs from the list by editing the CommonMPs.XML. I have pre-populated the white list and included the following MPs:
    • Microsoft.SystemCenter.Library
    • Microsoft.Windows.Library
    • System.Health.Library
    • System.Library
    • Microsoft.SystemCenter.DataWarehouse.Internal
    • Microsoft.SystemCenter.Notifications.Library
    • Microsoft.SystemCenter.DataWarehouse.Library
    • Microsoft.SystemCenter.OperationsManager.Library
    • System.ApplicationLog.Library
    • Microsoft.SystemCenter.Advisor.Internal
    • Microsoft.IntelligencePacks.Types
    • Microsoft.SystemCenter.Visualization.Configuration.Library
    • Microsoft.SystemCenter.Image.Library
    • Microsoft.SystemCenter.Visualization.ServiceLevelComponents
    • Microsoft.SystemCenter.NetworkDevice.Library
    • Microsoft.SystemCenter.InstanceGroup.Library
    • Microsoft.Windows.Client.Library

Instruction:

You can run this script on any computers have OpsMgr 2012 console /agent / management server installed. The script includes a help documentation. you can access it via:

get-help .\MPReferencesCleanUp.ps1 –full

SNAGHTML436c9dc6

Examples:

#1. Test run using -WhatIf: .\MPReferencesCleanUp.ps1 -ManagementServer “OPSMGRMS01″ –BackupBeforeModify –BackupLocation “C:\Temp” -IncrementVersion –WhatIf

image

#2. Real run without –WhatIf: .\MPReferencesCleanUp.ps1 -ManagementServer “OPSMGRMS01″ –BackupBeforeModify –BackupLocation “C:\Temp” –IncrementVersion

image

Download

The script can be downloaded HERE.

What’s next?

As I mentioned in the beginning, the next version of the OpsMgr 2012 Self Maintenance MP will have the ability to detect and remove these obsolete references. The MP is pretty much done. I’ve sent it to few people to test. I should be able to publish it in few days. Despite the new functionalities of the self maintenance MP, this script will still be a good standalone tool to run ad-hoc when needed.

Credit

I’d like to thank the following people for testing and advices provided to this script (in random order):

  • Cameron Fuller
  • Raphael Burri
  • Marnix Wolf
  • Bob Cornelissen
  • Dan Kregor

I also want to thank Matthew Dowst for the original script and Matthew Long for his blog post where I got the ideas from.

Lastly, as always, please feel free to contact me if you have questions / issues.