Anyone who Administers Workspace ONE would know the massive black hole that is logging. There are some, but its quite limited in what it returns back to UEM for consumption.
This is where Log Smuggler comes in.
What is Log Smuggler?
It is exactly what the same says, a script that is executed to “Smuggle” logs in Workspace ONE’s log collection process.
How does it work?
Log Smuggler is a three part process, unfortunately.
The first is a native package with a powershell script in it, the script is written to capture the logs we want, zip it up, and place it in the appropiate folder. More on that in a sec.
The second is basically running the Hub Device logs.


Powershell goodness!
Ok on to the script that does the work, you can pretty much put what you want in here to capture from the remote system. Eventlogs, patching logs, random whatever logs.
So all we have done above is just some general setup, where we are going to stick the logs temporarily.
########################### Airwatch Registry Install Logs ## Setup Log Paths $machineLogPath="$destinationFolder\WS1AppDeploymentLogs\System" if(!(Test-Path $machineLogPath)) { New-Item -Path $machineLogPath -ItemType Directory | Out-Null } $UserLogPath="$destinationFolder\WS1AppDeploymentLogs\User" if(!(Test-Path $UserLogPath)) { New-Item -Path $UserLogPath -ItemType Directory | Out-Null } ## Extract Machine Install Logs $apps=Get-ChildItem "HKLM:\SOFTWARE\AirWatchMDM\AppDeploymentAgent\S-1-5-18" foreach ($a in $apps) { $properties=Get-ItemProperty $a.PSPath $Logfile="$machineLogPath\" + $properties.Name +"-"+$properties.version+"-mdm.log" "Application: " + $properties.Name | out-file $Logfile -Force "Version: " + $properties.Version |out-file $Logfile -Append "Last Error Description: "+ $properties.LastErrorDesc|out-file $Logfile -Append "Last Error HRESULT: " + $properties.LastErrorHRESULT|out-file $Logfile -Append "Last Status Code: " + $properties.LastStatusCode|out-file $Logfile -Append "Dependencies: " + $properties.ReferencedDependencies|out-file $Logfile -Append "Is installed: " + $properties.IsInstalled|out-file $Logfile -Append "==================================================================================="|out-file $Logfile -Append $properties.LastDeploymentLog |Out-File $Logfile -append } ## Extract User Install Logs $AirWatchKeys=Get-ChildItem "HKLM:\SOFTWARE\AirWatchMDM\AppDeploymentAgent" $userKey=$AirWatchKeys.name -like "S-1-12-1-*" foreach($key in $AirWatchKeys) { $k=$key.name -split "\\" if ($k[4] -like "S-1-12-1-*") { $userkey=$k[4] } } $apps=Get-ChildItem "HKLM:\SOFTWARE\AirWatchMDM\AppDeploymentAgent\$userKey" foreach ($a in $apps) { $properties=Get-ItemProperty $a.PSPath $Logfile="$UserLogPath\" + $properties.Name +"-"+$properties.version+"-mdm.log" "Application: " + $properties.Name | out-file $Logfile -Force "Version: " + $properties.Version |out-file $Logfile -Append "Last Error Description: "+ $properties.LastErrorDesc|out-file $Logfile -Append "Last Error HRESULT: " + $properties.LastErrorHRESULT|out-file $Logfile -Append "Last Status Code: " + $properties.LastStatusCode|out-file $Logfile -Append "Dependencies: " + $properties.ReferencedDependencies|out-file $Logfile -Append "Is installed: " + $properties.IsInstalled|out-file $Logfile -Append "==================================================================================="|out-file $Logfile -Append $properties.LastDeploymentLog |Out-File $Logfile -append }
Why VMware decided to put app install logs in to the registry will always be a mystery, but the above snippet extracts those logs in to something more usable.
##########################Applocker rules ## Setup Log Paths $applockereLogPath="$destinationFolder\Applocker" if(!(Test-Path $applockereLogPath)) { New-Item -Path $applockereLogPath -ItemType Directory } wevtutil.exe epl "Microsoft-Windows-AppLocker/EXE and DLL" /q:"*[System[TimeCreated[timediff(@SystemTime) <= $eventLogTimeFilter]]]" "$applockereLogPath\Applocker_exe_and_dll.evtx" wevtutil.exe epl "Microsoft-Windows-AppLocker/MSI and Script" /q:"*[System[TimeCreated[timediff(@SystemTime) <= $eventLogTimeFilter]]]" "$applockereLogPath\Applocker_MSI_and_Script.evtx" wevtutil.exe epl "Microsoft-Windows-AppLocker/Packaged app-Deployment" /q:"*[System[TimeCreated[timediff(@SystemTime) <= $eventLogTimeFilter]]]" "$applockereLogPath\Applocker_Packaged_App_Deployment.evtx" wevtutil.exe epl "Microsoft-Windows-AppLocker/Packaged app-Execution" /q:"*[System[TimeCreated[timediff(@SystemTime) <= $eventLogTimeFilter]]]" "$applockereLogPath\Applocker_Packaged_App_Execution.evtx"
Microsoft Applocker eventlogs. Handy since there is no easy way to centrally manage them in the first place.
#######################Application Event Log wevtutil epl Application /q:"*[System[TimeCreated[timediff(@SystemTime) <= $eventLogTimeFilter]]]" "$destinationFolder\Application.evtx" #######################SecurityEvent Log wevtutil.exe epl Security "$destinationFolder\Security.evtx" #######################System Event Log wevtutil.exe epl System /q:"*[System[TimeCreated[timediff(@SystemTime) <= $eventLogTimeFilter]]]" "$destinationFolder\System.evtx" #######################Setup Event Log wevtutil.exe epl Setup /q:"*[System[TimeCreated[timediff(@SystemTime) <= $eventLogTimeFilter]]]" "$destinationFolder\Setup.evtx"
Your bog stock standard eventlogs. Huzzah.
############################Systeminfo systeminfo.exe |out-file "$destinationFolder\Systeminfo.log"
Systeminfo has some handy… well.. info.
Things like Last boot time, OS install date, Hardware info, timezones etc….
#######################OMA-DM Event Logs wevtutil.exe epl Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin "$destinationFolder\Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider-Admin.evtx" wevtutil.exe epl Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Operational "$destinationFolder\Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider-Operational.evtx" ####################Registry Items for Oma-Dm reg export HKLM\SOFTWARE\Microsoft\EnterpriseDesktopAppManagement $destinationFolder\EnterpriseDesktopAppManagement.reg reg export HKLM\SOFTWARE\Microsoft\Enrollments $destinationFolder\Enrollments.reg reg export HKLM\SOFTWARE\Microsoft\Provisioning\OMADM $destinationFolder\OMADM.reg
These are an important log for modern management, and are great for troubleshooting issues with Profiles, especially custom CSP’s.
#################################Running Processes get-process -IncludeUserName |Format-Table -AutoSize | out-file "$destinationfolder\proceses.log" #################################Running services Get-service | Format-Table -AutoSize| out-file "$destinationfolder\services.log" #################################Scheduled tasks schtasks /query | out-file "$destinationFolder\ScheduledTasks.log" #################################Local Admin Group Members Get-LocalGroupMember administrators | Out-File "$destinationFolder\LocalAdmins.log" #################################Devices Get-PnpDevice | Format-Table -AutoSize | out-file "$destinationFolder\devices.log"
The comments speak for themselves, but handy info to have when troubleshooting.
#################################Windows Update Information $x=Get-WindowsUpdateLog -LogPath "$destinationFolder\WindowsUpdates.Log" | Out-Null Copy-Item -Path C:\windows\logs\cbs\CBS.log $destinationFolder Copy-Item -Path C:\Windows\Logs\CBS\CBSPersist*.log $destinationFolder
Microsoft freaking updates. The bane of any IT admins existance. Logs that are handy for troubleshooting this mess.
################################# Firewall Logs $firewallLogPath="$destinationFolder\Firewall" if(!(Test-Path $firewallLogPath)) { New-Item -Path $firewallLogPath -ItemType Directory | Out-Null } Get-NetFirewallRule -Direction Inbound -Enabled True | Export-Csv "$firewallLogPath\InboundEnabledRules.csv" Get-NetFirewallRule -Direction Outbound -Enabled True | Export-Csv "$firewallLogPath\OutboundEnabledRules.csv" Get-NetFirewallRule |Export-Csv "$firewallLogPath\AllRules.csv" ####################Dism Log Copy-Item -path C:\Windows\Logs\DISM\dism.log $destinationFolder ####################Network WLAN Report Start-Process -FilePath netsh -ArgumentList "wlan show wlanreport" -Wait -NoNewWindow $zip=Compress-Archive -Path C:\ProgramData\Microsoft\Windows\WlanReport -DestinationPath "$destinationFolder\Wlan-Report.zip" -CompressionLevel Optimal -Force #Get Installed Apps Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Export-Csv $destinationFolder\InstalledApps64.csv -NoTypeInformation Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Export-Csv $destinationFolder\InstalledApps32.csv -NoTypeInformation #Windows store logging wevtutil.exe epl Microsoft-Windows-Store/Operational "$destinationFolder\WindowsStore.evtx" Wevtutil.exe epl Microsoft-Windows-AppXDeployment/Operational "$destinationFolder\AppXDeployment.evtx" wevtutil.exe epl Microsoft-Windows-AppXDeploymentServer/Operational "$destinationFolder\AppXDeployment-Server-Operational.evtx" wevtutil.exe epl Microsoft-Windows-TWinUI/Operational "$destinationFolder\Microsoft-Windows-TwinUI-Operational.evtx"
More logs. Grab what you need, add what you want. Chuck out what you don’t want. Its flexible, I just find having too much is better than not enough.
############################Zip it up $zip=Compress-Archive -Path "$destinationFolder\*" -DestinationPath "C:\ProgramData\Airwatch\UnifiedAgent\Logs\DigitalWorkplaceLogs.zip" -CompressionLevel Optimal -force | out-null Remove-Item $destinationFolder -Force -Recurse | Out-Null
And finally the Zipping and the shoving of the zip in to c:\ProgramData\Airwatch\UnifiedAgent\Logs, all ready to be grabbed by the log collection task.
Please remember this is just an example of what you can grab, excuse my coding, it could be done better but time is at a premium when you are rolling out a new platform in a short time period.
The Native Package
I’m not going to go in to how to create a package in UEM, there are good docos on the VMware docs website that cover the topic.
What I will go in to is how to get around some of the limitations. Chief one being, you cannot rerun a successfully run package.
I find this to be a major limitation, and one that I’ve raised via the feature request portal, as well as in direct meetings with VMware, however this isn’t a whinefest so to the workaround!
Set the package to always fail. Yup, its that easy. I’ve set the retry to 0, timeout to 5 minutes and the “When to Call Install Complete” criteria to rubbish.

The ending
And that is pretty much all there is to it.
This opens up a world of possibilities as far as getting information out of a managed Windows 10 box.
Comment below if there are other logs you’ve added, or anything else really.