我编写了这个PowerShell指令,以将给定的路径添加到新的PowerShell进程中的Microsoft排除列表中(具有提升的权限):
Start-Process powershell {Add-MpPreference -ExclusionPath "my/path/to/exe"; Read-Host;} -Verb "RunAs"令人惊讶的是,我得到了这个错误:
Add-MpPreference : A positional parameter cannot be found that accepts argument '-'.但是,如果我运行下面的行,输出(hi)将成功地显示在新进程中:
Start-Process powershell {echo "hi"; Read-Host} -Verb "RunAs"第一个PowerShell指令有什么问题?我怎么才能解决这个问题?
发布于 2022-01-25 19:46:13
在@mclement0的帮助下(请参阅上面的注释),我意识到我不得不使用带有Start-Process的双引号字符串来使指令工作:
Start-Process powershell "Add-MpPreference -ExclusionPath 'my/path/to/exe'" -Verb "RunAs"发布于 2022-01-27 04:23:03
使用命名参数
对于稍后来并寻求帮助的人,请使用错误信息:
<cmdlet>: A positional parameter cannot be found that accepts argument '<arg>'.快速修复方法是使用命名参数。命名参数总是有效的。
# Doesn't work. The parameter name *is not* given.
Get-ChildItem 32
# Works. The parameter name *is* given.
Get-ChildItem -Depth 32列表位置参数
或者,您可以检查cmdlet是否有任何位置参数。你可以搜索文档。但是一个快速的方法是让PowerShell来完成这项工作。使用下面的单线衬垫。然后用你感兴趣的cmdlet替换"Get-ChildItem“。请记住,如果输出仅显示“命名”,则cmdlet不接受位置参数。下面有两个位置参数:路径和过滤器。
Get-Help -Name "Get-ChildItem" -Parameter * |
Sort-Object -Property position |
Select-Object -Property name, position
name position
---- --------
Path 0
Filter 1
Attributes Named
Depth Named
Directory Named
Exclude Named
File Named
FollowSymlink Named
Force Named
Hidden Named
Include Named
LiteralPath Named
Name Named
ReadOnly Named
Recurse Named
System Named什么是位置参数?
参数是添加到命令中以更改命令工作方式的文本。“参数”一词通常指的是参数名称和参数值。参数名称前面有一个连字符'-‘
# | cmdlet | parameter name
# v v v parameter value
Get-ChildItem -Path './'大多数cmdlet提供了省略参数名称的快捷方式。这些都被称为位置参数。而cmdlet开发人员不需要支持位置参数。
# | cmdlet
# v v positional parameter
Get-ChildItem './'由于位置参数是未命名的,因此区分它们的唯一方法是根据它们在语句中的位置--名称位置参数--来区分它们。您可以通过使用Get-Help cmdlet、使用Microsoft联机或通过检查cmdlet供应商的文档来找到与您感兴趣的参数关联的位置。您可能需要进行一些搜索,因为参数是按名称而不是在帮助页中的位置进行索引的。第一个位置编号为0。随后的头寸增加了1。所以前四个位置是0,1,2,3…下面,我们可以看到Get的路径参数在0位置被接受.这是在以“立场?”开头的行上表示的。
Get-Help -Name "Get-ChildItem" -Parameter "Path"
-Path <string[]>
Required? false
Position? 0
Accept pipeline input? true (ByValue, ByPropertyName)
Parameter set name Items
Aliases None
Dynamic? false
Accept wildcard characters? false命名参数将显示“命名”作为其位置值。
Get-Help -Name "Get-ChildItem" -Parameter "LiteralPath"
-LiteralPath <string[]>
Required? true
Position? Named
Accept pipeline input? true (ByPropertyName)
Parameter set name LiteralItems
Aliases PSPath, LP
Dynamic? false
Accept wildcard characters? false通过在线阅读参数帮助主题了解更多信息。
错误信息详细信息
我希望能够从最初的查询中解释错误信息。但我没有得出结论。
查看文档,附加-MpPreference是不寻常的,因为它没有位置参数。
我的系统上没有要测试的Add-MpPreference cmdlet的副本。我发现Get-Unique是一个类似的cmdlet。我在Get-Unique中也产生了类似的错误
@("hello","hello") | get-unique -
Get-Unique: A positional parameter cannot be found that accepts argument '-'.
# Add-MpPreference : A positional parameter cannot be found that accepts argument '-'.所以我们必须考虑一下,如果有任何位置参数可用的话。我们可以看到代码和错误信息的比较。
从PowerShell 7开始,我们可以获得关于Get-Error上一条错误消息的更多信息。默认情况下,早期版本的PowerShell将打印大部分这些信息。但是PowerShell 7切换到了更简单的错误消息。
如果向下滚动到PositionMessage,它将告诉您是哪一行代码导致了执行错误。它将绘制一个小的图表,其中违规的表达式加下划线。这使得将错误连接到特定语法变得更加容易。
Get-Error
...
PositionMessage : At line:1 char:22
+ @("hello","hello") | get-unique -
+ ~~~~~~~~~~~~检查不良字符
有时,如果我们从网上复制和粘贴,我们可以选择排版字符,这些字符适合打印,但不适用于代码。例子包括聪明的引号(卷曲)和各种破折号,如emdash t(它比标准的破折号长)。Conhost和Windows终端应该能够处理这些问题。但我不确定脚本或其他主机(比如NSIS内部)。
检查的一种方法是转到shell并使用Format-Hex检查可疑代码的简短片段。我们需要使用这里-字符串来保留原始格式。
下面,我将错误消息复制到shell,并将其签出。我想知道结尾的连字符是否有正确的字符代码。我们可以在字节0x51或行50和列01处看到代码。那里的值是0x2D。我们可以通过直接在命令行输入连字符来检查它的正确值。一定要把它用引号括起来。经过第二次检查,我们看到正确的值是0x2D。因为我们正在调查的值匹配正确的值,所以看起来连字符并不是问题所在。如果您自己这样做,请确保从您的代码编辑器中复制,而不是任何错误消息,这是我不得不在这里使用的妥协。
@"
Add-MpPreference : A positional parameter cannot be found that accepts argument '-'.
"@ | Format-Hex
Label: String (System.String) <44085160>
Offset Bytes Ascii
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
------ ----------------------------------------------- -----
0000000000000000 41 64 64 2D 4D 70 50 72 65 66 65 72 65 6E 63 65 Add-MpPreference
0000000000000010 20 3A 20 41 20 70 6F 73 69 74 69 6F 6E 61 6C 20 : A positional
0000000000000020 70 61 72 61 6D 65 74 65 72 20 63 61 6E 6E 6F 74 parameter cannot
0000000000000030 20 62 65 20 66 6F 75 6E 64 20 74 68 61 74 20 61 be found that a
0000000000000040 63 63 65 70 74 73 20 61 72 67 75 6D 65 6E 74 20 ccepts argument
0000000000000050 27 2D 27 2E '-'.
'-' | Format-Hex
Label: String (System.String) <6ECC1D05>
Offset Bytes Ascii
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
------ ----------------------------------------------- -----
0000000000000000 2D -powershell.exe命令参数
我想一步一步地检查这个命令,看看是否有任何细微的语法错误。我在我的系统上碰到了一个不相关的bug,使我无法走得很远。但是,经过一番思考,我不知道为什么这些例子会奏效。在这种情况下,Start-Process应该将参数强制给[String[]]。powershell.exe应该将第一个字符串解释为文件名,而不是cmdlet。确实,powershell.exe可以识别没有参数名称的脚本块。但这并不适用于这里,因为强制的[String[]]。
如果接受的答案(与启动过程和引用相关)没有帮助,那么您可以为powershell.exe使用适当的参数。或者,当从PowerShell调用程序时,您可能需要探索引用和逃避的兔子洞。
# | Interprets strings as file names.
# | |----------- String passed to powershell.exe --------------|
# v | not a file |
Start-Process powershell {Add-MpPreference -ExclusionPath "my/path/to/exe"; Read-Host;} -Verb "RunAs"
Start-Process powershell "Add-MpPreference -ExclusionPath 'my/path/to/exe'" -Verb "RunAs"https://stackoverflow.com/questions/70853968
复制相似问题