Como crear accesos directos
Para hacer un programa, he necesitado crear por código un acceso directo y después hacer que el programa se inicie cuando se inicie Windows.
Como es natural he buscado por internet como se hace y he encontrado la solución, pero en el caso de crear un acceso directo, me ha costado bastante porque el código que he encontrado era realmente viejo, y ademas, estaba hecho con funciones “viejunas” de Formularios Windows.
Como estoy trabajando con WPF, he tenido que adaptar el codigo, y al final, ha funcionado.
Cómo ejecutar un programa al iniciar Windows 11
En esta pagina [ de genbeta ]
He encontrado una solución aceptable que consiste en guardar ( o mas bien copiar) un acceso directo que pone en programa en marcha, en la carpeta Inicio. Windows cuenta con una carpeta dentro del sistema llamada Inicio en la cual todos los programas que se almacenan pasan a iniciarse automáticamente al ejecutar Windows.
La carpeta Inicio, esta en la ruta Este equipo> Disco Local> ProgramData> Microsoft> Windows> Menú Inicio> Programas> Inicio .
Alternativamente se puede usar la ruta directa C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp.
Código Visual Basic .Net
'---------------------------------------------------------- ' Formulario WPF para estudiar como se crea un acceso directo por código ' para probar este formulario se necesitan dos botones ' un botón aceptar con el x:name = "ButtonEjecutar" ' un botón Terminar con el x:name = "ButtonTerminar" '---------------------------------------------------------- '---------------------------------------------------------------------- ' Añadir una referencia a Windows Script Host Object Model ' Se necesita para trabajar con [IWshShell_Class] y con [IWshShortcut_Class] Imports IWshRuntimeLibrary '---------------------------------------------------------------------- Class MainWindow Private Sub ButtonEjecutar_Click(sender As Object, e As RoutedEventArgs) Dim resultadoCreacion As System.Windows.Controls.ValidationResult ' llamar a la función que crea el acceso directo resultadoCreacion = CrearAccesoDirecto() If resultadoCreacion.IsValid = True Then ' copiar el acceso directo en la carpeta Inicio ' Ahora lo copio en la carpeta de Inicio resultadoCreacion = CopiarAccesoDirectoEnCarpetaInicio(resultadoCreacion.ErrorContent) ' Error en la copia en al carpeta Inicio If resultadoCreacion.IsValid = False Then MessageBox.Show(resultadoCreacion.ErrorContent, "Copia de un [Acceso Directo] en la carpeta de [Inicio]", MessageBoxButton.OKCancel, MessageBoxImage.Error) End If Else 'Error en la creación del Acceso Directo MessageBox.Show(resultadoCreacion.ErrorContent, "Creación de un [Acceso Directo]", MessageBoxButton.OKCancel, MessageBoxImage.Error) End If End Sub Private Sub ButtonTerminar_Click(sender As Object, e As RoutedEventArgs) ' Salir del programa Me.Close() End Sub ''' <summary> ''' Crea un acceso directo del ejecutable ''' en el directorio donde esta el ejecutable (exe) ''' </summary> ''' <returns> ''' Valor [System.Windows.Controls.ValidationResult] ''' Valor [System.Windows.Controls.ValidationResult] ''' Todo correcto - True Mas el nombre completo del fichero (Acceso directo) ''' Ha habido algún error - False Mas el texto que describe el error ''' </returns> ''' <remarks> ''' ---------------------------------------------------------------- ''' Esta función esta creada para estudiar el código necesario para crear un acceso directo. ''' ---------------------------------------------------------------- ''' Básicamente la forma de crear los accesos directos es ''' a) Crear una referencia al objeto Shell del Scripting Host: ''' Set wshShell = CreateObject("WScript.Shell") ''' b) Llamar al método CreateShorcut: ''' Set vLnk = wshShell.CreateShortcut(sLnkPath) ''' c)Asignar el path de destino ''' vLnk.Targetpath = sAppPath ''' d) y guardar los datos... ''' vLnk.Save ''' ---------------------------------------------------------------- ''' Necesito conocer: ''' a) El nombre completo del Ejecutable (del fichero exe) ''' b) y el nombre completo del Acceso Directo (el fichero [lnk]) ''' c) el nombre completo del icono asociado al programa (Opcional) ''' ---------------------------------------------------------------- ''' IMPORTANTE ''' Hay que añadir una referencia a [Windows Script Host Object Model] ''' Se necesita para trabajar con [IWshShell_Class] y con [IWshShortcut_Class] ''' Imports IWshRuntimeLibrary ''' ---------------------------------------------------------------- '''</remarks> ''' <example> ''' Bibliografía ''' <code> ''' https://www.elguille.info/vb/ejemplos/crear_links.htm ''' https://entredesarrolladores.com/973/creaci%C3%B3n-de-acceso-directo-en-vb-net ''' </code> ''' </example> ''' <dcterms.created> ''' <scheme>dcterms.ISO8601</scheme> ''' <content>2023-09-20T22:28:38Z</content> ''' </dcterms.created> Private Function CrearAccesoDirecto() As System.Windows.Controls.ValidationResult '-------------------------------------- ' El valor de retorno Dim resultadoCreacion As System.Windows.Controls.ValidationResult '---------------------------------------------------------------- ' Necesito conocer: ' a) El nombre completo del Ejecutable (del fichero exe) ' b) y el nombre completo del Acceso Directo (el fichero [lnk]) ' c) el nombre completo del icono asociado al programa (Opcional '---------------------------------------------------------------- ' En este ejemplo Voy a crear un acceso directo del ejecutable [EXE] ' en la carpeta donde esta el ejecutable '---------------------------------------------------------------- '------------------------------------- 'Obtener el nombre del ensamblado Dim NombreCompletoDelEnsamblado As String = System.Reflection.Assembly.GetExecutingAssembly().Location ' esto obtiene la DLL Dim RutaDelEnsamblado As String = System.IO.Path.GetDirectoryName(NombreCompletoDelEnsamblado) Dim SoloNombreEnsambladoSinExtension = System.IO.Path.GetFileNameWithoutExtension(NombreCompletoDelEnsamblado) '------------------------------------- 'Paso A) Nombre completo del ejecutable (El fichero exe) ' (ruta + nombre + extensión) Dim nombreCompletoDelEjecutable As String = System.IO.Path.Combine(RutaDelEnsamblado, SoloNombreEnsambladoSinExtension & ".exe") '------------------------------------- 'Paso B) Nombre completo del Acceso Directo (el fichero [lnk]) '(ruta + nombre + extensión) Dim NombreCompletoAccesoDirecto As String = System.IO.Path.Combine(RutaDelEnsamblado, SoloNombreEnsambladoSinExtension & ".lnk") '------------------------------------- ' ATENCIÓN ' Hay que añadir una referencia a [Windows Script Host Object Model] ' Se necesita para trabajar con [IWshShell_Class] y con [IWshShortcut_Class] ' Imports IWshRuntimeLibrary '------------------------------------- 'Crear una referencia al objeto Shell: Dim oShell As IWshShell_Class = Nothing Dim oShortcut As IWshShortcut_Class = Nothing Try oShell = CreateObject("WScript.Shell") oShortcut = oShell.CreateShortcut(NombreCompletoAccesoDirecto) oShortcut.TargetPath = nombreCompletoDelEjecutable oShortcut.WindowStyle = 1 ' ESTE FUNCIONA oShortcut.IconLocation = "D:\NET\VS2010 ImageLibrary\Annotations_Buttons\ico_format\WinVista\New.ico" ' ESTE NO 'oShortcut.IconLocation = "PruebasAccesoDirecto.exe, 0" oShortcut.Description = String.Format("Acceso directo al programa [{0}]", SoloNombreEnsambladoSinExtension) '------------------------------------------ ' Antes de grabar el acceso directo ' compruebo que no haya una version previa ' si existe previamente se borra para evitar problemas tontos If System.IO.File.Exists(NombreCompletoAccesoDirecto) = True Then System.IO.File.Delete(NombreCompletoAccesoDirecto) End If '--------------------------- ' Ahora grabo el nuevo acceso directo oShortcut.Save() '--------------------------- ' el informe del resultado de la copia resultadoCreacion = New System.Windows.Controls.ValidationResult(True, NombreCompletoAccesoDirecto) Catch ex As Exception '--------------------------- ' el informe del resultado de la copia Dim TextoMensajeError As String Using sw As New System.IO.StringWriter sw.WriteLine("PROBLEMA - No se puede crear el [Acceso Directo]") sw.WriteLine("del programa ejecutable [EXE]") sw.WriteLine("[{0}]", SoloNombreEnsambladoSinExtension) sw.WriteLine("en la carpeta donde esta el programa ejecutable ") sw.WriteLine("------------------------") sw.WriteLine("Valores de las variables") sw.WriteLine("Nombre fichero inicial [{0}]", NombreCompletoDelEnsamblado) sw.WriteLine("Nombre fichero inicial [{0}]", RutaDelEnsamblado) sw.WriteLine("Nombre fichero inicial [{0}]", SoloNombreEnsambladoSinExtension) sw.WriteLine("Nombre fichero inicial [{0}]", nombreCompletoDelEjecutable) sw.WriteLine("Nombre fichero inicial [{0}]", NombreCompletoAccesoDirecto) sw.WriteLine("------------------------") sw.WriteLine(ex.Message) TextoMensajeError = sw.ToString End Using resultadoCreacion = New System.Windows.Controls.ValidationResult(False, TextoMensajeError) Finally ' Destruir los objetos usados If oShell IsNot Nothing Then oShell = Nothing End If If oShortcut IsNot Nothing Then oShortcut = Nothing End If End Try ' Devolver el resultado Return resultadoCreacion End Function ''' <summary> ''' Copia el acceso directo que recibe por parámetro en la carpeta inicio ''' </summary> ''' <param name = "paramNombreCompletoAccesoDirecto"> ''' Una cadena con el nombre completo del fichero (Acceso directo) [Ruta + Nombre + Extension (.lnk)] ''' </param> ''' <returns> ''' Valor [System.Windows.Controls.ValidationResult] ''' Todo correcto - True Mas el nombre completo del fichero (Acceso directo) ''' Ha habido algún error - False Mas el texto que describe el error ''' </returns> ''' <remarks> ''' Cómo ejecutar un programa al iniciar Windows 11 ''' Solamente hay que guardar (copiar) el acceso directo en la carpeta Inicio ''' Windows cuenta con una carpeta dentro del sistema llamada Inicio en la cual todos ''' los programas que se almacenan pasan a iniciarse automáticamente al ejecutar Windows. ''' Para ello, lo primero es que tengas un acceso directo creado en tu ''' escritorio de esa aplicación que deseas ejecutar. ''' ''' Seguidamente, deberás acceder a esta carpeta siguiendo la ruta ''' Este equipo > Disco Local > ProgramData > Microsoft > Windows > Menú Inicio > Programas > Inicio. ''' Igualmente, también puedes entrar en Ejecutar e introducir la ruta directa ''' C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp. ''' ''' </remarks> ''' <example> ''' Bibliografía ''' <code> ''' https://www.genbeta.com/paso-a-paso/como-ejecutar-programa-al-iniciar-windows-11 ''' </code> ''' </example> ''' <dcterms.created> ''' <scheme>dcterms.ISO8601</scheme> ''' <content>2023-09-20T22:28:38Z</content> ''' </dcterms.created> Private Function CopiarAccesoDirectoEnCarpetaInicio(ByVal paramNombreCompletoAccesoDirecto As String) As System.Windows.Controls.ValidationResult ' '-------------------------------------- ' El valor de retorno Dim ResultadoDeLaCopia As System.Windows.Controls.ValidationResult '--------------------------- ' Generar el nombre completo del acceso directo en la carpeta Inicio ' a) La ruta Dim CarpetaDestino As String = Environment.GetFolderPath(Environment.SpecialFolder.Startup) ' "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp" ' b) El nombre de fichero (acceso directo( Dim SoloNombreMasExtensionAccesoDirecto As String = System.IO.Path.GetFileName(paramNombreCompletoAccesoDirecto) 'Dim SoloNombreSinExtensionAccesoDirecto As String = System.IO.Path.GetFileNameWithoutExtension(paramNombreCompletoAccesoDirecto) ' c) el nombre completo acceso directo, Ruta + nombre + extension) Dim NombreCompletoFicheroDestino As String = System.IO.Path.Combine(CarpetaDestino, SoloNombreMasExtensionAccesoDirecto) Try '--------------------------- ' si existe previamente se borra para evitar problemas tontos If System.IO.File.Exists(NombreCompletoFicheroDestino) = True Then System.IO.File.Delete(NombreCompletoFicheroDestino) End If '--------------------------- ' La copia System.IO.File.Copy(paramNombreCompletoAccesoDirecto, NombreCompletoFicheroDestino, True) '--------------------------- ' el informe del resultado de la copia ResultadoDeLaCopia = New System.Windows.Controls.ValidationResult(True, NombreCompletoFicheroDestino) Catch ex As Exception Dim TextoMensajeError As String Using sw As New System.IO.StringWriter sw.WriteLine("PROBLEMA - No se puede copiar el [Acceso Directo] en la carpeta Inicio") sw.WriteLine("Nombre fichero inicial [{0}]", paramNombreCompletoAccesoDirecto) sw.WriteLine("Nombre fichero destino [{0}]", NombreCompletoFicheroDestino) sw.WriteLine(ex.Message) TextoMensajeError = sw.ToString End Using ResultadoDeLaCopia = New System.Windows.Controls.ValidationResult(False, TextoMensajeError) End Try ' Devolver el resultado de la copia Return ResultadoDeLaCopia End Function End Class
Código Xaml
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:PruebasAccesoDirecto" mc:Ignorable="d" Title="Pruebas con Accesos directos " Height="150" Width="300"> <Grid> <Button x:Name="ButtonEjecutar" Content="Ejecutar" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="34,39,0,0" Click="ButtonEjecutar_Click"/> <Button x:Name="ButtonTerminar" Content="Terminar" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="110,39,0,0" Click="ButtonTerminar_Click"/> </Grid> </Window>