PowerShell: 使用相对路径从快捷方式运行脚本

8
编辑: 对于未来的读者,简言之,PowerShell 脚本并不是用于这种方式的,这就是为什么没有优雅的解决方案。
我有以下一行代码可以从快捷方式以管理员身份运行脚本:

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

我想要更改:

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

到类似于相对地址的形式:

".\test.ps1"

但我还没有想出如何做到。如何根据快捷方式所在位置运行脚本? (快捷方式和脚本在同一个文件夹中)

这是一个实际的快捷方式,就像您右键拖动并选择“在此处创建快捷方式”一样吗?还是一个批处理文件,用于启动您的PowerShell脚本?还是从计划任务中启动的?还是其他方式?请尽可能明确。 - Benjamin Hubbard
好的,那么如果您进入快捷方式属性,请转到“快捷方式”选项卡,并确保“起始位置”中的值与脚本的位置相同。尝试一下。 - Benjamin Hubbard
@Entbark:你试过了吗?我已经尝试过了,问题不在于它找不到 test.ps1,而是它甚至无法识别 .\test.ps1 是一个相对路径。 - Jesse Good
是的,我刚刚尝试了一下,它可以工作。我有一个文件夹中的脚本和一个完全不同的文件夹中的快捷方式。 快捷方式的属性:目标: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -noexit Start-Process Powershell -verb RunAs -ArgumentList ".\test.ps1"开始于: E:\test快捷方式的位置在我的桌面上。 - Benjamin Hubbard
1
@Entbark:感谢您的帮助。不幸的是,无论我尝试什么,都不能按照您的解释使其正常工作。我甚至复制了您评论中的内容,但仍然出现相同的错误。不过,noam下面的解决方案对我有用。 - Jesse Good
显示剩余4条评论
5个回答

3
这里有一个不太美观的解决方法。 Shortcut.lnk文件,目标为:%COMSPEC% /C .\launcher.cmdsource),启动项目为:%CD%(或blank)。 Launcher.cmd文件的内容:
Powershell -noprofile -noexit -File %CD%\PSlauncher.ps1

PSlauncher.ps1文件的内容:

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

当然有更好的解决方案。也许可以使用Start-Process-WorkingDirectory参数?或者使用Convert*-SecureString cmdlets来存储凭据?让我很好奇。 为什么你想要一个快捷方式?

谢谢,这个解决方案可行,但正如你所提到的,它很丑陋。基本上,我想要一种简单的方法将脚本分发给不懂PowerShell的人。看起来将脚本打包成exe或创建GUI可能是另一个解决方案。 - Jesse Good
是的。这个在演示中看起来不错,但我还没有尝试过。当然它附带了一台咖啡机和烤箱,你可能用不上... - noam

2
经过多次试验和错误,我想出了一个解决方案:
创建一个快捷方式,使用这个(编辑为您的 .ps1),以管理员身份运行脚本相对于任何目录:
CMD /C PowerShell "SL -PSPath '%CD%'; $Path = (GL).Path; SL ~; Start PowerShell -Verb RunAs -Args \""SL -PSPath '"$Path"'; & '".\YourScriptHere.ps1"'"\""

你需要清空快捷方式的“起始位置”字段,以便将其相对路径设置为工作目录。
或者,这里有一个脚本,可以为目录中的每个 .ps1 生成一个这样的快捷方式(已经清除了“起始位置”):
(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()
}

如果需要,在第一个\"后面添加-NoExit-ExecutionPolicy Unrestricted等。

注:
第一个实例使用CMD启动,因为PowerShell目前无法解析包含方括号的路径,将其解释为正则表达式字符。通常可以使用LiteralPath参数(又名PSPath)避免这种情况,但在这里,路径在启动时被传递到后台,需要由开发人员修复(我刚刚在这里提交了错误报告)。
第一个实例从第二个管理员实例启动的原因是,直接以管理员身份启动(通过勾选快捷方式的“以管理员身份运行”框),由于某些原因忽略了“开始位置”,并且始终在System32中启动。

如果我需要多个参数,似乎无法正常工作。例如: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

0

对于您的脚本,请将其默认设置为使用PowerShell打开。为您的脚本创建一个快捷方式,并通过右键单击快捷方式、选择属性、点击快捷方式选项卡来分配一个热键。将光标移动到选择快捷键并定义一个快捷键。每次按下快捷键,您的脚本都会运行。


0
当我从快捷方式运行脚本时,它使用实际脚本的路径。您可以使用pwd(当前工作目录)检查当前目录。您可以检查(然后使用)脚本路径,例如答案中所说的split-path-parent $MyInvocation.MyCommand.Definition,链接如:What's the best way to determine the location of the current PowerShell script?
所以,回答您的问题,您应该已经能够使用相对路径了。您尝试过吗?如果是,您的体验如何?

你能展示一下我需要使用的语法示例吗? - Jesse Good
你能具体说明需要哪一部分的语法吗?你在问题中已经展示了如何使用相对路径。 - Benjamin Hubbard
"C:\Documents\WindowsPowerShell\Scripts\test.ps1"更改为".\test.ps1",然后单击快捷方式会出现错误,无法将".\test.ps1"识别为cmdlet、可执行文件等。 - Jesse Good
以下是另一个示例 C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -noexit -command "& Start-Process Powershell -verb RunAs .\test.ps1"。如果从快捷方式运行,会导致错误,因为无法识别 .\test.ps1 - Jesse Good
你是如何告诉脚本从哪里运行的?你是通过更改目录(cd)来实现吗?还是指定了运行位置?如果你没有指定运行位置,它就不知道你想让它在哪里运行。 - Benjamin Hubbard

-1

这个问题看起来比实际上要复杂得多。

这个问题更可能影响到你在Windows Server上的使用。在普通的Windows系统上,你可以运行Set-ExecutionPolicy unrestricted命令,并且它将一直保持在机器上生效,但在Windows Server上(至少在AWS上),从powershell脚本中设置执行策略仅在脚本会话期间持续有效,而且脚本执行完后会立即关闭,所以你无法看到错误信息。

我刚刚在一个AWS实例上成功地修改了注册表bypassing group policy,现在我可以在任何目录中右键单击powershell脚本,发送一个可运行的快捷方式到桌面。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接