Utilizando el enlace anticipado en un objeto COM
-
13-09-2019 - |
Pregunta
Tengo este pedazo de código que funciona muy bien y me da la ruta del menú de inicio del usuario:
Dim oShell As Object = CreateObject("Shell.Application")
MsgBox(oShell.NameSpace(11).Self.Path)
Esto, obviamente, utiliza el enlace en tiempo. Ahora digo que quiero hacer esto en C # o VB.NET en modo estricto, ninguno de los cuales apoyar este tipo de sintaxis con el enlace en tiempo.
¿Es esto posible? ¿Cómo?
Gracias por su ayuda!
Solución
Si desea resolver este modo, el COM que tiene que averiguar, qué referencia COM para agregar en su proyecto de VB.
Abrir regedit y vaya a HKEY_CLASSES_ROOT\<class id>\CLSID
, es decir.
HKEY_CLASSES_ROOT\Shell.Application\CLSID
y encontrará el ID de clase que identifica únicamente el componente COM.
Bajo HKEY_CLASSES_ROOT\CLSID
ahora se puede buscar el archivo que está detrás de la componente COM:
HKEY_CLASSES_ROOT\CLSID\{13709620-C279-11CE-A49E-444553540000}\InProcServer32
muestra el siguiente valor:
%SystemRoot%\system32\SHELL32.dll
Ahora vaya a Visual Studio, y añadir una referencia a este archivo (en el Examinar ficha de los Agregar referencia de diálogo). Si abre las propiedades de proyectos, en realidad ver que el buen nombre del componente COM añadido es Controles de Microsoft Shell y Automatización .
Una vez que se añade la referencia se puede utilizar el objeto Shell.Application
de la siguiente manera:
Option Strict On
Module PrintStartMenuLocation
Sub Main()
Dim shell As New Shell32.Shell
Dim folder As Shell32.Folder
Dim folderItem As Shell32.FolderItem
Dim startMenuPath As String
folder = shell.NameSpace(Shell32.ShellSpecialFolderConstants.ssfSTARTMENU)
folderItem = CType(folder.Items(0), Shell32.FolderItem)
startMenuPath = folderItem.Path
Console.WriteLine(startMenuPath)
End Sub
End Module
Una versión en C # se vería de la siguiente manera:
class Program
{
static void Main(string[] args)
{
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder folder = shell.NameSpace(Shell32.ShellSpecialFolderConstants.ssfSTARTMENU);
Shell32.FolderItem folderItem = folder.Items().Item(0) as Shell32.FolderItem;
string startMenuPath = folderItem.Path;
Console.WriteLine(startMenuPath);
}
}
Sin embargo, si sólo hay que recuperar la ubicación de la carpeta del menú Inicio se puede hacer lo mismo directamente en .NET utilizando
Dim path As String = System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu)
Otros consejos
Bueno, en realidad se podría utilizar la reflexión:
Type shellType = Type.GetTypeFromProgID("Shell.Application", true);
object shell = Activator.CreateInstance(shellType);
object folder = shellType.InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, shell, new object[] { 11 });
object self = folder.GetType().InvokeMember("Self", BindingFlags.GetProperty, null, folder, new object[] { });
object path = self.GetType().InvokeMember("Path", BindingFlags.GetProperty, null, self, new object[] { });
Console.WriteLine(path);
No es el tipo de código que me gusta, pero en C # 4.0 se puede utilizar el tipo dinámico para limpiar este desastre.
Dim DirPath As String = _
System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu)
aquí por más.
Si no recuerdo mal, todo lo que tiene que hacer es echar la referencia de objeto en la interfaz apropiada. Si utiliza un objeto COM en .NET, que normalmente importar la biblioteca de tipos y luego tener las interfaces disponibles.