Vor kurzem musste ich einen symbolischen Link erstellen, während ich eine Überprüfung auf einigen Systemen durchführte, und stellte fest, dass es in PowerShell keine native Möglichkeit gab, dies zu erreichen. Jetzt kann ich mklink.exe verwenden, um dies zu bewerkstelligen, aber dies funktioniert nur unter cmd.exe. Das bedeutet, dass ich mklink.exe nicht unter PowerShell aufrufen kann.
mklink.exe
Stattdessen muss ich zuerst cmd.exe und dann mklink.exe aufrufen, um auf den Befehl zuzugreifen.
cmd.exe /c mklink.exe
So könnte man meinen, dass ich mit diesem Ergebnis zufrieden wäre. Nun, das bin ich nicht. Ich sollte nicht darauf angewiesen sein, zuerst cmd.exe aufzurufen, bevor ich mklink.exe verwende, um einen symbolischen Link zu erstellen. Und dank der Verwendung von Pinvoke, um in die Win32-API zu gelangen, muß ich dieses Schicksal nicht akzeptieren!
Wenn ich pinvoke.net aufrufe, sehe ich unter kernel32, daß es eine Funktion namens CreateSymbolicLink gibt, die das erfüllt, wonach ich suche.
Die Grundlagen dessen, was ich brauche, sind unten aufgeführt:
public static extern bool CreateSymbolicLink(strin
Ich musste das Schlüsselwort ‚public‘ am Anfang hinzufügen, damit diese Funktion verfügbar ist, wenn ich sie in meine Sitzung einfüge. Dies ist nicht der gesamte Code, sondern nur das, was auf der Website verfügbar war. Ich musste ein wenig C#-Programmierung vornehmen, um daraus einen Typ zu machen, den ich mit Add-Type in meine PowerShell-Sitzung importieren kann.
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
Jetzt habe ich einen Typ, der zum Erstellen eines symbolischen Links verwendet werden kann. Alles, was er benötigt, ist ein Pfad, der für den Link verwendet werden soll, und der eigentliche SymName und dann entweder eine 0 (Datei) oder eine 1 (Verzeichnis), um zu entscheiden, welche Art von symbolischem Link erstellt werden soll. Der resultierende Wert ist ein boolescher Wert, der einfach in eine If/Else-Anweisung eingefügt werden kann, um den Rest der Aktionen durchzuführen.
::CreateSymbolicLink('C:\Users\Administrator\Desktop\SQL2008Install',"\dc1\SharedStorage\SQL 2008",1)
Wenn man sich den symbolischen Link SQL2008Install anschaut, sieht man anhand der Attribute, dass es sich um einen symbolischen Link handelt, da er als ReparsePoint gekennzeichnet ist:
Damit habe ich jetzt einen symbolischen Link auf meinem Desktop, der auf den SQL2008-Installationsordner auf meinem Remote-Server zeigt.
Da diese Methode etwas Arbeit erfordert, ist es nur natürlich, dass dies eine Funktion wird, die wiederverwendbar ist.
New-SymLink
Diese Funktion tut im Grunde das, was ich Ihnen gezeigt habe, aber in einer Funktionsform, die portabel und einfacher zu verwenden ist. Damit können Sie einen symbolischen Link für ein Verzeichnis oder eine Datei erstellen.
Der Anfangsteil meiner Funktion beinhaltet die Überprüfung, ob ich meinen pinvoke-Typ bereits geladen habe, und wenn nicht, das Hinzufügen des Typs mit 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); } }"@ }}
Im Process-Block (ich erlaube Pipeline-Eingaben für den Path-Parameter) verwende ich meinen Typ, um den symbolischen Link zu erstellen, und beobachte während dieses Prozesses alle Probleme. Als zusätzlichen Punkt gebe ich ein Objekt aus, das den symbolischen Link und den Zielpfad zeigt, auf den der Link verweist.
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) } }}
Lassen Sie uns das in Aktion sehen!
New-SymLink -Path "C:\Users\Administrator\Downloads" -SymName Downloads -Directory -Verbose
Und damit erstellt die Funktion einen symbolischen Link für meinen Download-Ordner auf meinem Desktop. Den Link zum Herunterladen dieser Funktion finden Sie unten. Lassen Sie mich wissen, was Sie von dieser Funktion halten!
Download
Script Repository