Recent, am avut nevoie să creez o legătură simbolică în timp ce executam o scanare pe unele sisteme și am constatat că nu există o modalitate nativă în PowerShell de a realiza acest lucru. Acum pot folosi mklink.exe pentru a face acest lucru, dar acest lucru va funcționa numai sub cmd.exe. Acest lucru înseamnă că nu pot apela efectiv mklink.exe sub PowerShell.
mklink.exe
În schimb, trebuie să apelez mai întâi cmd.exe urmat de mklink.exe pentru a accesa comanda.
cmd.exe /c mklink.exe
Așa că ați putea crede că aș fi mulțumit de acest rezultat. Ei bine, eu nu sunt. Nu ar trebui să mă bazez pe faptul că trebuie să apelez mai întâi la cmd.exe înainte de a folosi mklink.exe pentru a crea o legătură simbolică. Și mulțumită folosirii Pinvoke pentru a intra în API-ul Win32, nu trebuie să accept această soartă!
Mergând pe pinvoke.net, văd sub kernel32 că există o funcție numită CreateSymbolicLink care îndeplinește ceea ce caut.
Bazele a ceea ce am nevoie sunt mai jos:
public static extern bool CreateSymbolicLink(strin
A trebuit să adaug cuvântul cheie ‘public’ la început pentru ca această funcție să fie disponibilă când o adaug în sesiunea mea. Acesta nu este tot codul, ci doar ceea ce era disponibil pe site. A trebuit să fac puțină codificare C# pentru a transforma acest lucru într-un tip pe care îl pot importa în sesiunea mea PowerShell folosind 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
Acum am un tip care poate fi folosit pentru a crea o legătură simbolică. Tot ce are nevoie este o cale de utilizat pentru legătură și SymName propriu-zis și apoi fie un 0 (File), fie un 1 (Directory) pentru a decide ce fel de legătură simbolică va fi creată. Valoarea rezultată este o valoare booleană care poate fi adăugată cu ușurință într-o declarație If/Else pentru a gestiona restul acțiunilor.
::CreateSymbolicLink('C:\Users\Administrator\Desktop\SQL2008Install',"\dc1\SharedStorage\SQL 2008",1)
Urmărind la legătura simbolică SQL2008Install, vedeți după atribute că este o legătură simbolică, deoarece este etichetată ca ReparsePoint:
Cu aceasta, am acum o legătură simbolică pe desktop-ul meu care indică spre folderul de instalare SQL2008 de pe serverul meu la distanță.
Având în vedere că această metodă necesită ceva muncă, este firesc ca aceasta să poată deveni o funcție reutilizabilă.
New-SymLink
Această funcție face practic ceea ce v-am arătat, dar într-o formă de funcție care este portabilă și mai ușor de utilizat. Aceasta vă permite să creați o legătură simbolică fie pentru un director, fie pentru un fișier.
Partea de început a funcției mele implică verificarea pentru a vedea dacă am încărcat deja tipul meu pinvoke și, dacă nu, adăugarea tipului folosind 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); } }"@ }}
Blocul Process (permit intrarea pipeline pentru parametrul Path) este cel în care folosesc tipul meu pentru a crea legătura simbolică și urmăresc orice problemă în timpul acestui proces. Ca un element adăugat, voi scoate un obiect care arată legătura simbolică și calea țintă la care face referire legătura.
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) } }}
Veziți să vedem acest lucru în acțiune!
New-SymLink -Path "C:\Users\Administrator\Downloads" -SymName Downloads -Directory -Verbose
Și cu asta, funcția creează o legătură simbolică pentru dosarul meu de descărcări de pe desktop. Linkul pentru a descărca această funcție este mai jos. Să-mi spuneți ce părere aveți despre această funcție!
Download
Repozitoriu de scripturi
.