A közelmúltban szükségem volt egy szimbolikus hivatkozás létrehozására néhány rendszer vizsgálatának futtatása során, és úgy találtam, hogy a PowerShellben nincs natív módja ennek megvalósítására. Most az mklink.exe segítségével tudom ezt megvalósítani, de ez csak a cmd.exe alatt működik. Ez azt jelenti, hogy az mklink.exe-t valójában nem tudom meghívni a PowerShell alatt.
mklink.exe
Ehelyett először a cmd.exe-t, majd az mklink.exe-t kell meghívnom ahhoz, hogy elérjem a parancsot.
cmd.exe /c mklink.exe
Az ember tehát azt gondolná, hogy elégedett leszek ezzel az eredménnyel. Nos, én nem vagyok az. Nem kellene arra hagyatkoznom, hogy először a cmd.exe-t kell meghívnom, mielőtt az mklink.exe segítségével szimbolikus linket hoznék létre. És hála annak, hogy a Pinvoke segítségével bejutottam a Win32 API-ba, nem kell elfogadnom ezt a sorsot!
A pinvoke.net oldalra lépve látom a kernel32 alatt, hogy van egy CreateSymbolicLink nevű függvény, amely megfelel annak, amit keresek.
Az alapjai annak, amire szükségem van, az alábbiak:
public static extern bool CreateSymbolicLink(strin
A ‘public’ kulcsszót kellett hozzáadnom az elején, hogy ez a függvény elérhető legyen, amikor hozzáadom a munkamenetemhez. Ez nem az összes kód, csak ami az oldalon elérhető volt. Egy kis C# kódolást kellett végeznem, hogy ebből egy olyan típus legyen, amelyet az Add-Type segítségével importálhatok a PowerShell munkamenetbe.
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
Most már van egy olyan típusom, amellyel szimbolikus hivatkozást hozhatok létre. Mindössze egy elérési útvonalra van szükség a hivatkozáshoz és a tényleges SymName-re, majd egy 0 (File) vagy egy 1 (Directory) értékre annak eldöntéséhez, hogy milyen típusú szimbolikus hivatkozás jön létre. A kapott érték egy bólus érték, amely könnyen hozzáadható egy If/Else utasításhoz a többi művelet kezeléséhez.
::CreateSymbolicLink('C:\Users\Administrator\Desktop\SQL2008Install',"\dc1\SharedStorage\SQL 2008",1)
Az SQL2008Install szimbolikus linkre pillantva az attribútumok alapján látható, hogy szimbolikus linkről van szó, mivel ReparsePointként van megjelölve:
Ezzel már van egy szimbolikus link az asztalomon, amely a távoli kiszolgálón lévő SQL2008 telepítési mappára mutat.
Mivel ez a módszer némi munkát igényel, természetes, hogy ez egy újrafelhasználható függvény lehet.
New-SymLink
Ez a függvény alapvetően azt teszi, amit mutattam, de egy olyan függvény formájában, amely hordozható és könnyebben használható. Ez lehetővé teszi, hogy szimbolikus linket hozzunk létre akár egy könyvtárhoz, akár egy fájlhoz.
A függvényem Kezdő része magában foglalja annak ellenőrzését, hogy betöltöttem-e már a pinvoke típusomat, és ha nem, akkor a típus hozzáadását az Add-Type segítségével.
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); } }"@ }}
A Process blokkban (a Path paraméterhez pipeline bemenetet engedélyezek) a típusomat használom a szimbolikus link létrehozására, és figyelek minden problémára a folyamat során. Kiegészítésként egy olyan objektumot adok ki, amely megmutatja a szimbolikus linket és a cél elérési útvonalat, amelyre a link hivatkozik.
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) } }}
Lássuk ezt működés közben!
New-SymLink -Path "C:\Users\Administrator\Downloads" -SymName Downloads -Directory -Verbose
És ezzel a funkció létrehoz egy szimbolikus linket a letöltések mappámhoz az asztalomon. A függvény letöltésének linkje alább található. Szóljatok, hogy mit gondoltok erről a függvényről!
Letöltés
Script Repository