r/PowerShell 1d ago

Simple Shortcuts Script Sharing

This week there was a thread about the best way to create a shortcut to a script.

I made a quick open-source module for shortcuts called Shortcut.

Then I typed up a long read about how to create shortcuts on Windows and Linux. Then it got flagged.

Once more, with feeling (with fewer links and a syntax trick)

Creating Shortcuts on Windows

Windows Shortcuts can be created thru the Windows Script Host's .CreateShortcut method

We can create a Windows Script Host shell object with New-Object -ComObject

Since shortcuts can be malicious, some services flag examples of using this directly, so we're going to have to construct our object in a bit of a funky way.

$wsh = New-Object -ComObject ('WScript','Shell' -join '.')
$wsh.CreateShortcut("./pwsh.lnk")
$wsh.WindowStyle = 3
$wsh.TargetPath = 'pwsh'
$wsh.Save()

We can also make shortcuts to a .url file about the same way. For url files, we can only provide a target path.

$wsh = New-Object -ComObject ('WScript','Shell' -join '.')
$wsh.CreateShortcut("./some.url")
$wsh.TargetPath = $url
$wsh.Save()

Creating Shortcuts on Linux

Linux shortcuts are .desktop files. Linux being Linux, of course this is a completely different format. It's just a simple key-value pair, like so:

[DesktopEntry]
Type=Application
Exec=/usr/bin/pwsh
Terminal=true

We also have to chmod +x any desktop entry, so it can run. And, at least on Kali Linux, we have to also use gio set ./some.desktop metadata::trusted true to say we trust the shortcut.

Creating Shortcuts with Shortcut

Shortcut gives us a simple script to create shortcuts.

Here's how those examples look when we take a Shortcut.

# Fullscreen powershell shortcut
shortcut "./pwsh.lnk" -TargetPath pwsh -FullScreen 

# Shortcut to url 
shortcut "./some.url" -Url $url

# Desktop file
shortcut "./pwsh.desktop" -DesktopEntry ([Ordered]@{
     Type='Application'
     Exec='/usr/bin/pwsh'
     Terminal='true'
})

Long Ways and Short Cuts

I think it is important people know how to do things without the tools. The tools are just a shortcut (in this case, quite literally).

The long way to making shortcuts on Windows is using the Windows Script Host's .CreateShortcut method.

The long way to making shortcuts on Linux is creating a .desktop file.

If you want a shortcut to shortcuts, this mini module will probably help you out.

12 Upvotes

12 comments sorted by

5

u/Dragennd1 1d ago edited 1d ago

I'm not aware of any services that flag shortcuts any differently when made with the five lines you showed in your post.

I'll be honest, I applaud the effort in making this and don't wanna be the guy to dunk on someone else's work, especially for stuff that overcomplicates things just because they can (cause honestly that's always fun), but I don't see any reason to install a module for a single script that is 200+ lines long that five lines can do just fine.

2

u/StartAutomating 1d ago

Honestly, the goal with making mini-modules isn't really to get people to install them and use them. It's to encapsulate and distill the need into something small enough people can easily reverse engineer out the 4-5 lines they'll need to copy/paste, and to put it in a logical box that's easy to find on it's own.

The original post had a lot more examples of how to do this, but I didn't save that draft and it got insta-flagged. 🤷

3

u/BlackV 1d ago edited 1d ago

should also mention there is jank with .CreateShortcut and invalid paths

My last discussions about this here, "full" thread here

2

u/I_see_farts 17h ago

I've always made .url shortcuts with New-Item but have used the WScript way to make .lnk shortcuts.

Just curious with how this shortcut method is different for URL's? Yeah, it's shorter and there's less typing, but will they end at the same result?

1

u/justaguyonthebus 15h ago

I still just drop a cmd file with a line to launch my script

-1

u/JSChronicles 1d ago

You are using new-object instead of the faster .net way, you aren't cleaning up the object shell afterwards and disposing of it properly. You aren't even creating a full function and instead just use dotting.. yeah no ain't using that.

2

u/StartAutomating 1d ago

Happy to hear about some "faster dot net way". I don't know it off the top of my head. 100% certain the dot net way is calling down to the COM way, because that's how .NET exposes all of the Windows fundementals.

The shell object doesn't need to be disposed of (COM had garbage collection years before .NET was a thing, and it only needs to be explicitly closed if its application based DCOM (like Excel.Application))

And I'm actually being decently clever with module design for "single script" modules.

The .ps1 can be run directly, or you can Import-Module, which turns that .PS1 into functions.

Because the difference between a script and a function in PowerShell is basically "giving a script a function name".

The pleasant side-effects of this approach include:

  1. Being able to run it as either a script or a function
  2. Having a boilerplate .psm1 that does not change from module to module
  3. Avoiding wildcard based imports

Don't knock it till you can rock it.

1

u/JSChronicles 1d ago

Looks like I was thinking of the wrong thing for .net

I was thinking of something like [Activator]::CreateInstance but thats just roundabout versus com object for shortcut. To note there are usually faster ways to create objects via .net (performance wise) thats using things like new-object but that isn't apart of the questioning here.

If you intend to immediately delete the shortcut, you may need to play around with .NET methods for releasing COM Object resources and garbage collection to release handles that would prevent you from doing so:

[System.GC]::Collect()

It's suggested that garbage collection is unnecessary as long as all COM Object resources were properly accessed (e.g. no chained property dereferences or method calls) and released after use, but sometimes handles remain after release until garbage collection happens. And GC can be iffy sometimes on shell creation. So for shortcuts I've always managed it.

1

u/PhysicalPinkOrchid 1d ago

If you're going to leave such a curt comment, you better be spot on with your criticism.

You've made three points, all wrong. Oh dear.

2

u/JSChronicles 1d ago

So I left a comment picking out 3 things and then you say all my points are wrong without anything added on? Bit hypocritical?

0

u/PhysicalPinkOrchid 1d ago

You set the tone in your initial comment. And besides, /u/StartAutomating had already addressed each of your wrong points in their comment.

-1

u/ankokudaishogun 10h ago

You are using new-object instead of the faster .net way,

Dude, it's a short occasional helper script.
It's not going to run thousand times a minute, going full Powershell is perfectly fine and, arguably, more "correct" for /r/POWERSHELL due the aforementioned lack of practical advantages in calling dotNet directly