繁体   English   中英

如何使@'...'@ 在 powershell.exe -command “”中工作?

[英]How to make @'…'@ work in powershell.exe -command “”?

背景

这是一个 PowerShell 脚本,用于刷新我从批处理文件中获得的 Internet 代理设置以禁用 Internet 选项代理服务器

function Refresh-System {
    $signature = @'
[DllImport("wininet.dll", SetLastError = true, CharSet=CharSet.Auto)]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
'@

    $INTERNET_OPTION_SETTINGS_CHANGED   = 39
    $INTERNET_OPTION_REFRESH            = 37
    $type = Add-Type -MemberDefinition $signature -Name wininet -Namespace pinvoke -PassThru
    $a = $type::InternetSetOption(0, $INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
    $b = $type::InternetSetOption(0, $INTERNET_OPTION_REFRESH, 0, 0)
    return $a -and $b
}
Refresh-System

问题

我想在批处理文件或命令提示符中将其作为单个命令运行,例如

powershell.exe -Command "stmnt1; stmnt2; ..."

我从How to condens PowerShell script to fit on a single line 中学到了这一点

方法

我试图将它完全组合成一行并执行它。

powershell -command "$signature = @'[DllImport("wininet.dll", SetLastError = true, CharSet=CharSet.Auto)] public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength)'@; $INTERNET_OPTION_SETTINGS_CHANGED   = 39; $INTERNET_OPTION_REFRESH            = 37; $type = Add-Type -MemberDefinition $signature -Name wininet -Namespace pinvoke -PassThru; $a = $type::InternetSetOption(0, $INTERNET_OPTION_SETTINGS_CHANGED, 0, 0); $b = $type::InternetSetOption(0, $INTERNET_OPTION_REFRESH, 0, 0);"

但它给我返回了一个错误。

At line:1 char:16
+ $signature = @'[DllImport(wininet.dll, SetLastError = true, CharSet=C ...
+                ~
No characters are allowed after a here-string header but before the end
of the line.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedCharactersAfterHereStringHeader

问题

我该如何解决? 有没有更好的方法来浓缩上面的function?

$signature变量周围的@字符就是所谓的Here-String并且明确地用于可能包含新行的文本块。

签名定义只是 C# 代码,并且该特定代码片段实际上不需要包含到 function 的换行符。 所以可以将其声明为常规字符串。

$signature = '[DllImport("wininet.dll", SetLastError = true, CharSet=CharSet.Auto)] public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);'

但是,您还必须处理 escaping 嵌入式双引号,根据此答案的“从 cmd.exe 或类似 POSIX 的外壳程序调用 PowerShell 的 CLI”部分,这意味着您应该将它们中的每一个替换为"^""

是否有特殊原因必须将 PowerShell 代码嵌入到批处理文件中,而不是您的批处理文件引用的它自己的.ps1文件中? 因为如果你能管理它,那是最省事的。

您的另一个选择是使用 PowerShell 通过-EncodedCommand参数运行 Base64 编码脚本的能力,而不是单行化和转义 PowerShell 代码。 假设您已经拥有Refresh-System.ps1脚本,您可以执行类似的操作来生成批处理文件。

$scriptText = Get-Content .\Refresh-System.ps1 -Raw
$scriptB64 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($scriptText))
"powershell.exe -EncodedCommand `"$scriptB64`"" | Out-File refresh-system.cmd -Encoding ascii

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM