ikas-mc / ContextMenuForWindows11

Add Custom Context Menu For Windows11
GNU Lesser General Public License v3.0
1.85k stars 90 forks source link

I want to add "Scan with Microsoft Defender" to the Windows 11 Modern Context Menu #144

Open bagarwa opened 1 month ago

bagarwa commented 1 month ago

Issue

In Windows 11, if I want to scan any file / folder for security issue, I have to right click it to bring modern context menu, then click "Show More options" to bring classic context menu and then click "Scan with Microsoft Defender".

I want to bring this to the modern context menu itself.

Tried

I figured if I can add the Defender's exe to CCM setting, I can probably get it working. But I couldn't find proper exe location -

C:\Program Files\Windows Defender\ has 3 exe, none of which seem to be correct one.

`C:\Program Files\Windows Defender Advanced Threat Protection\' too has bunch of exe but I'm not sure which one is correct.

Question

Is this even doable? If yes, can someone please help me with it?

ikas-mc commented 1 month ago

I have disabled the anti-virus software,but you can try

https://learn.microsoft.com/en-us/defender-endpoint/command-line-arguments-microsoft-defender-antivirus

bagarwa commented 1 month ago

I have disabled the anti-virus software,but you can try https://learn.microsoft.com/en-us/defender-endpoint/command-line-arguments-microsoft-defender-antivirus

That's just a command-line util though. It runs the command in the terminal itself and not in Defender GUI. For example -

C:\Users\Test>"C:\program files\windows defender\mpcmdrun.exe" -scan -scantype 3 -File "test.zip"
Scan starting...
Scan finished.
Scanning test.zip found no threats.

Moreover, when I add that command as a context menu option in the CCM app, save, right click any file and click this option, the terminal window opens and closes within fraction of seconds. I'm guessing the scan runs, finishes, and closes; as mpcmdrun itself isn't a terminal window but terminal util.

Anyway, I am looking for a way to trigger the Defender GUI. i.e. replicate the exact behavior of the "Scan with Microsoft Defender" option, but in the modern context menu, instead of classic context menu.

flipeador commented 1 month ago

Using MpCmdRun.exe (CLI)

Configure ContextMenuForWindows11 as follows to prevent the window from closing automatically:

Option Value
Exe cmd.exe
Param /k MpCmdRun.exe -Scan -ScanType 3 -File "{path}" -DisableRemediation

[!NOTE]
Set the -DisableRemediation option to ignore file and directory exclusions, also actions are not applied after detection.

Note that MpCmdRun.exe must be in the PATH environment variable:

$DIR = "%ProgramFiles%\Windows Defender"
$PATH = [Environment]::GetEnvironmentVariable("PATH", "User")
[System.Environment]::SetEnvironmentVariable("PATH", "$PATH;$DIR", "User")

Using shellext.dll (GUI)

You can invoke the Scan with Microsoft Defender item from the context menu to open the GUI.

```ahk IID_IShellFolder := '{000214E6-0000-0000-C000-000000000046}' IID_IDataObject := '{0000010E-0000-0000-C000-000000000046}' IID_IContextMenu := '{000214E4-0000-0000-C000-000000000046}' IID_IShellExtInit := '{000214E8-0000-0000-C000-000000000046}' IID_IMicrosoftDef := '{09A47860-11B0-4DA5-AFA5-26D86198A780}' IID_IQueryAssociations := '{C46CA590-3C3F-11D2-BEE6-0000F805CA57}' SFGAO_VALIDATE := 0x01000000 ; Get the file or directory to scan. if A_Args.Length < 1 A_Args.push(FileSelect(3)) if !A_Args[1] ExitApp() item := ParseDisplayName(A_Args[1], SFGAO_VALIDATE) IShellFolder := BindToParent(item, IID_IShellFolder, &PIDL_CHILD) IDataObject := GetUIObjectOf(IShellFolder, PIDL_CHILD, IID_IDataObject) IQueryAssociations := GetUIObjectOf(IShellFolder, PIDL_CHILD, IID_IQueryAssociations) ; IQueryAssociations::GetKey method. ; https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-iqueryassociations-getkey ComCall(5, IQueryAssociations, 'Int', 0, 'Int', 3, 'Ptr', 0, 'PtrP', &hKey:=0) ; IShellExtInit::Initialize method. ; https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellextinit-initialize IShellExtInit := ComObject(IID_IMicrosoftDef, IID_IShellExtInit) ComCall(3, IShellExtInit, 'Ptr', item, 'Ptr', IDataObject, 'Ptr', hKey) ; IContextMenu::InvokeCommand method. ; https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-icontextmenu-invokecommand IContextMenu := ComObjQuery(IShellExtInit, IID_IContextMenu) CMINVOKECOMMANDINFO := Buffer(4*4+5*A_PtrSize, 0) NumPut('UInt', CMINVOKECOMMANDINFO.Size, CMINVOKECOMMANDINFO) ; Set the menu-identifier offset of the command. NumPut('Ptr', 0, CMINVOKECOMMANDINFO, 8+A_PtrSize) ; Scan with Microsoft Defender ComCall(4, IContextMenu, 'Ptr', CMINVOKECOMMANDINFO) /** * Convert a string to a pointer to an item identifier list (PIDL). * @see https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shparsedisplayname */ ParseDisplayName(name, attr:=0) { DllCall('shell32\SHParseDisplayName', 'Str', name, 'Ptr', 0 , 'PtrP', &PIDL:=0, 'UInt', attr, 'Ptr', 0, 'HRESULT') return PIDL } /** * Takes a pointer to a fully qualified PIDL, and returns a specified interface pointer * @see https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shbindtoparent */ BindToParent(PIDL, CLSID, &PIDL_CHILD) { CLSID := CLSIDFromString(CLSID) DllCall('shell32\SHBindToParent', 'Ptr', PIDL, 'Ptr', CLSID , 'PtrP', &PTR:=0, 'PtrP', &PIDL_CHILD:=0, 'HRESULT') return PTR } /** * Gets an object that can be used to carry out actions on the specified file objects or folders. * @see https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellfolder-getuiobjectof */ GetUIObjectOf(obj, PIDL, CLSID) { CLSID := CLSIDFromString(CLSID) ComCall(10, obj, 'Ptr', A_ScriptHwnd, 'UInt', 1 , 'PtrP', PIDL, 'Ptr', CLSID, 'Ptr', 0, 'PtrP', &ptr:=0) return ptr } CLSIDFromString(str) { CLSID := Buffer(16) DllCall('ole32\CLSIDFromString', 'Str', str, 'Ptr', CLSID, 'HRESULT') return CLSID } ```
Config Value
Exe C:\shellext.exe
Param "{path}"

[!NOTE]

  • I barely tested the use of the context menu, you should probably stick with the CLI.
  • I have used AutoHotkey because it is pretty easy to use for this kind of thing.
bagarwa commented 1 month ago

That worked great. Thanks for the detailed write-up. Really appreciate it.