任何双击的方式,PS1文件&在PowerShell中打开它们?

ig9co6j1  于 2023-04-30  发布在  Shell
关注(0)|答案(4)|浏览(626)

我有我的项目。ps1文件,我从其中激活虚拟环境并启动我的项目。
目前,我需要打开我的powershell,然后在我需要去目录,我已经保存了我的。ps1文件&必须只从powershell打开它。
有没有办法让我可以双击。ps1文件&它会在power shell中自动打开?

jdgnovmf

jdgnovmf1#

根据设计,双击(打开)*.ps1文件Windows [GUI] shell(本例中:桌面,文件资源管理器和任务栏,通过固定的项目)不会执行它们-相反,它们会在记事本或PowerShell伊势中打开以进行编辑,具体取决于Windows / PowerShell版本。
但是,至少从Windows 7开始,*.ps1文件的快捷菜单包含**Run with PowerShell命令**,该命令 * 确实 * 调用手头的脚本;这 * 可能 * 对你的目的来说已经足够了,但是这个调用方法有限制-详情请看下面的部分。

如果你确实想*重新定义 * 双击/打开,让它 * 执行 * *.ps1脚本,有两个选择:

注意事项:

对于 * 给定 * 脚本(而不是 * 所有 * .ps1文件),您可以选择创建一个 * 快捷方式文件 * 或 * 批处理文件 * 来启动它,但不是一般的解决方案,因为您必须通过双击为您想要运行的每个.ps1文件创建一个配套文件。但是,它确实给予您能够完全控制调用。您可以通过文件资源管理器交互式 * 创建快捷方式文件,如this answer中所述,或 * 以编程方式 * 创建快捷方式文件,如this answer中所示。同样,您可以创建一个配套的 * 批处理文件*(.cmd.bat)来调用您的脚本,因为批处理文件 * 在双击时 * 执行;例如,如果您将一个与.ps1脚本具有相同基本名称的批处理文件放在同一目录中(e.例如,foo.cmd紧挨着foo.ps1),您可以从批处理文件调用它,如下所示;-NoExit保持会话打开:

@powershell.exe -NoExit -File "%~dpn0.ps1" %*
  • 注意:如果你想绕过有效的execution policy * 只用于这个调用 *,在-File之前放置一个-ExecutionPolicy Bypass参数。
  • 下面的方法还允许在cmd.exe控制台窗口*中直接同步执行.ps1脚本 *。换句话说:您可以直接执行脚本foo.ps1,而不必使用PowerShell CLI,比如powershell.exe -File foo.ps1
[* 不推荐 *] GUI 方法:

使用文件资源管理器使PowerShell默认执行.ps1文件:

  • 右键单击.ps1文件并选择Properties
  • 单击Opens with:标签旁边的Change...
  • 单击列表底部的More apps并向下滚动到Look for another app on this PC
  • 浏览或粘贴文件路径C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe并提交。

此方法无法控制PowerShell调用的具体细节,且有主要限制;实际上,您将以以下行为结束:

*主要限制
*脚本路径 * 带有嵌入空格 * 和'字符。不能以这种方式调用,因为,即使这样的路径是用双引号传递的,后者实际上被PowerShell * 剥离 *,因为路径被传递给 implied-Command参数,其首先剥离在将结果 * 解释为PowerShell代码 * 之前,命令行中的(非转义)双引号-在这种情况下,带空格的路径被视为 * 多个 * 参数/包含(奇数个)'的路径导致语法错误。

  • 请注意,如果您选择pwsh.exe,即跨平台按需安装PowerShell (Core) 7+ edition的CLI,则该问题 * 不会 * 出现,因为它默认为-File参数-在这种情况下,双引号脚本文件路径 * 被 * 正确识别。
  • 有关使用-Command与使用-File的,参见this answer
    *不支持传递参数,如果您想直接 * 从cmd.exe * 调用.ps1文件,并且需要传递参数,这一点很重要。
  • 重新定义只对 * 当前用户 * 有效-这可能是一件好事,因为其他用户可能不会期望此更改,这可能会导致不必要的脚本执行。
  • 任何执行政策都将被执行;例如,如果Restricted有效,则调用将完全失败。
  • 与默认的Run in PowerShell命令一样,脚本运行的窗口将在脚本结束时自动关闭 * -因此,除非脚本在退出前明确提示用户,否则您可能无法检查其输出。
    要对PowerShell调用脚本的方式进行更多控制,包括支持带空格的路径 * 和 * 传递参数*,请使用下一节中所示的编程方法。
* 编程 * 方法:

重要
*GUI方法 * 覆盖 * 编程解决方案,因此必须将其删除-下面的代码将 * 自动 * 删除。

  • 不幸的是,如果您安装了Visual Studio Code,则可能会发生另一个意外 * 覆盖每当您使用文件资源管理器的 * 快捷菜单 * 在Visual Studio Code中打开文件时,它意外地成为 * 默认操作。下面的代码会检测到这种情况并修复问题,但下次以这种方式打开.ps1文件时,它会重新出现**。

修改注册表,重新定义HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\Open\Command*.ps1文件的Open快捷菜单命令,如下图所示。

您可以按原样运行代码,创建一个用户级文件类型定义,该文件类型定义:

  • 使用运行当前PowerShell会话的可执行文件,即例如 Windows PowerShell 中的powershell.exePowerShell(Core)7+ 中的pwsh.exe
  • 尊重有效的execution policy-添加-ExecutionPolicy参数以覆盖。
  • 首先加载profiles-添加-NoProfile以抑制加载;如果您计划直接从cmd.exe * 调用.ps1文件 *,而不是(仅)从文件资源管理器,并结合使用-NoExitnot,则这将非常有用。
  • 运行在脚本自己的目录中
  • 在脚本退出后保持会话打开-删除-NoExit以在脚本结束时退出会话;如果您计划直接从cmd.exe * 调用.ps1文件 *,而不是(仅)从文件资源管理器调用,那么这将非常有用。

如果您的要求不同-如果您需要不同的CLI parameters和/或您想使用pwsh.exe,i.e. PowerShell(Core)7+ 代替-首先通过修改下面的$cmd = ...行来调整代码;看上面的评论。

# Specify if the change should apply to the CURRENT USER only, or to ALL users.
# NOTE: If you set this to $true - which is NOT ADVISABLE - 
#       you'll need to run this code ELEVATED (as administrator)
$forAllUsers = $false

# Determine the chosen scope's target registry key path.
$targetKey = "$(('HKCU', 'HKLM')[$forAllUsers]):\Software\Classes\Microsoft.PowerShellScript.1\shell\Open\Command"

# In the user-specific hive (HKCU: == HKEY_CURRENT_USER), the target key
# doesn't exist by default (whereas it does in the local-machine hive (HLKM: == HKEY_LOCAL_MACHINE)),
# so we need to make sure that it exists.
if (-not $forAllUsers -and -not (Test-Path -LiteralPath $targetKey)) {
  $null = New-Item -Path $targetKey -Force -ErrorAction Stop
}

# Specify the command to use when opening / double-clicking *.ps1 scripts:
# As written here:
#   * The script runs in the directory in which it resides.
#   * The profiles are loaded (add -NoProfile to change).
#   * The current execution policy is respected (add -ExecutionPolicy <policy> to override, if possible)
#   * The window stays open after the script exits (remove -NoExit to change)
# For help with all parameters, see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe
$cmd = "`"$((Get-Process -Id $PID).Path)`" -nologo -noexit -file `"%1`" %*"

# Write the command to the registry.
Set-ItemProperty -ErrorAction Stop -LiteralPath $targetKey -Name '(default)' -Value $cmd

Write-Verbose -Verbose "$(('User-level', 'Machine-level')[$forAllUsers]) file-type definition for *.ps1 files successfully updated."

# Additionally, make sure that NO OVERRIDES preempt the new definition.

# See if a user override established interactively via File Explorer happens to be defined,
# and remove it, if so.
if ($fileExplorerOverrideKey = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\UserChoice') {  
  Write-Verbose -Verbose 'Removing File Explorer override...'
  # Get the parent key path and the key name
  $parentKeyPath = $fileExplorerOverrideKey.PSParentPath -replace '^.+?::\w+\\' # Remove the 'Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\' prefix
  $keyName = $fileExplorerOverrideKey.PSChildName
  $key = $null
  try {
    # Open the *parent* key for writing.
    $key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubkey($parentKeyPath, $true)
    # Delete the subkey.
    # !! Due to the specific permissions assigned by File Explorer to the key
    # !! (an additional DENY access-control entry for the current user, for the key itself only, for the 'Set Value' permission),
    # !! using the .DeleteSubKey*Tree*() method fails (Remove-Item implicitly uses this method and therefore fails too)
    # !! However, since there should be no nested subkeys, using .DeleteSubkey() should work fine.
    $key.DeleteSubKey($keyName)
  }
  catch {
    throw
  }
  finally {
    if ($key) { $key.Close()}
  }
}

# See if *Visual Studio Code* was most recently used to open a *.ps1 file:
# If so, it inexplicably OVERRIDES a file-type definition.
# (This doesn't seem to happen with other executables.)
# !! We fix the problem, but it will RESURFACE the next time File Explorer's shortcut menu
# !! is used to open a *.ps1 file in Visual Studio Code.
if ($itm = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\OpenWithList') {
  if (($names = $itm.GetValueNames().Where({ $itm.GetValue($_) -ceq 'Code.exe' })) -and ($mruList = $itm.GetValue('MRUList')) -and $mruList[0] -in $names) {
    Write-Warning "Visual Studio Code was most recently used to open a .ps1 file, which unexpectedly overrides the file-type definition.`nCorrecting the problem for now, but it will resurface the next time you use File Explorer's shortcut menu to open a .ps1 file in Visual Studio Code."
    # Note: Normally there aren't, but there *can* be *multiple* Code.exe entries, namely after manual removal of the MRUList:
    #       The next time you choose to open in VSCode via File Explorer's shortcut menu, an *additional* Code.exe entry is added.
    do { # Trim the start of the MRUList until its first entry no longer references Code.exe
      $mruList = $mruList.Substring(1)
    } while ($mruList[0] -in $names)
    # Update the MRUList value in the registry.
    $itm | Set-ItemProperty -Name 'MRUList' -Value $mruList
  }
}
**预定义 * Run in PowerShell快捷菜单命令说明 *:

它在注册表项HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\0\Command(从Windows 10开始)中定义如下:

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
  • 这个命令是 * 有缺陷的 *,因为它与碰巧包含'字符的脚本文件路径断开。
    除非执行策略AllSigned生效-这种情况下,只有 * 签名 * 的脚本才能执行,但执行时 * 没有提示 * -该命令尝试将被调用进程的执行策略设置为Bypass,这意味着任何 * 脚本都可以执行。但仅在用户预先响应 * 确认提示之后(不管脚本是否签名,以及是否从web下载)。
  • 至少在早期的Windows 7发行版/ PowerShell版本中,该命令被 * 错误定义 [1],实际上忽略了设置进程执行策略的尝试,这意味着无论执行策略被永久配置都将应用-并且没有显示确认提示。
    ***除非目标脚本在退出前显式暂停以等待用户输入,否则脚本完成时脚本将 * 自动关闭
    **的窗口,因此您可能无法看到其输出。
  • 目标脚本在其所在目录作为工作目录(当前位置)执行

[1]较早的,被破坏的命令定义是"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1" "-Command" "if((Get-ExecutionPolicy ) -ne AllSigned) { Set-ExecutionPolicy -Scope Process Bypass }",这意味着-file "%1"之后的任何内容都作为 arguments 传递到文件"%1",而不是-Command之后的命令的预期执行;另外-一个有争议的问题-AllSigned操作数将需要被引用。

wlwcrazw

wlwcrazw2#

双击执行PS1文件(运行)

为文件创建快捷方式并将目标设置为:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Temp\MyPowershellScript.ps1"

用脚本的位置替换第二个目录(引号中的那个)。

双击读取PS1文件(编辑)

同上,但以伊势为目标,因为这将强制其进入编辑模式。

C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe "C:\Temp\MyPowershellScript.ps1"
14ifxucb

14ifxucb3#

默认情况下,Server 2012和更新版本不关联。PS1文件扩展名与PowerShell可执行文件;而是默认为打开。PS1文件与记事本默认为安全原因。
如果您有访问权限,则需要通过控制面板中的“默认程序”更改文件关联。PS1文件执行双击。
还要注意,您可能必须更改执行策略,才能运行特定的脚本。
此外,听起来这个脚本可能是一个核心自动化,您可以使用其中任何一个从另一个脚本中执行脚本,而无需更改活动工作目录:调用项“”&"

alen0pnh

alen0pnh4#

我已经修复了注册表值,以便ps1脚本可以通过双击或使用“使用PowerShell运行”从任何位置执行,即使路径中有多个连续空格和撇号:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.ps1]
@="Microsoft.PowerShellScript.1"

[HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""

[HKEY_CLASSES_ROOT\Directory\Shell\Powershell\command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""

[HKEY_CLASSES_ROOT\Drive\shell\Powershell\command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""

[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\DefaultIcon]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\",0"

[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\0\Command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""

[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\Edit\Command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell_ise.exe\" -File \"%1\""

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell]
"ExecutionPolicy"="RemoteSigned"

相关问题