Skip to content

Optimize Windows Defender exclusion script with native PowerShell #2930 #2939

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

IamLRBA
Copy link

@IamLRBA IamLRBA commented Apr 24, 2025

cc
@HannesWell
Hello,
Since the script as per @fdcastel, to add an exclusion to Windows Defender seems overly complex. Based on your concerns about the proposed Add-MpPreference -ExclusionProcess 'C:\Program Files\DBeaver\dbeaver.exe' script, this script replaces the original complex LINQ-based exclusion check with a more idiomatic and simpler version PowerShell implementation.

How It Addresses the your Concerns:

  • Duplicate Prevention: HashSet.Contains() check is just as effective as LINQ
  • Single Admin Context: All operations happen in one PowerShell invocation
  • No Growing Exclusion Lists: Only genuinely new paths get added

Fixes #2930

…ipse-platform#2930

Since the script to add an exclusion to Windows Defender seems overly complex, this script replaces the complex LINQ-based exclusion check with a more idiomatic and simpler version PowerShell implementation.

Fixes eclipse-platform#2930
@HannesWell
Copy link
Member

Thank you for this contribution. The changes look good too me and the script indeed looks cleaner. I'm not very familiar with Powershell and that was what I came up with after searching the internet a bit.

However, I could confirm that @fdcastel's objection is correct and this script could be even simpler.
If he doesn't want to contribute the simplification by himself, you could update this PR accordingly, but I would await his reaction first.

@IamLRBA
Copy link
Author

IamLRBA commented Apr 27, 2025

Thank you for this contribution. The changes look good too me and the script indeed looks cleaner. I'm not very familiar with Powershell and that was what I came up with after searching the internet a bit.

However, I could confirm that @fdcastel's objection is correct and this script could be even simpler. If he doesn't want to contribute the simplification by himself, you could update this PR accordingly, but I would await his reaction first.

Thanks for your feedback @HannesWell, If @fdcastel approves I can proceed to update the PR...as per your guidance ofcourse!
Cheers!

@fdcastel
Copy link

fdcastel commented Apr 28, 2025

Apologies for the delay (I was abroad).

I agree with @HannesWell that the script can be simplified even further.

@IamLRBA Based on my tests (and I believe @HannesWell can confirm as well), just using the call

Add-MpPreference -ExclusionProcess $pathsToExclude

should be sufficient. There is no need for any if statements or for instantiating a new Collections.Generic.HashSet[String].

@IamLRBA
Copy link
Author

IamLRBA commented Apr 30, 2025

Thank you for the feedback @fdcastel . You're right upon re-testing with just: Add-MpPreference -ExclusionProcess $pathsToExclude, the command handles duplicates cleanly without throwing errors. I’ll simplify the script accordingly and update the PR shortly.

@fdcastel, I've updated the script to simplify it as suggested. It now directly uses `Add-MpPreference -ExclusionProcess $pathsToExclude` without the extra conditionals or set creation. Let me know if anything else needs tweaking.
Thanks!
cc @HannesWell
@IamLRBA
Copy link
Author

IamLRBA commented Apr 30, 2025

@fdcastel, I've updated the script to simplify it as suggested. It now directly uses Add-MpPreference -ExclusionProcess $pathsToExclude without the extra conditionals or set creation. Let me know if anything else needs tweaking.
Thanks!
cc @HannesWell

@fdcastel
Copy link

Looks good to me! I don’t have a Java setup here to test it out, but the changes seem fine. 🚀 👍🏻

Copy link
Member

@HannesWell HannesWell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update.
Unfortunately this currently does not compile and a few points should be adjusted, but I made corresponding remarks below.

Furthermore, please squash your changes into one commit and force push that to your existing branch of this PR. Eventually we want to have this as one commit.

"if($existingExclusions -eq $null) { $existingExclusions = New-Object Collections.Generic.HashSet[String] }", //$NON-NLS-1$
"$exclusionsToAdd=[Linq.Enumerable]::ToArray([Linq.Enumerable]::Where($exclusions,[Func[object,bool]]{param($ex)!$existingExclusions.Contains($ex)}))", //$NON-NLS-1$
"if($exclusionsToAdd.Length -gt 0){ Add-MpPreference -" + exclusionType + " $exclusionsToAdd }"); //$NON-NLS-1$ //$NON-NLS-2$
String excludedPaths = paths.stream().map(Path::toString).map(p -> "'" + p.replace("'", "''") + "'")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain the advantage of using single-quotes (and escaping them) over double-quotes in a powershell script? As far as I can tell double-quotes are not allowed in Windows paths and therefore don't have to be escaped.

@@ -342,14 +342,12 @@ public static String createAddExclusionsPowershellCommand(String extraSeparator)
//
// For .NET's stream API called LINQ see:
// https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire comment block (starting at its first line) can be replaced by the following:

		// For detailed explanations about how to add new exclusions see:
		// https://learn.microsoft.com/en-us/powershell/module/defender/add-mppreference?view=windowsserver2019-ps

"$exclusionsToAdd=[Linq.Enumerable]::ToArray([Linq.Enumerable]::Where($exclusions,[Func[object,bool]]{param($ex)!$existingExclusions.Contains($ex)}))", //$NON-NLS-1$
"if($exclusionsToAdd.Length -gt 0){ Add-MpPreference -" + exclusionType + " $exclusionsToAdd }"); //$NON-NLS-1$ //$NON-NLS-2$
String excludedPaths = paths.stream().map(Path::toString).map(p -> "'" + p.replace("'", "''") + "'")
.collect(Collectors.joining(','));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep the addition of the extraSeparator as otherwise the formatting in the preferences view doesn't look good.

Suggested change
.collect(Collectors.joining(','));
.collect(Collectors.joining(',' + extraSeparator));

Comment on lines +347 to +349
return String.join(";",
"$pathsToExclude = @(" + excludedPaths + ")",
"Add-MpPreference -ExclusionProcess $pathsToExclude"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep the extraSeparators here as well and keep the name of the name of the variable:

Suggested change
return String.join(";",
"$pathsToExclude = @(" + excludedPaths + ")",
"Add-MpPreference -ExclusionProcess $pathsToExclude"
return String.join(';' + extraSeparator, "$exclusions=@(" + extraSeparator + excludedPaths + ')', //$NON-NLS-1$
"Add-MpPreference -ExclusionProcess $pathsToExclude"

Alternatively, as the script seems now easy enough, we could skip the creation of a variable and just pass the string-array directly to make it even more compact:

Suggested change
return String.join(";",
"$pathsToExclude = @(" + excludedPaths + ")",
"Add-MpPreference -ExclusionProcess $pathsToExclude"
return "Add-MpPreference -ExclusionProcess " + extraSeparator + excludedPaths; //$NON-NLS-1$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Script to add an exclusion to Windows Defender may be simplified
3 participants