Récemment, j’ai eu besoin de créer un lien symbolique tout en exécutant un scan sur certains systèmes et j’ai constaté qu’il n’y avait pas de moyen natif dans PowerShell pour accomplir cela. Maintenant, je peux utiliser mklink.exe pour que cela fonctionne, mais cela ne fonctionnera que sous cmd.exe. Cela signifie que je ne peux pas réellement appeler mklink.exe sous PowerShell.
mklink.exe
A la place, je dois d’abord appeler cmd.exe suivi de mklink.exe afin d’accéder à la commande.
cmd.exe /c mklink.exe
Alors vous pourriez penser que je serais satisfait de ce résultat. Eh bien, je ne le suis pas. Je ne devrais pas avoir à compter sur le fait d’appeler d’abord cmd.exe avant d’utiliser mklink.exe pour créer un lien symbolique. Et grâce à l’utilisation de Pinvoke pour accéder à l’API Win32, je n’ai pas à accepter ce destin !
En allant sur pinvoke.net, je vois sous le kernel32 qu’il existe une fonction appelée CreateSymbolicLink qui répond à ce que je recherche.
Les bases de ce dont j’ai besoin sont ci-dessous:
public static extern bool CreateSymbolicLink(strin
J’ai dû ajouter le mot clé ‘public’ au début pour que cette fonction soit disponible lorsque je l’ajouterai dans ma session. Ce n’est pas tout le code, juste ce qui était disponible sur le site. J’ai dû faire un peu de codage C# pour en faire un type que je peux importer dans ma session PowerShell en utilisant 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
Maintenant j’ai un type qui peut être utilisé pour créer un lien symbolique. Tout ce qu’il faut, c’est un chemin à utiliser pour le lien et le SymName réel, puis un 0 (fichier) ou un 1 (répertoire) pour décider du type de lien symbolique qui sera créé. La valeur résultante est une valeur booléenne qui peut être facilement ajoutée dans une instruction If/Else pour gérer le reste des actions.
::CreateSymbolicLink('C:\Users\Administrator\Desktop\SQL2008Install',"\dc1\SharedStorage\SQL 2008",1)
En regardant le lien symbolique SQL2008Install, vous voyez par les attributs que c’est un lien symbolique car il est étiqueté comme un ReparsePoint:
Avec cela, j’ai maintenant un lien symbolique sur mon bureau qui pointe vers le dossier d’installation de SQL2008 sur mon serveur distant.
Etant donné que cette méthode nécessite un certain travail, il est tout à fait naturel que cela puisse devenir une fonction réutilisable.
New-SymLink
Cette fonction fait essentiellement ce que je vous ai montré, mais sous une forme de fonction qui est portable et plus facile à utiliser. Cela vous permet de créer un lien symbolique soit pour un répertoire, soit pour un fichier.
La partie Begin de ma fonction implique de vérifier si j’ai déjà chargé mon type pinvoke et si ce n’est pas le cas, d’ajouter le type en utilisant 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); } }"@ }}
Le bloc Process (j’autorise l’entrée pipeline pour le paramètre Path) est l’endroit où j’utilise mon type pour créer le lien symbolique et où je surveille tout problème pendant ce processus. Comme élément supplémentaire, je vais sortir un objet montrant le lien symbolique et le chemin cible auquel le lien fait référence.
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) } }}
Voyons cela en action !
New-SymLink -Path "C:\Users\Administrator\Downloads" -SymName Downloads -Directory -Verbose
Et avec cela, la fonction crée un lien symbolique pour mon dossier de téléchargements sur mon bureau. Le lien pour télécharger cette fonction est ci-dessous. Faites-moi savoir ce que vous pensez de cette fonction !
Téléchargement
Dépôt de scripts
.