For nylig havde jeg brug for at oprette et symbolsk link, mens jeg kørte en scanning på nogle systemer, og jeg fandt ud af, at der ikke var en indfødt måde i PowerShell til at udføre dette på. Nu kan jeg bruge mklink.exe til at få dette til at fungere, men det virker kun under cmd.exe. Det betyder, at jeg faktisk ikke kan kalde mklink.exe under PowerShell.
mklink.exe
I stedet skal jeg først kalde cmd.exe efterfulgt af mklink.exe for at få adgang til kommandoen.
cmd.exe /c mklink.exe
Så man kunne tro, at jeg ville være tilfreds med dette resultat. Men det er jeg ikke. Jeg burde ikke være afhængig af at skulle kalde cmd.exe først, før jeg bruger mklink.exe til at oprette et symbolsk link. Og takket være brugen af Pinvoke til at komme ind i Win32-API’en behøver jeg ikke at acceptere denne skæbne!
Går jeg ud på pinvoke.net, kan jeg se under kernel32, at der er en funktion kaldet CreateSymbolicLink, der opfylder det, jeg søger.
Det grundlæggende i det, jeg har brug for, er nedenfor:
public static extern bool CreateSymbolicLink(strin
Jeg var nødt til at tilføje nøgleordet ‘public’ i begyndelsen, så denne funktion vil være tilgængelig, når jeg tilføjer den i min session. Dette er ikke hele koden, kun det, der var tilgængeligt på webstedet. Jeg måtte lave lidt C#-kodning for at gøre dette til en type, som jeg kan importere til min PowerShell-session ved hjælp af 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
Nu har jeg en type, der kan bruges til at oprette et symbolsk link. Det eneste, den kræver, er en sti, der skal bruges til linket, og det faktiske SymName og derefter enten en 0 (fil) eller en 1 (mappe) for at bestemme, hvilken slags symbolsk link der skal oprettes. Den resulterende værdi er en boolsk værdi, som nemt kan tilføjes i en If/Else-erklæring for at håndtere resten af handlingerne.
::CreateSymbolicLink('C:\Users\Administrator\Desktop\SQL2008Install',"\dc1\SharedStorage\SQL 2008",1)
Kigger man på det symbolske link SQL2008Install, kan man ved hjælp af attributterne se, at det er et symbolsk link, da det er mærket som et ReparsePoint:
Dermed har jeg nu et symbolsk link på mit skrivebord, der peger på mappen SQL2008Install på min fjernserver.
Da denne metode kræver en del arbejde, er det kun naturligt, at det kan blive en funktion, der kan genbruges.
New-SymLink
Denne funktion gør i princippet det, jeg har vist dig, men i en funktionsform, der er transportabel og mere let at bruge. Den giver dig mulighed for at oprette et symbolsk link til enten en mappe eller en fil.
Begyndelsesdelen af min funktion omfatter kontrol af, om jeg allerede har indlæst min pinvoke-type, og hvis ikke, tilføjes typen ved hjælp af 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); } }"@ }}
Procesblokken (jeg tillader pipeline-input for Path-parameteren) er der, hvor jeg bruger min type til at oprette det symbolske link og holder øje med eventuelle problemer under denne proces. Som en ekstra ting vil jeg output et objekt, der viser det symbolske link og den målsti, som linket henviser til.
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) } }}
Lad os se dette i aktion!
New-SymLink -Path "C:\Users\Administrator\Downloads" -SymName Downloads -Directory -Verbose
Og dermed opretter funktionen et symbolsk link til min downloads-mappe på mit skrivebord. Linket til at downloade denne funktion er nedenfor. Lad mig vide, hvad du synes om denne funktion!
Download
Script Repository