Crear un enlace simbólico usando PowerShell

Recientemente, tuve la necesidad de crear un enlace simbólico mientras ejecutaba un escaneo en algunos sistemas y encontré que no había una forma nativa en PowerShell para lograr esto. Ahora puedo usar mklink.exe para hacer que esto funcione, pero esto sólo funcionará bajo cmd.exe. Esto significa que no puedo llamar a mklink.exe bajo PowerShell.

mklink.exe

image

En su lugar, tengo que llamar primero a cmd.exe seguido de mklink.exe para acceder al comando.

cmd.exe /c mklink.exe

image

Así que podrías pensar que estaría satisfecho con este resultado. Pues no lo estoy. No debería depender de llamar primero a cmd.exe antes de usar mklink.exe para crear un enlace simbólico. Y gracias al uso de Pinvoke para entrar en la API de Win32, no tengo que aceptar este destino¡

Saliendo a pinvoke.net, veo bajo el kernel32 que hay una función llamada CreateSymbolicLink que cumple lo que busco.

image

Los fundamentos de lo que necesito están abajo:

public static extern bool CreateSymbolicLink(strin

He tenido que añadir la palabra clave ‘public’ al principio para que esta función esté disponible cuando la añada a mi sesión. Esto no es todo el código, sólo lo que estaba disponible en el sitio. Tuve que hacer un poco de codificación C# para hacer esto en un tipo que puedo importar en mi sesión de PowerShell usando Add-Type.

Add-Type @"using System;using System.Runtime.InteropServices; namespace mklink{ public class symlink { public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); }}"@
 | get-member -static

image

Ahora tengo un tipo que se puede utilizar para crear un enlace simbólico. Todo lo que requiere es una Ruta a utilizar para el enlace y el SymName real y luego un 0 (Archivo) o un 1 (Directorio) para decidir qué tipo de enlace simbólico se creará. El valor resultante es un valor booleano que puede añadirse fácilmente a una sentencia If/Else para manejar el resto de las acciones.

::CreateSymbolicLink('C:\Users\Administrator\Desktop\SQL2008Install',"\dc1\SharedStorage\SQL 2008",1)

image

Mirando el enlace simbólico SQL2008Install, se ve por los atributos que es un enlace simbólico ya que está etiquetado como un ReparsePoint:

image

Con eso, ahora tengo un enlace simbólico en mi escritorio que apunta a la carpeta de instalación de SQL2008 en mi servidor remoto.

Siendo que este método requiere algo de trabajo es natural que esto pueda convertirse en una función que sea reutilizable.

Nuevo-SymLink

Esta función básicamente hace lo que te he mostrado, pero en una forma de función que es portable y más fácil de usar. Esto le permite crear un enlace simbólico, ya sea para un directorio o un archivo.

La parte de inicio de mi función implica la comprobación para ver si ya he cargado mi tipo pinvoke y si no, añadiendo el tipo usando Add-Type.

Begin { Try { $null = } Catch { Add-Type @" using System; using System.Runtime.InteropServices; namespace mklink { public class symlink { public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); } }"@ }}

El bloque de proceso (estoy permitiendo la entrada de la tubería para el parámetro Path) es donde utilizo mi tipo para crear el enlace simbólico y ver cualquier problema durante este proceso. Como un elemento adicional, voy a la salida de un objeto que muestra el enlace simbólico y la ruta de destino que el enlace se refiere.

Process { #Assume target Symlink is on current directory if not giving full path or UNC If ($SymName -notmatch "^(?::\)|(?:\\\w+\$)") { $SymName = "{0}\{1}" -f $pwd,$SymName } $Flag = @{ File = 0 Directory = 1 } If ($PScmdlet.ShouldProcess($Path,'Create Symbolic Link')) { Try { $return = ::CreateSymbolicLink($SymName,$Path,$Flag) If ($return) { $object = New-Object PSObject -Property @{ SymLink = $SymName Target = $Path Type = $PScmdlet.ParameterSetName } $object.pstypenames.insert(0,'System.File.SymbolicLink') $object } Else { Throw "Unable to create symbolic link!" } } Catch { Write-warning ("{0}: {1}" -f $path,$_.Exception.Message) } }}

Veamos esto en acción!

New-SymLink -Path "C:\Users\Administrator\Downloads" -SymName Downloads -Directory -Verbose

image

Y con eso, la función crea un enlace simbólico para mi carpeta de descargas en mi escritorio. El enlace para descargar esta función está abajo. Déjame saber lo que piensas de esta función!

Descargar

Repositorio de Scripts

Deja una respuesta

Tu dirección de correo electrónico no será publicada.