@@ -16,6 +16,7 @@ using namespace NppShell::Helpers;
1616using namespace NppShell ::Installer;
1717
1818extern HMODULE thisModule;
19+ extern thread ensureRegistrationThread;
1920
2021const wstring SparsePackageName = L" NotepadPlusPlus" ;
2122constexpr int FirstWindows11BuildNumber = 22000 ;
@@ -255,6 +256,33 @@ void ResetAclPermissionsOnApplicationFolder()
255256 aclHelper.ResetAcl (applicationPath);
256257}
257258
259+ Package GetSparsePackage ()
260+ {
261+ PackageManager packageManager;
262+ IIterable<Package> packages;
263+
264+ try
265+ {
266+ packages = packageManager.FindPackagesForUser (L" " );
267+ }
268+ catch (winrt::hresult_error)
269+ {
270+ return NULL ;
271+ }
272+
273+ for (const Package& package : packages)
274+ {
275+ if (package.Id ().Name () != SparsePackageName)
276+ {
277+ continue ;
278+ }
279+
280+ return package;
281+ }
282+
283+ return NULL ;
284+ }
285+
258286HRESULT NppShell::Installer::RegisterSparsePackage ()
259287{
260288 PackageManager packageManager;
@@ -284,32 +312,20 @@ HRESULT NppShell::Installer::UnregisterSparsePackage()
284312 PackageManager packageManager;
285313 IIterable<Package> packages;
286314
287- try
288- {
289- packages = packageManager.FindPackagesForUser (L" " );
290- }
291- catch (winrt::hresult_error const & ex)
315+ Package package = GetSparsePackage ();
316+
317+ if (package == NULL )
292318 {
293- return ex. code () ;
319+ return S_FALSE ;
294320 }
295321
296- for (const Package& package : packages)
297- {
298- if (package.Id ().Name () != SparsePackageName)
299- {
300- continue ;
301- }
302-
303- winrt::hstring fullName = package.Id ().FullName ();
304- auto deploymentOperation = packageManager.RemovePackageAsync (fullName, RemovalOptions::None);
305- auto deployResult = deploymentOperation.get ();
306-
307- if (!SUCCEEDED (deployResult.ExtendedErrorCode ()))
308- {
309- return deployResult.ExtendedErrorCode ();
310- }
322+ winrt::hstring fullName = package.Id ().FullName ();
323+ auto deploymentOperation = packageManager.RemovePackageAsync (fullName, RemovalOptions::None);
324+ auto deployResult = deploymentOperation.get ();
311325
312- break ;
326+ if (!SUCCEEDED (deployResult.ExtendedErrorCode ()))
327+ {
328+ return deployResult.ExtendedErrorCode ();
313329 }
314330
315331 // After unregistering the sparse package, we reset the folder permissions of the folder where we are installed.
@@ -409,6 +425,41 @@ HRESULT NppShell::Installer::Uninstall()
409425 return S_OK;
410426}
411427
428+ void EnsureRegistrationOnCurrentUserWorker ()
429+ {
430+ // Initialize the WinRT apartment.
431+ winrt::init_apartment ();
432+
433+ // Get the package to check if it is already installed for the current user.
434+ Package existingPackage = GetSparsePackage ();
435+
436+ if (existingPackage == NULL )
437+ {
438+ // The package is not installed for the current user - but we know that Notepad++ is.
439+ // If it wasn't, this code wouldn't be running, so it is safe to just register the package.
440+ RegisterSparsePackage ();
441+
442+ // Finally we notify the shell that we have made changes, so it reloads the right click menu items.
443+ SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0 , 0 );
444+ }
445+ }
446+
447+ void NppShell::Installer::EnsureRegistrationOnCurrentUser ()
448+ {
449+ // First we find the name of the process the DLL is being loaded into.
450+ wstring moduleName = GetExecutingModuleName ();
451+
452+ if (moduleName == L" explorer.exe" )
453+ {
454+ // We are being loaded into explorer.exe, so we can continue.
455+ // Explorer.exe only loads the DLL on the first time a user right-clicks a file
456+ // after that it stays in memory for the rest of their session.
457+ // Since we are here, we spawn a thread and call the EnsureRegistrationOnCurrentUserWorker function.
458+ ensureRegistrationThread = thread (EnsureRegistrationOnCurrentUserWorker);
459+ ensureRegistrationThread.detach ();
460+ }
461+ }
462+
412463STDAPI CleanupDll ()
413464{
414465 wstring currentFilePath (MAX_PATH, L' \0 ' );
0 commit comments