From 7a49557073025199a0c06877f667810a549d3532 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Thu, 16 Mar 2006 18:38:46 +0000 Subject: [PATCH] SD2-568 - No code completion for COM references. COM interops now loaded after a build. Type library filenames now have end digits removed from filenames in the add reference dialog. In the MSBuild file the COM reference include attribute is now set to the type library short name and not its description. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1223 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../ReferenceDialog/COMReferencePanel.cs | 2 +- .../Project/Items/ComReferenceProjectItem.cs | 18 +++ .../Project/Src/Project/Items/TypeLibrary.cs | 136 +++++++++++++++--- .../ParserService/ParseProjectContent.cs | 20 +++ 4 files changed, 153 insertions(+), 23 deletions(-) diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/COMReferencePanel.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/COMReferencePanel.cs index 4fb01911b7..d383801601 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/COMReferencePanel.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/COMReferencePanel.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.SharpDevelop.Gui void PopulateListView() { foreach (TypeLibrary typeLib in TypeLibrary.Libraries) { - ListViewItem newItem = new ListViewItem(new string[] { typeLib.Name, typeLib.Path }); + ListViewItem newItem = new ListViewItem(new string[] { typeLib.Description, typeLib.Path }); newItem.Tag = typeLib; Items.Add(newItem); } diff --git a/src/Main/Base/Project/Src/Project/Items/ComReferenceProjectItem.cs b/src/Main/Base/Project/Src/Project/Items/ComReferenceProjectItem.cs index c683973b0e..8ffe120b37 100644 --- a/src/Main/Base/Project/Src/Project/Items/ComReferenceProjectItem.cs +++ b/src/Main/Base/Project/Src/Project/Items/ComReferenceProjectItem.cs @@ -100,5 +100,23 @@ namespace ICSharpCode.SharpDevelop.Project Include, Properties); } + + public override string FileName { + get { + try { + if (Project != null && Project.OutputAssemblyFullPath != null) { + string outputFolder = Path.GetDirectoryName(Project.OutputAssemblyFullPath); + string interopFileName = Path.Combine(outputFolder, String.Concat("Interop.", Include, ".dll")); + if (File.Exists(interopFileName)) { + return interopFileName; + } + } + } + catch (Exception) { } + return Include; + } + set { + } + } } } diff --git a/src/Main/Base/Project/Src/Project/Items/TypeLibrary.cs b/src/Main/Base/Project/Src/Project/Items/TypeLibrary.cs index 3e7b6d209f..9337d8b9ea 100644 --- a/src/Main/Base/Project/Src/Project/Items/TypeLibrary.cs +++ b/src/Main/Base/Project/Src/Project/Items/TypeLibrary.cs @@ -7,16 +7,17 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using Microsoft.Win32; namespace ICSharpCode.SharpDevelop.Project { - /// - /// Description of TypeLibrary. - /// public class TypeLibrary { string name; + string description; string path; string guid; string version; @@ -43,10 +44,19 @@ namespace ICSharpCode.SharpDevelop.Project public string Name { get { + if (name == null) { + name = GetTypeLibName(); + } return name; } } + public string Description { + get { + return description; + } + } + public string Path { get { return path; @@ -90,40 +100,40 @@ namespace ICSharpCode.SharpDevelop.Project public static IEnumerable Libraries { get { - RegistryKey typelibsKey = Registry.ClassesRoot.OpenSubKey("TypeLib"); - foreach (string typelibKeyName in typelibsKey.GetSubKeyNames()) { - RegistryKey typelibKey = typelibsKey.OpenSubKey(typelibKeyName); - if (typelibKey == null) { + RegistryKey typeLibsKey = Registry.ClassesRoot.OpenSubKey("TypeLib"); + foreach (string typeLibKeyName in typeLibsKey.GetSubKeyNames()) { + RegistryKey typeLibKey = typeLibsKey.OpenSubKey(typeLibKeyName); + if (typeLibKey == null) { continue; } - TypeLibrary lib = Create(typelibKey); - if (lib != null && lib.Name != null && lib.Path != null && lib.Name.Length > 0 && lib.Path.Length > 0) { + TypeLibrary lib = Create(typeLibKey); + if (lib != null && lib.Description != null && lib.Path != null && lib.Description.Length > 0 && lib.Path.Length > 0) { yield return lib; } } } } - static TypeLibrary Create(RegistryKey typelibKey) + static TypeLibrary Create(RegistryKey typeLibKey) { - string[] versions = typelibKey.GetSubKeyNames(); + string[] versions = typeLibKey.GetSubKeyNames(); if (versions.Length > 0) { TypeLibrary lib = new TypeLibrary(); // Use the last version lib.version = versions[versions.Length - 1]; - RegistryKey versionKey = typelibKey.OpenSubKey(lib.version); - lib.name = (string)versionKey.GetValue(null); - lib.path = GetTypelibPath(versionKey, ref lib.lcid); - lib.guid = System.IO.Path.GetFileName(typelibKey.Name); + RegistryKey versionKey = typeLibKey.OpenSubKey(lib.version); + lib.description = (string)versionKey.GetValue(null); + lib.path = GetTypeLibPath(versionKey, ref lib.lcid); + lib.guid = System.IO.Path.GetFileName(typeLibKey.Name); return lib; } return null; } - static string GetTypelibPath(RegistryKey versionKey, ref string lcid) + static string GetTypeLibPath(RegistryKey versionKey, ref string lcid) { // Get the default value of the (typically) 0\win32 subkey: string[] subkeys = versionKey.GetSubKeyNames(); @@ -132,17 +142,15 @@ namespace ICSharpCode.SharpDevelop.Project return null; } for (int i = 0; i < subkeys.Length; i++) { - try { - int.Parse(subkeys[i]); // The right key is a number + int result; + if (Int32.TryParse(subkeys[i], out result)) { lcid = subkeys[i]; RegistryKey NullKey = versionKey.OpenSubKey(subkeys[i]); string[] subsubkeys = NullKey.GetSubKeyNames(); RegistryKey win32Key = NullKey.OpenSubKey("win32"); - return win32Key == null || win32Key.GetValue(null) == null ? null : win32Key.GetValue(null).ToString(); - } catch (FormatException) { - // Wrong keys don't parse til int - } + return win32Key == null || win32Key.GetValue(null) == null ? null : GetTypeLibPath(win32Key.GetValue(null).ToString()); + } } return null; } @@ -155,5 +163,89 @@ namespace ICSharpCode.SharpDevelop.Project } return -1; } + + string GetTypeLibName() + { + string name = null; + + int typeLibLcid; + if (guid != null && lcid != null && Int32.TryParse(lcid, out typeLibLcid)) { + Guid typeLibGuid = new Guid(this.guid); + name = GetTypeLibNameFromGuid(ref typeLibGuid, (short)VersionMajor, (short)VersionMinor, typeLibLcid); + } + + if (name == null) { + name = GetTypeLibNameFromFile(path); + } + + if (name != null) { + return name; + } + return description; + } + + /// + /// Removes the trailing part of the type library filename if it + /// starts with a number. + /// + static string GetTypeLibPath(string fileName) + { + if (fileName != null) { + int index = fileName.LastIndexOf('\\'); + if (index > 0 && index + 1 < fileName.Length) { + if (Char.IsDigit(fileName[index + 1])) { + return fileName.Substring(0, index); + } + } + } + return fileName; + } + + static string GetTypeLibNameFromFile(string fileName) + { + if (fileName != null && fileName.Length > 0 && File.Exists(fileName)) { + ITypeLib typeLib; + if (LoadTypeLibEx(fileName, RegKind.None, out typeLib) == 0) { + try { + return Marshal.GetTypeLibName(typeLib); + } finally { + Marshal.ReleaseComObject(typeLib); + } + } + } + return null; + } + + static string GetTypeLibNameFromGuid(ref Guid guid, short versionMajor, short versionMinor, int lcid) + { + ITypeLib typeLib; + if (LoadRegTypeLib(ref guid, versionMajor, versionMinor, lcid, out typeLib) == 0) { + try { + return Marshal.GetTypeLibName(typeLib); + } finally { + Marshal.ReleaseComObject(typeLib); + } + } + return null; + } + + enum RegKind { + Default, + Register, + None + } + + [DllImport("oleaut32.dll")] + static extern int LoadTypeLibEx([MarshalAs(UnmanagedType.BStr)] string szFile, + RegKind regkind, + out ITypeLib pptlib); + + [DllImport("oleaut32.dll")] + static extern int LoadRegTypeLib( + ref Guid rguid, + short wVerMajor, + short wVerMinor, + int lcid, + out ITypeLib pptlib); } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs index a7cb19b815..7069cc72fe 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs @@ -6,6 +6,7 @@ // using System; +using System.IO; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Project; @@ -54,12 +55,14 @@ namespace ICSharpCode.Core ProjectItem[] items = project.Items.ToArray(); ProjectService.ProjectItemAdded += OnProjectItemAdded; ProjectService.ProjectItemRemoved += OnProjectItemRemoved; + ProjectService.EndBuild += OnEndBuild; UpdateDefaultImports(items); foreach (ProjectItem item in items) { if (!initializing) return; // abort initialization switch (item.ItemType) { case ItemType.Reference: case ItemType.ProjectReference: + case ItemType.COMReference: AddReference(item as ReferenceProjectItem, false); break; } @@ -208,8 +211,25 @@ namespace ICSharpCode.Core { ProjectService.ProjectItemAdded -= OnProjectItemAdded; ProjectService.ProjectItemRemoved -= OnProjectItemRemoved; + ProjectService.EndBuild -= OnEndBuild; initializing = false; base.Dispose(); } + + void OnEndBuild(object source, EventArgs e) + { + AddComReferences(); + } + + void AddComReferences() + { + if (project != null) { + foreach (ProjectItem item in project.Items) { + if (item.ItemType == ItemType.COMReference) { + System.Threading.ThreadPool.QueueUserWorkItem(AddReference, item as ReferenceProjectItem); + } + } + } + } } }