Skip to content

Commit 8463203

Browse files
Merge pull request #3895 from windows-toolkit/andrewleader/notif-settingsfix-with-cleanup
Fix notification settings disabled for unpackaged apps on 19042 and older
2 parents 25442e3 + 94a1be2 commit 8463203

File tree

2 files changed

+122
-22
lines changed

2 files changed

+122
-22
lines changed

Microsoft.Toolkit.Uwp.Notifications/Toasts/Compat/Desktop/Win32AppInfo.cs

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ internal class Win32AppInfo
2727

2828
public string Aumid { get; set; }
2929

30+
/// <summary>
31+
/// Gets the AUMID before it was fixed up with the backslash issue
32+
/// </summary>
33+
public string Pre7_0_1Aumid { get; private set; }
34+
3035
public string DisplayName { get; set; }
3136

3237
public string IconPath { get; set; }
@@ -39,8 +44,29 @@ public static Win32AppInfo Get()
3944
IApplicationResolver appResolver = (IApplicationResolver)new CAppResolver();
4045
appResolver.GetAppIDForProcess(Convert.ToUInt32(process.Id), out string appId, out _, out _, out _);
4146

42-
// Use app ID (or hashed app ID) as AUMID
43-
string aumid = appId.Length > AUMID_MAX_LENGTH ? HashAppId(appId) : appId;
47+
string aumid;
48+
string pre7_0_1Aumid = null;
49+
50+
// If the app ID is too long
51+
if (appId.Length > AUMID_MAX_LENGTH)
52+
{
53+
// Hash the AUMID
54+
aumid = HashAppId(appId);
55+
}
56+
57+
// Else if it contains a backslash
58+
else if (appId.Contains('\\'))
59+
{
60+
// For versions 19042 and older of Windows 10, we can't use backslashes - Issue #3870
61+
// So we change it to not include those
62+
aumid = appId.Replace('\\', '/');
63+
pre7_0_1Aumid = appId;
64+
}
65+
else
66+
{
67+
// Use as-is
68+
aumid = appId;
69+
}
4470

4571
// Then try to get the shortcut (for display name and icon)
4672
IShellItem shortcutItem = null;
@@ -73,11 +99,11 @@ public static Win32AppInfo Get()
7399
if (IsAlphaBitmap(bmp, out var bmpData))
74100
{
75101
var alphaBitmap = GetAlphaBitmapFromBitmapData(bmpData);
76-
iconPath = SaveIconToAppPath(alphaBitmap, appId);
102+
iconPath = SaveIconToAppPath(alphaBitmap, aumid);
77103
}
78104
else
79105
{
80-
iconPath = SaveIconToAppPath(bmp, appId);
106+
iconPath = SaveIconToAppPath(bmp, aumid);
81107
}
82108
}
83109
catch
@@ -103,12 +129,13 @@ public static Win32AppInfo Get()
103129
if (string.IsNullOrWhiteSpace(iconPath))
104130
{
105131
// We use the one from the process
106-
iconPath = ExtractAndObtainIconFromCurrentProcess(process, appId);
132+
iconPath = ExtractAndObtainIconFromCurrentProcess(process, aumid);
107133
}
108134

109135
return new Win32AppInfo()
110136
{
111137
Aumid = aumid,
138+
Pre7_0_1Aumid = pre7_0_1Aumid,
112139
DisplayName = displayName,
113140
IconPath = iconPath
114141
};
@@ -136,12 +163,12 @@ private static string GetDisplayNameFromCurrentProcess(Process process)
136163
return process.ProcessName;
137164
}
138165

139-
private static string ExtractAndObtainIconFromCurrentProcess(Process process, string appId)
166+
private static string ExtractAndObtainIconFromCurrentProcess(Process process, string aumid)
140167
{
141-
return ExtractAndObtainIconFromPath(process.MainModule.FileName, appId);
168+
return ExtractAndObtainIconFromPath(process.MainModule.FileName, aumid);
142169
}
143170

144-
private static string ExtractAndObtainIconFromPath(string pathToExtract, string appId)
171+
private static string ExtractAndObtainIconFromPath(string pathToExtract, string aumid)
145172
{
146173
try
147174
{
@@ -150,7 +177,7 @@ private static string ExtractAndObtainIconFromPath(string pathToExtract, string
150177

151178
using (var bmp = icon.ToBitmap())
152179
{
153-
return SaveIconToAppPath(bmp, appId);
180+
return SaveIconToAppPath(bmp, aumid);
154181
}
155182
}
156183
catch
@@ -159,11 +186,11 @@ private static string ExtractAndObtainIconFromPath(string pathToExtract, string
159186
}
160187
}
161188

162-
private static string SaveIconToAppPath(Bitmap bitmap, string appId)
189+
private static string SaveIconToAppPath(Bitmap bitmap, string aumid)
163190
{
164191
try
165192
{
166-
var path = Path.Combine(GetAppDataFolderPath(appId), "Icon.png");
193+
var path = Path.Combine(GetAppDataFolderPath(aumid), "Icon.png");
167194

168195
// Ensure the directories exist
169196
Directory.CreateDirectory(Path.GetDirectoryName(path));
@@ -182,9 +209,9 @@ private static string SaveIconToAppPath(Bitmap bitmap, string appId)
182209
/// Gets the app data folder path within the ToastNotificationManagerCompat folder, used for storing icon assets and any additional data.
183210
/// </summary>
184211
/// <returns>Returns a string of the absolute folder path.</returns>
185-
public static string GetAppDataFolderPath(string appId)
212+
public static string GetAppDataFolderPath(string aumid)
186213
{
187-
string conciseAumid = appId.Contains("\\") ? GenerateGuid(appId) : appId;
214+
string conciseAumid = aumid.Contains('\\') || aumid.Contains('/') ? GenerateGuid(aumid) : aumid;
188215

189216
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ToastNotificationManagerCompat", "Apps", conciseAumid);
190217
}

Microsoft.Toolkit.Uwp.Notifications/Toasts/Compat/ToastNotificationManagerCompat.cs

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public static class ToastNotificationManagerCompat
2727
#if WIN32
2828
private const string TOAST_ACTIVATED_LAUNCH_ARG = "-ToastActivated";
2929
private const string REG_HAS_SENT_NOTIFICATION = "HasSentNotification";
30+
private const string REG_HAS_7_0_1_FIX = "Has7.0.1Fix";
3031
internal const string DEFAULT_GROUP = "toolkitGroupNull";
3132

3233
private const int CLASS_E_NOAGGREGATION = -2147221232;
@@ -175,6 +176,23 @@ private static void Initialize()
175176

176177
// Additionally, we need to read whether they've sent a notification before
177178
_hasSentNotification = rootKey.GetValue(REG_HAS_SENT_NOTIFICATION) != null;
179+
180+
// And read if we've already applied the 7_0_1 fix
181+
bool has7_0_1fix = rootKey.GetValue(REG_HAS_7_0_1_FIX) != null;
182+
183+
// If it doesn't have the fix yet
184+
if (!has7_0_1fix)
185+
{
186+
// If the AUMID changed
187+
if (win32AppInfo.Pre7_0_1Aumid != null)
188+
{
189+
// Uninstall the old AUMID
190+
CleanUpOldAumid(win32AppInfo.Pre7_0_1Aumid);
191+
}
192+
193+
// Set that it has the fix so we don't try uninstalling again in the future
194+
rootKey.SetValue(REG_HAS_7_0_1_FIX, 1);
195+
}
178196
}
179197

180198
rootKey.SetValue("CustomActivator", string.Format("{{{0}}}", activatorType.GUID));
@@ -183,7 +201,12 @@ private static void Initialize()
183201

184202
private static string GetRegistrySubKey()
185203
{
186-
return @"Software\Classes\AppUserModelId\" + _win32Aumid;
204+
return GetRegistrySubKey(_win32Aumid);
205+
}
206+
207+
private static string GetRegistrySubKey(string win32Aumid)
208+
{
209+
return @"Software\Classes\AppUserModelId\" + win32Aumid;
187210
}
188211

189212
private static Type CreateActivatorType()
@@ -443,7 +466,7 @@ public static void Uninstall()
443466
{
444467
// Remove all scheduled notifications (do this first before clearing current notifications)
445468
var notifier = CreateToastNotifier();
446-
foreach (var scheduled in CreateToastNotifier().GetScheduledToastNotifications())
469+
foreach (var scheduled in notifier.GetScheduledToastNotifications())
447470
{
448471
try
449472
{
@@ -516,21 +539,71 @@ public static void Uninstall()
516539
{
517540
}
518541

519-
if (!DesktopBridgeHelpers.HasIdentity() && _win32Aumid != null)
542+
try
520543
{
521-
try
544+
// Delete any of the app files
545+
var appDataFolderPath = Win32AppInfo.GetAppDataFolderPath(_win32Aumid);
546+
if (Directory.Exists(appDataFolderPath))
522547
{
523-
// Delete any of the app files
524-
var appDataFolderPath = Win32AppInfo.GetAppDataFolderPath(_win32Aumid);
525-
if (Directory.Exists(appDataFolderPath))
548+
Directory.Delete(appDataFolderPath, recursive: true);
549+
}
550+
}
551+
catch
552+
{
553+
}
554+
}
555+
556+
private static void CleanUpOldAumid(string oldAumid)
557+
{
558+
try
559+
{
560+
// Remove all scheduled notifications (do this first before clearing current notifications)
561+
var notifier = ToastNotificationManager.CreateToastNotifier(oldAumid);
562+
foreach (var scheduled in notifier.GetScheduledToastNotifications())
563+
{
564+
try
565+
{
566+
notifier.RemoveFromSchedule(scheduled);
567+
}
568+
catch
526569
{
527-
Directory.Delete(appDataFolderPath, recursive: true);
528570
}
529571
}
530-
catch
572+
}
573+
catch
574+
{
575+
}
576+
577+
try
578+
{
579+
// Clear all current notifications
580+
ToastNotificationManager.History.Clear(oldAumid);
581+
}
582+
catch
583+
{
584+
}
585+
586+
try
587+
{
588+
// Remove registry key
589+
Registry.CurrentUser.DeleteSubKey(GetRegistrySubKey(oldAumid));
590+
}
591+
catch
592+
{
593+
}
594+
595+
try
596+
{
597+
// Delete any of the app files
598+
var appDataFolderPath = Win32AppInfo.GetAppDataFolderPath(oldAumid);
599+
if (Directory.Exists(appDataFolderPath))
531600
{
601+
Directory.Delete(appDataFolderPath, recursive: true);
532602
}
533603
}
604+
catch
605+
{
606+
}
534607
}
535608
#endif
536609

0 commit comments

Comments
 (0)