Using a Flic Smart Button as a PowerPoint Remote

When speaking at conferences, you usually spend a lot of time time asking the organizer questions like “what inputs will you have, will there be a digital switcher, etc.”.  This usually leads to carrying an array of adapters to be sure you’re prepared for those circumstances where there’s just VGA at the podium when you need micro/mini HDMI, DVI, USB to RJ45, and more…

One of the most common requirements is something to control your presentation.  If you’re like me, you often find yourself either running out of USB ports or having large inputs making nearby ports inaccessible or don’t want to carry a USB hub around with you.  At the same time, many conferences don’t provide remotes for controlling your presentations (they have a propensity to “walk away” or someone leaves the session before yours with the input – leaving a hapless remote behind).

A couple of weeks ago, I picked up a Flic Smart Button that we had provided our MVP’s as swag at the 2019 MVP Summit and stashed it away in my desk drawer, not quite sure what I’d use it for.

If you’re not familiar with Flic, check out https://flic.io.

With the SharePoint Conference just a week away, I started to think about ways I could use the Flic Smart Button, but everything I found limited its’ use to a connection with a mobile device…  then I discovered the Flic App for Mac – perfect I thought – I’ll use the keyboard shortcuts action I saw in the mobile app on my MacBook as a way to remote control PowerPoint.

After installing the Flic App for Mac, I couldn’t find the keyboard actions so started to do a little research to find a plugin that would work…  I couldn’t find anything that would do what I wanted it to do so decided to build my own…

It took a little bit of time to get it right, at the same time, simple – but I was able to build a user defined plugin to use with my Flic Smart Button and Mac to act as a PowerPoint remote.

Screen Shot 2019-05-15 at 11.17.09 AM

If you’re interested in using the plugin, I’ve made it available here on Github.

FileChecker Migration Assessment Sample Available for SharePoint Online and OneDrive for Business

Know before you go…

If you’re considering migrating file shares or other file-centric containers to OneDrive for Business or SharePoint Online it’s useful to understand if the source files are supported for storage or synchronization.  This code sample at https://github.com/wbaer/FileChecker helps to identify illegal characters, length restrictions, and more in one or more file names that can potentially prevent proper synchronization with Microsoft SharePoint and OneDrive for Business or fail to render through the Microsoft SharePoint or OneDrive for Business Web UX.

Extend FileChecker.exe at https://github.com/wbaer/FileChecker or download a working sample and read the documentation at http://wbaer.io/2oaQ9HP.

UX

filechecker_core

Command Line

filechecker_cl

Output

filechecker_results

Quick Starting Demos and Windows PowerShell

Preparing virtual machines for demonstrations can be a tedious process, compounding this is when virtual machines need to be started or shut down in a specific order.  For example, starting database servers prior to starting web servers, or starting the preferred active node before the passive node.  Starting those machines; however, is only a portion of the process, in most cases you will want them to be “available” before starting a subsequent machine.  For example, having an iSCSI Target available before the consuming iSCSI initiators are available.  Windows PowerShell, is perfect to support this scenario – it’s something I use almost everyday and have shared an example (below) of how you can accomplish all of these tasks…

So what does it do?

Provides parameters to Start/Shut Down one or more virtual machines.

Checks for process elevation, escapes if the script is not run elevated.

Starts the Hyper-V Virtual Machine Management Service if not running.

Iterates through an array of virtual machines stored in a .txt file.

Starts each virtual machine in the .txt file and waits for the heartbeat status to report ‘OK’ before starting the next virtual machine in the list.  Virtual machines are started in the order they appear in the source file, waiting ensures a clean start up – particularly where a defined start order with dependencies exists.

Shuts down virtual machines in the reverse order they were started by reading the source file bottom to top.  Waits for the virtual machine heartbeat status to report ‘’ before processing the next virtual machine.

Displays a progress bar to report on the status of the operation.

Script

[CmdletBinding(ConfirmImpact="Low")]

Param(
     [Parameter(Mandatory=$True,Position=0,ValueFromPipeline=$False,HelpMessage="Operation to perform on one or more virtual machines.")][ValidateSet("Start","Stop")]
     [String]$operation,
     [Parameter(Mandatory=$True,Position=1,ValueFromPipeline=$False,HelpMessage="Collection of virtual machines on which operation is to be performed.")][ValidateNotNullorEmpty()]
     [String]$source
)

$ErrorActionPreference = "Stop"

Process
{
     $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
     $principal = New-Object System.Security.Principal.WindowsPrincipal($identity)
     $role = [System.Security.Principal.WindowsBuiltInRole]::Administrator
     $elevated = $principal.IsInRole($role)

     If ($operation -eq "Start")
     {
         $service = Get-Service -Name vmms

         If ($service.Status -ne "Running")
         {
             Try
             {
                 If ($elevated)
                 {
                     Start-Service $service

                     Write-Host "Starting the Hyper-V Virtual Machine Management Service."

                     Start-Sleep -s 10

                     Clear-Host
                 }
                 Else
                 {
                     Write-Host "Requires elevation."
                     break
                 }
             }
             Catch
             {
                 [System.Exception]
                 Write-Host "Could not start Virtual Machine Management Service."
                 break
             }
         }

         $exists = Test-Path "$(Get-Location)$source.txt" 

         If ($exists -eq $True)
         {
             Try
             {
                 $list = Get-Content "$(Get-Location)$source.txt"
             }
             Catch
             {
                 [System.Exception]
                 break
             }
         }
         Else
         {
             Write-Host "The file could not be found: $source.  The document name or path is not valid."
             break
         }

         For ( $count = 0; $count -lt $list.Count; $count++
         { 
             $guest = $list[$count]

             $progress = 100 / $list.Count * ($count + 1)

             Write-Progress -Activity "Starting virtual machine…" -CurrentOperation "Starting…" -Status $guest -PercentComplete $progress

             Try
             {
                 If ($elevated)
                 {
                     Start-VM -Name $guest
                 }
                 Else
                 {
                     Write-Host "Requires elevation."
                     break
                 }
             }
             Catch
             {
                 Write-Host "Could not start virtual machine(s)."
                 break
             }

             Write-Progress -Activity "Starting virtual machine…" -CurrentOperation "Waiting…" -Status $guest -PercentComplete $progress

             do {Start-Sleep -milliseconds 100
             until ((Get-VMIntegrationService $guest | ?{$_.name -eq "Heartbeat"}).PrimaryStatusDescription -eq "OK")
         }
     }

     ElseIf ($operation -eq "Stop")
     {
         $exists = Test-Path "$(Get-Location)$source.txt" 

         If ($exists -eq $True)
         {
             Try
             {
                 $list = Get-Content "$(Get-Location)$source.txt"
             }
             Catch
             {
                 [System.Exception]
                 break
             }
         }
         Else
         {
             Write-Host "The file could not be found: $source.  The document name or path is not valid."
             break
         }

         For ($count = $list.Length1; $count -ge 0 ; $count)
         { 
             $guest = $list[$count]

             $progress = 100 / $list.Count * ($count + 1)

             Write-Progress -Activity "Stopping virtual machine…" -CurrentOperation "Stopping…" -Status $guest -PercentComplete $progress
    
             Try
             {
                 Stop-VM -Name $guest
             }
             Catch
             {
                 Write-Host "Could not stop virtual machine."
                 break
             }

             Write-Progress -Activity "Stopping virtual machine…" -CurrentOperation "Waiting…" -Status $guest -PercentComplete $progress

             do {Start-Sleep -milliseconds 100
             until ((Get-VMIntegrationService $guest | ?{$_.name -eq "Heartbeat"}).PrimaryStatusDescription -ne "OK")
         }

         Start-Sleep -s 10

         If ($elevated)
         {
             Try
             {
                 Stop-Service vmms
                 Write-Host "Stopping the Hyper-V Virtual Machine Management Service…"
             }
             Catch
             {
                 [System.Exception]
                 Write-Host "Could not stop the Hyper-V Virtual Machine Management Service."
                 break
             }
         }
         Else
         {
             Write-Host "Requires elevation."
             break
         }

         Clear-Host
     }
}

Usage

Using the scripts requires 1) saving the attached script as <name>.ps1 2) creating source .txt file with virtual machines listed in the preferred start up order.  For example,

Machine1

Machine2

Machine3

3) Saving the script and source .txt file in the same location.

4) Running the script as <name>.ps1 –Operation Start –Source <name>

Yammer Redirection in SharePoint Server 2013 Service Pack 1

In previous articles I discussed redirecting OneDrive for Business to Office 365 in SharePoint Server 2013 Service Pack 1.  In addition to new functionality that allows IT administrators to redirect OneDrive for Business and Sites pages to Office 365, Service Pack 1 also allows IT administrators to activate Yammer as the default social experience for SharePoint Server 2013.

When activated, the Newsfeed link in the navigation bar is replaced with a Yammer link that directs users to the organizations’ Yammer network. 

Yammer Configuration page in Central Admin

While a simplified Activate/Deactivate configuration is provided in Service Pack 1, proper identity management planning is required to deliver a consistent and integrated user experience.

For organizations with an established Active Directory and identity management infrastructure and practices

Directory Synchronization with Office 365 is a distinct configuration that provides an integrated identity solution for applications within the Office 365 suite with the exception of Yammer.  Integrated identity with Yammer requires a separate implementation of a directory synchronization solution provided by Yammer, Yammer Directory Sync (DSync).

Similar to Directory Synchronization, Yammer Directory Sync (DSync) is a Windows application that automates user provisioning in your Yammer network by querying your Active Directory (AD) host(s).

 

Sites Page

The Sites page introduced in SharePoint Server 2013 is designed to provide users a unified location to create new sites and view sites they are following.

Managing Sites Page Redirection

Service Pack 1 also includes within OneDrive for Business redirection the option to redirect users Sites page to Office 365.

Example 1 C#

        static void Main(string[] args)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://sharepoint.spc.com.co"));
 
                foreach (SPSite site in webApp.Sites)
                {
                    foreach (SPWeb web in site.AllWebs)
                    {
                        if (web.Features != null)
                        {
                            web.Features.Remove(new Guid("{043C4BDD-9745-441a-A9A7-0BCD9B910319}"));
                        }
                    }
                }
            });
        }

Example 1 Windows PowerShell

This example can be used to deactivate a specific Feature across all sites within the specified Web application.

$webApp = Get-SPWebApplication -Identity http://sharepoint.contoso.com

$webApp | Get-SPSite -limit all | ForEach-Object {Disable-SPFeature -Identity “FeatureName” -Url $_.Url}

The Uninstall-SPFeature cmdlet removes the specified feature definition from the collection of feature definitions in the farm.

Uninstall-SPFeature –Identity

Other Social Capability Considerations

In addition to addressing scenarios such as Following Content you should also consider the management of other SharePoint Server 2013 social capabilities such as:

  • Removing the SharePoint Server social web parts from My Sites and Team Sites.
  • Hiding user interface controls that provide social functionality.

For additional information on replacing the social features in SharePoint Server 2013 with equivalent Yammer features in a SharePoint Server 2013 on-premises deployment see also http://technet.microsoft.com/en-us/library/dn270535(v=office.15).aspx.

Resources

Add Yammer to the navigation bar for SharePoint 2013 [http://technet.microsoft.com/en-us/library/dn627521(v=office.15).aspx]

Code Samples, Simple Translation using CSOM, REST, and Machine Translation Services

Machine Translation Services is a powerful Shared Service Application in SharePoint Server 2013 that provides automation synchronous and asynchronous translation of documents, folders, and sites.  The code samples in this post provide simple examples of synchronous document translation using the Client Side Object Model in managed (C#) applications and Windows PowerShell in addition to accessing Machine Translation Services via REST.

CSOM

The Client Side Object Model (CSOM) provides a rich alternative to earlier Web Services in providing an object-oriented system for interoperating with SharePoint data from a remote (client) machine.

The foundation of CSOM interop is the client context object which represents the current request context.  In the provided samples, it is represented in the C# example as:

new ClientContext(site)

or in the Windows PowerShell sample as:

New-Object Microsoft.SharePoint.Client.ClientContext($url) where the $url in this example is a parameter passed to the script.

Through this context you can obtain access to client objects to include site collections and their subordinates as represented in the above examples.

For example, in the sample scripts (download link below), the top-level site collection represents the new client context which is passed to the SyncTranslator class of the TranslationServices namespace as the Context property.

$context = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$context.Credentials = $credentials

$job = New-Object Microsoft.Office.Client.TranslationServices.SyncTranslator($context, $language)

REST

REST or Representational State Transfer in the context of SharePoint 2013 development opens it to standard Web languages and technologies.  Technologies such as CSOM (as shown above) have been available to SharePoint over several releases; however, such APIs are limited to .NET applications and languages.  REST; however, enables accessing SharePoint capabilities and entities with standard Web languages such as JavaScript and preprocessor hypertext (PHP) in addition to any technology stack that supports REST.   One of the predominant benefits of REST is that it allows for limiting the footprint of Web applications, as such, reduces the barrier to entry to accessing cloud services and deploying applications whose target is such.

In SharePoint the REST service is implemented in client.svc contained within _vti_bin; however, through substitution _api is used and establishes the base Url for each endpoint.

The service Url of specific endpoints is appended to the base Url, in the sample code:

$request = [System.Net.WebRequest]::Create($url +"/_api/TranslationJob.EnumerateSupportedLanguages")

These samples are intended to illustrate how Windows PowerShell can be used to access cloud services through CSOM and REST.

Download the samples here:

CSOM (Windows PowerShell and C# Samples)

REST (Windows PowerShell Samples)