jayrha / endpointanalyticsremediationscripts Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Firstly, thank you! this is one of the most useful and impactful remediation scripts I have found.
We are using C4B to maintain our devices in conjunction with this script. Detection is working well, but remediation is failing the RemediationStatus 5 and RemediationScriptStatus Timed out
Investigating this in the IntuneManagementExtension.log located in C:\ProgramData\Microsoft\IntuneManagementExtension\Logs with CMTrace, I can see that Proactive Remediation has a timeout of 3600 seconds.
Is it possible to create multiple 'Remediations' using the same detection script against different groups and remediate in a different way?
ie. All devices have a setting of 'change-me' with a value of 1, I need to change one group of devices to a value of 2 and another group to a value of 3.
Running the Winget Update remediation script.
<#
Version: 1.0
Author:
- Joey Verlinden (joeyverlinden.com)
- Andrew Taylor (andrewstaylor.com)
- Florian Slazmann (scloud.work)
- Jannik Reinhard (jannikreinhard.com)
Script: winget-upgrade-remediate.ps1
Description: Updates all apps via Winget
Hint: This is a community script. There is no guarantee for this. Please check thoroughly before running.
Version 1.0: Init
Run as: System
Context: 64 Bit
#>
$Winget = Get-ChildItem -Path (Join-Path -Path (Join-Path -Path $env:ProgramFiles -ChildPath "WindowsApps") -ChildPath "Microsoft.DesktopAppInstaller*_x64*\AppInstallerCLI.exe")
&$winget upgrade --all --force --silent
However, it fails. I enabled script logging on a Windows 11 x64 Enterprise Edition and ran the script there. Output is below.
What could be the reason?
**********************
Windows PowerShell transcript start
Start time: 20230711185706
Username: WORKGROUP\SYSTEM
RunAs User: WORKGROUP\SYSTEM
Configuration Name:
Machine: DESKTOP-TU33KA5 (Microsoft Windows NT 10.0.22621.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -executionPolicy bypass -file C:\WINDOWS\IMECache\HealthScripts\aa5e509b-0345-44ee-b489-64231866412e_5\remediate.ps1
Process ID: 31824
PSVersion: 5.1.22621.1778
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.22621.1778
BuildVersion: 10.0.22621.1778
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20230711185706
**********************
PS>CommandInvocation(remediate.ps1): "remediate.ps1"
**********************
Windows PowerShell transcript start
Start time: 20230711185706
Username: WORKGROUP\SYSTEM
RunAs User: WORKGROUP\SYSTEM
Configuration Name:
Machine: DESKTOP-TU33KA5 (Microsoft Windows NT 10.0.22621.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -executionPolicy bypass -file C:\WINDOWS\IMECache\HealthScripts\aa5e509b-0345-44ee-b489-64231866412e_5\remediate.ps1
Process ID: 31824
PSVersion: 5.1.22621.1778
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.22621.1778
BuildVersion: 10.0.22621.1778
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
**********************
Command start time: 20230711185707
**********************
PS>CommandInvocation(Out-String): "Out-String"
>> ParameterBinding(Out-String): name="InputObject"; value="The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object."
The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name,
a script block, or a CommandInfo object.
At C:\WINDOWS\IMECache\HealthScripts\aa5e509b-0345-44ee-b489-64231866412e_5\remediate.ps1:18 char:2
+ &$winget upgrade --all --force --silent
+ ~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : BadExpression
The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name,
a script block, or a CommandInfo object.
At C:\WINDOWS\IMECache\HealthScripts\aa5e509b-0345-44ee-b489-64231866412e_5\remediate.ps1:18 char:2
+ &$winget upgrade --all --force --silent
+ ~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : BadExpression
The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command
name, a script block, or a CommandInfo object.
At C:\WINDOWS\IMECache\HealthScripts\aa5e509b-0345-44ee-b489-64231866412e_5\remediate.ps1:18 char:2
+ &$winget upgrade --all --force --silent
+ ~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : BadExpression
**********************
Command start time: 20230711185707
**********************
PS>$global:?
True
**********************
Windows PowerShell transcript end
End time: 20230711185707
**********************
Multiple devices are displaying the following in PreRemediationDetectionScriptError
C:\WINDOWS\IMECache\HealthScripts\344df8ae-cb9b-466b-bfe3-088003882b53_2\detect.ps1 : Error reading apps: Exception
calling "Substring" with "2" argument(s): "Length cannot be less than zero.
Parameter name: length"
The DetectionScriptStatus returns Without Issues and RemediationScriptStatus Not run
I needed the functionality to not only update or create registry keys, but also to Delete registry keys. I altered your code to reflect this and I thought I would share with you in case anyone else needed the same functionality.
Change-MultipleRegistryKeysDetection.ps1
`
<#
Version: 1.0
Author:
<#
Description: This script creates the registry keys defined below.
Output: (single line)
If ok, a prefix string (33) + each the key name
e.g: All OK | Registry values created: YourFirstKeyName, YourSecondKeyName
If not ok, a prefix string (52) + each created key (without the not created keys)
e.g: Something went wrong :-( | Registry values created: YourFirstKeyName, YourSecondKeyName
Author: Rob Whitley
2024-07-17 Added functionality to handle the Action 'Delete'
#>
#region Define registry keys to create here
$RegistrySettingsToValidate = @(
[pscustomobject]@{
Action = 'Delete'
Hive = 'HKLM:'
Key = 'SOFTWARE\Contoso\Product'
Name = 'ImportantKey'
Type = ''
Value = 0
},
[pscustomobject]@{
Action = 'Update'
Hive = 'HKLM:'
Key = 'SOFTWARE\Contoso\Product'
Name = 'AnotherKey'
Type = 'REG_SZ'
Value = "SomeValue"
}
)
#endregion
#region helper functions, enums and maps
$RegTypeMap = @{
REG_DWORD = [Microsoft.Win32.RegistryValueKind]::DWord
REG_SZ = [Microsoft.Win32.RegistryValueKind]::String
REG_QWORD = [Microsoft.Win32.RegistryValueKind]::QWord
REG_BINARY = [Microsoft.Win32.RegistryValueKind]::Binary
REG_MULTI_SZ = [Microsoft.Win32.RegistryValueKind]::MultiString
REG_EXPAND_SZ = [Microsoft.Win32.RegistryValueKind]::ExpandString
}
#endregion
#region Create registry keys
$Output = "Something went wrong :-("
$Names = @()
$ExitCode = 1
Foreach ($reg in $RegistrySettingsToValidate) {
$DesiredAction = $reg.Action
$DesiredPath = "$($reg.Hive)$($reg.Key)"
$DesiredName = $reg.Name
$DesiredType = $RegTypeMap[$reg.Type]
$DesiredValue = $reg.Value
#Write-Host "Creating registry value: $DesiredPath | $DesiredName | $($reg.Type) | $DesiredValue"
# Check if the Action is Delete
If ($DesiredAction -eq 'Delete') {
Remove-ItemProperty -Path $DesiredPath -Name $DesiredName
$Names += $DesiredName
} Else {
If (-not (Test-Path -Path $DesiredPath)) {
New-Item -Path $DesiredPath -Force | Out-Null
}
New-ItemProperty -Path $DesiredPath -Name $DesiredName -PropertyType $DesiredType -Value $DesiredValue -Force -ErrorAction SilentlyContinue | Out-Null
$Names += $DesiredName
}
}
#endregion
#region Check if registry keys are set correctly
If ($Names.count -eq $RegistrySettingsToValidate.count) {
$ExitCode = 0
} else {
$ExitCode = 1
}
#endregion
Write-Output $Output
Exit $ExitCode
`
Change-MultipleRegistryKeysRemediaton.ps1
`
<#
Version: 1.0
Author:
<#
Description: This script creates the registry keys defined below.
Output: (single line)
If ok, a prefix string (33) + each the key name
e.g: All OK | Registry values created: YourFirstKeyName, YourSecondKeyName
If not ok, a prefix string (52) + each created key (without the not created keys)
e.g: Something went wrong :-( | Registry values created: YourFirstKeyName, YourSecondKeyName
Author: Rob Whitley
2024-07-17 Added functionality to handle the Action 'Delete'
#>
#region Define registry keys to create here
$RegistrySettingsToValidate = @(
[pscustomobject]@{
Action = 'Delete'
Hive = 'HKLM:'
Key = 'SOFTWARE\Contoso\Product'
Name = 'ImportantKey'
Type = ''
Value = 0
},
[pscustomobject]@{
Action = 'Update'
Hive = 'HKLM:'
Key = 'SOFTWARE\Contoso\Product'
Name = 'AnotherKey'
Type = 'REG_SZ'
Value = "SomeValue"
}
)
#endregion
#region helper functions, enums and maps
$RegTypeMap = @{
REG_DWORD = [Microsoft.Win32.RegistryValueKind]::DWord
REG_SZ = [Microsoft.Win32.RegistryValueKind]::String
REG_QWORD = [Microsoft.Win32.RegistryValueKind]::QWord
REG_BINARY = [Microsoft.Win32.RegistryValueKind]::Binary
REG_MULTI_SZ = [Microsoft.Win32.RegistryValueKind]::MultiString
REG_EXPAND_SZ = [Microsoft.Win32.RegistryValueKind]::ExpandString
}
#endregion
#region Create registry keys
$Output = "Something went wrong :-("
$Names = @()
$ExitCode = 1
Foreach ($reg in $RegistrySettingsToValidate) {
$DesiredAction = $reg.Action
$DesiredPath = "$($reg.Hive)$($reg.Key)"
$DesiredName = $reg.Name
$DesiredType = $RegTypeMap[$reg.Type]
$DesiredValue = $reg.Value
#Write-Host "Creating registry value: $DesiredPath | $DesiredName | $($reg.Type) | $DesiredValue"
# Check if the Action is Delete
If ($DesiredAction -eq 'Delete') {
Remove-ItemProperty -Path $DesiredPath -Name $DesiredName
$Names += $DesiredName
} Else {
If (-not (Test-Path -Path $DesiredPath)) {
New-Item -Path $DesiredPath -Force | Out-Null
}
New-ItemProperty -Path $DesiredPath -Name $DesiredName -PropertyType $DesiredType -Value $DesiredValue -Force -ErrorAction SilentlyContinue | Out-Null
$Names += $DesiredName
}
}
#endregion
#region Check if registry keys are set correctly
If ($Names.count -eq $RegistrySettingsToValidate.count) {
$ExitCode = 0
} else {
$ExitCode = 1
}
#endregion
Write-Output $Output
Exit $ExitCode
`
Typo in the Path
HKLM:\SSYSTEM\CurrentControlSet\Control\TimeZoneInformation
Should be:
HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
The script used to detect the last time a system was restarted gives an error on my Windows 10 build (19045.2728 Dutch)
https://github.com/JayRHa/EndpointAnalyticsRemediationScripts/blob/main/Toast-RebootMessage/detect-reboot.ps1
The error is
`
Cannot convert value "1680444208,84456" to type "System.Int32". Error: "De indeling van de invoertekenreeks is onjuist."
At line:1 char:1
It's triggered by the command $diff = $now - $poweron, but the problem is probably related to the values of $now and $poweron.
The returned values in the original script are
1680444208,84456
for $now and 1680444197,71884
for $differ.
If you replace the , with a . by changing the $now and $differ to these commands, it works.
$now = (Get-Date -UFormat "%s" -Date (Get-Date)) -replace (",",".")
$poweron = (Get-Date -UFormat "%s" -Date (Get-Process -Id $pid).StartTime) -replace (",",".")
New values are 1680444208.84456
for $now and 1680444197.71884
for $differ and then the calculations work.
I think it has something to do with the region we run in our enviroment Windows (Dutch), so the characters used for numbering might differ.
I would like to ask for help with a challenge I am having with an Intune script for detection and remediation. Despite multiple attempts, I have been encountering issues when uploading it to the Intune Admin Portal.
Problem Overview:
Detection Status: Shows "With Issues" or sometimes "Without issues"
Remediation Status: Shows "Recurred" or "Failed"
Attempts to Resolve:
Exit Code Adjustments: I have tried adjusting the exit codes within the script to ensure proper success (exit 0) and failure (exit 1) signaling.
Logging: Implemented logging within the script to capture any errors or unexpected behavior, but the root cause remains elusive.
Syntax Checks: Checked for syntax errors and verified the compatibility of PowerShell commands with the Intune execution environment.
Environment Testing: Tested the script locally on a device to ensure it runs as expected, without encountering errors.
Intune Logs Examination: Reviewed the IntuneManagementExtension.log on the endpoint for potential error messages, but no clear resolution emerged.
I would greatly appreciate your insights. Please share any suggestions, best practices, or potential pitfalls to look out for. I am open to feedback on script structure, exit codes, or any other considerations that might impact the script's behavior in the Intune environment.
Here are my full script details. Your expertise and guidance would be immensely valuable in helping me overcome this challenge.
$adminUsername = "OfflineAdmin"
$defaultPassword = "MESY@15586!!!"
$logFilePath = "C:\ps_script_logs\ChangeLog.txt"
if (Get-LocalUser -Name $adminUsername -ErrorAction SilentlyContinue) {
# Admin user exists, check if the password has changed
$currentPassword = (Get-LocalUser -Name $adminUsername).Password
if ($currentPassword -ne $defaultPassword) {
# Password has changed, log the event
Add-Content -Path $logFilePath -Value "$(Get-Date) - Admin password changed."
# Set exit code for password change
Exit 1
} else {
# Password has not changed, exit with code 0 (no action needed)
Exit 0
}
}
else {
Admin user doesn't exist, exit with code 2 (requires remediation)
Exit 2
}
===========================================================
$adminUsername = "OfflineAdmin"
$defaultPassword = "MESY@15586!!!"
$logFilePath = "C:\ps_script_logs\RemediationLog.txt"
$password = ConvertTo-SecureString -String $defaultPassword -AsPlainText -Force
Set-LocalUser -Name $adminUsername -Password $password
Set-LocalUser -Name $adminUsername -PasswordNeverExpires $true -CannotChangePassword $true
Add-Content -Path
Exit 0
Thank you in advance for your time and assistance. I am eager to learn from your experiences and insights.
Hello I'm looking for a Remediation Script to detect outdated Defender Antivirus Client and Definitions once detected the remediation would then go and check for the update and update the client and definitions.
Could anyone assist with this please.
Hi there. Can I request a detection and remediation script that checks if the below registry value is 0, and if not sets it to 0 please?
Thanks.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CI\Policy]
"VerifiedAndReputablePolicyState"=dword:00000000
I'm not exactly the best GitHub user. But from my point of view the following would fit here at most:
My idea for a new remediation script:
I often see that Microsoft Teams is no longer updated automatically by Intune (as a part of the Microsoft 365 Apps-Suite) on computers that were joined to Azure a long time ago. The regular user does not have the rights for a manual update because of "Teams Machine-Wide Installer" is forbidden to touch for him. A weekly check by proactive remediations could ensure that all Teams installations are up to date. But not easy to realize.
I tried to check by "winget upgrade" and if "Teams Machine-Wide Installer" is found then do the "CheckMsiOverride.ps1" script by Github TeamsMsiOverride
But no success. Maybe you can find a working solution ...
Typo in the Path:
HKLM\SSYSTEM\CurrentControlSet\Control\TimeZoneInformation
Should be:
HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
In the comments for "Uninstall-Private teams" the context "Admin" is documented, which is wrong.
The problem is, that the following line is executed in a user context:
Get-AppxPackage -Name MicrosoftTeams | Remove-AppxPackage -ErrorAction stop
Microsoft documentation for Get-AppxPackage:
Gets a list of the app packages that are installed in a user profile.
The script would work if executed in the user context. But you could also rewrite it, and add the flag "-allusers", to Get-AppxPackage so that you can run the script as admin. More Information:
https://learn.microsoft.com/en-us/powershell/module/appx/get-appxpackage?view=windowsserver2022-ps
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.