提问人:Alexander 提问时间:8/10/2023 最后编辑:mklement0Alexander 更新时间:8/11/2023 访问量:52
如何只允许通过脚本而不是终端 wt.exe (PowerShell) 运行函数
How can I only allow a function to be run via a script and not the terminal wt.exe (PowerShell)
问:
几个小时以来,我一直在尝试制作一个函数,使其仅在由脚本而不是终端运行时才运行。
我有一个 Profile.ps1,它在每个终端实例上运行。就像 linux .bashrc 文件一样。C:\Users\Alexander\Documents\PowerShell\Profile.ps1
在我的文件中,我有这个。Profile.ps1
# Get PowerShell Profile Path
$pwsh = [System.Environment]::GetFolderPath("MyDocuments") + "\powershell"
# Dot source the internal functions I only want to be able to access via script and not terminal.
. $pwsh\internal\funcs.ps1
在文件中,我有这个。$pwsh\internal\funcs.ps1
function MyPrivateFunction {
Write-Host "Hello"
}
我试过使用,它按预期工作。$MyInvocation.CommandOrigin
function MyPrivateFunction {
if ($MyInvocation.CommandOrigin -eq "Runspace") {
return
}
Write-Host "Hello"
}
当我启动一个新终端时,字符串会写入屏幕。"Hello"
如果我像这样调用命令 MyPrivateFunction:它有效并且不返回任何内容。PS C:\Users\Alexander> MyPrivateFunction
但是我遇到的问题是我不想在所有函数中编写if语句。
这将是大量的代码重复,而且一点也不好。
如果我在以下位置制作这样的函数:funcs.ps1
function Get-Origin {
if ($MyInvocation.CommandOrigin -eq "Runspace") {
Exit
}
}
function MyPrivateFunction {
Get-Origin
Write-Host "Hello"
}
这是行不通的。因为当我调用它时,它会返回,因为它被函数调用。MyPrivateFunction
Internal
MyPrivateFunction
因此,即使您直接在终端中键入 MyPrivateFunction,它仍将被视为 并且仍然打印 。internal
"Hello"
而且我只希望它由脚本运行时运行。
有点像蟒蛇:.python if __name__ == __main__
我也尝试过使用 .psm1 模块,但它仍然会打印.Hello
我尝试使用 a 导入函数,但由于我猜在相同的范围内,它仍然会打印。.psm1 module
Hello
我唯一的解决方案是在每个函数上编写 但是由于大量代码重复,我认为这不是一个可行的选择。if ($MyInvocation.CommandOrigin -eq "Runspace")
一定有比这更好的东西。
我也认为这个问题是独一无二的,以前没有被问过。因为我已经搜索并尝试了要使用的答案,但它没有按照我想要的方式运行。PowerShell modules
我希望它只允许在脚本中运行,而不是通过powershell终端。MyPrivateFunction
由于使用点源文件,它就在那里。funcs.ps1
一种可能可行的方法是运行 python 脚本并在那里执行所有操作,但这将是另一个过程。
答:
如果您不介意丢失 Tab 自动补全(这应该无关紧要,因为您不应该以交互方式运行函数),一种可能的解决方案是使用一个调用函数脚本的脚本,执行所需的函数,但前提是它通过脚本运行。
funcs.ps1:
Param(
[parameter(Position=0)]$FunctionName,
[parameter(Position=1,ValueFromRemainingArguments= $true)]$FunctionArgs
)
. $pwsh\internal\subfuncs.ps1
if($MyInvocation.CommandOrigin -eq "Runspace"){Write-Warning 'Cannot be run interactively';return}
&$FunctionName @FunctionArgs
然后将所有函数移动到 subfuncs.ps1 中。然后,您可以在个人资料中将其称为:
$pwsh\internal\funcs.ps1 MyPrivateFunction
或者,如果您不喜欢按名称调用脚本,则可以创建一个函数来调用它,并对调用者函数进行门禁:
Function Call-Function{
if($MyInvocation.CommandOrigin -eq "Runspace"){
Write-Warning 'Cannot be run interactively'
return
}
& $pwsh\internal\funcs.ps1 @args
}
然后在你的脚本中只是 ,或者如果太长,将函数名称减少到 or 其他什么,它只是 .Call-Function myprivatefunction
cf
cf myprivatefunction
评论
我终于做到了!包括使用别名。
C:\Users\Alexander\Documents\PowerShell
├── Profile.ps1
├── internal
│ ├── funcs.ps1
│ └── subfuncs.ps1
└── powershell.config.json
Profile.ps1:
$pwsh = [System.Environment]::GetFolderPath("MyDocuments") + "\powershell"
function Open-Function{
if($MyInvocation.CommandOrigin -eq "Runspace"){
Write-Warning 'Cannot be run interactively'
return
}
& $pwsh\internal\funcs.ps1 @args
}
function New-Ln-Link {
Open-Function "New-SymbolicLink" @args
}
function New-Admin-Right {
Open-Function "Update-Rights"
}
function New-Wtd {
param (
[string[]]$Arguments
)
$targetPath = Join-Path (Get-Location) ($Arguments -join " ")
# Assuming Open-Function is a custom command to call functions dynamically
Open-Function "Start-WindowsTerminalInDirectory" $targetPath
}
New-Alias -Name ln -Value New-Ln-Link @args
New-Alias -Name admin -Value New-Admin-Right
New-Alias -Name wtd -Value New-Wtd
subfuncs.ps1:
function Update-Rights {
if(!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
$workingDirectory = Get-Location
Write-Host $MyInvocation.MyCommand.UnboundArguments
Start-Process -FilePath wt.exe -Verb Runas -ArgumentList "-d `"$($workingDirectory)`" `"$($MyInvocation.MyCommand.UnboundArguments)`""
Exit
}
}
function Start-WindowsTerminalInDirectory {
param (
[string]$Directory = (Get-Location)
)
Start-Process -FilePath "wt.exe" -ArgumentList "-d $Directory"
}
function New-SymbolicLink {
param(
[string]$Source = (Get-Location).Path,
[string]$Target
)
if (-not $Source) {
Write-Error "Please provide a valid source path."
return
}
if (-not $Target) {
Write-Error "Please provide a valid target path."
return
}
$Source = Join-Path (Get-Location).Path $Source
New-Item -Path $Target -ItemType SymbolicLink -Value $Source
}
funcs.ps1:
Param(
[parameter(Position=0)]$FunctionName,
[parameter(Position=1,ValueFromRemainingArguments= $true)]$FunctionArgs
)
. $pwsh\internal\subfuncs.ps1
if($MyInvocation.CommandOrigin -eq "Runspace"){Write-Warning 'Cannot be run interactively';return}
&$FunctionName @FunctionArgs
就是这样!
您不能直接在终端中调用。Start-WindowsTerminalInDirectory
评论
Export-ModuleMember -Function 'PublicFunction1','PublicFunction2', ...