@@ -18,6 +18,7 @@ using namespace NppShell::Installer;
1818using namespace NppShell ::Registry;
1919
2020extern HMODULE thisModule;
21+ extern thread ensureRegistrationThread;
2122
2223const wstring SparsePackageName = L" NotepadPlusPlus" ;
2324constexpr int FirstWindows11BuildNumber = 22000 ;
@@ -178,6 +179,33 @@ void ResetAclPermissionsOnApplicationFolder()
178179 aclHelper.ResetAcl (applicationPath);
179180}
180181
182+ Package GetSparsePackage ()
183+ {
184+ PackageManager packageManager;
185+ IIterable<Package> packages;
186+
187+ try
188+ {
189+ packages = packageManager.FindPackagesForUser (L" " );
190+ }
191+ catch (winrt::hresult_error)
192+ {
193+ return NULL ;
194+ }
195+
196+ for (const Package& package : packages)
197+ {
198+ if (package.Id ().Name () != SparsePackageName)
199+ {
200+ continue ;
201+ }
202+
203+ return package;
204+ }
205+
206+ return NULL ;
207+ }
208+
181209HRESULT NppShell::Installer::RegisterSparsePackage ()
182210{
183211 PackageManager packageManager;
@@ -207,32 +235,20 @@ HRESULT NppShell::Installer::UnregisterSparsePackage()
207235 PackageManager packageManager;
208236 IIterable<Package> packages;
209237
210- try
238+ Package package = GetSparsePackage ();
239+
240+ if (package == NULL )
211241 {
212- packages = packageManager.FindPackagesForUser (L" " );
213- }
214- catch (winrt::hresult_error const & ex)
215- {
216- return ex.code ();
242+ return S_FALSE;
217243 }
218244
219- for (const Package& package : packages)
220- {
221- if (package.Id ().Name () != SparsePackageName)
222- {
223- continue ;
224- }
225-
226- winrt::hstring fullName = package.Id ().FullName ();
227- auto deploymentOperation = packageManager.RemovePackageAsync (fullName, RemovalOptions::None);
228- auto deployResult = deploymentOperation.get ();
229-
230- if (!SUCCEEDED (deployResult.ExtendedErrorCode ()))
231- {
232- return deployResult.ExtendedErrorCode ();
233- }
245+ winrt::hstring fullName = package.Id ().FullName ();
246+ auto deploymentOperation = packageManager.RemovePackageAsync (fullName, RemovalOptions::None);
247+ auto deployResult = deploymentOperation.get ();
234248
235- break ;
249+ if (!SUCCEEDED (deployResult.ExtendedErrorCode ()))
250+ {
251+ return deployResult.ExtendedErrorCode ();
236252 }
237253
238254 // After unregistering the sparse package, we reset the folder permissions of the folder where we are installed.
@@ -347,6 +363,41 @@ HRESULT NppShell::Installer::Uninstall()
347363 return S_OK;
348364}
349365
366+ void EnsureRegistrationOnCurrentUserWorker ()
367+ {
368+ // Initialize the WinRT apartment.
369+ winrt::init_apartment ();
370+
371+ // Get the package to check if it is already installed for the current user.
372+ Package existingPackage = GetSparsePackage ();
373+
374+ if (existingPackage == NULL )
375+ {
376+ // The package is not installed for the current user - but we know that Notepad++ is.
377+ // If it wasn't, this code wouldn't be running, so it is safe to just register the package.
378+ RegisterSparsePackage ();
379+
380+ // Finally we notify the shell that we have made changes, so it reloads the right click menu items.
381+ SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0 , 0 );
382+ }
383+ }
384+
385+ void NppShell::Installer::EnsureRegistrationOnCurrentUser ()
386+ {
387+ // First we find the name of the process the DLL is being loaded into.
388+ wstring moduleName = GetExecutingModuleName ();
389+
390+ if (moduleName == L" explorer.exe" )
391+ {
392+ // We are being loaded into explorer.exe, so we can continue.
393+ // Explorer.exe only loads the DLL on the first time a user right-clicks a file
394+ // after that it stays in memory for the rest of their session.
395+ // Since we are here, we spawn a thread and call the EnsureRegistrationOnCurrentUserWorker function.
396+ ensureRegistrationThread = thread (EnsureRegistrationOnCurrentUserWorker);
397+ ensureRegistrationThread.detach ();
398+ }
399+ }
400+
350401STDAPI CleanupDll ()
351402{
352403 // First we get the full path to this DLL.
0 commit comments