【问题标题】:Powershell ps1 file fails but code is goodPowershell ps1文件失败但代码很好
【发布时间】:2017-11-15 09:29:59
【问题描述】:

当我从命令行运行我的 Powershell 脚本时,它会失败,但是如果我逐行复制并在 Powershell 控制台中运行它,它运行良好。

powershell -ExecutionPolicy Bypass -File "F:\email.ps1" -FFFeatureOff

产量:

在 F:\email.ps1:16 char:126 + ... ential("用户名", "密码"); + ~~~ 字符串缺少终止符:".

在 F:\email.ps1:9 char:1 + { + ~ 在语句块或类型定义中缺少结束“}”。

如果我打开 powershell 窗口并粘贴脚本,它真的很奇怪,它可以工作,但是运行 ps1 文件我得到错误,即使在编辑器中我也会遇到同样的问题

完整脚本:

$EmailTo = "xxxxx"
$EmailFrom = "xxxxxx"
$Subject = "LicenceKey & Instructions"
$Body = "This is an automated email"
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$files=Get-ChildItem "C:\Users\alber\Desktop\LicenceKey\newuser"
Foreach($file in $files)
{
    Write-Host “Attaching File :- ” $file
    $attachment = New-Object System.Net.Mail.Attachment –ArgumentList "C:\Users\alber\Desktop\LicenceKey\newuser\$file"
    $SMTPMessage.Attachments.Add($attachment)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true 
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("username", "password");
$SMTPClient.Send($SMTPMessage)

【问题讨论】:

  • 这可能与this 重复,因为与Attaching File 一致,您似乎有不同的引号。另一种可能性是,例如密码包含双引号。他们需要使用 ` 进行转义
  • 与几乎所有其他语言不同,Powershell 可以使用智能引号“ ”。我个人不使用它们,但这是 PS 之前的习惯。
  • 您发布的脚本没有解释您的症状。顺便说一句:调用 cmdlet 时最好避免使用方法语法;例如,代替New-Object System.Net.NetworkCredential("username", "password") 调用New-Object System.Net.NetworkCredential -ArgumentList "username", "password"
  • 脚本文件应包含 BOM 以便正确识别 UTF8。

标签: powershell


【解决方案1】:

James C.'s answer 被 OP 接受的事实表明,它的动机是 OP 对其中包含的普遍有用但非特定 - 并且最终可能令人困惑的指针表示感谢。

不幸的是,它不能满足未来读者的普遍兴趣,并且可能会引起混淆;在撰写本文时:

  • 它包含一个明显不正确的声明:

这里的问题是 $file 在消息的参数之外,移动引号将解决这个问题:Write-Host “Attaching File :- $file”

但是,Write-Host “Attaching File :- ” $file 没有 问题,因为 Write-Host 只是将多个参数与空格连接起来 - 不需要单个 参数。
(如上所述,PowerShell 识别“智能引号”(非 ASCII 引号),假设它们已正确编码 - 见下文)。

  • 它确实没有解释所发布的 OP 的症状。

  • 由于 PowerShell 的限制,这几乎让人觉得不可能在双引号字符串中嵌入文字 " - 或 $,当然,不是真的;只需使用反引号转义:"Pa`$`$`"w0rd"


相反,PetSerAl 对问题的帮助的 cmets大概指向了实际答案:

  • 可能存在字符编码问题,因为使用了“智能引号”(非 ASCII 引号字符),这会以错误的方式显示编码的脚本文件

  • PetSerAl 的 answer here 建议必须将 UTF-8 编码的脚本内容保存到带有 BOM 的文件,以便 PowerShell 识别编码。

    李>
  • 更新:PetSerAl 推测“真正的麻烦制造者是这里的 EN DASH:
    –ArgumentList,当解码不当时:[Text.Encoding]::GetEncoding(1250).GetString([Text.Encoding]‌​::UTF8.GetBytes('–')‌​),产生 –,一个不成对的双引号。”

【讨论】:

  • 感谢所有信息。我发现了这个问题。是我的密码引起的问题。我改变了它,现在它可以工作了,不敢相信我错过了。此外,所有这一切都使我研究了另一个问题并找到了答案。仅供参考:对于多行正文, $mail.BodyFormat = MailFormat.Html 然后 $Body = @" 并以 "@ 结尾
【解决方案2】:

在 F:\email.ps1:9 char:1 + { + ~ 在语句块或类型定义中缺少结束 '}'。

这里的问题是$file 在消息的参数之外,移动引号将解决这个问题:

Write-Host “Attaching File :- $file”

(Smart Quotes “ ” 被 PowerShell 接受,但不是大多数其他语言,我个人肯定会避免使用它们。)


在 F:\email.ps1:16 char:126 + ... ential("username", "password"); + ~~~ 字符串缺少终止符:".

您在此处使用的双引号:("username", "password") 如果密码包含某些特殊字符,可能会导致 Powershell 错误地解释密码的结束位置。

例如,密码Pa$$"w0rd 在脚本中使用时会因为其中的双引号引起问题。

它会被解释为"Pa$$",剩下的w0rd"(它只包含一个单引号并且没有正确地以字符串结尾)

为避免这种情况,您可以改用单引号,它们不会被计算并被解释为文字:

$SMTPClient.Credentials = New-Object System.Net.NetworkCredential('username', 'password')

有关单引号和双引号的更多信息,请参阅about_quoting_rules

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多