2010-08-05 20 views
14

Tengo un archivo ejecutable en mi disco-en-clave en dir \ program \ prog.exe Me gustaría tener un acceso directo al ejecutable en el directorio raíz del DoK, es decir, prog.lnk se referiría a dir \ programa \ prog.exe.¿Cómo creo un atajo (.lnk) con un objetivo relativo?

Sin embargo, parece que prog.lnk no puede tener un objetivo relativo. Este es un problema cuando el DoK tendrá asignadas diferentes letras de unidad, según la PC a la que esté conectado.

¿Alguna sugerencia, aparte de la obvia de poner prog.exe en el directorio raíz?

(en última instancia, me gustaría hacer esto en tiempo de instalación utilizando INE)

Gracias,

Rony

Respuesta

8

Si bien es posible que los accesos directos contengan una ruta relativa al destino (los archivos .lnk tienen una marca llamada SLDF_HAS_RELPATH) NSIS no admite la creación de nada que no sean accesos directos "normales", por lo que debe escribir los datos binarios directamente (el formato .lnk es bastante estable y ha sido documentado por MS)

!macro FileWriteHexBytes h b 
push ${h} 
push ${b} 
call FileWriteHexBytes 
!macroend 
Function FileWriteHexBytes 
exch $9 
exch 
exch $0 
push $1 
push $2 
loop: 
    StrCpy $2 $9 2 
    StrLen $1 $2 
    IntCmp $1 2 0 end 
    FileWriteByte $0 "0x$2" 
    StrCpy $9 $9 "" 2 
    goto loop 
end: 
pop $2 
pop $1 
pop $0 
pop $9 
FunctionEnd 


Function CreateRelativeLnk 
exch $9 
exch 
exch $0 
push $1 
FileOpen $0 "$0" w 
StrCmp $0 "" clean 
!insertmacro FileWriteHexBytes $0 "4C0000000114020000000000C000000000000046" 
!insertmacro FileWriteHexBytes $0 48010400 ;flags 
!insertmacro FileWriteHexBytes $0 00000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000 

StrLen $1 $9 ;must be < 255! 
FileWriteByte $0 $1 
FileWriteByte $0 0 
FileWrite $0 "$9" ;relative target path 

!if 0 
;The icon is problematic, does not seem like it works with relative paths (but you can use system icons...) 
StrCpy $9 "explorer.exe" 
StrLen $1 $9 
FileWriteByte $0 $1 
FileWriteByte $0 0 
FileWrite $0 "$9" 
!else 
!insertmacro FileWriteHexBytes $0 05003e2e657865 ;fake default .exe icon 
!endif 

clean: 
FileClose $0 
pop $1 
pop $0 
pop $9 
FunctionEnd 

llamada así:

push "$temp\testlink.lnk" 
push "testdir\testapp.exe" ;full path to this is $temp\testdir\testapp.exe 
call CreateRelativeLnk 

Mientras que el .lnk generada parece funcionar, no estoy seguro si lo haría use esto en el código de producción

Una solución mucho mejor es crear un poco de NSIS aplicación como sugiere Oleg (NSIS aplicaciones pueden contener datos incrustados al final del archivo .exe que se puede leer de sí mismo en tiempo de ejecución, etc ..)

+0

.lnk file format documentation file: http://msdn.microsoft.com/en-us/library/dd871305.aspx – n611x007

1

Tiene usted razón. No puede usar accesos directos (.lnk) en un medio removible, porque como usted mismo escribió, los medios extraíbles pueden tener diferentes letras de unidad en diferentes situaciones.

Si necesita tener algo en un directorio raíz de la unidad, utilice una CMD, VBS o JS en lugar de un acceso directo. En alguna situación, uno usa también un EXE estándar que usa un archivo de configuración como archivo INI para iniciar otro programa desde el otro subdirectorio. Es una práctica típica para CD/DVD implementar el inicio de un programa de instalación después de insertar el disco. Probablemente de esta manera también estará bien para sus necesidades?

10

Si nos asumen cmd.exe estaría en la misma ruta absoluta para todas las instalaciones de windows (probable, pero no a prueba de tontos) se puede divisar el archivo .lnk para comenzar cmd como esto

cmd.exe /c start /d. your command here 

/d establece el directorio de el directorio del archivo .lnk

Puede haber otras opciones útiles para el comando de inicio (p./B)

3

instalar "relativo"

estoy usando un poco de un truco. El enfoque se muestra en esta captura de pantalla:

Comienza el explorador.exe y luego pasa a un pariente ruta así:

%windir%\explorer.exe path\to\your\files\youFileName.example 

estoy usando un small tool called "Relative" para esto. Después de instalarlo, puede hacer clic con el botón derecho en un archivo y luego seleccionar Create relative shortcut.... Aparecerá un cuadro Save as.... Esto no es tan cómodo como simplemente arrastrar y soltar, pero ayuda. (También usa su propio icono especial para los enlaces que crea. Por lo tanto, ya no tiene el icono original en el vínculo. Consulte más arriba. Puede que le guste o no).

0

Creo que el NT 4 Resource Kit el comando SHORTCUT.exe crearía atajos vinculados relativos. Me gustaría que Microsoft creara una nueva utilidad soportada o Powershell Cmdlet para facilitar la creación de archivos .lnk relativos o hacer que los enlaces NTFS funcionen más como enlaces simbólicos de Linux. Hasta entonces, uso archivos .cmd/.bat y .ps1 para este propósito.

Program.cmd

@"%~dp0Relative\Path\Program.exe" %* 
  • @ = Suprime el eco de comandos.
  • % ~ dp0 = se expande al directorio del script.
  • Relative \ Path = podría incluir ... para hacer una copia de seguridad de un directorio.
  • % * = pasa cualquier parámetro recibido por el script en Program.exe.

Program.ps1

Lamentablemente, sin embargo .cmd/.bat se realizarán desde cualquier contexto (el diálogo de ejecución y una pronta CMD, en Powershell, hacer doble clic en el Explorador de archivos, etc.), no pueden llamar cosas almacenadas en una ruta UNC. Para exponer cosas en una ruta UNC, en Powershell (hago esto para herramientas como Git y Mercurial), crearé una versión de Powershell del script anterior.

&"$PSScriptRoot\Relative\Path\Program.exe" @args 
  • & = Powershell pone en modo de comando, de modo que la cadena entre comillas se corrió.
  • "" = contiene una cadena, expandiendo cualquier variable.
  • $ PSScriptRoot = se expande al directorio del script.
  • Relative \ Path = podría incluir ... para hacer una copia de seguridad de un directorio.
  • @args = pasa cualquier parámetro recibido por el script en Program.exe.
Cuestiones relacionadas