Introducción:
En este artículo te presento la clase UtilRegistry que
tiene ciertas funciones para manipular el registro de Windows.
Esta clase la hice para el proyecto principal del último
capítulo de mi libro Manual Imprescindible de Visual
Basic 2005 y la he
modificado añadiendo nuevas funciones y mejorando otras.
También la he convertido a C#, con idea de que si es ese
el lenguaje que utilizas, pues que también puedas hacerlo.
Asociar extensiones con una aplicación
En este artículo de hoy te voy a mostrar las dos
funciones principales de esta clase.
Una de ellas (AsociarExtension) sirve para asociar
una extensión con cualquier ejecutable (o cambiar una existente), también
permite añadir nuevas funciones u opciones a una extensión existente.
La otra (DesasociarExtension) sirve para lo
contrario, es decir, para quitar un tipo de archivo asociado del registro.
La clase UtilRegistry tiene todos los métodos compartidos
(estáticos), en realidad en Visual Basic se podría haber hecho como módulo
(Module), pero la he creado como clase (Class).
Recibir notificaciones de los errores producidos en la clase
Esta clase define un evento (ErrorRegistry)
que se producirá cuando haya algún error al ejecutar los métodos de la
clase.
Para poder recibir las notificaciones que produzca ese evento tenemos que
crear una método de evento en la clase que utilice UtilRegistry, por ejemplo
un formulario.
El problema con el que nos podemos encontrar (al menos
los que se decidan por usar Visual Basic) es que al ser una clase que tiene
los métodos compartidos (estáticos), pues no podremos crearla con WithEvents
ni usar Handles para asociar el método con el evento, para ello tendremos
que asociar manualmente el método con el evento de la clase, esto lo haremos
de la siguiente forma (muestro tanto el código de VB como el de C#):
En Visual Basic:
' Asociar la clase UtilRegistry con el método de evento
' en VB hay que hacerlo así porque los eventos compartidos
' no se pueden usar con Handles
AddHandler UtilRegistry.ErrorRegistry, AddressOf UtilRegistry_Error
En C#:
UtilRegistry.ErrorRegistry += new UtilRegistryEventHandler(UtilRegistry_Error);
Aplicación para manejar las extensiones registradas y registrar nuevas
Para probar esta clase, he creado una pequeña aplicación que permite
mostrar los datos de una extensión y también registrar nuevas extensiones,
así como eliminar extensiones que ya estén registradas.
AVISO IMPORTANTE
La utilidad permite borrar y modificar las extensiones existentes, esto
significa que puedes modificar o eliminar tipos de ficheros asociados con
aplicaciones actualmente instaladas en tu equipo, si eso ocurre con algunas
extensiones, puede que tengas que volver a reinstalar esa aplicación.
En la utilidad, el código de los botones que eliminan las extensiones o
que la desasocian están deshabilitados y el código comentado, con idea de
que si te bajas el código de ejemplo y quieras utilizar esa funcionalidad
tengas que quitar los comentarios y así te darás cuenta del riego que corres
si no lo usas adecuadamente.
En cualquier caso, declino cualquier responsabilidad derivada por el uso
de esta utilidad y de las clases que la acompañan.
El mero hecho de usar el código mostrado en esta página o la utilidad de
ejemplo me libera de esas responsabilidades y te las paso a ti.
Avisado estás.
¿Por que ese "peazo" de aviso?
Es que una vez uno que usó un ejemplo que tengo en mi sitio y que también
manejaba las extensiones asociadas, se ve que hizo algo raro y se cargó
algunas extensiones del registro y después quería hacerme a mi
responsable... En fin...
El interfaz de la utilidad de ejemplo es como la mostrada en la figura 1:
Figura 1. La aplicación de ejemplo
En el combo que hay junto a Extensión se mostrarán algunas extensiones
que casi seguro que tienes en tu equipo, pulsando en Mostrar ProgId te
mostrará el valor ese que tenga la extensión.
Si quieres añadir una nueva extensión y asociarla con un ejecutable,
puedes usar las opciones que hay debajo, en el que puedes indicar varios
datos, no solo el comando para abrirlo (que será open), sino que puedes
añadir otros comandos, por ejemplo Editar a una extensión existente o lo que
te apetezca.
Tanto lo de añadir un nuevo comando a una extensión, modificar uno
existente o registrar una nueva extensión, se hace por medio del botón
Registrar extensión.
El botón Quitar del registro, es el que sirve para desasociar una extensión,
pero en realidad lo que hace es quietarla del registro, es decir, la elimina
completamente.
Estos dos botones están deshabilitados (aunque en la figura se muestren
normales, pero es porque es en modo de diseño), por tanto para usarlos
tendrás que modificar el código y habilitarlos (lee el aviso ese que he
puesto antes).
El código que hace las operaciones "peligrosas" también está comentado,
además de que te preguntará un par de veces antes de hacer los cambios.
Si después de todas estas advertencias y precauciones te cargas algo...
en fin... no te digo nada...
Debido a que la manipulación del registro requiere que el usuario ejecute
la aplicación como administrador, en la utilidad he añadido la función
EsAdministrador para comprobar si se está ejecutando la
aplicación con todos los privilegios de administrador. El código de esa
función lo puedes ver en este artículo:
Saber si la
aplicación se está ejecutando como administrador.
Bueno, ya no te meto más miedo, que al final no te vas a bajar el código,
je, je.
Más abajo tienes parte del código de Visual Basic
y el de C# de la clase
UtilRegistry y un poco más abajo tienes el
ZIP con los dos proyectos de ejemplo con todo el código
completo, uno es para Visual Basic
2005 y el otro es para Visual C# 2005.
¡Que lo registres bien!
Nos vemos.
Guillermo
El código para Visual Basic .NET (cualquier versión)
'------------------------------------------------------------------------------
' UtilRegistry (28/Jun/06)
' Clase para manipular el registro del sistema
'
' Ejemplo para el libro Manual Imprescindible de Visual Basic 2005
'
' Adapatada para publicar en mi sitio (el Guille) (21/Sep/07)
'
' IMPORTANTE:
' La manipulación del registro requiere que la aplicación se ejecute
' con privilegios de administrador.
' En Windows Vista habrá que ejecutar la aplicación "como administrador".
'
' MÁS IMPORTANTE:
' La manipulación incorrecta del registro puede hacer inestable el sistema.
' Modificar el registro para extesiones existentes puede provocar que
' la aplicación que estaba asociada no funcione correctamente.
'
' El uso de esta clase y los métodos definidos en ella
' es bajo tu entera responsabilidad.
'
' El autor no se hace responsable de que los cambios en el registro altere
' el funcionamiento del equipo.
'
' Avisado estás... así que...
' CUIDADO al usar esta clase y el código de ejemplo que la acompaña.
'
' ©Guillermo 'guille' Som, 2006-2007
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Imports Microsoft.VisualBasic
Imports vb = Microsoft.VisualBasic
Imports System
Imports Microsoft.Win32
Public Delegate Sub UtilRegistryEventHandler(ByVal message As String)
Public Class UtilRegistry
Public Shared Event ErrorRegistry As UtilRegistryEventHandler
''' <summary>
''' Asocia una extensión con un ejecutable y una acción
''' </summary>
''' <param name="ext">
''' La extensión a asociar
''' </param>
''' <param name="exe">
''' El ejecutable a asociar con la extensión
''' </param>
''' <param name="progId">
''' El progId a asociar con la extensión
''' </param>
''' <param name="comando">
''' El comando con el que se asociará, por defecto será open
''' </param>
''' <param name="descripcion">
''' La descripción del tipo de archivo relacionado con la extensión
''' </param>
''' <returns>
''' Devuelve un valor verdadero o falso
''' según se haya podido registrar o no la extensión
''' </returns>
''' <remarks>
''' También sirve para añadir nuevos comandos a extensiones existentes
''' </remarks>
Public Shared Function AsociarExtension(ByVal ext As String, _
ByVal exe As String, _
ByVal progId As String, _
ByVal comando As String, _
ByVal descripcion As String _
) As Boolean
' Si no se indican valores
' en los tres primeros parámetros
' devolver False
If String.IsNullOrEmpty(ext) _
OrElse String.IsNullOrEmpty(exe) _
OrElse String.IsNullOrEmpty(progId) Then
Return False
End If
' El comando predeterminado es open
If String.IsNullOrEmpty(comando) Then
comando = "open"
End If
' Si no se especifica la descripción
If String.IsNullOrEmpty(descripcion) Then
descripcion = ext & " Descripción de " & progId
End If
' Si no se especifica el punto
If ext.IndexOf(".") = -1 Then
ext = "." & ext
End If
Dim value As String
Dim rk As RegistryKey = Nothing
Dim rkShell As RegistryKey = Nothing
Try
value = GetProgId(ext)
If String.IsNullOrEmpty(value) _
OrElse value.Length = 0 Then
' Crear la clave, etc.
rk = Registry.ClassesRoot.CreateSubKey(ext)
rk.SetValue("", progId)
rk = Registry.ClassesRoot.CreateSubKey(progId)
rk.SetValue("", descripcion)
value = "shell\" & comando & "\command"
rkShell = rk.CreateSubKey(value)
Else
' Ya existe, solo actualizar los valores
' pero debemos abrir la clave indicando que vamos a escribir
' para que nos permita crear nuevas subclaves.
rk = Registry.ClassesRoot.OpenSubKey(progId, True)
value = "shell\" & comando & "\command"
rkShell = rk.OpenSubKey(value, True)
' Si es un comando que se añade, no existirá
If rkShell Is Nothing Then
rkShell = rk.CreateSubKey(value)
End If
End If
If rkShell IsNot Nothing Then
rkShell.SetValue("", ChrW(34) & exe & ChrW(34) & " " & _
ChrW(34) & "%1" & ChrW(34))
rkShell.Close()
End If
Catch ex As Exception
RaiseEvent ErrorRegistry(ex.Message)
Return False
Finally
If rk IsNot Nothing Then
rk.Close()
End If
End Try
Return True
End Function
'------------------------------------------------------------------
' Sobrecargas para no usar Optional y facilitar la conversión a C#
'------------------------------------------------------------------
''' <summary>
''' Asocia una extensión con un ejecutable y una acción
''' </summary>
''' <param name="ext">
''' La extensión a asociar
''' </param>
''' <param name="exe">
''' El ejecutable a asociar con la extensión
''' </param>
''' <param name="progId">
''' El progId a asociar con la extensión
''' </param>
''' <returns>
''' Devuelve un valor verdadero o falso
''' según se haya podido registrar o no la extensión
''' </returns>
''' <remarks>
''' También sirve para añadir nuevos comandos a extensiones existentes.
''' El comando usado es open
''' </remarks>
Public Shared Function AsociarExtension(ByVal ext As String, _
ByVal exe As String, _
ByVal progId As String _
) As Boolean
Return AsociarExtension(ext, exe, progId, "open", "")
End Function
''' <summary>
''' Asocia una extensión con un ejecutable y una acción
''' </summary>
''' <param name="ext">
''' La extensión a asociar
''' </param>
''' <param name="exe">
''' El ejecutable a asociar con la extensión
''' </param>
''' <param name="progId">
''' El progId a asociar con la extensión
''' </param>
''' <param name="comando">
''' El comando con el que se asociará, por defecto será open
''' </param>
''' <returns>
''' Devuelve un valor verdadero o falso
''' según se haya podido registrar o no la extensión
''' </returns>
''' <remarks>
''' También sirve para añadir nuevos comandos a extensiones existentes
''' </remarks>
Public Shared Function AsociarExtension(ByVal ext As String, _
ByVal exe As String, _
ByVal progId As String, _
ByVal comando As String _
) As Boolean
Return AsociarExtension(ext, exe, progId, comando, "")
End Function
''' <summary>
''' Permite quitar un comando asociado con una extensión
''' </summary>
''' <param name="ext">
''' La extensión de la que se quitará el comando
''' </param>
''' <param name="comando">
''' El comando a quitar
''' </param>
''' <returns>
''' Un valor verdadero o falso según todo haya ido correcto o no
''' </returns>
''' <remarks>
''' Este método permite quitar comandos asociados previamente,
''' sin eliminar la extensión.
''' El comando open (o el predeterminado)
''' no se puede quitar usando este método.
''' </remarks>
Public Shared Function QuitarComandoExtension(ByVal ext As String, _
ByVal comando As String _
) As Boolean
' No permitir cadenas vacías en el comando
If String.IsNullOrEmpty(comando) Then
Return False
End If
' No permitir quitar el comando open
If comando.ToLower.Contains("open") Then
Return False
End If
' Si no se especifica el punto en la extensión
If ext.IndexOf(".") = -1 Then
ext = "." & ext
End If
' Averiguar el progId de esta extensión
Dim progId As String = GetProgId(ext)
Try
If String.IsNullOrEmpty(progId) = False _
AndAlso progId.Length > 0 Then
Using rk As RegistryKey = Registry.ClassesRoot.OpenSubKey(progId, True)
If rk IsNot Nothing Then
Dim value As String = "shell\" & comando
rk.DeleteSubKeyTree(value)
Return True
End If
End Using
End If
Catch ex As Exception
RaiseEvent ErrorRegistry(ex.Message)
End Try
Return False
End Function
''' <summary>
''' Quita la extensión indicada de los tipos de archivos registrados
''' </summary>
''' <param name="ext">
''' La extensión a quitar del registro
''' </param>
''' <returns>
''' Devuelve un valor verdadero o falso según se haya quitado
''' correctamente o no la extensión
''' </returns>
''' <remarks>
''' ATENCIÓN, este método elimina totalmente la extensión del registro
''' </remarks>
Public Shared Function DesasociarExtension(ByVal ext As String) As Boolean
' Si no se especifica el punto
If ext.IndexOf(".") = -1 Then
ext = "." & ext
End If
Dim progId As String = GetProgId(ext)
Try
'If vb.Len(progId) > 0 Then
If String.IsNullOrEmpty(progId) = False _
AndAlso progId.Length > 0 Then
' Eliminar la clave
Registry.ClassesRoot.DeleteSubKeyTree(ext)
Registry.ClassesRoot.DeleteSubKeyTree(progId)
Return True
End If
Catch ex As Exception
RaiseEvent ErrorRegistry(ex.Message)
End Try
Return False
End Function
''' <summary>
''' Comprueba si la extensión indicada está registrada.
''' </summary>
''' <param name="ext">
''' La extensión a comprobar
''' </param>
''' <returns>
''' Un valor verdadero o falso según esté registrada o no
''' </returns>
''' <remarks></remarks>
Public Shared Function Existe(ByVal ext As String) As Boolean
' Si no se especifica el punto
If ext.IndexOf(".") = -1 Then
ext = "." & ext
End If
Dim s As String = GetProgId(ext)
If String.IsNullOrEmpty(s) Then
Return False
End If
Return (s.Length > 0)
'Return (vb.Len(getProgId(ext)) > 0)
End Function
''' <summary>
''' Método para obtener el progId de una extensión.
''' </summary>
''' <param name="ext">
''' Extensión de la que se quiere obtener el progId
''' </param>
''' <returns>
''' Devuelve una cadena con el progId de la extensión
''' o una cadena vacía si no existe
''' </returns>
''' <remarks></remarks>
Public Shared Function GetProgId(ByVal ext As String) As String
Dim progId As String = ""
Try
Using rk As RegistryKey = Registry.ClassesRoot.OpenSubKey(ext)
If rk IsNot Nothing Then
progId = rk.GetValue("").ToString
rk.Close()
End If
End Using
Catch ex As Exception
RaiseEvent ErrorRegistry(ex.Message)
Return ""
End Try
Return progId
End Function
End Class
El código para C# (cualquier versión)
//-----------------------------------------------------------------------------
// UtilRegistry para C# (22/Sep/07)
//
// Convertido de Visual Basic a C# con gsConvertirCodigo
//
// Basada en la versión de Visual Basic 2005:
// UtilRegistry (28/Jun/06)
// Clase para manipular el registro del sistema
//
// Ejemplo para el libro Manual Imprescindible de Visual Basic 2005
//
// Adapatada para publicar en mi sitio (el Guille) (21/Sep/07)
//
// IMPORTANTE:
// La manipulación del registro requiere que la aplicación se ejecute
// con privilegios de administrador.
// En Windows Vista habrá que ejecutar la aplicación "como administrador".
//
// MÁS IMPORTANTE:
// La manipulación incorrecta del registro puede hacer inestable el sistema.
// Modificar el registro para extesiones existentes puede provocar que
// la aplicación que estaba asociada no funcione correctamente.
//
// El uso de esta clase y los métodos definidos en ella
// es bajo tu entera responsabilidad.
//
// El autor no se hace responsable de que los cambios en el registro altere
// el funcionamiento del equipo.
//
// Avisado estás... así que...
// CUIDADO al usar esta clase y el código de ejemplo que la acompaña.
//
// ©Guillermo 'guille' Som, 2006-2007
//-----------------------------------------------------------------------------
using System;
using Microsoft.Win32;
namespace asociar_extensionCS
{
public delegate void UtilRegistryEventHandler(string message);
public class UtilRegistry
{
public static event UtilRegistryEventHandler ErrorRegistry;
/// <summary>
/// Asocia una extensión con un ejecutable y una acción
/// </summary>
/// <param name="ext">
/// La extensión a asociar
/// </param>
/// <param name="exe">
/// El ejecutable a asociar con la extensión
/// </param>
/// <param name="progId">
/// El progId a asociar con la extensión
/// </param>
/// <param name="comando">
/// El comando con el que se asociará, por defecto será open
/// </param>
/// <param name="descripcion">
/// La descripción del tipo de archivo relacionado con la extensión
/// </param>
/// <returns>
/// Devuelve un valor verdadero o falso
/// según se haya podido registrar o no la extensión
/// </returns>
/// <remarks>
/// También sirve para añadir nuevos comandos a extensiones existentes
/// </remarks>
public static bool AsociarExtension(string ext, string exe,
string progId, string comando, string descripcion)
{
// Si no se indican valores
// en los tres primeros parámetros
// devolver False
if(String.IsNullOrEmpty(ext) || String.IsNullOrEmpty(exe) || String.IsNullOrEmpty(progId))
{
return false;
}
// El comando predeterminado es open
if(String.IsNullOrEmpty(comando))
{
comando = "open";
}
// Si no se especifica la descripción
if(String.IsNullOrEmpty(descripcion))
{
descripcion = ext + " Descripción de " + progId;
}
// Si no se especifica el punto
if(ext.IndexOf(".") == -1)
{
ext = "." + ext;
}
string value;
RegistryKey rk = null;
RegistryKey rkShell = null;
try
{
value = GetProgId(ext);
if(String.IsNullOrEmpty(value) || value.Length == 0)
{
// Crear la clave, etc.
rk = Registry.ClassesRoot.CreateSubKey(ext);
rk.SetValue("", progId);
rk = Registry.ClassesRoot.CreateSubKey(progId);
rk.SetValue("", descripcion);
value = @"shell\" + comando + @"\command";
rkShell = rk.CreateSubKey(value);
}
else
{
// Ya existe, solo actualizar los valores
// pero debemos abrir la clave indicando que vamos a escribir
// para que nos permita crear nuevas subclaves.
rk = Registry.ClassesRoot.OpenSubKey(progId, true);
value = @"shell\" + comando + @"\command";
rkShell = rk.OpenSubKey(value, true);
// Si es un comando que se añade, no existirá
if(rkShell == null)
{
rkShell = rk.CreateSubKey(value);
}
}
if(rkShell != null)
{
rkShell.SetValue("", (char)(34) + exe + (char)(34) + " " + (char)(34) + "%1" + (char)(34));
rkShell.Close();
}
}
catch(Exception ex)
{
if(ErrorRegistry != null)
ErrorRegistry(ex.Message); /* Si hay que lanzar el evento */
;
return false;
}
finally
{
if(rk != null)
{
rk.Close();
}
}
return true;
}
//------------------------------------------------------------------
// Sobrecargas para no usar Optional y facilitar la conversión a C#
//------------------------------------------------------------------
/// <summary>
/// Asocia una extensión con un ejecutable y una acción
/// </summary>
/// <param name="ext">
/// La extensión a asociar
/// </param>
/// <param name="exe">
/// El ejecutable a asociar con la extensión
/// </param>
/// <param name="progId">
/// El progId a asociar con la extensión
/// </param>
/// <returns>
/// Devuelve un valor verdadero o falso
/// según se haya podido registrar o no la extensión
/// </returns>
/// <remarks>
/// También sirve para añadir nuevos comandos a extensiones existentes.
/// El comando usado es open
/// </remarks>
public static bool AsociarExtension(string ext, string exe, string progId)
{
return AsociarExtension(ext, exe, progId, "open", "");
}
/// <summary>
/// Asocia una extensión con un ejecutable y una acción
/// </summary>
/// <param name="ext">
/// La extensión a asociar
/// </param>
/// <param name="exe">
/// El ejecutable a asociar con la extensión
/// </param>
/// <param name="progId">
/// El progId a asociar con la extensión
/// </param>
/// <param name="comando">
/// El comando con el que se asociará, por defecto será open
/// </param>
/// <returns>
/// Devuelve un valor verdadero o falso
/// según se haya podido registrar o no la extensión
/// </returns>
/// <remarks>
/// También sirve para añadir nuevos comandos a extensiones existentes
/// </remarks>
public static bool AsociarExtension(string ext, string exe, string progId, string comando)
{
return AsociarExtension(ext, exe, progId, comando, "");
}
/// <summary>
/// Permite quitar un comando asociado con una extensión
/// </summary>
/// <param name="ext">
/// La extensión de la que se quitará el comando
/// </param>
/// <param name="comando">
/// El comando a quitar
/// </param>
/// <returns>
/// Un valor verdadero o falso según todo haya ido correcto o no
/// </returns>
/// <remarks>
/// Este método permite quitar comandos asociados previamente,
/// sin eliminar la extensión.
/// El comando open (o el predeterminado)
/// no se puede quitar usando este método.
/// </remarks>
public static bool QuitarComandoExtension(string ext, string comando)
{
// No permitir cadenas vacías en el comando
if(String.IsNullOrEmpty(comando))
{
return false;
}
// No permitir quitar el comando open
if(comando.ToLower().Contains("open"))
{
return false;
}
// Si no se especifica el punto en la extensión
if(ext.IndexOf(".") == -1)
{
ext = "." + ext;
}
// Averiguar el progId de esta extensión
string progId = GetProgId(ext);
try
{
if(String.IsNullOrEmpty(progId) == false && progId.Length > 0)
{
using(RegistryKey rk = Registry.ClassesRoot.OpenSubKey(progId, true))
{
if(rk != null)
{
string value = @"shell\" + comando;
rk.DeleteSubKeyTree(value);
return true;
}
}
}
}
catch(Exception ex)
{
if(ErrorRegistry != null)
ErrorRegistry(ex.Message);
}
return false;
}
/// <summary>
/// Quita la extensión indicada de los tipos de archivos registrados
/// </summary>
/// <param name="ext">
/// La extensión a quitar del registro
/// </param>
/// <returns>
/// Devuelve un valor verdadero o falso según se haya quitado
/// correctamente o no la extensión
/// </returns>
/// <remarks>
/// ATENCIÓN, este método elimina totalmente la extensión del registro
/// </remarks>
public static bool DesasociarExtension(string ext)
{
// Si no se especifica el punto
if(ext.IndexOf(".") == -1)
{
ext = "." + ext;
}
string progId = GetProgId(ext);
try
{
if(String.IsNullOrEmpty(progId) == false && progId.Length > 0)
{
// Eliminar la clave
Registry.ClassesRoot.DeleteSubKeyTree(ext);
Registry.ClassesRoot.DeleteSubKeyTree(progId);
return true;
}
}
catch(Exception ex)
{
if(ErrorRegistry != null)
ErrorRegistry(ex.Message);
}
return false;
}
/// <summary>
/// Comprueba si la extensión indicada está registrada.
/// </summary>
/// <param name="ext">
/// La extensión a comprobar
/// </param>
/// <returns>
/// Un valor verdadero o falso según esté registrada o no
/// </returns>
/// <remarks></remarks>
public static bool Existe(string ext)
{
// Si no se especifica el punto
if(ext.IndexOf(".") == -1)
{
ext = "." + ext;
}
string s = GetProgId(ext);
if(String.IsNullOrEmpty(s))
{
return false;
}
return (s.Length > 0);
}
/// <summary>
/// Método para obtener el progId de una extensión.
/// </summary>
/// <param name="ext">
/// Extensión de la que se quiere obtener el progId
/// </param>
/// <returns>
/// Devuelve una cadena con el progId de la extensión
/// o una cadena vacía si no existe
/// </returns>
/// <remarks></remarks>
public static string GetProgId(string ext)
{
string progId = "";
try
{
using(RegistryKey rk = Registry.ClassesRoot.OpenSubKey(ext))
{
if(rk != null)
{
progId = rk.GetValue("").ToString();
rk.Close();
}
}
}
catch(Exception ex)
{
if(ErrorRegistry != null)
ErrorRegistry(ex.Message);
return "";
}
return progId;
}
}
}
Espacios de nombres usados en el código de este artículo:
Microsoft.Win32