Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Hutchinson <m.j.hutchinson@gmail.com>2015-02-01 12:08:42 +0300
committerMichael Hutchinson <m.j.hutchinson@gmail.com>2015-02-01 12:10:10 +0300
commit885fc597386c4f261e5976fbfae1295f369d2dd8 (patch)
tree437ef988f3ae56679c7ab52099159a3a6b6c1218 /main/src/addins/WindowsPlatform
parente766c859555369406c167c8db511cef51c89ab37 (diff)
[Windows] Fix default app in Open With list
Diffstat (limited to 'main/src/addins/WindowsPlatform')
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs119
1 files changed, 60 insertions, 59 deletions
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
index 3210d87bce..e1da8f4654 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
@@ -299,6 +299,7 @@ namespace MonoDevelop.Platform
flags |= AssociationFlags.NoTruncate;
const uint E_POINTER = 0x80004003;
+ const uint E_NO_ASSOCIATION = 0x80070483;
var builder = new StringBuilder (512);
int size = builder.Length;
@@ -309,89 +310,89 @@ namespace MonoDevelop.Platform
builder.Length = size;
result = Win32.AssocQueryStringW (flags, str, assoc, extra, builder, ref size);
}
- Marshal.ThrowExceptionForHR (result);
- return builder.ToString ();
- }
- static string GetDefaultApp (string extension)
- {
- string appDefault = null;
- using (RegistryKey RegKey = Registry.ClassesRoot.OpenSubKey (extension)) {
- if (RegKey != null)
- appDefault = (string)RegKey.GetValue ("", null);
+ if (result == unchecked((int)E_NO_ASSOCIATION)) {
+ return null;
}
- return appDefault;
+
+ Marshal.ThrowExceptionForHR (result);
+ return builder.ToString ();
}
public override IEnumerable<DesktopApplication> GetApplications (string filename)
{
string extension = Path.GetExtension (filename);
if (string.IsNullOrEmpty (extension))
- yield break;
- string defaultApp = GetDefaultApp (extension);
+ return new DesktopApplication[0];
- foreach (var app in GetAppsForExtension (extension, defaultApp))
- yield return app;
+ return GetAppsForExtension (extension);
}
- enum AppOpenWithRegistryType {
- FromValue,
- FromMRUList,
- FromSubkey,
+ static IEnumerable<RegistryKey> GetOpenWithProgidsKeys (string extension)
+ {
+ yield return Registry.CurrentUser.OpenSubKey (@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" + extension);
+ yield return Registry.CurrentUser.OpenSubKey (@"Software\Classes\" + extension);
+ yield return Registry.LocalMachine.OpenSubKey (@"Software\Classes\" + extension);
+ yield return Registry.ClassesRoot.OpenSubKey (extension);
}
- const string assocBaseKey = @"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\";
- static IEnumerable<DesktopApplication> GetAppFromRegistry (RegistryKey key, string defaultApp, HashSet<string> uniqueAppsSet, AssociationFlags flags, AppOpenWithRegistryType type)
+
+ static IEnumerable<DesktopApplication> GetAppsForExtension (string extension)
{
- if (key != null) {
- var apps = new string[0];
- if (type == AppOpenWithRegistryType.FromValue)
- apps = key.GetValueNames ();
- else if (type == AppOpenWithRegistryType.FromSubkey)
- apps = key.GetSubKeyNames ();
- else if (type == AppOpenWithRegistryType.FromMRUList) {
- string list = (string)key.GetValue ("MRUList");
- apps = list.Select (c => (string)key.GetValue (c.ToString ())).ToArray ();
- }
+ var apps = new Dictionary<string,WindowsDesktopApplication> ();
- foreach (string appName in apps) {
- var app = WindowsAppFromName (appName, defaultApp, flags);
- if (app != null && uniqueAppsSet.Add (app.ExePath))
- yield return app;
+ WindowsDesktopApplication defaultApp = null;
+
+ //first check for the user's preferred app for this file type and use it as the default
+ using (var key = Registry.CurrentUser.OpenSubKey (@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\" + extension + @"\UserChoice")) {
+ var progid = key.GetValue ("ProgId") as string;
+ if (progid != null)
+ apps[progid] = defaultApp = WindowsAppFromName (progid, true, AssociationFlags.None);
+ }
+
+ //look in all the locatiosn where progids can be registered as handler for files
+ //starting with local user and falling back to system
+ foreach (var key in GetOpenWithProgidsKeys (extension)) {
+ using (key) {
+ //if we didn't find a default app yet, check for one
+ if (defaultApp == null) {
+ var defaultProgid = key.GetValue ("") as string;
+ if (defaultProgid != null)
+ apps[defaultProgid] = defaultApp = WindowsAppFromName (defaultProgid, true, AssociationFlags.None);
+ }
+ using (var sk = key.OpenSubKey ("OpenWithProgids")) {
+ foreach (var progid in sk.GetValueNames ()) {
+ if (!apps.ContainsKey (progid))
+ apps[progid] = WindowsAppFromName (progid, false, AssociationFlags.None);
+ }
+ }
}
}
- }
- static IEnumerable<DesktopApplication> GetAppsForExtension (string extension, string defaultApp)
- {
- var uniqueAppsSet = new HashSet<string> ();
- // Query Explorer OpenWithProgids.
- using (RegistryKey key = Registry.CurrentUser.OpenSubKey (assocBaseKey + extension + @"\OpenWithProgids"))
- foreach (var app in GetAppFromRegistry (key, defaultApp, uniqueAppsSet, AssociationFlags.None, AppOpenWithRegistryType.FromValue))
- yield return app;
-
- // Query extension OpenWithProgids.
- using (RegistryKey key = Registry.ClassesRoot.OpenSubKey (extension + @"\OpenWithProgids"))
- foreach (var app in GetAppFromRegistry (key, defaultApp, uniqueAppsSet, AssociationFlags.None, AppOpenWithRegistryType.FromValue))
- yield return app;
-
- // Query Explorer OpenWithList.
- using (RegistryKey key = Registry.CurrentUser.OpenSubKey (assocBaseKey + extension + @"\OpenWithList"))
- foreach (var app in GetAppFromRegistry (key, defaultApp, uniqueAppsSet, AssociationFlags.OpenByExeName, AppOpenWithRegistryType.FromMRUList))
- yield return app;
-
- // Query extension OpenWithList.
- using (RegistryKey key = Registry.ClassesRoot.OpenSubKey (extension + @"\OpenWithList"))
- foreach (var app in GetAppFromRegistry (key, defaultApp, uniqueAppsSet, AssociationFlags.OpenByExeName, AppOpenWithRegistryType.FromSubkey))
- yield return app;
+ //return non-duplicate executables, giving precedence to the default
+ var exePaths = new HashSet<string> ();
+
+ if (defaultApp != null) {
+ yield return defaultApp;
+ exePaths.Add (defaultApp.ExePath);
+ }
+
+ foreach (var a in apps.Values) {
+ if (a != null && exePaths.Add (a.ExePath)) {
+ yield return a;
+ }
+ }
}
- static WindowsDesktopApplication WindowsAppFromName (string appName, string defaultApp, AssociationFlags flags)
+ static WindowsDesktopApplication WindowsAppFromName (string appName, bool isDefault, AssociationFlags flags)
{
try {
string displayName = QueryAssociationString (appName, AssociationString.FriendlyAppName, flags, "open");
string exePath = QueryAssociationString (appName, AssociationString.Executable, flags, "open");
+ //ignore apps with missing information, it's not worth logging
+ if (exePath == null || displayName == null)
+ return null;
if (System.Reflection.Assembly.GetEntryAssembly ().Location != exePath)
- return new WindowsDesktopApplication (appName, displayName, exePath, appName.Equals (defaultApp));
+ return new WindowsDesktopApplication (appName, displayName, exePath, isDefault);
} catch (Exception ex) {
LoggingService.LogError (string.Format ("Failed to read info for {0} '{1}'", flags == AssociationFlags.None ? "ProgId" : "ExeName", appName), ex);
}