Set-ShortcutElevation allows you to enable or disable elevation on one or multiple shortcuts using the .NET classes "ReadAllBytes" and "WriteAllBytes," which are more efficient and quicker than using the FileStream and BinaryReader. For single shortcut .lnk files: For multiple shortcut .lnk files in a specific folder or directory: Code: Function Set-ShortcutElevation { <# .SYNOPSIS Sets or removes elevation on shortcuts. .DESCRIPTION Sets or removes elevation on either a single shortcut .lnk file or multiple shortcut .lnk files in a specific folder or directory. .PARAMETER Path The full path to the shortcut, or the directory containing multiple shortcuts. .PARAMETER Disable Disables elevation. .EXAMPLE PS C:\> Set-ShortcutElevation -Path "C:\My Shortcut.lnk" PS C:\> "C:\My Shortcut.lnk" | Set-ShortcutElevation -Disable PS C:\> Get-ChildItem -Path "C:\My Custom Files" -Filter *.lnk | ForEach { Set-ShortcutElevation -Path $_.FullName } #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'The full path to the shortcut, or the directory containing multiple shortcuts.')] [ValidateScript( { Test-Path $(Resolve-Path -Path $_) })] [string]$Path, [Parameter(HelpMessage = 'Disables elevation.')] [switch]$Disable ) Begin { $Offset = 0x15 } Process { If ((Get-Item -Path $Path).Extension.Equals('.lnk')) { Try { $Bytes = [System.IO.File]::ReadAllBytes($Path) $Bytes[$Offset] = @(0x00, 0x20)[!$Disable] [System.IO.File]::WriteAllBytes($Path, $Bytes) } Catch { $PSCmdlet.ThrowTerminatingError($_) } } } }
Nice!! Would it be possible to filter by "target path"??? I struggle with this since long time let's say I want to change many (.bat) uninstallers links located in different folders in the start menu, but all pointing to the same folder in programdata.. If I make this: Code: Get-ChildItem -Path "$env:programdata\Microsoft\Windows\Start Menu\Programs\" -recurse | Where-Object {$_.Name -like "*lnk*" -and $_.Name -like "*Uninstall*"} | Set-ShortcutElevation -enable it will change every other installer...Is it possible to filter lnk by their "target path"? (for ex: change only those pointing to programdata/test)
For what you're asking, you would simply add all the paths to an array, and then loop through it, piping each output to the Set-ShortcutElevation function. Code: $Paths = @("C:\Derp", "C:\Derp1", "C:\Derp2") ForEach ($Path In $Paths) { Get-ChildItem -Path $Path -Filter *.lnk | Where-Object Name -ILike *Uninstall* | ForEach-Object { Set-ShortcutElevation -Path $_.FullName } } Also, the function does not require an -Enable switch. It only requires -Disable if you instead want to disable elevation.
Not really the expected answer...How do I know the folders ? and what if they are many links and mixed with other uninstallers ??? btw this is a bit better, filtering .bat targets only and optionally adding a string/text that is found inside that bat Code: $source = "$env:programdata\Microsoft\Windows\Start Menu\Programs" $ws = New-Object -ComObject Wscript.Shell Get-ChildItem $source -recurse -Filter *.lnk | Foreach { $tp = Get-Item $ws.CreateShortcut($_.fullname).TargetPath -Ea 0 | Where {$_.Extension -eq ".bat" -and $_.Name -like "*uninst*"} | Select-String anystringyouwant if($tp) { Set-ShortcutElevation -Path $_.FullName } } still I would like to filter by target path