Reconnect Series: Aaron Nelson

Reconnect Series: Aaron Nelson

This article is contributed. See the original author and article here.

For the final instalment this year, it is time once again to Reconnect! For this very special edition of the blog, we are joined by eight-time Data Platform MVP titleholder Aaron Nelson.

 

Hailing from Georgia, United States, Aaron is a SQL Server Architect with more than 20 years of experience in Architecture, Business Intelligence, Development, and Performance Tuning of SQL Server.

 

Aaron’s accomplishments read like a laundry list of tech experience. He is a Microsoft Certified Professional as a Business Intelligence Developer, Database Administrator, and Database Developer. Meanwhile, Aaron helped to pen Microsoft SQL Server 2012 Bible, an in-depth guide crammed with specific examples, sample code, and a host of tips, workarounds, and best practices.

 

This extensive experience led Aaron to begin work as a senior consultant for Microsoft in April 2019, where he assists premier customers on data platform design and Azure across the United States.

 

In addition, Aaron has been very active in his community. Aaron has volunteered with the PowerShell Virtual Chapter of PASS since its inception in October 2010, with the chapter growing to more than 5,000 members and amassing a following on YouTube. Further, Aaron serves as a board member of the Technology Association of Georgia Young Professionals, and volunteers with Atlanta Microsoft Database Forum.

 

Since 2010, Aaron has have spoken at more than 100 events across the US, Canada, Europe, and the Caribbean. His personal highlights include PASS Summit, Teched North America, TechEd Europe, and SQLRally.

 

For more on Aaron, check out his Twitter @SQLvariant

 

NELSON.jpg

SharePoint Roadmap Pitstop: December 2020

SharePoint Roadmap Pitstop: December 2020

This article is contributed. See the original author and article here.

Before. 2020. Blink. Breathe. 2021 (soon). Breathe. Begin.


 


To close out the year, December 2020 brought many a new offering: SharePoint site header updates, send pages to Yammer, “SharePoint Success” site template, add Microsoft Teams to SharePoint team sites update (aka, Teamify), Microsoft Lists adoption center, Microsoft Graph Toolkit v2.0, and more. Details and screenshots below, including our audible companion: The Intrazone Roadmap Pitstop: December 2020 podcast episode – all to help answer, “What’s rolling out now for SharePoint and related technologies into Microsoft 365?” Blink. Breathe.


 


https://html5-player.libsyn.com/embed/episode/id/17363762/height/90/theme/custom/thumbnail/yes/direction/backward/render-playlist/no/custom-color/247bc1/


 


In the podcast episode, listen to an exclusive chat with @Tejas Mehta (LinkedIn | Twitter), principal program manager on the SharePoint team who owns content services integration work with Microsoft Teams. I nabbed a 6ft-apart check-in with Tejas to talk about life for SharePoint before Teams, ongoing integration work including this month’s #teamify update, and what the future may bring in this space. Also, exclusive this month on The Intrazone, we share the Top 10 SharePoint features released in 2020.


 


Tejas Mehta, principal program manager at Microsoft (SharePoint + Teams integration) [Intrazone guest]; myself and Tejas social-distanced, 6ft-pic-nic table-apart	 podcasting at Sammamish Commons.Tejas Mehta, principal program manager at Microsoft (SharePoint + Teams integration) [Intrazone guest]; myself and Tejas social-distanced, 6ft-pic-nic table-apart podcasting at Sammamish Commons.


All features listed below began rolling out to Targeted Release customers in Microsoft 365 as of December 2020 (possibly early January 2021). Blink. Breathe.


 


Inform and engage with dynamic employee experiences


Build your intelligent intranet on SharePoint in Microsoft 365 and get the benefits of investing in business outcomes – reducing IT and development costs, increasing business speed and agility, and up-leveling the dynamic, personalized, and welcoming nature of your intranet.


 


SharePoint site header updates


We are making it easier to customize the header of your site. The default site header for new SharePoint sites will be the compact header instead of the standard header. Site owners will see updated options in the “Change the Look” panel, including: a minimal header which has a reduced height to provide quick, visual access to content, an extended header includes an optional background image, expanded site logo widths, and options for logo alignment – left, middle, right. And now it’s easy to toggle site title label to be on or off.


 


From the upper-right gear icon, click into the “Change the look” panel, select “Header” and then customize it the way you prefer.From the upper-right gear icon, click into the “Change the look” panel, select “Header” and then customize it the way you prefer.


Now you can truly control your site’s first impression, starting at the very top with the site header – just the way you want it.


 



 


Send SharePoint pages to Yammer


Expand the reach and the conversation of your SharePoint pages news posts. You can now send articles from SharePoint directly into Yammer communities and include questions, polls, praise, and rich text. It’s also possible to upload images and files to the post linked to the share.


 


The SharePoint Send-to-Yammer dialog provides a rich preview for media and the ability add text to the post.The SharePoint Send-to-Yammer dialog provides a rich preview for media and the ability add text to the post.


Page to post in a few clicks.


 



 


“SharePoint Success” site template


Now available via the SharePoint Look Book, the “SharePoint Success” site template is a ready to deploy, customizable SharePoint communication site that helps your colleagues create high-impact sites to meet the goals of your organization. It comes pre-populated with site creation inspiration and training on how to create high quality and purposeful SharePoint sites. You’ll find Microsoft maintained SharePoint training content feed, success stories, and site creation guidelines.


 


Make this site your own to establish a learning destination to help everyone make SharePoint a success for your organization.Make this site your own to establish a learning destination to help everyone make SharePoint a success for your organization.



 


Teams and OneDrive destinations when using Migration Manager in the SharePoint admin center


Admins now have greater visibility and choice selecting destination(s) for files and folders when moving content from on-premises file shares into Microsoft 365. New beyond SharePoint, admins can select OneDrive usernames or URLs and/or select various Teams team and channels as migration destinations – moving files exactly where you want them.


 


When moving files and folders into Microsoft 365 from on-premises file shares, admins choose OneDrive, SharePoint, and Teams as destinations.When moving files and folders into Microsoft 365 from on-premises file shares, admins choose OneDrive, SharePoint, and Teams as destinations.


A note on credentials: You need to have access to the destination as a global admin or OneDrive/SharePoint admin to the Microsoft 365 tenant where you want to migrate your content to, and access to the source; aka, Windows credentials that have read access to any of the network file shares you plan to migrate.


 



 


Teamwork updates across SharePoint team sites, OneDrive, and Microsoft Teams


Microsoft 365 is designed to be a universal toolkit for teamwork – to give you the right tools for the right task, along with common services to help you seamlessly work across applications. SharePoint is the intelligent content service that powers teamwork – to better collaborate on proposals, projects, and campaigns throughout your organization – with integration across Microsoft Teams, OneDrive, Yammer, Stream, Planner and much more.


 


Add Microsoft Teams to your SharePoint team site


We’re pleased to announce that we are making it even easier to bring SharePoint content into Teams, in the same motion of adding Microsoft Teams to your team site, aka #teamify. As you connect SharePoint to Teams, you choose what lists, libraries, and pages you want to bring into Teams as tabs in the new, default General channel.


 


Choose what SharePoint lists, libraries, and pages to bring into Microsoft Teams as tabs in the new, default General channel when adding Teams to your SharePoint team site.Choose what SharePoint lists, libraries, and pages to bring into Microsoft Teams as tabs in the new, default General channel when adding Teams to your SharePoint team site.


By default, your team site home page will be selected, you can change it to suit your needs, and you can fully navigate the primary document library from the Files tab – just follow the new folder breadcrumbs from the channel folder up to the root of the library. This helps bring content and collaboration to more of the sites you use for teamwork excellence.



 


Microsoft Lists adoption center on adoption.microsoft.com (managed by @Andrea Lum)


Simplify and accelerate your time to value throughout your organization. We know your time is important, so we’ve created adoption materials to help onboard employees at scale while being confident that you are improving the employee experience.


 


For Microsoft Lists, you’ll find an adoption playbook, day-in-the-life guides, a quick start guide, a look book, internal communication templates, pointers to documentation and training, plus materials to help build an internal Lists champion program within your organization.


 


Screenshot showing the Microsoft Lists adoption center at https://aka.ms/ListsAdoption.Screenshot showing the Microsoft Lists adoption center at https://aka.ms/ListsAdoption.


Learn more:



 


Related technology


OneDrive 2020 summary of highlights


It was a big year for OneDrive. And much of the value you see promoted by and for OneDrive also improves productivity experiences within SharePoint and Teams. Things like differential sync, 100GB file uploads, Add to OneDrive, expiring access for external users, and more.


 


This month’s The Intrazone Roadmap Pitstop: December 2020 audio companion (above) contains a segment of audio where we hear from @Randy Wong, Principal PM Manager, recap 2020 and explain the 200 million monthly active user impact on the service and how the team work hard to keep pace with both scale and innovation.


 


PowerPoint slide from Microsoft Ignite 2020 highlighting the OneDrive 2020 roadmap.PowerPoint slide from Microsoft Ignite 2020 highlighting the OneDrive 2020 roadmap.


The above below is a roadmap summary PowerPoint slide from Microsoft Ignite 2020, taken from the “What’s new and coming to OneDrive” session presented by @Ankita Kirti and @Jason Moore.


 


The Microsoft Graph Toolkit 2.0


A better dev toolkit is better for everyone. The Microsoft Graph Toolkit is great for developers of all experience levels looking to develop a web application, Microsoft Teams tab, or SharePoint web part that connects to and accesses data from Microsoft Graph. Collectively, it’s a collection of components and providers designed to ease app integration with Microsoft Graph – as easy as writing two lines of code. In 2.0, you’ll find reusable, framework-agnostic components and authentication providers for accessing and working with Microsoft Graph:


 



  • Now broken into several packages so you only get the code you need.

  • A new React package, making it simpler to use the toolkit when developing React applications by wrapping all components and exporting them as React components.

  • New components like the Person Card 2.0, a new To Do component, and all components have better caching, theming, localization, accessibility with general bug fixes all around.


 


1.0 was so yesterday. 2.0 is here and awaits your Graph-powered apps. Dev with it today!


 



 


SharePoint and Microsoft Lists sweater backgrounds for Microsoft Teams meetings


Be the foreground. Be it in memory of the holidays, a New Year’s Eve Teams call, or you just wanna get cozy and warm on any chat or concall in 2021. SharePoint, Lists and many others got your back(ground) in Teams meetings.


 


Some examples of what the cozy Microsoft-365-app-inspored holiday backgrounds look like in Microsoft Teams; clockwise from top left: Wenvi Hidayat + SharePoint + Christmas, Ben Truelove + Lists + Christmas, Mark Kashman + SharePoint + Hanukkah + Teams, and YOU + SharePoint.Some examples of what the cozy Microsoft-365-app-inspored holiday backgrounds look like in Microsoft Teams; clockwise from top left: Wenvi Hidayat + SharePoint + Christmas, Ben Truelove + Lists + Christmas, Mark Kashman + SharePoint + Hanukkah + Teams, and YOU + SharePoint.


Big thanks to my colleagues @Wenvi and @Ben Truelove for creating and getting these out there – and to our community members, Jason Custer and Michael Gillet.


 


Follow this all-in-one tweet thread to see all the designs and link to grad the full-res version that most captures your mood. Plus learn how to change your background for a Microsoft Teams meeting.


 


January 2021 teasers


Psst, still here? Still scrolling the page looking for more roadmap goodness? If so, here is a few teasers of what’s to come to production next month…



  • Teaser #1 | JSON list form customization: footer, header, body [Roadmap ID: 63519]

  • Teaser #2 | Microsoft Lists: Integrate menu item [Roadmap ID: 64869]


… shhh, tell everyone.


 


Helpful, ongoing change management resources





  • Follow me to catch news and interesting SharePoint things: @mkashman; warning, occasional bad puns may fly in a tweet or two here and there.


Thanks for tuning in and/or reading this episode/blog of the Intrazone Roadmap Pitstop – December 2020 (blog/podcast). We are open to your feedback in comments below to hear how both the Roadmap Pitstop podcast episodes and blogs can be improved over time.


 


Engage with us. Ask questions. Push us where you want and need to get the best information and insights. We are here to put both our and your best change management foot forward.


Stay safe out there on the road’map, and thanks for listening and reading.


 


Appreciate your time,


Mark “HNY” Kashman – senior product manager (SharePoint/Lists) | Microsoft)


 


The Intrazone Roadmap Pitstop - December 2020 graphic showing some of the highlighted release features.The Intrazone Roadmap Pitstop – December 2020 graphic showing some of the highlighted release features.


Subscribe to The Intrazone at aka.ms/TheIntrazone, or where you get your podcasts (direct links to The Intrazone on various podcast platforms:



And listen and subscribe to other Microsoft podcasts: aka.ms/microsoft/podcasts


 


The Intrazone, a show about the Microsoft 365 intelligent intranet: https://aka.ms/TheIntrazone.The Intrazone, a show about the Microsoft 365 intelligent intranet: https://aka.ms/TheIntrazone.

Trigger Conditions not working in a Cloud Flow? Here’s Why | Power Automate Quick Tip

Trigger Conditions not working in a Cloud Flow? Here’s Why | Power Automate Quick Tip

At times, you’re pretty sure that the trigger condition you’ve put in a Cloud Flow is correct but it still doesn’t trigger.

Scenario

Here’s a scenario which I came across where the Trigger Conditions weren’t triggering. The trigger was Common Data Service (Current Environment) connector and the Trigger Conditions were supposed to check for a specific value to fire.

However, even upon fulfilling the criteria, the Flow was not firing.

Here’s why

Let’s look at what happened here –

  1. Now, as expected the Flow should have triggered when my field Account Type has Option Set value of 3 i.e. “Partner”(on the label)
  2. The reason was that the Filtering Attribute too was added in the Trigger which clashed.
  3. And this was a clash between the two. Hence, the Condition Trigger was not fired.
  4. On the other hand, if the field which is in the Filtering Attributes was changed, the Flow was triggered.

Takeaway

So here are the takeaways –

  1. Trigger Conditions won’t fire even if the condition is matched because there’s a Filtering Attribute added to an Update trigger on the Common Data Service (Current Environment) connector.
  2. Even if Trigger Condition exists, the Filtering Attributes takes higher precedence and hence, an update on the Filtering Attributes will trigger rather than Trigger Conditions.

Hope this helps!

Here are some more Power Automate / Cloud Flows posts you might want to check –

  1. Read OptionSet Labels from CDS/Dataverse Triggers or Action Steps in a Flow | Power Automate
  2. InvalidWorkflowTriggerName or InvalidWorkflowRunActionName error in saving Cloud Flows | Power Automate Quick Tip
  3. Create a Team, add Members in Microsoft Teams upon Project and Team Members creation in PSA / Project Operations | Power Automate
  4. Using outputs() function and JSON Parse to read data from missing dynamic value in a Flow | Power Automate
  5. Make On-Demand Flow to show up in Dynamics 365 | Power Automate
  6. Run As context in CDS (Current Environment) Flow Trigger | Power Automate
  7. Adaptive Cards for Outlook Actionable Messages using Power Automate | Power Platform
  8. Task Completion reminder using Flow Bot in Microsoft Teams | Power Automate
  9. Using triggerBody() / triggerOutput() to read CDS trigger metadata attributes in a Flow | Power Automate
  10. Terminate a Flow with Failed/Cancelled status | Power Automate

Thank you!!

Brought to you by Dr. Ware, Microsoft Office 365 Silver Partner, Charleston SC.

Calling Graph API from Azure Logic Apps using delegated permissions

Calling Graph API from Azure Logic Apps using delegated permissions

This article is contributed. See the original author and article here.

Microsoft Graph API is a powerful REST API that enables access to cloud resources and it supports two types of permissions, application and delegated permissions. 


 


Some operations do not support application permissions, it only support delegated permissions.


 


To call Graph API from Azure Logic Apps using delegated permissions, follow the steps below:


 


1. Register an app, add required delegated API permissions to your registered app and grant admin consent.



  1. Go to your Azure Active directory

  2. From left side menu, click on Manage -> App registerations

  3. Click + New registeration

  4. Specify a name for the registered app and click Register, app Overview is opened.

  5. Copy the Application (client) id and Directory (tenant) id to a text editor for later useInitialize.png

  6. From left side menu, click on Manage -> Certificates & secrets

  7. Under Client secrets, click + New client secret

  8. Specify a description, select an expiry duration and click Add

  9. Copy the secret value to a text editor for later useInitialize.png

  10. From left side menu, click Manage -> API permissions

  11. Click + Add a permission

  12. From select an API, select Microsoft Graph

  13. Select Delegated permissions

  14. Select the permissions by checking the checkbox next to required permissions and click Add permissions

  15. Click Grant admin consent


2. In your Logic app, before the Graph API HTTP action, add another HTTP action to get an access token for Microsoft Graph:



  1. From Method dropdown list, select POST method

  2. For URI, enter https://login.microsoftonline.com/your tenant id/oauth2/token, for your tenant id, check step 1.e above

  3. Add header with key: Content-Type, value: application/x-www-form-urlencoded

  4. For Body, enter:


grant_type=password&resource=https://graph.microsoft.com&client_id=your client id&username=service account username&password=service account password&client_secret=client secret


 


Note that client_id (check step 1.e above) and client_secret (check step 1.i above) are for your registered App, service account username and password are for a user account in your active directory.


Initialize.png


3. Add Data operationsParse JSON action



  1. For Content, select Body from the Dynamic content list

  2. For Schema, enter the following schema:


{


    “properties”: {


        “access_token”: {


            “type”: “string”


        },


        “expires_in”: {


            “type”: “string”


        },


        “expires_on”: {


            “type”: “string”


        },


        “ext_expires_in”: {


           “type”: “string”


        },


        “not_before”: {


            “type”: “string”


        },


        “resource”: {


            “type”: “string”


        },


        “token_type”: {


            “type”: “string”


        }


    },


    “type”: “object”


}


Initialize.png


4. Add VariablesInitialize variable action



  1. Enter name for the variable: AuthorizationHeaderValue

  2. From Type dropdown list, select String


Initialize.png


5. Add VariablesSet variable action



  1. From name dropdown list, select AuthorizationHeaderValue variable

  2. For value, enter Bearer  access_token; note that there is a single space left after Bearer, and access_token is selected from Dynamic content list


Initialize.png


6. For the last step, the HTTP action that calls Microsoft Graph API



  1. From Method dropdown list, select required method

  2. For URI, enter the graph API method you want to call

  3. Add header with key: Authorization, value: select AuthorizationHeaderValue variable


Initialize.png


 


Your workflow should look as follows:


GraphDemo.png

Managing Hybrid Runbook Worker At Scale

Managing Hybrid Runbook Worker At Scale

This article is contributed. See the original author and article here.

Hello readers :smile:,


The Azure Automation question of today is: how can we manage (registration or de-registration) the Hybrid Runbook Workers (HRW) at scale?


In this automated world, it is fool to think that we need to go each computer one by one and run a given script to accomplish the task for the question above. My customers were struggling to find a solution to the question.


For those of you which are not aware of what an HRW is, let me give a brief description of it: Hybrid Runbook Worker feature of Azure Automation can be used to run runbooks directly on the machine (read: inside the guest OS) that’s hosting the role and against resources in the environment to manage those local resources. Hence, this feature can enable the interaction with any physical or virtual on-prem server, Azure VM as well as with any 3rd party cloud VMs.


You can read more on the official documentation page at https://docs.microsoft.com/en-us/azure/automation/automation-hybrid-runbook-worker


 


HRW.png


 


Coming back to the question, I found some methods to manage your HRWs at scale. The choice, which is always up to you, could be influenced by the products and the configurations already in use in your data center.


Below, I am going to describe 3 common ways:



Let’s start then …


 


Using Azure Automation State Configuration


As first method presented here, we can use Azure Automation State Configuration to manage our HRW at scale. Thanks to my colleague @Anthony Watherston, I was able to provide my customer with a DSC configuration file to fulfill the request.


In this case, the given computer(s), has to be already onboarded as DSC node (see Enable Azure Automation State Configuration | Microsoft Docs for more details).


So, assuming that DSC nodes are configured correctly, you can move on adding your configuration and then compiling it to make it usable by the nodes. Last step will be to assign a compiled configuration to a node (or nodes) to be applied to.


I will not dig into all necessary phases (adding, compiling, and assigning configuration). I’ll just focus on the method and will provide you with the sample configuration file (basically a .ps1 file) that you can compile and use to onboard the HRW.


 


 


NOTE: This script can onboard either a single HRW or a group, depending on the optional parameter hrwName. If you pass an empty value, then it will be assigned to the NetBIOS computer name, thus creating a single HRW.


 


 


 

Configuration OnboardHRW
{
    Param(
        [Parameter(Mandatory=$True)]
        [ValidateNotNullOrEmpty()]
        [string]$primaryKey,

        [Parameter(Mandatory=$True)]
        [ValidateNotNullOrEmpty()]
        [string]$endPointUrl,

        [Parameter(Mandatory=$false)]
        [string]$hrwName
        )

    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'

    Node localhost
    {
        Script onboard
        {
            GetScript = { return @{Present = $true } }
            TestScript = {
                if (Test-Path HKLM:SOFTWAREMicrosoftHybridRunbookWorker)
                {
                    $epURL = $using:endPointUrl
                    $dir = Get-ChildItem HKLM:SOFTWAREMicrosoftHybridRunbookWorker | Where-Object PSChildName -eq $epURL.Split("/")[-1]
                    if ($dir)
                    {
                        if((Get-ChildItem HKLM:SOFTWAREMicrosoftHybridRunbookWorker$($epURL.Split("/")[-1])).Name.Count -gt 1 )
                        {
                            return $true
                        }
                        else
                        {
                            return $false
                        }
                    }
                    else
                    { 
                        return $false
                    }
                }
                else
                {
                    return $false
                }
            }
            SetScript = {
                # Getting the AutomationAccount version directly from the folder inside the server. Saving 1 parameter.
                $AzureAutomationVersion = Get-ChildItem -LiteralPath "C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation" | Select -ExpandProperty Name

                # Validating group name paramter or setting the HRW name to be the NetBIOS computer name
                $myHrwName = $using:hrwName

                if(([string]::IsNullOrEmpty($myHrwName)) -or ([string]::IsNullOrWhitespace($myHrwName)))
                {
                    $myHrwName = $env:COMPUTERNAME
                }
                else
                {
                    $myHrwName = $myHrwName.Trim()
                }

                Import-Module -FullyQualifiedName "C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation$AzureAutomationVersionHybridRegistrationHybridRegistration.psd1"
                Add-HybridRunbookWorker -GroupName $myHrwName -Url $using:endPointUrl -Key $using:primaryKey
            }
        }
    }
}

 


 


You can modify the above configuration to be compiled using PowerShell instead of using the Azure State Configuration from the portal or to unregister the HRW. Give the Azure Automation State Configuration enough time (based on the node onboarding settings you have specified) and you will get your HRW registered on all assigned nodes.


 


The ‘PowerShell Remoting’ way


Another good method that I followed during some of my on-sites, is based on a PowerShell script that I created to make the HRW management at scale possible.


I came up with the idea of having a list of HRW, for instance in a csv file (in this case the content is supposed to be a 1:1 match of the HRW names with the computer names plus the necessary action) and passing each record as well as the necessary additional parameters to the script. This script could be executed from one computer to manage (just) one or more servers, according to what’s in the list. In case of multiple entries, we could leverage the PowerShell Remoting.


The structure of the csv is quite simple, it’s just a list of names followed by the corresponding action and separated by a comma (“,”) like the one in the screenshot below:


 


ServerList.PNG


 


The script will read the list and for every record will perform the registration:



  • Locally if the local computer name is equal to one of the records.

  • Remotely using PowerShell Remoting, if none of the records is matching the local computer name.


 


 


NOTE: Actions have been defined according to those available in the HybridRegistration PowerShell module. Refresh is an additional one which just execute Remove and Add in sequence.


 


 


The remote installation will be done using a dedicated remote session established every time with the New-PSSession cmdlet.


 


You can leverage my sample script below or create a brand new one if you like. The code I used is:


 


 

param(
        [Parameter(Mandatory=$True,
                ValueFromPipelineByPropertyName=$false,
                HelpMessage='Insert the automation account endpoint from the Azure Portal --> Automation Account --> Keys --> URL',
                Position=0)]
                [string]$AutomationAccountURL,
        [Parameter(Mandatory=$True,
                ValueFromPipelineByPropertyName=$false,
                HelpMessage='Insert the automation account key from the Azure Portal --> Automation Account --> Keys --> Primary Access Key',
                Position=0)]
                [string]$AutomationAccountKey
)

#Region Functions

Function doAction ([string]$fAction, [string]$fAutomationAccountURL, [string]$fAutomationAccountKey, [string]$fAzureAutomationVersion, [string]$fRegKey)
{
    #Logging action and computer
    Write-Host "Performing action <$fAction> on server <$env:COMPUTERNAME>"

    Switch($fAction)
    {
        "Remove"
        {
            try
            {
                Remove-HybridRunbookWorker -url $fAutomationAccountURL -key $fAutomationAccountKey -ErrorAction Stop
                write-host "The hybrid worker <$env:COMPUTERNAME> has been succesfully de-registered." -ForegroundColor Green
            }
            catch
            {
                Write-Host "The hybrid worker <$env:COMPUTERNAME> was not registered."
            }
            
            if (Test-Path $fRegKey)
			{
				write-host "Deleting the corresponding registry key <$fRegKey> and all its subkeys."
				Remove-Item $fRegKey -Recurse
				write-host "Registry key <$fRegKey> and all its subkeys have been successfully deleted." -ForegroundColor Green
			}
			else
			{
				write-host "The corresponding registry key <$fRegKey> was not existing or has been succesfully removed by the de-registration process" -ForegroundColor Yellow
			}

    		# Restarting the service
            Restart-Service healthservice
        }

        "Add"
        {
            if(Test-Path "C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation$fAzureAutomationVersionHybridRegistration")
            {
                cd "C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation$fAzureAutomationVersionHybridRegistration"
                Import-Module .HybridRegistration.psd1
                try
                {
                    Add-HybridRunbookWorker -Name $env:COMPUTERNAME -EndPoint $fAutomationAccountURL -Token $fAutomationAccountKey -ErrorAction Stop
                    write-host "The hybrid worker <$env:COMPUTERNAME> has been succesfully registered." -ForegroundColor Green
                }
                catch
                {
                    Write-Host "Exception generated while registering hybrid worker <$env:COMPUTERNAME>. The error is: $($_.exception)" -ForegroundColor Red
                }
            }
            else
            {
                write-host "Path 'C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation$fAzureAutomationVersionHybridRegistration' does not exist on computer <$env:COMPUTERNAME>. Check if the MMA is installed and that the AzureAutomation version folder is correct." -ForegroundColor Red
            }
        }

        "Refresh"
        {
            # Performing a remove operation
            try
            {
                Remove-HybridRunbookWorker -url $fAutomationAccountURL -key $fAutomationAccountKey -ErrorAction Stop

				if (Test-Path $fRegKey)
				{
				    Remove-Item $fRegKey -Recurse
				}

    		    # Restarting the service
                Restart-Service healthservice

				# Performing an Add operation
				if(Test-Path "C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation$fAzureAutomationVersionHybridRegistration")
				{
					cd "C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation$fAzureAutomationVersionHybridRegistration"
					Import-Module .HybridRegistration.psd1
					try
					{
							Add-HybridRunbookWorker -Name $env:COMPUTERNAME -EndPoint $fAutomationAccountURL -Token $fAutomationAccountKey -ErrorAction Stop
							write-host "The hybrid worker <$env:COMPUTERNAME> has been succesfully re-registered (refresh)." -ForegroundColor Green
					}
					catch
					{
							Write-Host "Exception generated while registering hybrid worker <$env:COMPUTERNAM>. The error is: $($_.exception)" -ForegroundColor Red
					}
				}
				else
				{
						write-host "Path 'C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation$fAzureAutomationVersionHybridRegistration' does not exist. Check if the MMA is installed and that the AzureAutomation version folder is correct." -ForegroundColor Red
				}
			}
            catch
            {
                Write-Host "Exception generated while removing hybrid worker <$env:COMPUTERNAME>. The error is: $($_.exception)" -ForegroundColor Red
            }
        }
    }
}

#endregion

$currentLocation = Get-Location
$regKey = "HKLM:SOFTWAREMICROSOFTHybridRunbookWorker"
$AzureAutomationVersion = Get-ChildItem -LiteralPath "C:Program FilesMicrosoft Monitoring AgentAgentAzureAutomation" | Select -ExpandProperty Name

$srvList = Get-Content ".ServerList.csv"
ForEach ($srv in $srvList) 
{
    If (!($srv -like "#*")-and !([string]::IsNullOrEmpty($srv)))
    {
        #parsing file
        [string]$srvName = $srv.Split(",")[0].trim(""",""");
        [string]$Action = $srv.Split(",")[1].trim(""",""").trim(" "," ");

        Set-Location $currentLocation
        Start-Transcript -Path ".Manage-HybridWorker-At-Scale-$srvName.Log"

        if($srvName -eq $env:COMPUTERNAME)
        {
            #Installing locally
            Write-Host "======================================================" -ForegroundColor Magenta
            Write-Host "======================================================" -ForegroundColor Magenta
            write-host "Executing locally on server <$srvName>." -ForegroundColor Cyan
            doAction $Action $AutomationAccountURL $AutomationAccountKey $AzureAutomationVersion $regKey
        }
        else
        {
            #Installing remotely
            Write-Host "======================================================" -ForegroundColor Magenta
            Write-Host "======================================================" -ForegroundColor Magenta
            write-host "Connecting to server <$srvName> using PowerShell Remote session." -ForegroundColor Cyan
            $psrSess = New-PSSession -ComputerName $srvName

            If($psrSess.State -eq "Opened")
            {
                Invoke-Command -Session $psrSess -ScriptBlock ${function:doAction} -Args $Action, $AutomationAccountURL, $AutomationAccountKey, $AzureAutomationVersion, $regKey
                #write-host "Installation on server <$srvName>, finished." -ForegroundColor Green
            }
            else
            {
                write-host "Error opening the remote session on server <$srvName>" -ForegroundColor Green
            }
            Remove-PSSession $psrSess
        }

        Stop-Transcript
    }
}

Set-Location $currentLocation

#Logging and of script
Write-Host "All the servers in the file have been processed."
Write-Host "<<End of script>>"

 


 


To run it, you can use the command below. Make sure you replace the highlighted values:


 


 

.Manage-HybridWorker-At-Scale.ps1 -AutomationAccountURL "<PUT_YOUR_AUTOMATIONACCOUNT_URL>" -AutomationAccountKey "<PUT_YOUR_AUTOMATIONACCOUNT_PRIMARYACCESSKEY>"

 


 


Leveraging SCOM


There’s also another way to achieve our goal. During a customer engagement, something shone a light in me. This customer was still using SCOM and he had the SCOM Management management pack (aka mp) from Kevin Holman imported. Should you want to know more about importing management packs, please refer the How to Import, Export, and Remove an Operations Manager Management Pack | Microsoft Docs page.


One of the greatest features in this MP is that you can execute any PowerShell script. Here comes the idea. Since all the agents were directly connected with Log Analytics and the necessary solution in place (see Deploy a Windows Hybrid Runbook Worker in Azure Automation | Microsoft Docs), why not using this agent task passing a one-line script to it? Doing this way, we could make multiple selection, meaning that we will configure at scale.


By now, you should have everything necessary in place to go ahead with this proposed approach. If so:



  1. Open the Operations Console (see How to Connect to the Operations and Web Console | Microsoft Docs).

  2. In the bottom-left corner, select Monitoring.


 


Monitoring.png


 



  1. In the folder list, navigate to the SCOM Management view folder, expand it and select SCOM Agents.


ScomAgents.png


 



  1. In the center pane, select the agents you want to register as HRW.


ScomAgents_2.png


 



  1. In the Task pane on the right, under the SCOM Management Base Class Tasks, click on the task called Execute any PowerShell.


ExecuteAnyPowerShell.png


 



  1. Click on Override.


Override.png


 



  1. Configure the ScriptBody parameter with one of the commands below according to the purpose and click Override:

    • To register:




 

Add-HybridRunbookWorker -Name "$env:COMPUTERNAME" -EndPoint "<YourAutomationAccountUrl>" -Token "<YourAutomationAccountPrimaryAccessKey>”

 



  • To un-register:


 

Remove-HybridRunbookWorker -url "<YourAutomationAccountUrl>" -key "<YourAutomationAccountPrimaryAccessKey>"

 


 


ScriptBody.png


 


NOTE: You should replace the values in the above command with those pertaining to your environment.


 


 



  1. Click Run.


Run.png


 


These 3 methods are surely not the only ones existing, but they’re a good starting point to start thinking AT SCALE. Isn’t it :happyface:?


 


Thanks for reading,


Bruno.