【问题标题】:Expressions are only allowed as the first element of a pipeline表达式只允许作为管道的第一个元素
【发布时间】:2011-11-01 08:41:09
【问题描述】:

我是使用 powershell 编写的新手,但这是我想要完成的。

  1. 我想比较两个 Excel 文件的日期以确定一个是否比另一个新。
  2. 我想在没有 excel 的计算机上将文件从 csv 转换为 xls。只有当上面的陈述为真时,初始的 xls 文件已经被复制了。
  3. 我想将新转换的 xls 文件复制到另一个位置
  4. 如果文件已经打开,它将无法复制,所以我想发送一封电子邮件提醒此操作成功或失败。

这是我遇到问题的脚本。错误是“表达式只允许作为管道的第一个元素。”我知道这与电子邮件操作有关,但我不知道如何在包含所有这些变量的情况下手动写出来。可能还有更多错误,但我现在没有看到它们。感谢您的帮助,我很感激!

$CSV = "C:filename.csv"
$LocalXLS = "C:\filename.xls"
$RemoteXLS = "D:\filename.xls"
$LocalDate = (Get-Item $LocalXLS).LASTWRITETIME
$RemoteDate = (Get-Item $RemoteXLS).LASTWRITETIME
$convert = "D:\CSV Converter\csvcnv.exe"
if ($LocalDate -eq $RemoteDate) {break}
else { 
& $convert $CSV $LocalXLS
$FromAddress = "email@address.com"
$ToAddress = "email@address.com"
$MessageSubject = "vague subject"
$SendingServer = "mail.mail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage $FromAddress, $ToAddress, $MessageSubject, $MessageBody
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SendEmailSuccess = $MessageBody = "The copy completed successfully!" | New-Object System.Net.Mail.SMTPClient mail.mail.com $SMTPMessage
$RenamedXLS = {$_.BaseName+(Get-Date -f yyyy-MM-dd)+$_.Extension}

Rename-Item -path $RemoteXLS -newname $RenamedXLS -force -erroraction silentlycontinue
If (!$error)
    { $SendEmailSuccess | copy-item $LocalXLS -destination $RemoteXLS -force }
Else
    {$MessageBody = "The copy failed, please make sure the file is closed." | $SMTPClient.Send($SMTPMessage)}
}   

【问题讨论】:

  • 我不确定您要在这一行上完成什么: $SendEmailSuccess = $MessageBody = "复制成功完成!" | New-Object System.Net.Mail.SMTPClient mail.mail.com $SMTPMessage 但我想这是错误的罪魁祸首。
  • @meep - 不要编辑内容。那时你的问题根本没有意义。即使您已经弄清楚了,这对未来的访问者也会很有用。附加您的修改。

标签: powershell


【解决方案1】:

当您尝试从管道链中执行独立的代码块时,您会收到此错误。

作为一个不同的例子,想象一下这段代码使用 jQuery:

$("div").not(".main").console.log(this)

每个点 (.) 将数组链接到下一个函数。在上面的函数中,这与console 中断,因为它并不意味着有任何值通过管道输入。如果我们想从我们的链接中中断以执行一些代码(可能在链中的对象上 - 我们可以使用each 这样做这个:

$("div").not(".main").each(function() {console.log(this)})

解决方案是 powershell 是相同的。如果您想对链中的每个项目单独运行脚本,可以使用 ForEach-Object 或其别名 (%)。

假设您在 Powershell 中有以下功能:

$settings | ?{$_.Key -eq 'Environment' } | $_.Value = "Prod" 

最后一行无法执行,因为是脚本,但是we can fix that with ForEach是这样的:

$settings | ?{$_.Key -eq 'Environment' } | %{ $_.Value = "Prod" }

【讨论】:

    【解决方案2】:

    这个错误基本上发生在当你在管道的接收端使用表达式时它无法从管道接收对象。

    如果你这样做,你会得到错误:

    $a="test" | $a
    

    甚至这个:

    "test" | $a
    

    我不知道为什么到处都是管道。我建议您学习有关 Powershell 流水线的基础知识。你接近它是错误的。另外,我认为您可以参考下面的链接以查看如何发送邮件,应该是直截了当的,没有您在管道中添加的复杂性:http://www.searchmarked.com/windows/how-to-send-an-email-using-a-windows-powershell-script.php

    【讨论】:

    • 我喜欢烟斗,但我发现它被过度使用了。尤其是在脚本内部。我一直在命令提示符下使用管道,但我很少在脚本中使用它。
    • @EBGreen - 我认为真正的问题只是当你不真正了解正在发生的事情时。例如,您可以使用$a | write-host 而不是write-host $a。是的,有时它被过度使用。编写单行代码很好,但很难维护其他人必须阅读和维护的脚本。
    • 是的,即使它们在脚本中被完全正确地使用,我也只是将其视为良好习惯的问题(无论如何对我自己而言),继续在脚本中尽可能明确。这意味着更少的管道和明确的 cmdlet 名称而不是别名。
    • 我试图让它根据错误结果发送不同的消息。您在该脚本中向我展示的内容是我已经尝试过的。当我把它发送到电子邮件时,结果是一样的。请解释我如何让它根据不同的响应发送不同的消息。
    猜你喜欢
    • 2014-05-26
    • 2014-12-01
    • 2014-09-24
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 2023-02-01
    • 1970-01-01
    相关资源
    最近更新 更多