Script needed that extracts link targets to a text file

Hi experts.

Preparing a win8.1->win10 migration, I noticed that Microsoft does not migrate the pinned win8.1 start menu tiles to the new start menu - what a shame. And while in win8.1 we could even use GPOs to pin certain installed applications, this feature is deprecated in win10.
I'd like to assist my users in migrating those so I have been looking for a scripted solution.

I found this so far which works:
What I need for completion is a script that we can run against a directory full of link files (.lnk) and that will write the link targets to a text file which can be used by this powershell cmdlet afterwards.

I already found something but I am struggling to get it to work with links that include spaces, so I am looking for help here.
This is it: target.bat from

I hope to be able to run target.bat somefolderFulloflinks and get a text file like
"c:\anotherpath with spaces\another.exe"
LVL 63
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Since your "Pin" script is Powershell, here's a Powershell script you can use as function or stand-alone script.
It'll return a custom object that you can then pipe to Select-Object and/or Export-Csv as you need.
It accepts pipeline input, so you can just pass it the results of a Get-ChildItem. Advertiseed shortcuts are supported.
Get-ChildItem -Path "C:\ProgramData\Microsoft\Windows\Start Menu" -Recurse -Filter *.lnk | % {.\Get-Shortcut.ps1 -Path $_.FullName} | Export-Csv -Path C:\Temp\Shortcuts.csv -NoTypeInformation

Open in new window

	[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, Position=0)][ValidateNotNull()]
Begin {
	$Shell = New-Object -ComObject WScript.Shell
	$Installer = New-Object -ComObject WindowsInstaller.Installer
Process {
	$Path | ForEach-Object {
		If (Test-Path -Path $_ -PathType Leaf) {
			$Shortcut = $Shell.CreateShortcut($_) | Select-Object -Property `
				@{Name="IsAdvertised"; Expression={$False}},
				@{Name="TargetExists"; Expression={$False}},
			$Shortcut.Name = [IO.Path]::GetFileName($_)
			If ([string]::IsNullOrEmpty($Shortcut.TargetPath)) {
				$Shortcut.Error = "Not a valid shortcut."
			} ElseIf ($Shortcut.TargetPath.ToUpper().StartsWith("${ENV:Systemroot}\Installer\".ToUpper())) {
				$Shortcut.IsAdvertised = $True
				Try {
					$ShortcutTarget = $Installer.GetType().InvokeMember("ShortcutTarget", "GetProperty", $Null, $Installer, $_)
					$StringData = 1, 3 | % {$ShortcutTarget.GetType().InvokeMember("StringData", "GetProperty", $Null, $ShortcutTarget, $_)}
					$Shortcut.AdvertisedTargetPath = $Installer.GetType().InvokeMember("ComponentPath", "GetProperty", $Null, $Installer, $StringData)
				} Catch {
					$Shortcut.Error = "Advertised product not installed."
			$Shortcut.TargetExists = ![string]::IsNullOrEmpty($Shortcut.TargetPath) -And ((Get-Item -Path $Shortcut.TargetPath -ErrorAction SilentlyContinue) -ne $Null)
			$Shortcut | Write-Output
		} Else {
			"Shortcut '$_' not found!" | Write-Error
End {

Open in new window

McKnifeAuthor Commented:
Hi ObdA.

That looks good.
So I modified it a little and started
Get-ChildItem -Path "$env:APPDATA\Microsoft\Windows\Start Menu\programs" -Filter *.lnk | % {D:\Documents\Get-Shortcut.ps1 -Path $_.FullName} | Export-Csv -Path C:\Temp\Shortcuts.csv -NoTypeInformation

Open in new window

so that it will look only in %appdata%\Microsoft\Windows\Start Menu\programs. It works but the output is rather large. I am not able to modify it so that it only includes targetpath. Could you help again?
Well, nothing keeps you from exporting everything as it is to a file, then importing the file again with Import-Csv and using just the TargetPath property, probably about like this:
Import-Csv -Path C:\Temp\Shortcuts.csv | % {Set-OSCPin -Path $_.TargetPath}

Open in new window

If you really want only a list of the target paths, you can use Select-Object and Set-Content:
Get-ChildItem -Path "$env:APPDATA\Microsoft\Windows\Start Menu\programs" -Filter *.lnk | % {D:\Documents\Get-Shortcut.ps1 -Path $_.FullName} | Select-Object -ExpandProperty TargetPath | Set-Content -Path "C:\Temp\Shortcuts.txt"

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
McKnifeAuthor Commented:
Wonderful, thanks. Would have taken me a some time to figure this out.
You should write an article to make it usable for others that like to migrate their start menu tiles to win10.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.