8
votes

EDIT: To future readers, in short, PowerShell scripts weren't intended to be used this way which is why there is no elegant solution.

I have the following line which runs a script as an administrator from a shortcut:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -noexit Start-Process Powershell -verb RunAs -ArgumentList "C:\Documents\WindowsPowerShell\Scripts\test.ps1"

I want to change:

"C:\Documents\WindowsPowerShell\Scripts\test.ps1"

to a relative path like:

".\test.ps1"

but I haven't figured out how I can do that. How can I run the script relative to the location of the shortcut? (The shortcut and script are in the same folder)

5
Is this an actual shortcut like you would get by right-click-dragging and selecting Create Shortcuts Here? Or is this a batch file that launches your PowerShell script? Or is this being launched from Scheduled Tasks? Or other? Please be as explicit as possible.Benjamin Hubbard
@Entbark: Its and actual shortcut created by right-clicking and selecting create shortcuts here.Jesse Good
OK, then if you go into the shortcut properties, go to the Shortcut tab, and make sure that the value in Start In is the same as the location of your script. Try that.Benjamin Hubbard
@Entbark: Thanks for the help. Unfortunately, no matter what I try I cannot get it to work as you explain. I even copied exactly what is in your comment and still got the same error. noam's solution below however worked for me.Jesse Good

5 Answers

3
votes

Here is an ugly workaround.

Shortcut.lnk file with Target: %COMSPEC% /C .\launcher.cmd (source) and Start In: %CD% (or blank).

Launcher.cmd file with contents:

Powershell -noprofile -noexit -File %CD%\PSlauncher.ps1

PSlauncher.ps1 file with contents:

Start-Process Powershell -verb RunAs -ArgumentList ($pwd.path + "\test.ps1")

Surely there is a better solution. Maybe with the -WorkingDirectory parameter of Start-Process? Or storing credentials with the Convert*-SecureString cmdlets? Count me curious.

Why do you want a shortcut?

2
votes

After much trial and error, I've come up with a solution:

Create a shortcut with this (edited for your .ps1) to have scrips run as admin relative to any directory:

CMD /C PowerShell "SL -PSPath '%CD%'; $Path = (GL).Path; SL ~; Start PowerShell -Verb RunAs -Args \""SL -PSPath '"$Path"'; & '".\YourScriptHere.ps1"'"\""

You'll have to empty the shortcut's "Start in" field to have its relative path be set as the working directory.

Or, here's a script that will generate one of these shortcuts for each .ps1 in a directory (with "Start in" already cleared):

(GCI | Where-Object {$_.Extension -eq ".ps1"}).Name | ForEach-Object {
    $WshShell = New-Object -ComObject WScript.Shell
    $Shortcut = $WshShell.CreateShortcut((GL).Path+"\$_ Run.lnk")
    $Shortcut.TargetPath = 'CMD'
    $Shortcut.Arguments = "/C PowerShell `"SL -PSPath `'%CD%`'; `$Path = (GL).Path; SL ~; Start PowerShell -Verb RunAs -Args \`"`"SL -PSPath `'`"`$Path`"`'; & `'`".\$_`"`'`"\`"`""    
    $Shortcut.IconLocation = 'PowerShell.exe'
    $Shortcut.Save()
}

If needed, add -NoExit, -ExecutionPolicy Unrestricted, etc. just after the first \".

Notes:

The reason for a second, admin instance of PowerShell launching from the first, is that launching as admin directly (by ticking a shortcut's "Run as administrator" box), for some reason ignores "Start in" and always launches in System32.

CMD is being used to launch the first instance because PowerShell currently fails to resolve paths containing square brackets, interpreting them as regex characters. This would normally be avoided using the LiteralPath parameter (aka PSPath), but here, the path is being passed behind the scenes at launch, and it's up to the developers to fix (I just filed a bug report here).

0
votes

When I run a script from a shortcut, it uses the path of the actual script. You can check the current directory with pwd (present working directory). You can check (and then use) the path of the script with split-path -parent $MyInvocation.MyCommand.Definition like the answer says in What's the best way to determine the location of the current PowerShell script?.

So to answer your question, you should already be able to use relative paths. Have you tried it? If so, what was your experience?

0
votes

For your script, set it to open using Powershell by default. Create a shortcut for your script and assign it a hot key by right clicking on your shortcut, selecting properties, click the shortcut tab. Move your cursor the select shortcut key and define a shortcut key. Each time you press the shortcut key your script will run

-1
votes

This is definitely made out to be more difficult than it is.

This issue is more likely to affect you on Windows Server. On regular Windows, you can run Set-ExecutionPolicy unrestricted and it will stay in affect on the machine, on Windows Server (at least on AWS), setting the execution policy from a powershell script only lasts for the session of the script and it closes immediately so you can't see the error.

I just successfully modded the registry on an AWS instance bypassing group policy and can simply right click powershell scripts from any directory and send a shortcut to the desktop that is runnable.