Using the Intune Management Extension, on a 64-bit platform, for a very happy New Year!

Let’s start the New Year with a quick tip about the Intune Management Extension, which is used for running PowerShell scripts, in combination with a 64-bit platform. The Intune Management Extension is 32-bit and will run PowerShell scripts in a 32-bit environment. This is not always the desired behavior. Actually, many activities and/or cmdlets, require a 64-bit environment. In this blog post I’ll provide a simple workaround, to run the PowerShell scripts in a 64-bit environment, and I’ll show the behavior of that simple workaround.

The (example) script

Now let’s start by looking at that simple workaround. That workaround is actually a simple addition to a script that starts the same script, by using the 64-bit environment of PowerShell. This is achieved by starting with the following assumptions:

  • The script  doesn’t have to deal with parameters – This saves me from doing difficult with providing parameters to it;
  • The script should only switch on a 64-bit platform running a 32-bit process – This makes sure that it won’t break on a 32-bit platform. That can be achieved by using $ENV:PROCESSOR_ARCHITEW643. That environment variable is set when running a 32-bit process on a 64-bit platform;
  • The script needs the right location of PowerShell – This makes sure that this time the 64-bit environment of PowerShell will be started. That can be achieved by using SysNative. That alias is used to point a 32-bit process to C:\Windows\System32;
  • The script needs the right location of the script – This makes sure that the same script is started again. That can be achieved by using $PSCOMMANDPATH. That automatic variable contains the full path and file name of the script that is being run.

These four assumptions bring me to the following small script snippet that can be added to the top of any script. For looking at the results, I’ve added an additional line at the beginning and the ending of the script snippet. Those additional lines write the environment of the process to a file.

Begin: $ENV:PROCESSOR_ARCHITECTURE” >> “C:\Windows\Temp\Test.txt”
If ($ENV:PROCESSOR_ARCHITEW6432 -eq “AMD64”) {
     Try {
         &”$ENV:WINDIR\SysNative\WindowsPowershell\v1.0\PowerShell.exe” -File $PSCOMMANDPATH
     }
     Catch {
         Throw “Failed to start $PSCOMMANDPATH”
     }
     Exit
}

“End: $ENV:PROCESSOR_ARCHITECTURE” >> “C:\Windows\Temp\Test.txt”

Important: The Intune Management Extension will only report over the initial script. To also report over the newly started script, you might want to look into building something smart that will monitor the newly start script before exiting the initial script. The example above simply exits the initial script.

The (example) results

Let’s end this post by looking at the example script, mentioned above, when deployed via Microsoft Intune. The example script writes, at the beginning and the ending, an entry to a file named Test.txt. After a successful execution, it contains the following three entries:

  1. 64-resultThe first entry is related to the beginning of the initial script, which is triggered by the Intune Management Extension. At that moment it’s started as a 32-bit process;
  2. The second entry is related to the beginning of the newly started version of the script, which is triggered by the initial script. At that moment it’s started as a 64-bit process;
  3. The third entry is related to the ending of the newly started version of the script. At that moment it successfully went through the complete script as a 64-bit process.

More information

For more information about automatic variables in PowerShell, refer to the documentation About Automatic Variables.

Running scripts on Christmas day (and any other day)

My last blog post of this year will also be about a new (pre-release) feature of Configuration Manager, version 1710. This post will be all about the ability to create and run scripts from the Configuration Manager administration console. To be correct, the ability to create and run scripts was added in Configuration Manager, version 1706, and Configuration Manager, version 1710, added the ability to use parameters with those scripts. It completed the functionality.  My Christmas day present for the community is a walkthrough through this functionality and how it runs on the client device. After reading this post you should be able to understand how your script can create the output and how you can find the correct GUIDs to follow the activity on the client device.

Introduction

Starting with Configuration Manager, version 1706, it’s possible to run PowerShell scripts, via the Configuration Manager console, directly on client devices. Configuration Manager, version 1710, completed this functionality by adding the use of parameters. The ability to run PowerShell scripts on client devices is available in the Configuration Manager administration console, via the Run Scripts option. This makes it easier to automate tasks and, in general, the scripts are understood by a large population. It really simplifies building custom tools. Think about all the custom right-click actions that can now be integrated in this functionality. The biggest advantages of using the Run Script option, are the usage of the notification channel and getting good monitoring information. That means, quick results shown in the Configuration Manager administration console. In this post I’ll show the Run Script option by using a simple PowerShell script that will restart a service on the client device. That service is provided to the script via a script parameter.

Script

Now let’s have a look at the Run Script option in the Configuration Manager administration console. I’ll start by looking at a couple of important prerequisites, followed by how to create, approve and run scripts. I’ll end this section by following the script action to the client device.

Prerequisites

Before looking into the possibilities of the Run Script option, the following prerequisites should be in place to take full advantage of the available possibilities:

  • The client device must be running PowerShell version 3.0, or later;
  • The Configuration Manager clients must be running client version 1706, or later;

Create script

Let;s start by looking at the required steps to create a PowerShell script that can become available via the Run Script option. I’ll do that by using a simple script that can restart a service on a client device, based on the provided script parameter. Based on the result, of the script, a specific script output will be returned. The administrative user, creating the script, must have at least the Create permission for SMS Scripts object class.The following six steps walk through the creation of a PowerShell script (step 3 contains the used script):

1 Open the Configuration Manager administration console and navigate to Software Library > Overview > Scripts;
2 On the Home tab, in the Create group, click Create Script to open the Create Script wizard;
3

CS_ScriptOn the Script page, provide the following information and click Next;

  • Script name: Provide a name for the script;
  • Script language: Select PowerShell, as it’s currently the only option;
  • Script: Click Import to browse to a script file and to display it in the wizard. It’s also still possible to edit the imported script;

Note: Declaring variables, as shown with number 1 on the right, will enable an additional page in the wizard for configuring script parameters. The output shown with number 2, can be returned by the client device.

4a

CS_ScriptParametersOn the Script Parameters page, an overview is shown of the provided parameters with the script and it provides the option to set a Default Value. Select the variable and click Edit to adjust the parameter properties (see step 4b). After that, click Next.

Note: This page should provide an overview of the variables as declared in step 3.

4b

CS_ScriptParameterPropertiesOn the Script Parameter Properties dialog box, the information about the name, required status, hidden status and data type is prepopulated based on the declaration of the variable (see step 3). Use this dialog box to configure the following validation properties and click OK:

  • Minimum Length: Specify the minimum number of characters;
  • Maximum Length: Specify the maximum number of characters;
  • RegEx: Specify a regular expression validation;
  • Custom Error: Specify a custom error message.
5 On the Summary page, verify the configuration and click Next;
6 On the Completion page, verify the result and click Close.

Approve script

Before the just created PowerShell script becomes available via the Run Script option, it must be approved by another administrative user with at least the Approve permission for SMS Scripts object class. That will prevent unverified scripts from running on client devices, which should decrease the possibility of running faulty scripts on client devices. The following seven steps walk through the approval of a PowerShell script:

HierarchySettings_GeneralBy default it’s not possible for a script author to approve and/or deny their own scripts. To enable script authors to approve and/or deny their own scripts, open the Configuration Manager administration console and navigate to Administration > Overview > Site Configuration > Site. Now open the Hierarchy Settings and remove the checkbox with Do not allow script authors to approve their own scripts.

Important: It’s strongly advised to only do this in test and/or lab environments.

1 Open the Configuration Manager administration console and navigate to Software Library > Overview > Scripts;
2 Select the just created script and click Approve/Deny, in the Scripts group, on the Home tab, in the Create group, to open the Approve or deny script wizard;
3

ADS_ScriptOn the Script page, verify the script and click Next;

4

ADS_ScriptParametersOn the Script Parameters page, verify the parameters and click Next;

Note: To verify the details of a parameter, select a parameter and click Details. That will show the script parameter properties, as configured during the creation of the script.

5

ADS_ApproveScriptOn the Approve or deny script page, select Approve, provide an Approver Comment (optional) and click Next;

Note: I know this is stating the obvious, but only approve scripts once you’re certain about their behavior. The ability to run scripts on client devices is just really strong and once the script is triggered it will run almost instantly.

6 On the Summary page, verify the configuration and click Next;
7 On the Completion page, verify the result and click Close.

Run script

After approving the just created PowerShell script, it becomes available via the Run Script option. The administrative user, that will run the script, must have at least the Run permission for SMS Scripts object class and the script will be executed in SYSTEM context on the client device. The following six steps walk through running a PowerShell script:

1 Open the Configuration Manager administration console and navigate to Assets and Compliance > Overview > Device Collections;
2

Open a device collection and right-click a client device and select Run Script to open the Run Script wizard;

Note: It’s also possible to start the Run Script wizard by right-clicking a device collection.

3

RS_ScriptOn the Script page, select the just created script and click Next;

Note: The script GUID is interesting for monitoring the script execution.

4

RS_ScriptParametersOn the Script Parameters page, provide a value for the available parameters and click Next.

5 On the Summary page, verify the details and click Next;
6

RS_MonitoringOn the Monitoring page, verify the script output and click Close.

The script output, on the Summary tab, shows the output as provided in the initial script. Within this summary it’s also possible to look at the exit codes and to look at different chart forms. The Script Details tab shows the general information about the script, like the name, version and parameters and the Run Details tab shows the details about the results, like the device name, execution status, exit code and script output.

Monitor script

Now let’s end this post by looking at the monitoring options for the initiated script. This can be done in real-time, as shown in the step 6, and this can be done by looking at the Script Status node in the Monitoring workspace. Below is on overview of the just triggered script and I’ve included the following highlighted numbers:

  • Number 1 highlights the Show Status button that can be used
    to get the script details, as shown in step 6 of the Run script
    section;
  • Number 2 highlights the Client Task ID that can be used to
    follow the script through the server log files (bgbserver.log) and the client
    log files (ccmnotification.log and script.log), as shown below;
  • Number 3 highlights the Script Guid, as also shown in step
    3 of the Run script section, that can be used to follow the script
    activity in the client log files (script.log), as shown below;
  • Number 4 highlights the Script Output that can be used to
    verify the results. It should refer to the scripted output, as shown in step 3
    of the Create script section.

ConfigMgrConsole_ScriptMonitoring

Let’s continue by following the initiated script through the log files. At least the three log files below are related to this action and together those log files provide a lot of information. As there is some overlap with the log files of last week, I won’t provide the generic information about the log files this time.

BgbServer.log: When initiating a script to run on a client device, this log file shows the information about pushing the script action to the client device, followed by information about the generation of the BGB task status report (.BTS) in the bgb.box inbox (see below). The processing of the BGB task status report can be followed through the bgbmgr.log.

Script_bgbserver

CcmNotificationAgent.log: When initiating a script to run on a client device, this log file shows the arrival of the script action on the client device (see below).

Script_ccmnotification

Script.log: When initiating a script to run on a client device, this log file will show the details about the script that will be executed. That includes the earlier mentioned IDs and the command line that will be used.

Script_script

Let’s end this section by looking at the executed command line in more detail. Below is the highlighted version of the executed command line. That command line clearly shows that the script on the client device is signed, that it uses parameters and that it’s stored locally. The script is stored in C:\Windows\CCM\ScriptStore, which is a hidden folder on the client device. By default only the SYSTEM account has permissions on the script files in that folder.

Executing command line: “C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell.exe” -NoProfile -ExecutionPolicy RemoteSigned -File “C:\Windows\CCM\ScriptStore\D5FF9FBE-D25B-45DB-9771-946076A9FFAD_EB1AA60AF73737F0B342AEED2C5ECB15A9956654BDA4D30263178B3A79E79DD4.ps1” -ServiceName “Group Policy Client”

More information

For more information about the Run Script option, please refer to this article about creating and running PowerShell scripts from the Configuration Manager console.

Combining the powers of the Intune Management Extension and Chocolatey

A bit more than a week ago the Intune Management Extension was added to Microsoft Intune to facilitate the ability to run PowerShell scripts on Windows 10 devices that are managed via MDM. That addition opens a whole new world for managing Windows 10 devices via MDM. Looking at app deployment specifically, this enables the administrator to look at something like Chocolatey for deploying packages. That would make the app deployment via Microsoft Intune suddenly flexible. In this blog post I’ll start with a little introduction about the Intune Management Extension and Chocolatey, followed by the configuration of a PowerShell script to install Chocolatey packages. I’ll end this post by looking at the end result.

Introduction

Let’s start with a short introduction about the awesome Intune Management Extension. The Intune Management Extension supplements the out-of-the-box MDM capabilities of Windows 10. It will be installed automatically on Windows 10 devices, that are managed via MDM, and it simply enables administrators to run PowerShell scripts on Windows 10 devices. Those PowerShell scripts can be used to provide additional capabilities that are missing from the out-of-the-box MDM functionality. The first scenario that the Intune Management Extension enabled, for me, is super easy app deployment via Chocolatey.

Chocolatey is a global PowerShell execution engine using the NuGet packaging infrastructure. Think of it as the ultimate automation tool for Windows. Chocolatey is a package manager that can also embed/wrap native installers and has functions for downloading and check-summing resources from the Internet. Super easy for installing application packages on Windows 10 devices.

Configuration

Now let’s have a look at the configuration. The configuration contains 3 steps. The first step is to create the required PowerShell script, the second step is to upload the PowerShell script to Intune and the third step is to assign the PowerShell script to an Azure AD group.

Step 1: Create PowerShell script

The first step is to create a PowerShell script that will check for the installation of Chocolatey, and that will install Chocolatey if it’s not yet installed. Once Chocolatey is installed the PowerShell script will install the required Chocolatey packages. Now let’s walk through the PowerShell script that I’ll use to do exactly that. The first thing that the script uses, are 2 variables. The first variable $ChocoPackages contains an array with the required Chocolatey packages and the second variable, $ChocoInstall, contains the default installation directory of Chocolatey (see below).

$ChocoPackages = @(“googlechrome”,”adobereader”,”notepadplusplus.install”,”7zip.install”)

$ChocoInstall = Join-Path ([System.Environment]::GetFolderPath(“CommonApplicationData”)) “Chocolatey\bin\choco.exe”

The second thing that the PowerShell script does is verifying the existence of the installation of Chocolatey. This is done by simply testing for the existence of choco.exe by using the $ChocoInstall variable. When choco.exe is not found, the online installation of Chocolatey will be triggered (see below).

if(!(Test-Path $ChocoInstall)) {
     try {

         Invoke-Expression ((New-Object net.webclient).DownloadString(‘https://chocolatey.org/install.ps1’)) -ErrorAction Stop
     }
     catch {
         Throw “Failed to install Chocolatey”
     }      
}

The third and last thing that the PowerShell script does is triggering the installation of the Chocolatey packages. This is done by running through the Chocolatey packages in the $ChocoPackages variable. For every package the installation will be triggered by using Chocolatey (see below).

foreach($Package in $ChocoPackages) {
     try {
         Invoke-Expression “cmd.exe /c $ChocoInstall Install $Package -y” -ErrorAction Stop
     }
     catch {
         Throw “Failed to install $Package”
     }
}

Now put these three pieces together in one script and save it as a PowerShell script (.ps1).

Step 2: Upload PowerShell script

The second step is to upload the created PowerShell script in Intune. To upload the PowerShell script, follow the next 5 steps.

1 Open the Azure portal and navigate to Intune > Device configuration > PowerShell scripts;
2 On the Device configuration – PowerShell scripts blade, click Add script to open the Script Settings blade;
3

Intune_AddPowerShellScriptOn the Add PowerShell script blade, provide the following information and click Settings to open the Script Settings blade;

  • Name: Provide a valid name for the PowerShell script policy;
  • Description: (Optional) Provide a description for the PowerShell script policy;
  • Script location: Browse to the PowerShell script.

Note: The script must be less than 10 KB (ASCII) or 5 KB (Unicode).

4

Intune_ScriptSettingsOn the Script Settings blade, provide the following configuration and click OK to return to the PowerShell script blade;

  • Run the script using the logged on credentials: No;
  • Enforce script signature check: No;

Note: Configure Run the script using the logged on credentials to No means that the PowerShell script will run in SYSTEM context;

5 Back on the Add PowerShell script blade, click Create.

Step 3: Assign PowerShell script

The third and last step is to assign the PowerShell script to an Azure AD group. To assign the PowerShell script, follow the next 5 steps.

1 Open the Azure portal and navigate to Intune > Device configuration > PowerShell scripts;
2 On the Device configuration – PowerShell scripts blade, select the uploaded PowerShell script and click Assignments to open the {ScriptName} – Assignments blade;
3 On the {ScriptName} – Assignments blade, select the required Azure AD group and click Save.

Note: Keep in mind that the Intune Management Extension synchronizes to Intune once every hour.

Result

Now let’s end this post by looking at the end result. Yes, I can show the installed applications, but it’s better for understanding the process to look at some log files. From an Intune Management Extension perspective, the most interesting log file is IntuneManagementExtension.log. That log file is located at C:\ProgramData\Microsoft\IntuneManagementExtension\Logs. Below is an example, in which I would like to highlight 2 sections:

  1. The first section shows that the first time a PowerShell script arrives on a device, as a policy, the complete script is shown in the log file;
  2. The second section clearly shows the configuration of the PowerShell script, by showing the configuration of the signature check and the context (as configured in step 2.4);

IME_Chocolatey_Result

From a Chocolatey perspective, the most interesting log files are choco.log and choco.summary.log. These log files are located at C:\ProgramData\chocolatey\logs. To show the most interesting information, I would like to highlight 2 sections from the choco.summary.log below:

  1. The first section shows the detection of a Chocolatey packages that is already installed;
  2. The second section shows the installation of a Chocolatey package;

Choco_Chocolatey_Result

The nice thing about Chocolatey is that it already contains a lot of intelligence. A simple example of that is that it checks for the installation of the packages, before starting the installation. That enables me to use one script for installing the packages by simply adding new packages to the $ChocoPackages variable. When the script runs on the client, only the newly added packages will be installed.

Note: Keep in mind that you can also use Chocolatey for updating the installed packages.

More information

For more information about the Intune Management Extension and Chocolatey, please refer to the following articles:

Updated tool: Remote Mobile Device Manager

My early Christmas present, for the community, is an updated version of my Remote Mobile Device Manager tool! This version includes a couple of bug fixes, a couple of added functionalities and a couple of look-and-feel adjustments. In this blog post I’ll provide an overview of those changes, I’ll provide an overview of the new look-and-feel and I’ll show the usage. For an overview of all the previously available features, please refer to my blog post about the previous version of my Remote Mobile Device Manager tool.

>> The updated version is now available for download <<

Changes

Now let’s start with a quick overview of the changes to this new release of my Remote Mobile Device Manager tool. This version includes the following changes and bug fixes:

  • Bug fix 1: In the previous release it was possible to perform remote actions on Windows 10 devices that were not applicable. This has been adjusted by first verifying the platform of the selected device, before providing the list of applicable remote actions;
  • Bug fix 2: In the previous release it could happen that devices were shown that didn’t belong to the provided user. This has been adjusted by adjusting the query, to select the devices of a user, to join on device identifier instead of device name (thanks for the suggestion Iain Fairbairn);
  • Functional 1: Added functionality to sent a sync request to
    de selected device (new functionality starting with Configuration Manager 1610);
  • Functional 2: Added functionality to get the status of a
    sync request for the selected device (new functionality starting with
    Configuration Manager 1610);
  • Look-and-feel 1: In the previous release it would show a button for every remote action. This has been adjusted to a combo box that shows applicable items based on the platform of the selected device (thanks for the suggestion Nickolaj);
  • Look-and-feel 2: Added additional columns to provide information about the serial number and the IMEI of the device (thanks for the suggestion Kent).

Overview

Let’s continue with how these changes impact the new look-and-feel of my Remote Mobile Device Manager tool. This version provides the following look-and-feel.

RMDM_v12

In this look-and-feel there are three sections that I would really like to highlight:

  1. The Remote Actions section has changed. It now provides a combo box and a single button. This combo box will only show the remote actions that are applicable to the platform of the selected device;
  2. The Sync Request and Sync Request State remote actions have been added. The Sync Request remote action will trigger a device to check for new polices and the Sync Request State remote action will show the status of the Sync Request remote action. These remote actions require Configuration Manager 1610;
  3. The Serial number and IMEI columns have been added. These columns provide information that can help with easily getting an overview of relevant information for a device.

Usage

Let’s end this post with the usage of my Remote Mobile Device Manager tool. The good news is. this hasn’t changed. It’s still built on WMI and it still doesn’t require the Configuration Manager cmdlets. Also, to start this tool the following parameters are still available:

  • SiteServer: This parameter is mandatory and should point to a server containing the SMS provider;
  • AllowWipe: This switch is optional and enables the button to wipe (factory reset) a device.

Send sync request to devices

In preparation for an upcoming new release of my Remote Mobile Device Manager tool, this week a short blog post about the Send Sync Request feature. This feature enables the administrator, in a Microsoft Intune hybrid environment, to remotely trigger a synchronization of a device and is available starting with Configuration Manager 1610. In this post I’ll provide some basic information, go through the methods to trigger this action, the Configuration Manager console and PowerShell, and I’ll provide some information about the administrator experience.

Information

Before showing the methods to use the Send Sync Request feature, it’s good to provide some information about when a device typically checks in. The first thing to keep in mind is that when an app, or policy, is deployed, Microsoft Intune will immediately attempt to notify the targeted devices to check in. This should take less than five minutes. If the device doesn’t check in to get the deployed app, or policy, Microsoft Intune tries three more times. When Microsoft Intune couldn’t reach the device, the device will get the deployed app, or policy, on the next scheduled check in. The default check in interval is shown in the table below.

Platform Just enrolled device Default
iOS and Mac OS X Every 15 minutes for 6 hours Every 6 hours
Android Every 3 minutes for 15 minutes, then every 15 minutes for 2 hours Every 8 hours
Windows Phone Every 5 minutes for 15 minutes, then every 15 minutes for 2 hours Every 8 hours
Windows 8.1/10 PCs Every 3 minutes for 30 minutes Every 8 hours

Besides the mentioned check in interval of the device, the end-user can always use the Company Portal app to immediately make the device check for policies. New in this chain is the ability of the administrator to use the Send Sync Request feature. This will request a policy sync on the device.

Method 1: Configuration Manager console

Now let’s start with the easiest method to use the Send Sync Request feature, which is using the Configuration Manager console. This can be achieved by simply performing the next steps.

1 Open the Configuration Manager administration console and navigate to Assets and Compliance > Overview > Devices.

2

MenuOptionSelect a device, managed via Microsoft Intune, right click the device and select Remote Device Actions > Send Sync Request.

Note: The same action is available when selecting a device, managed via Microsoft Intune, and selecting Remote Device Actions > Send Sync Request in the Device section of the Home tab.

Method 2: PowerShell

Next is the method that was the trigger for this blog post, which is using PowerShell. The first thing I noticed is that the Send Sync Request feature is not yet available via the Invoke-CMDeviceAction cmdlet. Not a problem, as I wanted to use WMI. Using WMI removes the requirement of the Configuration Manager cmdlets, which is great for my tool.

This can be achieved by using the Invoke-WmiMethod cmdlet. First connect to the site server (ComputerName) and the correct namespace (Namespace). Now use the SyncNow (Name) method, of SMS_DeviceMethods (Class), with the device identifier as parameter (ArgumentList). Below is an example that brings these parameters together.

Invoke-WmiMethod -ComputerName $SiteServer ` -Namespace root/SMS/site_$($SiteCode) ` -Class SMS_DeviceMethods ` -Name SyncNow ` -ArgumentList ($MobileDeviceId) ` -ErrorAction Stop

Administrator experience

Usually I’ll end my post with showing the end-user experience, but in this case it’s more interesting to look at the administrator experience. The administrator can add an additional column, named Sync Request State, in the Configuration Manager administration console, when looking at devices. That column will provide the status of the sync request, as shown below.

SyncAdminConsole

Another interesting location, to look at, is the SMSProv.log. That log file shows the execution of the sync request. Once the administrator uses the Send Sync Request feature, a similar activity, as shown below, will be available in the log file.

SyncSMSProv

More information

Fore more information about the Send Sync Request feature and the device check in interval, please refer to:

Use PowerShell and Microsoft Graph to access data in Microsoft Intune

This week a short blog about using PowerShell to access data in Microsoft Intune. This can be achieved by using Microsoft Graph. A couple of weeks ago there was a blog post on the Microsoft Intune Support Team Blog about Using the Microsoft Graph API to access data in Microsoft Intune. That post triggered me to look at the PowerShell possibilities, as the Microsoft Graph has an API and an API can be used with PowerShell.

In this blog post I’ll provide the high-level prerequisites for connecting to the Microsoft Graph API and I’ll provide a few examples for querying Microsoft Intune data.

Prerequisites

This blog post is really focused on the queries to the Microsoft Intune data. However, to successfully connect with the Microsoft Graph API there are a few prerequisites that should be in place.

Examples

Now let’s have a look at the PowerShell versions of the published Microsoft Graph Explorer commands and the results of them. I’ll go through all of them and provide the required input and show an example result

User

The first example is to get data related to a single user. This requires a user principal name (UPN), in my case pvanderwoude@petervanderwoude.nl, and the token as input.

Invoke-RestMethod https://graph.microsoft.com/v1.0/users/$UPN ` -Method Get ` -Headers @{"Authorization" = "Bearer $accessToken"}

userUPN

Owned devices

The second example is to get data related to the devices of a single user. Thee information is about the compliance state of the devices of the user. This requires a user principal name (UPN), in my case pvanderwoude@petervanderwoude.nl, and the token as input. The returned information is stored in a hash table.

Invoke-RestMethod https://graph.microsoft.com/v1.0/users/$UPN/ownedDevices ` -Method Get ` -Headers @{"Authorization" = "Bearer $accessToken"}

registeredDevices

Registered owners

The third example is to get the owners of a device. This requires a device GUID and the token as input. The returned information is stored in a hash table.

Invoke-RestMethod https://graph.microsoft.com/v1.0/devices/$GUID/registeredOwners ` -Method Get ` -Headers @{"Authorization" = "Bearer $accessToken"}

registeredOwners

Registered users

The fourth example is to get the users of a device. This requires a device GUID and the token as input. The returned information is stored in a hash table.

Invoke-RestMethod https://graph.microsoft.com/v1.0/devices/$GUID/registeredUsers ` -Method Get ` -Headers @{"Authorization" = "Bearer $accessToken"}

registeredUsers

Applications

The fifth example is to get a list of uploaded applications in Microsoft Intune. This requires the token as input and the returned information is stored in a hash table. However, based on the returned  information, it currently seems to return the applications registered in Azure AD.

Invoke-RestMethod https://graph.microsoft.com/beta/applications ` -Method Get ` -Headers @{"Authorization" = "Bearer $accessToken"}

petervanderwoude.nl

More information

Fore more information about the Microsoft Graph API, in combination with Microsoft Intune and the different tokens, please refer to:

Windows 10 MDM and the MDM Bridge WMI Provider

This week another blog post about Windows 10 and OMA-DM, but this week will be short and different. Starting this week I won’t be referring to OMA-DM anymore, instead I’ll be referring to Windows 10 MDM. The main reason for that is change is to align with Microsoft. Also, it simply makes more sense. OMA-DM is the standards based protocol on which the Windows 10 MDM protocol is based. In other words, Windows 10 MDM is not exactly the same as the OMA-DM standards. Technically speaking it’s not wrong to refer to OMA-DM, but it simply makes more sense to refer to Windows 10 MDM.

That being said, this blog post will be different for another reason. This week I’ll try to bring Windows 10 MDM closer to the regular methods, by simply pointing out the existence of the MDM Bridge WMI Provider. This post is all about creating awareness.

MDM Bridge WMI Provider

One of the most heard comments about Windows 10 MDM is related to the lack of knowing what’s happening. Well, I can’t really take that away, maybe the newly introduced logging in 1607 can, but I can show how to see the changes of the Windows 10 MDM configurations.

The MDM Bridge WMI Provider is the bridge to the Windows 10 MDM capabilities. An easy method to see what’s happening is using a WMI Explorer, or something simple as Windows Management Instrumentation Tester (wbemtest). Simply connecting to the root\cimv2\mdm\dmmap namespace is similar to connecting to the MDM Bridge WMI Provider. The classes in this namespace all translate to a configuration service provider (CSP) of Windows 10 MDM. This makes it fairly easy to see what’s happening to the configurations done via Windows 10 MDM.

Below is an example of the MDM_Policy_Result01_Experience02 class, in which the AllowManualMDMUnenrollment instance property was changed during the enrollment of the device. That class and instance property relates to the configuration OMA-URI of ./Vendor/MSFT/Policy/Config/Experience/AllowManualMDMUnenrollment.

Before After
BeforeEnroll AfterEnroll

Knowing this immediately opens up another world. This enables everyone to get information through the MDM Bridge WMI Provider by simply using PowerShell. Looking at the previous example, I can simply use the following PowerShell command, as there is only one instance, to get the information as shown in the table below.

Get-CimInstance -Namespace "root\cimv2\mdm\dmmap" ` -ClassName "MDM_Policy_Result01_Experience02"

Before After
BeforeEnroll_PS AfterEnroll_PS

This also means that the MDM Bridge WMI Provider can be used to trigger configuration changes through Windows 10 MDM. For now, I’ll leave that up to everyone’s imagination.

Important notes

There are a few important notes about the MDM Bridge WMI Provider that should be known and I’ll try to summarize them briefly:

  • Administrative permissions are required to connect with the MDM Bridge WMI Provider. Without those permissions there will be an access denied error when connecting to the MDM Bridge WMI Provider;
  • The local system context is required to view and adjust device settings. This can be achieved by using something like PsExec.exe;
  • Be aware that there is a difference between user settings and device settings. Specific user settings won’t show when connected in the system context and specific device settings won’t show when connected in the user context;
  • Be aware that my example mixed Config and Result properties and nodes. That’s related to the design of the Policy CSP. The Config section handles the configurations requests and the Result section provides a read-only path to the actual configuration.

More information

Fore more information about Windows 10 MDM, the Windows 10 CSP and the MDM Bridge WMI Provider, please refer to:

New tool: Remote Mobile Device Manager

This blog post will be about a new tool, written in PowerShell, to remotely manage mobile devices. This tool is based on the ConfigMgr SDK and contains all the available options for remotely managing mobile devices. That means it can retire, wipe, lock and pin reset mobile devices. Basically, it’s a version 2.0 of the tool I made a couple of months ago. That tool is limited to the ConfigMgr 2012 R2 functionality, of wipe and retire, and this new tool also contains the ConfigMgr 2012 R2 SP1 functionality, of lock and pin reset.

The use case for this tool is still the same. In most cases the service desk is responsible for helping end-users with their mobile devices. What if the company rather not provides the ConfigMgr console to the service desk? What if the company wants to prevent the service desk from wiping a mobile device? Well, that’s were this tool comes in place. This tool provides the possibility to remotely manage mobile devices without using the ConfigMgr console and it also provides the possibility to prevent the usage of the wipe functionality.

>> Available via download here on the TechNet Galleries! <<

Overview

RMDM_Overview_v10Now lets start with a good overview of this tool. The interface is pretty straight forward. It provides a textbox to provide a username. This textbox has a tooltip to provide information about the required information. After providing a username the Get Mobile Devices button can be used to get the registered (primary) mobile devices of the specified user.

The mobile devices, of the specified user, will be shown in the datagridview. After selecting a mobile device, in the datagridview, the Reset Passcode, the View Passcode State, the Remote Lock, the View Remote Lock State, the Retire and the Wipe buttons will enable, if applicable and if allowed. The Wipe and Reset Passcode functionality are not applicable for Windows (RT) devices. Also, the Wipe functionality needs to be specifically enabled via the AllowWipe switch.

Messages

This tool provides a lot of messages based on the actions performed by the administrative user. Based on the action the following messages can show.

RMDM_UseVerVal_v10The error message Please provide a valid username. will show when no username was specified. Together with this error message, also the error message Please verify the username will show next to the textbox.
RMDM_UseVerExi_v10The error message Please provide an existing username. will show when a wrong, not existing, username was specified. Together with this error message, also the error message Please verify the username will show next to the textbox.
RMDM_UseVerPri_v10The error message Please provide an user with a primary mobile device. will show when the specified username has no (primary) mobile device(s) configured. Together with this error message, also the error message Please verify the username will show next to the textbox.

RMDM_UseVerCon_v10The error message Please verify the connection with the specified site server. will show when something else went wrong. Based on the second part of the error message it can be determined at which stage this happened.

In most cases these error messages will be prevented already because of the check at the startup of the tool. During the startup it will try to get the SiteCode based on the specified SiteServer. When this action fails, the tool won’t start and it will show the error message Unable to connect to the SMS Provider location on <SiteServer>..

RMDM_PinStaInf_No_v10The informational message There is no PINRESET state information available for the mobile device named <Name>. will show when the View Passcode State button is used and no PINRESET state information is available.
RMDM_PinVer_v10The verification message Are you sure that you want to PINRESET the mobile device named <Name>? will show when the Reset Passcode button is used.
RMDM_PinNot_v10The informational message The action to PINRESET the mobile device named <Name> is successful initiated. will show when the action to PINRESET the device is successful initiated.
RMDM_PinStaInf_v10The information message about the PINRESET state information will show when the View Passcode State button is used and PINRESET state information is available.
RMDM_LocStaInf_No_v10The informational message There is no LOCK state information available for the mobile device named <Name>. will show when the View Remote Lock State button is used and no LOCK state information is available
RMDM_LocVer_v10The verification message Are you sure that you want to LOCK the mobile device named <Name>? will show when the Remote Lock button is used.
RMDM_LocNot_v10The informational message The action to LOCK the mobile device named <Name> is successful initiated. will show when the action to LOCK the device is successful initiated.
RMDM_LocStaInf_v10The informational message about the LOCK state information will show when the View Remote Lock State button is used and LOCK state information is available.
RMDM_RetVer_v10The verification message Are you sure that you want to RETIRE the mobile device named <Name>? will show when the Retire button is used.
RMDM_RetNot_v10The informational message The action to RETIRE the mobile device named <Name> is successful initiated. will show when the action to RETIRE the device is successful initiated.
RMDM_WipVer_v10The verification message Are you sure that you want to WIPE the mobile device named <Name>? will show when the Wipe button is used.
RMDM_WipNot_v10The informational message The action to WIPE the mobile device named <Name> is successful initiated. will show when the action to WIPE the device is successful initiated.

Usage

Before this tool can be used, the administrative user, or service account, used to start this tool, requires at least the permissions as described in this post and the permissions to read user device affinities (User Device Affinities > Read). Besides those permissions, there are no special requirements for using this tool. I also didn’t use the ConfigMgr cmdlets, which completely removes the dependency to install the ConfigMgr console, or to do something creative with the ConfigMgr cmdlets.

To start this tool the following parameters are available.

  • SiteServer: This parameter is mandatory and should point to a server containing the SMS provider;
  • AllowWipe: This switch is optional and enables the button to wipe a mobile device.

All these parameters together will make a complete example look like this.

.\Manage-MobileDevice_v10.ps1 -SiteServer CLDSRV02 -AllowWipe

Thanks

A special thanks goes to everybody that volunteered to do some beta testing of this tool. Thank you Nickolaj, John, Jörgen, Stefan, Kim and Tom!

Invoke remote device actions via PowerShell

This will be a short blog post about a the newly introduced WMI class, in the latest service pack, called SMS_DeviceAction. As I’m currently working on a new tool to remotely manage mobile devices, which will be released soon, I noticed that the SMS_DeviceAction class is used to invoke and query the Lock and PinReset actions. What’s even more important is the fact that the SMS_DeviceAction class isn’t documented, yet. In this blog post I’ll post the required information to successfully query the SMS_DeviceAction class and to successfully invoke the methods of the SMS_DeviceAction class.

Methods

The SMS_DeviceAction class contains the method InvokeAction. The InvokeAction method requires the following input parameters.

Parameter Data Type Description
Action String This parameter is required and should contain the name of the Action. That name can be either Lock or PinReset.
ResourceID Unit32 This parameter is required and should contain the Resource ID of the mobile device.
ResourceType Unit32 This parameter is required and should contain the Resource Type of the mobile device. The Resource Type of a mobile device is 5.

Properties

The SMS_DeviceAction class contains the following properties.

Property Data Type Description
Action String This property contains the name of the Action. That name is either Lock or PinReset.
LastUpdateTime String This property contains the time of the latest status change and is stored in the WMI time format.
ResourceID Unit32 This property contains the Resource ID of the mobile device.
ResourceText String This property contains the Response Text of the PinReset action.
SMSID String This property contains the ID of the mobile device.
SourceType Unit32 This property contains the Source Type of the mobile device.
State Unit32 This property contains the state of the action. The state will be 1 for completed and 4 for pending.

Examples

Now lets go through a couple of examples to show the usage of the SMS_DeviceAction class. This first example shows a simple query to get the information of a specific mobile device and the Lock action.

Get-WmiObject -ComputerName $SiteServer ` -NameSpace root/SMS/site_$($SiteCode) -Class SMS_DeviceAction ` -Filter "Action='Lock' and ResourceID='$MobileDeviceId'"

This second example shows an invoke of the Lock action, on a specific mobile device, via the InvokeAction method.

Invoke-WmiMethod -ComputerName $SiteServer ` -Namespace root/SMS/site_$($SiteCode) -Class SMS_DeviceAction ` -Name InvokeAction -ArgumentList ("Lock",$MobileDeviceId,5)

Automagically set the mobile device owner to company

Before I’ll start with this blog post I would like to say thank you to Kim Oppalfens, for his great suggestion to look at WMI Eventing. I didn’t know that it was that versatile and powerful! Thanks Kim!

Scenario

DeviceOwnerThe scenario for this post is actually quite simple and is applicable to an environment with Microsoft Intune integrated with ConfigMgr. By default, the device owner of a mobile device is set to Personal and that’s not always the desired value. A lot of customers still provide their employees with (mobile) devices and want the tooling to reflect that information. This blog post will provide an automagic method to set the mobile device owner to Company, by default. The best thing is that it’s still possible to switch a mobile device to Personal if that’s required. Only newly added mobile devices will be automagically set to Company.

Solution

Now let’s start about the solution for this scenario. Initially I thought that I could easily tackle this scenario via a Status Filter Rule, only to find out that there is no status message generated for the creation of a new mobile device object. That was the moment that I needed advice and I got pointed in to the direction of WMI Eventing. In the rest of this blog post I’ll describe the key parts of the scripts that I used to automatigally set the mobile device owner to Company after it’s enrolled. The complete scripts are available for download in the TechNet Galleries.

>> Available via download here on the TechNet Galleries! <<

The action

Before I’ll start with explaining the key parts of the script for using WMI for monitoring and responding to events, I’ll start with a short piece about changing the device owner, similar to this post about changing the device ownership. As mentioned in that post, I can simply use call the WMI method ChangeOwnership, of the SMS_Collection class, by providing the device owner and the resource id. Together that would make the action to change the device owner look like this.

Invoke-WmiMethod -ComputerName $SiteServer ` -Namespace root\SMS\site_$($SiteCode) -Class SMS_Collection ` -Name ChangeOwnership -ArgumentList @($DeviceOwner,$ResourceId) ` -ErrorAction Stop

The event filter

WMI_EventFilterThe first thing that I need to create now is the event filter, as shown in the picture. An event filter is a WMI class that describes which events WMI delivers to a physical consumer. It also describes the conditions under which WMI delivers the events. Let’s start with the latter and start with describing the conditions. To do this I use the following hash table that contains the conditions for the event filter.

$PropertyHash = @{ QueryLanguage = "WQL"; Query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 ` WHERE TargetInstance ISA 'SMS_R_System' AND ` TargetInstance.DeviceOwner = '2'"; Name = "DeviceOwnerFilter"; EventNameSpace="root\sms\site_$($SiteCode)" }

The most important part of the conditions is the query. In this query I select the creation, by using __InstanceCreationEvent, of mobile devices, by using  TargetInstance ISA ‘SMS_R_System’ AND TargetInstance.DeviceOwner = ‘2’, every 5 seconds, by using WITHIN 5. Effectively this query will run twice every 5 seconds and the differences are my results. I can imagine that running this every 5 seconds might be too aggressive, in that case simply adjust this value to any desired number.

Now, to create an event filter, I need to create a new instance of the __EventFilter class. To do this I can use the New-CimInstance cmdlet together with the just defined hash table, like this.

$InstanceFilter = New-CimInstance -Namespace root\subscription ` -ClassName __EventFilter -Property $PropertyHash -ErrorAction Stop

The event consumer

WMI_EventConsumerThe next thing that I need to create is the event consumer, as shown in the picture. An event consumer can be used to perform actions based on events. Each consumer takes a specific action after it receives an event notification. Let’s start with describing the actions for the consumer. To do this I use the following hash table that contains the actions for the event consumer.

$PropertyHash =@{ Name = "DeviceOwnerConsumer"; CommandLineTemplate = "PowerShell.exe ` -File $ScriptPath\Change-Ownership.ps1 -SiteServer $SiteServer` -SiteCode $SiteCode -DeviceOwner 1 ` -ResourceId %TargetInstance.ResourceId%" }

The most important part in the defined action is, of course, the location of the script file that performs the action. Almost as important is to get the resource id of the mobile device, as input for the action script.  Luckily, every instance creation event contains an embedded object called TargetInstance, which, in this case, is a representation of the created SMS_R_System object. That TargetInstance object is what I can use as input in my script, like this %TargetInstance.ResourceId%.

In this case I choose to use a command line event consumer. That means I need to create a new instance of the CommandLineEventConsumer class. To do this I use the New-CimInstance cmdlet, again, together with the just defined hash table, like this.

$InstanceConsumer = New-CimInstance -Namespace root\subscription ` -ClassName CommandLineEventConsumer -Property $PropertyHash ` -ErrorAction Stop

Binding the filter and the consumer

WMI_EventBindingThe last thing that I have to do, is to bind the event filter with the event consumer, as shown in the picture. This will make sure that when an event occurs that matches the specified filter, the action specified by the consumer will occur. To do this I first create the following hash table that contains a reference to the event filter and the event consumer.

$PropertyHash = @{ Filter = [ref]$InstanceFilter; Consumer = [ref]$InstanceConsumer }

Now I need to relate them by creating a new instance of __FilterToConsumerBinding. To do this I use the New-CimInstance cmdlet, one last time, together with the hash table, like this.

$InstanceBinding = New-CimInstance -Namespace root/subscription ` -ClassName __FilterToConsumerBinding -Property $PropertyHash ` -ErrorAction Stop

Result

The result of all of this is an event consumer that will change the device owner of every mobile device that’s found by the event filter. There are multiple way’s to verify that everything is created and working as expected. To check if everything is created in WMI, as scripted, either use PowerShell or simply use a WMI Explorer.

More importantly, to check if the consumer is working as expected, simply check the event viewer. My script to change the device owner writes a 3000 event in the Application log for every successful change and a 3001 event for every failure. Both of them use the SMS Server as source. A good place to check the functionality of the event filter is to look at the SMSProv.log. This log will show a hit, in this case, every 5 seconds as shown in the example below. Every hit will be performed by the SYSTEM account.

Every5Sec

More information

For a lot more information about the basics of WMI Eventing and about how this can be used in combination with scripting, have a look at the following great posts: