簡體   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