Author Posts

August 10, 2017 at 2:19 pm

What do you think of this? As a test I'm trying to run every shortcut in the start menu for 5 seconds. But the targetpath from CreateShortcut() doesn't give what I want for certain shortcuts, like Adobe Reader, Microsoft Office, or TightVNC. (Some windows don't close, and you have to cancel any elevation prompts.)

Adobe Reader XI.lnk C:\Windows\Installer\{AC76BA86-7AD7-1033-7B44-AB0000000001}\SC_Reader.ico
Word 2016.lnk C:\Windows\Installer\{90160000-0011-0000-1000-0000000FF1CE}\wordicon.exe
Excel 2016.lnk C:\Windows\Installer\{90160000-0011-0000-1000-0000000FF1CE}\xlicons.exe
TightVNC Viewer.lnk C:\Windows\Installer\{D2372F87-7DA2-47F7-A102-AF2181B8EAA2}\viewer.ico

# https://gist.github.com/DBremen/54403d02c24e303cb5f1

$sh = New-Object -ComObject WScript.Shell


# ls *.lnk | foreach { runshort $_ }
# $args | 

ls -r 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\*.lnk' |

foreach { 
  $lnk = $_
  # must be full path, or wrong subdir
  $shortcut = $sh.CreateShortcut($lnk)
  $targetpath = $shortcut.TargetPath
  $arguments = $shortcut.Arguments
    
  "lnk $lnk targetpath $targetpath arguments $arguments"
  
  if ($targetpath -notmatch 'pdf$|html?$|url$|txt$'){     
    $prog = [Diagnostics.Process]::Start($targetpath,$arguments)
    $end = (get-date) + '0:0:15' # timeout 15 seconds
      while ($prog.MainWindowHandle -eq 0 -and (get-date) -lt $end){ # wait for window
      sleep -Milliseconds 100
    }
    sleep 5
    $prog.kill()
  }

}


	
			
	

August 10, 2017 at 2:32 pm

not sure if this will help from http://www.computerperformance.co.uk/powershell/powershell_function_shortcut.htm

Function Get-StartMenu{
Begin{
Clear-Host
$Path = "$Env:ProgramData\Microsoft\Windows\Start Menu\Programs"
$x=0
} # End of Begin
Process {
$StartMenu = Get-ChildItem $Path -Recurse -Include *.lnk
ForEach($ShortCut in $StartMenu) {
$Shell = New-Object -ComObject WScript.Shell
$Properties = @{
ShortcutName = $Shortcut.Name
LinkTarget = $Shell.CreateShortcut($Shortcut).targetpath
}
New-Object PSObject -Property $Properties
$x ++
} #End of ForEach
[Runtime.InteropServices.Marshal]::ReleaseComObject($Shell) | Out-Null
} # End of Process
End{
"`nStart Menu items = $x "
}
}
#Example of function in action:

Get-StartMenu | Sort ShortcutName | Ft LinkTarget -Auto

August 10, 2017 at 2:44 pm

Thanks, but that's basically the same thing.

August 10, 2017 at 2:48 pm

yes but when I ran it I got the correct shortcut link returned. Don't as me why 🙂

August 10, 2017 at 2:50 pm

It works most of the time, just not with those shortcuts that you can't see the properties for with the mouse, like Adobe Reader or Microsoft Word.

August 10, 2017 at 2:55 pm

Mmm I just has a look at my adobe in the start menu and it looks like a shortcut in explorer

August 10, 2017 at 3:29 pm

Right click the shortcut for adobe reader and look at the target. Mine just says "Adobe Reader XI (11.0.20)", and it's greyed out, instead of being a path to the real .exe file, "C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe".

August 10, 2017 at 10:01 pm

Search for "MSI advertised shortcuts". These links point to the installation msi. Once clicked the system will check if everything is like it is supposed to, repair it if it's not and then start the application.

What's the actual purpose of this script?

August 10, 2017 at 10:07 pm

Just to test that everything launches without error.

August 11, 2017 at 2:30 pm

I can get the target of an msi shortcut in vbscript:

set msi = CreateObject("WindowsInstaller.Installer")
Set MSITarget = msi.ShortcutTarget('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2016\Word 2016.lnk')
MsgBox msi.ComponentPath(MSITarget.StringData(1), MSITarget.StringData(3))

But somehow it doesn't translate easily to powershell.

$Msi = New-Object -ComObject WindowsInstaller.Installer
$MSITarget = $Msi.ShortcutTarget('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2016\Word 2016.lnk')
$Msi.ComponentPath($MSITarget.StringData[1], $MSITarget.StringData[3])

Cannot index into a null array.
At line:1 char:1
+ $Msi.ComponentPath($MSITarget.StringData[1], $MSITarget.StringData[3] ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

I tried this too:

$Msi = New-Object -ComObject WindowsInstaller.Installer
$Msi.GetType().InvokeMember('ShortcutTarget', 'InvokeMethod', $Null, $Msi, @('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office 2016\Word 2016.lnk'))

Exception calling "InvokeMember" with "5" argument(s): "Member not found. (Exception from HRESULT: 0x80020003
(DISP_E_MEMBERNOTFOUND))"
At line:1 char:78
+ ... ll, $Msi, @('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Mic ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : COMException

August 11, 2017 at 2:40 pm

I dont have the windows installer module install atm but the bottom answer to this link may help so not tested.

https://superuser.com/questions/263505/how-do-i-find-the-target-of-an-advertised-shortcut

https://github.com/heaths/psmsi

August 11, 2017 at 7:15 pm

Here's my kludge solution:

# fix msi shortcuts
if ($targetpath -match 'c:\\windows\\installer') {
    $targetpath = cscript /nologo $PSScriptRoot\getrealtarget.vbs $lnk
}