Suchen und Ersetzen in Verknüpfungen (.LNK-, .URL- und .WebSite-Dateien) auf dem Desktop automatisieren


Angenommen, man hat einen üblichen Desktop vor sich. Dieser ist mit zig Dateien und Verknüpfungen übersäht. Wenn man dann wissen möchte, welcher Link auf ein bestimmtes Verzeichnis verweist, dann kann das schnell in Arbeit ausarten. Wenn man dann noch etwas ersetzen muss, kann man in vielen Umgebungen Spaß mit fehlender UAC Unterstützung unter Windows haben. Am Ende flucht man, warum man nicht mal mit Admin-Rechten einen einfachen Link aktualisieren kann.

In allen diesen Fällen hilft wie immer Omo, nö Powershell wars.

Zunächst gilt es alle Verknüpfungen auf dem Desktop zu finden. Man erzeugt zunächst ein Shell-Objekt:

$shell = New-Object –ComObject Shell.Application

Nun benötigt man die Links vom Desktop. Man könnte nun direkt auf den Pfad des aktuellen Benutzers verweisen aber noch eleganter ist es, sich vom System den Pfad geben zu lassen:

$desktop = $shell.Namespace(0x10)

Wenn man sich $desktop anschaut erhält man:

Title                      : Desktop
Application                : System.__ComObject
Parent                     :
ParentFolder               : System.__ComObject
Self                       : System.__ComObject
OfflineStatus              :
HaveToShowWebViewBarricade : False
ShowWebViewBarricade       : False

Nicht sehr überzeugend oder? Besser wird es damit:

PS > $desktop.Self

Application  : System.__ComObject
Parent       : System.__ComObject
Name         : Desktop
Path         : C:\Users\Benutzer\Desktop
GetLink      :
GetFolder    : System.__ComObject
IsLink       : False
IsFolder     : True
IsFileSystem : True
IsBrowsable  : False
ModifyDate   : 17.09.2015 17:31:32
Size         : 0
Type         : Dateiordner

Man bekommt also mittels $desktop.Self.Path den aktuellen Pfad zum Desktop. Damit kann man nun etwas anfangen, z. B. die Verknüpfungen ermitteln:

Get-ChildItem $desktop.Self.Path -Filter *.lnk

Aber Moment, wer sich vielleicht wundert, warum nicht alle Verknüpfungen auftauchen, die ein Benutzer auf seinem Desktop hat, dem sei gesagt, es gibt auch einen öffentlichen Desktop, der für alle Benutzer gilt. Obiger Namespaceaufruf hatte nur den Desktop des aktuellen Benutzers zurückgegeben. Die öffentliche Variante erhält man so:

$publicDesktop = $shell.Namespace(0x19)

wenn man sich hier $publicDesktop.Self.Path anschaut erhält man

C:\Users\Public\Desktop

Kurz noch als Erklärung zu 0x10 bzw. 0x19, dabei handelt es sich um Konstanten aus den Shell Special Folders, eine Auflistung ist hier zu finden: https://msdn.microsoft.com/en-us/library/windows/desktop/bb774096(v=vs.85).aspx. Da es wie immer eine Tortur ist, eine aktuelle Beschreibung in der MSDN zu finden, sei noch diese Methode genannt, um alle möglichen Werte zu sehen:

0..250| % { $v=($shell.NameSpace($_)).Self; if ($v -ne $null) { New-Object psObject -Property @{Index=$_; Name=$v.Name; Path=$v.Path}} }

Weiter beim eigentlichen Thema. Nun wird es langsam was, so bekommt man beides zusammen:

$dl = Get-ChildItem $desktop.Self.Path -Filter *.lnk
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.lnk

Nun enthält $dl tatsächlich alle LNK-Dateiverweise. Jetzt also zum Inhalt der Verknüpfungen. Da LNK-Dateien ein eigenwilliges Binärformat haben, muss dieses speziell gelesen werden. Aber die Shell-Klassen bieten hier auch Unterstützung. Dazu gibt es die Methode ParseName, welche so angewendet werden kann:

$fileItem = $desktop.ParseName($dl[0].Name)
$fileItem.IsLink

Erst jetzt weiß man, ob die LNK-Datei wirklich eine Linkdatei ist. Wenn dem so ist, kann man hiermit das Link-Objekt instanzieren:

$sc = $fileItem.GetLink

$sc enthält, dann z. B. Daten wie diese:

Path             : C:\Windows\SysWOW64\cmd.exe
Description      :
WorkingDirectory : C:\windows\SysWOW64
Arguments        :
Hotkey           : 0
ShowCommand      : 1
Target           : System.__ComObject

Hier kann man nun konkret auch den Pfad oder das Working-Directory ändern. So kann man z. B. im obigen Beispiel den Pfad von SysWOW64 in System32 ändern, welches dann so aussieht:

$sc.Path = $sc.Path.Replace("SysWOW64", "System32")

Damit diese Änderung aber tatsächlich auch auf der Platte landet, muss die Änderung noch gespeichert werden:

$sc.Save

Leider hat die bisherige Vorgehensweise ein paar Probleme. Denn das obige Zusammenführen des User- und des Öffentlichen-Desktop, macht Probleme. denn ParseName verlangt immer den reinen Dateinamen ohne Pfad, was dann bei Anwendung obiger Methode bei öffentlichen Desktopobjekten beim Aufruf über $desktop nicht zum Ziel führt. Man sollte also $dl nach dem Pfad abfragen und entsprechend $desktop oder $publicDesktop verwenden.

if ($_.DirectoryName –eq $desktop.Self.Path) {
  $fi = $desktop.ParseName($_)
} else {
  $fi = $publicDesktop.ParseName($_)
}

Somit hat man nun in $fi immer das richtige FileItem und kann so weiterverfahren:

if ($fi.IsLink) {
  $sc = $fi.GetLink
  $sc.Path = $sc.Path.Replace("ALT", "NEU")
  $sc.Save

}

Übrigens kann man nicht nur LNK-Dateien sondern auch .URL und .WebSite –Dateien damit bearbeiten, welche etwas abgewandelte Link-Dateien sind. Von der Verarbeitung jedoch ändert sich nichts, man geht direkt auf die Pfad-Eigenschaft los und ändert diese.

So da es nun wie so oft etwas unübersichtlich wurde, alles nochmal geballt, inkl. .URL und .WEBSITE:

$shell = New-Object –ComObject Shell.Application
$desktop = $shell.Namespace(0x10)
$publicDesktop = $shell.Namespace(0x19)
$dl = Get-ChildItem $desktop.Self.Path -Filter *.lnk
$dl += Get-ChildItem $desktop.Self.Path -Filter *.url
$dl += Get-ChildItem $desktop.Self.Path -Filter *.website
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.lnk
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.url
$dl += Get-ChildItem $publicDesktop.Self.Path -Filter *.website
$dl | foreach {
    if ($_.DirectoryName –eq $desktop.Self.Path) {
         $fi = $desktop.ParseName($_.Name)
    } else {
         $fi = $publicDesktop.ParseName($_.Name)
    }
    if ($fi.IsLink) {
       $sc = $fi.GetLink
       $sc.Path = $sc.Path.Replace("ALT", "NEU")
       $sc.Save()
    }
}

Falls man eine Fehlermeldung wie z. B. diese bekommt

Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
In Zeile:21 Zeichen:8
+        $sc.Path = $sc.Path.Replace("ALT", "NEU")
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

sollte man sich überlegen, das Script vielleicht als Admin auszuführen, denn es ist nicht so gern gesehen, wenn einfache Benutzer den Öffentlichen Desktop verändern!

3 Antworten to “Suchen und Ersetzen in Verknüpfungen (.LNK-, .URL- und .WebSite-Dateien) auf dem Desktop automatisieren”

  1. Quirel Says:

    Hier noch weitere Infos zum Thema Links: Neueste Referenz für IShellLink: http://go.microsoft.com/fwlink/?LinkId=145763, sowie die offizielle Doku: https://msdn.microsoft.com/en-us/library/dd871305.aspx

  2. Quirel Says:

    Für Internet-Shortcuts gilt dies zu beachten: https://msdn.microsoft.com/en-us/library/dd565671(v=vs.85).aspx

    und Powershell bietet nun auch eine Unterstützung mittels New-Item, siehe: http://stackoverflow.com/questions/9701840/how-to-create-a-shortcut-using-powershell, um Links anlegen zu können. Allerdings hat der SymbolicLink auch ein paar Nachteile.

    Der Vollständigkeithalber noch der Link zum IShellLink Interface: https://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx

  3. Lord Grabiner Says:

    Lord Grabiner

    Suchen und Ersetzen in Verknüpfungen (.LNK-, .URL- und .WebSite-Dateien) auf dem Desktop automatisieren | Das nie endende Chaos!

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s


%d Bloggern gefällt das: