简体   繁体   English

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

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

Background背景

This is a PowerShell script for refreshing Internet proxy settings which I got from Batch File to disable internet options proxy server .这是一个 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

Problem问题

I want to run it in batch file or command prompt as a single command such as我想在批处理文件或命令提示符中将其作为单个命令运行,例如

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

Which I learned from How to condense PowerShell script to fit on a single line .我从How to condens PowerShell script to fit on a single line 中学到了这一点

Approach方法

I've tried to combine it altogether into one line and execute it.我试图将它完全组合成一行并执行它。

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);"

But it returned me an error.但它给我返回了一个错误。

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

Question问题

How do I solve it?我该如何解决? Is there any better ways to condense the function above?有没有更好的方法来浓缩上面的function?

The @ characters around the $signature variable are what's known as a Here-String and are explicitly intended for blocks of text that may include new lines. $signature变量周围的@字符就是所谓的Here-String并且明确地用于可能包含新行的文本块。

The signature definition is just C# code and that particular code snippet doesn't actually need the included line breaks to function.签名定义只是 C# 代码,并且该特定代码片段实际上不需要包含到 function 的换行符。 So can just declare it like a regular string instead.所以可以将其声明为常规字符串。

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

However, you're also going to have to deal with escaping the embedded double quotes which according to the "Calling PowerShell's CLI from cmd.exe or POSIX-like shells" section of this answer means you should replace each of them with "^""但是,您还必须处理 escaping 嵌入式双引号,根据此答案的“从 cmd.exe 或类似 POSIX 的外壳程序调用 PowerShell 的 CLI”部分,这意味着您应该将它们中的每一个替换为"^""

Is there a particular reason the PowerShell code has to be embedded in the batch file rather than its own .ps1 file along side it that your batch file references?是否有特殊原因必须将 PowerShell 代码嵌入到批处理文件中,而不是您的批处理文件引用的它自己的.ps1文件中? Because that's the least hassle if you can manage it.因为如果你能管理它,那是最省事的。

Your other option instead of having to one-line'ify and escape the PowerShell code is to use PowerShell's ability to run a Base64 encoded script via the -EncodedCommand parameter.您的另一个选择是使用 PowerShell 通过-EncodedCommand参数运行 Base64 编码脚本的能力,而不是单行化和转义 PowerShell 代码。 Assuming you have your Refresh-System.ps1 script already, you could do something like this to generate the batch file.假设您已经拥有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