Intune Client-Side Logs in Windows 10

Note to self (and anyone interested!) about the client-side location of logs and management components of Intune on a Windows 10 device.

Diagnostic Report

A diagnostic report can be generated client-side from Settings > Access Work and School > Connected to <Tenant>’s Azure AD > Info > Create Report

The report will be saved to:

C:\Users\Public\Public Documents\MDMDiagnostics\MDMDiagReport.html

Intune Management Extension

Information on the parameters for the IME can be found in the registry:

HKLM:\Software\Microsoft\EnterpriseDesktopAppManagement\<SID>\MSI\<ProductCode>

The MSI itself can be found here, together with an installer log:

C:\Windows\System32\config\systemprofile\AppData\Local\mdm

Note: if you disconnect a device from Azure AD and rejoin it again, you will need to reinstall the IME as it will have a different device identifier.

IME logs can be found here:

C:\ProgramData\Microsoft\IntuneManagementExtension\Logs

The logs are:

  • AgentExecutor
  • ClientHealth
  • IntuneManagementExtension

Script Execution

When a PowerShell script is run on the client from Intune, the scripts and the script output will be stored here, but only until execution is complete:

C:\Program files (x86)\Microsoft Intune Management Extension\Policies\Scripts

C:\Program files (x86)\Microsoft Intune Management Extension\Policies\Results

A transcript of the script execution can be found underneath C:_showmewindows (a hidden folder)

The full content of the script will also be logged in the IntuneManagementExtension.log (be careful of sensitive data in scripts!)

The error code and result output of the script can also be found in the registry:

HKLM:\Software\Microsoft\IntuneManagementExtension\Policies\<UserGUID>\<ScriptGUID>

Event Logs

There are a couple of MDM event logs which can be found here:

Applications and Services Logs > Microsoft > Windows > DeviceManagement-Enterprise-Diagnostics-Provider

Services

The IME runs as a service called “Microsoft Intune Management Extension”. You can restart this to force a check for new policies.

Scheduled Task

The IME runs a health evaluation every day as a scheduled task, and logs the results in the ClientHealth.log:

Microsoft > Intune > Intune Management Extension Health Evaluation

If you know of any other log locations, please let me know!

Lots of great info on the IME by Oliver Kieselbach here and here.

Create Disk Usage Reports with PowerShell and WizTree

Recently I discovered a neat little utility called WizTree, which can be used to report on space used by files and folders on a drive. There are many utilities out there that can do that, but this one supports running on the command line which makes it very useful for scripting scenarios. It also works extremely quickly because it uses the Master File Table on disk instead of the slower Windows / .Net methods.

I wanted to create a disk usage report for systems that have less than 20GB of free space – the recommended minimum for doing a Windows 10 in-place upgrade – so that I can easily review it and identify files / folders that could potentially be deleted to free space on the disk. I wanted to script it so that it can be run in the background and deployed via ConfigMgr, and the resulting reports copied to a server share for review.

The following script does just that.

First, it runs WizTree on the command line and generates two CSV reports, one each for all files and folders on the drive. Next, since the generated CSV files contain sizes in bytes, the script imports the CSVs, converts the size data to include KB, MB and GB, then outputs to 2 new CSV files.

The script then generates 2 custom HTML reports that contain a list of the largest 100 files and folders, sorted by size.

Next it generates an HTML summary report that shows visually how much space is used on the disk and tells you how much space you need to free up to drop under the minimum 20GB-free limit.

Finally, it copies those reports to a server share, which will look like this:

fs

The Disk Usage Summary report will look something like this:

dus

And here’s a snippet from the large directories and files reports:

ld

lf

There are also CSV reports which contain the entire list of files and directories on the drive:

csv

To use the script, simply download the WizTree Portable app, extract the WizTree64.exe and place it in the same location as the script (assuming 64-bit OS).  Set the run location in the script (ie $PSScriptRoot if calling the script, or the directory location if running in the ISE), the temporary location where it can create files, and the server share where you want to copy the reports to. Then just run the script in admin context.

Fix Http 500.19 Error after Removing WSUS

This post is more of a ‘note to self’ for troubleshooting IIS errors.

Recently I decided to remove the WSUS role from an SCCM distribution point as it was previously being used for patching during OSD, but now we patch only the reference image instead. After removing the WSUS role, I also did some cleanup including deleting the WSUS_Updates directory, the %Program Files%\Update Services directory and removing the WsusPool website and application pool from IIS.

After that, clients using that distribution point failed to get content for packages, returning an Http 500 error:

smsts

Checking the IIS log on the distribution point I found the following corresponding entry:

iis

The error code is 500.19 which translates to ‘Internal Server Error / Configuration data is invalid‘ and is documented in more detail in this Microsoft article. A further clue is found in the 126 windows error code, which translates to ‘The specified module could not be found‘.

Browsing to the website directly, ie http://localhost/SMS_DP_SMSPKG$, gave the following information:

siteerror

The error code 0x8007007e is the same as the windows error code 126 and also means ‘The specified module could not be found”. The module referenced in the error is the DynamicCompressionModule.

To get more detailed information on the error, I decided to enable Failed Request Tracing in IIS and log the 500.19 error. The process for enabling and using Failed Request Tracing is nicely summarised here as well as documented by Microsoft here. Using that, I found that a couple of modules were being referenced that were no longer present.

ftrerror

Following a hint from here, I checked the applicationHost.config file and found a reference to a dll in the %Program Files%\Update Services directory that was installed with WSUS and that I deleted after removing the WSUS role:


<scheme name="xpress" doStaticCompression="false" doDynamicCompression="true" dll="C:\Program Files\Update Services\WebServices\suscomp.dll" staticCompressionLevel="10" dynamicCompressionLevel="0" />

To remove the reference, I ran the following command as admin:


%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /-[name='xpress']

You can find more info on IIS modules and how to add/remove/disable/enable here.

After removing the reference to the xpress schema and restarting the W3SVC service, everything was back to normal 🙂

Find the Full Windows Build Number with PowerShell

Much to my surprise I discovered that the full build number for a Windows OS is not stored in WMI in the usual Win32_OperatingSystem class.

In Windows 10 at least, the full build number containing the “UBR”, or essentially the CU patch level of the build, is a useful piece of information.

Open Settings > System > About on a Windows 10 box, and you’ll find the OS Build value, in my case 15063.183

W10

If I run the usual WMI query to get the build number I just get 15063:

WMI

Same if I query the environment:

DotNet

To find the full number I have to query the registry in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion branch.

So I put together a PowerShell script that can be used to get the Windows version for a local or remote computer (or group of computers) which includes the Edition, Version and full OS Build values.

Query the local system like this:


Get-WindowsVersion

Or query remote computers:


Get-WindowsVersion -ComputerName PC001


Get-WindowsVersion -ComputerName @("PC001","PC002","SRV001","SRV002")

Result:

result

The script

ConfigMgr Content Distribution Fails with 0x80041001

Today I came across an unusual issue on a couple of SCCM distribution points where two particular software update packages were failing to distribute. Using the distmgr.log and the PkgXferMgr.log on the site server, as well as the Distribution Point Job Queue Manager tool, I could see that these packages were trying to distribute again and again, but returning a failure on certain files.

In the PkgXferMgr.log I found these entries repeatedly:


ExecStaticMethod failed (80041001) SMS_DistributionPoint, FinalizeContent
CSendFileAction::SendContent failed; 0x80041001
Sending failed. Failure count = 2, Restart time = 24/04/2017 15:30:57 W. Europe Daylight Time

0x80041001 is a WMI error meaning “Generic failure” – not overly helpful.

So I went to the distribution point itself to investigate, and found these entries repeatedly in the smsdpprov.log


[BA4][Mon 04/24/2017 22:24:19]:MoveFile failed for \\?\C:\SCCMContentLib\DataLib\24688509-2940-44e9-9d7d-9a6c2e33c9a1.ABC002C2.temp to \\?\C:\SCCMContentLib\DataLib\24688509-2940-44e9-9d7d-9a6c2e33c9a1
[BA4][Mon 04/24/2017 22:24:19]:FileRename failed; 0x80070005
[BA4][Mon 04/24/2017 22:24:19]:CContentDefinition::Finalize failed; 0x80070005
[BA4][Mon 04/24/2017 22:24:19]:Failed to finalize content '24688509-2940-44e9-9d7d-9a6c2e33c9a1' for package 'ABC002C2'. Error code: 0X80070005

0x80070005 means “access denied”. So I browsed to the location in Explorer and sure enough:

pic

If I try to view the Security tab on the directory, apparently I don’t have permission:

pic2

If I click Advanced, it seems we don’t have an owner, so clearly something is corrupted as the other files and directories in this location are owned by the SYSTEM account.

pic3

If I try to change the ownership in the UI, nothing happens.

So I use PSEXEC to open a cmd prompt in SYSTEM context, and try to take ownership on one of the directories, but still no joy:

pic4

Next I run Process Explorer to find if something has a handle on it, and yes, WMI does.

pic5

So I stop the WMI service, and suddenly the directory disappears!

Start the WMI service (and it’s dependencies) and then kick off the distributions again using the DP Job Queue Manager tool, and finally the packages distribute successfully 🙂

New Free Tool: ConfigMgr Remote Compliance

Remote Compliance

Today I released a new free tool for ConfigMgr administrators and support staff.

ConfigMgr Remote Compliance can be used to view, evaluate and report on System Center Configuration Manager Compliance Baselines on a remote computer. It provides similar functionality to the Configurations tab of the Configuration Manager Control Panel, but for remote computers. It is a useful troubleshooting tool for remotely viewing client compliance, evaluating baselines, viewing the evaluation report or opening DCM log files from the client, without needing to access the client computer directly.

ConfigMgr Remote Compliance can be downloaded from here.

Source code for this application is available on GitHub and code contributions are welcome.

Decrypting Remote Desktop Connection Manager Passwords with PowerShell

Today I needed to find a password for a certain account I had used before (but had forgotten), and I remembered that I had stored the credentials in the Remote Desktop Connection Manager, Microsoft’s free RD tool. Of course, it crossed my mind whether these credentials could be decrypted, and it turns out they can, quite easily, with a little PowerShell.

The credentials are stored in encrypted form in the RDG file you create for your RDP connections. It’s just an XML file, so can be easily parsed with PowerShell. Using a handy trick blogged by , I decrypted all the credentials found in the RDG file.

The passwords can only be decrypted with the user profile that added them to the RDG file, however, so they are still reasonably secure. If the credentials were added by another account or on another system, you will get a “Failed to decrypt” error as seen below, which is the same error you get if you try to copy the RDG file and open it on another computer or with another user profile.

Needless to say, I found the password I needed!

capture


# Path to RDCMan.exe
$RDCMan = "C:\Program Files (x86)\Microsoft\Remote Desktop Connection Manager\RDCMan.exe"
# Path to RDG file
$RDGFile = "$env:USERPROFILE\Documents\RDPConnections.rdg"
$TempLocation = "C:\temp"

Copy-Item $RDCMan "$TempLocation\RDCMan.dll"
Import-Module "$TempLocation\RDCMan.dll"
$EncryptionSettings = New-Object -TypeName RdcMan.EncryptionSettings

$XML = New-Object -TypeName XML
$XML.Load($RDGFile)
$logonCredentials = Select-XML -Xml $XML -XPath '//logonCredentials'

$Credentials = New-Object System.Collections.Arraylist
$logonCredentials | foreach {
    [void]$Credentials.Add([pscustomobject]@{
    Username = $_.Node.userName
    Password = $(Try{[RdcMan.Encryption]::DecryptString($_.Node.password, $EncryptionSettings)}Catch{$_.Exception.InnerException.Message})
    Domain = $_.Node.domain
    })
    } | Sort Username

$Credentials | Sort Username