@@ -18,6 +18,7 @@ using namespace NppShell::Installer;
18
18
using namespace NppShell ::Registry;
19
19
20
20
extern HMODULE thisModule;
21
+ extern thread ensureRegistrationThread;
21
22
22
23
const wstring SparsePackageName = L" NotepadPlusPlus" ;
23
24
constexpr int FirstWindows11BuildNumber = 22000 ;
@@ -178,6 +179,33 @@ void ResetAclPermissionsOnApplicationFolder()
178
179
aclHelper.ResetAcl (applicationPath);
179
180
}
180
181
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
+
181
209
HRESULT NppShell::Installer::RegisterSparsePackage ()
182
210
{
183
211
PackageManager packageManager;
@@ -207,32 +235,20 @@ HRESULT NppShell::Installer::UnregisterSparsePackage()
207
235
PackageManager packageManager;
208
236
IIterable<Package> packages;
209
237
210
- try
238
+ Package package = GetSparsePackage ();
239
+
240
+ if (package == NULL )
211
241
{
212
- packages = packageManager.FindPackagesForUser (L" " );
213
- }
214
- catch (winrt::hresult_error const & ex)
215
- {
216
- return ex.code ();
242
+ return S_FALSE;
217
243
}
218
244
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 ();
234
248
235
- break ;
249
+ if (!SUCCEEDED (deployResult.ExtendedErrorCode ()))
250
+ {
251
+ return deployResult.ExtendedErrorCode ();
236
252
}
237
253
238
254
// 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()
347
363
return S_OK;
348
364
}
349
365
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
+
350
401
STDAPI CleanupDll ()
351
402
{
352
403
// First we get the full path to this DLL.
0 commit comments