8

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)

Jesse Good
  • 50,901
  • 14
  • 124
  • 166
  • possible duplicate of [What's the best way to determine the location of the current PowerShell script?](http://stackoverflow.com/questions/5466329/whats-the-best-way-to-determine-the-location-of-the-current-powershell-script) – Benjamin Hubbard Mar 18 '14 at 21:14
  • 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 Mar 18 '14 at 22:19
  • @Entbark: Its and actual shortcut created by right-clicking and selecting create shortcuts here. – Jesse Good Mar 18 '14 at 22:22
  • 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 Mar 19 '14 at 17:31
  • @Entbark: Have you tried it? I've already tried that, the problem is not that it cannot find `test.ps1`, but that it cannot even recognize that `.\test.ps1` is a relative path. – Jesse Good Mar 19 '14 at 20:37
  • Yes, I tried it just now and it worked. I have the script in one folder and the shortcut in a completely different folder. The properties of the shortcut: Target: `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -noexit Start-Process Powershell -verb RunAs -ArgumentList ".\test.ps1"` Start in: `E:\test` Location of the shortcut is on my desktop. – Benjamin Hubbard Mar 20 '14 at 13:19
  • "Start in" can't be a relative path, it appears. But I moved the shortcut to the same folder as the script itself and ran it again without modifying the shortcut, and it worked still. – Benjamin Hubbard Mar 20 '14 at 13:23
  • 1
    @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 Mar 20 '14 at 14:12
  • @JesseGood - just wanted to check if you have run `Set-ExecutionPolicy unrestricted` on the system? Without that, I get the shortcut dying immediately after opening. – cchamberlain Jan 14 '16 at 05:52

5 Answers5

3

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?

Community
  • 1
  • 1
noam
  • 1,914
  • 2
  • 20
  • 26
  • Thanks this solution works, but as you mentioned it is ugly. Basically I wanted an easy way to distribute scripts to people who know nothing about PowerShell. Looking around it seems packaging scripts into an exe or creating a gui would be the other solution. – Jesse Good Mar 20 '14 at 14:08
  • Yeah. [This](https://labs.vmware.com/flings/web-commander) looked good in a demo, but i haven't tried it. Of course it comes with a coffee maker and toaster oven you probably won't need... – noam Mar 20 '14 at 16:14
2

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).

Community
  • 1
  • 1
Mica
  • 383
  • 3
  • 14
  • If I need multiple parameters, it doesn't seem to work. E.g. CMD /C PowerShell "SL -PSPath '%CD%'; $Path = (GL).Path; SL ~; Start PowerShell -Verb RunAs -Args \"-ExecutionPolicy ByPass -WindowStyle Hidden" SL -PSPath '"$Path"'; & '".\DisconnectOnIdle.ps1"'"\"" – shadowz1337 May 26 '21 at 22:30
0

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?

Community
  • 1
  • 1
Benjamin Hubbard
  • 2,797
  • 22
  • 28
  • Can you show an example of the syntax I need to use? – Jesse Good Mar 18 '14 at 21:29
  • Can you be more specific? Which part are you needing syntax for? You already seem to know how to use relative paths as demonstrated in your question. – Benjamin Hubbard Mar 18 '14 at 21:52
  • Changing `"C:\Documents\WindowsPowerShell\Scripts\test.ps1"` to `".\test.ps1"` and clicking the shortcut gives an error that it cannot recognize `".\test.ps1"` as a cmdlet, executable, etc. – Jesse Good Mar 18 '14 at 21:58
  • Here is another example `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -noexit -command "& Start-Process Powershell -verb RunAs .\test.ps1"`, this will cause an error when run from a shortcut that `.\test.ps1` cannot be recognized. – Jesse Good Mar 18 '14 at 22:08
  • How are you telling the script where to run from? Are you changing directories (`cd`) to it? Or are you specifying where to run from? If you don't specify the run-from location, it won't know you want it to run there. – Benjamin Hubbard Mar 18 '14 at 22:17
0

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

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.

cchamberlain
  • 17,444
  • 7
  • 59
  • 72