Csv PowerShell脚本循环-警告已创建的新文件

Csv PowerShell脚本循环-警告已创建的新文件,csv,powershell,Csv,Powershell,我希望有PowerShell经验的人能够非常友好地建议(如果可能的话)我们如何循环这个脚本。不幸的是,我们还不太熟悉PowerShell脚本循环,正在寻找一些建议,看看哪种方法/方式是最好的。我们在工作中使用下面的脚本,当在指定日期开始的指定文件夹和/或文件夹中创建新文件时,向员工发送电子邮件警报,其中包括一个.csv文件,列出该文件,然后将其删除。我们不需要保留发送警报后生成的.csv文件。现在,我们正在一次又一次地复制和粘贴代码,并在添加新文件夹时修改部分代码。然而,我们担心的是,随着周/月

我希望有PowerShell经验的人能够非常友好地建议(如果可能的话)我们如何循环这个脚本。不幸的是,我们还不太熟悉PowerShell脚本循环,正在寻找一些建议,看看哪种方法/方式是最好的。我们在工作中使用下面的脚本,当在指定日期开始的指定文件夹和/或文件夹中创建新文件时,向员工发送电子邮件警报,其中包括一个.csv文件,列出该文件,然后将其删除。我们不需要保留发送警报后生成的.csv文件。现在,我们正在一次又一次地复制和粘贴代码,并在添加新文件夹时修改部分代码。然而,我们担心的是,随着周/月/年的流逝,随着文件夹的添加,最终该文件将变长,并且必须添加新文件夹

理想情况下,我们对脚本所做的唯一更改是在网络驱动器中查看的文件夹路径、创建时间以及它将要发送到的收件人

我们非常感谢您就实现所有或任何目标的最佳方式提出的任何建议

非常感谢

$arr = @()
$file = "\\DesignatedNetworkDrive\NewFileFinderReport.csv"
$mesg = "Please see the attached file for a list of files that were created after July 1, 2016."


# Folder: Corporateshare

gci \\DesignatedNetworkDrive\,\\DesignatedNetworkDrive\Corporateshare\  | Where-Object { $_.CreationTime -ge "07/02/2016" } | % {
  $obj = New-Object PSObject
  $obj | Add-Member NoteProperty FullName $_.FullName
  $obj | Add-Member NoteProperty Length $_.Length
  $obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
  $obj | Add-Member NoteProperty LastAccessTime $_.LastAccessTime
  $obj | Add-Member NoteProperty LastWriteTime $_.LastWriteTime
  $obj | Add-Member NoteProperty CreationTime $_.CreationTime

  $arr += $obj
  }
  $arr | Export-CSV -notypeinformation "$file"



if ($(get-item -path "$file").length -gt 0) {send-mailmessage -from "sysadmin@something.com" -to "jendoe@something.com","johndoe@something.com" -subject "New File Found in Corporateshare" -body "$mesg" -Attachments "$file" -smtpServer mail.somecompany.com}

Remove-Item $file



# Folder: Administration
$arr = @()
$file = "\\DesignatedNetworkDrive\NewFileFinderReport.csv"
$mesg = "Please see the attached file for a list of files that were created after May 3, 2016."


gci \\DesignatedNetworkDrive\Administration\,\\DesignatedNetworkDrive\Administration\_Private\  | Where-Object { $_.CreationTime -ge "05/04/2016" } | % {
  $obj = New-Object PSObject
  $obj | Add-Member NoteProperty FullName $_.FullName
  $obj | Add-Member NoteProperty Length $_.Length
  $obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
  $obj | Add-Member NoteProperty LastAccessTime $_.LastAccessTime
  $obj | Add-Member NoteProperty LastWriteTime $_.LastWriteTime
  $obj | Add-Member NoteProperty CreationTime $_.CreationTime

  $arr += $obj
  }
  $arr | Export-CSV -notypeinformation "$file"



if ($(get-item -path "$file").length -gt 0) {send-mailmessage -from "jendoe@something.com","johndoe@something.com" -body "$mesg" -Attachments "$file" -smtpServer mail.somecompany.com}

Remove-Item $file


# Folder: Procurement
$arr = @()
$file = "\\DesignatedNetworkDrive\NewFileFinderReport.csv"
$mesg = "Please see the attached file for a list of files that were created after May 24, 2016."


gci \\DesignatedNetworkDrive\Procurement\  | Where-Object { $_.CreationTime -ge "05/25/2016" } | % {
  $obj = New-Object PSObject
  $obj | Add-Member NoteProperty FullName $_.FullName
  $obj | Add-Member NoteProperty Length $_.Length
  $obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
  $obj | Add-Member NoteProperty LastAccessTime $_.LastAccessTime
  $obj | Add-Member NoteProperty LastWriteTime $_.LastWriteTime
  $obj | Add-Member NoteProperty CreationTime $_.CreationTime

  $arr += $obj
  }
  $arr | Export-CSV -notypeinformation "$file"



if ($(get-item -path "$file").length -gt 0) {send-mailmessage -from "jendoe@something.com","johndoe@something.com" -subject "New File Found in Procurement" -body "$mesg" -Attachments "$file" -smtpServer mail.somecompany.com}

Remove-Item $file

您需要将过程抽象为一个函数

将PowerShell代码片段转换为有用函数的关键是识别它的可变部分-这些应该转换为参数,然后在调用函数时可以传递给函数

查看您的代码,很少有部分是变量,即:

  • 创建日期
  • 文件夹路径
此外,您可能希望允许对电子邮件收件人、邮件主题和SMTP服务器进行可选更改-这些内容可能会在将来更改,或因特定目的而有所不同

考虑到这一点,我们最终得出如下结论:

function Check-NewFiles 
{
    param(
        [Parameter(Mandatory)]
        [string[]]$Path,
        [Parameter(Mandatory)]
        [datetime]$CreatedAfter,
        [string]$Subject = "New files found",
        [string[]]$Recipients = @("jendoe@something.com","johndoe@something.com"),
        [string]$MailFrom = "noreply@something.com",
        [string]$SmtpServer
    )

    # Folder: Administration
    $arr = @()
    $file = "\\DesignatedNetworkDrive\NewFileFinderReport.csv"
    $mesg = "Please see the attached file for a list of files that were created after {0:MMM dd, yyyy}" -f $CreatedAfter

    Get-ChildItem $Path  | Where-Object { $_.CreationTime -ge $CreatedAfter } | ForEach-Object {
        $obj = New-Object PSObject
        $obj | Add-Member NoteProperty FullName $_.FullName
        $obj | Add-Member NoteProperty Length $_.Length
        $obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
        $obj | Add-Member NoteProperty LastAccessTime $_.LastAccessTime
        $obj | Add-Member NoteProperty LastWriteTime $_.LastWriteTime
        $obj | Add-Member NoteProperty CreationTime $_.CreationTime

        $arr += $obj
    }
    $arr | Export-CSV -notypeinformation "$file"



    if ($(get-item -path "$file").length -gt 0) {
        Send-MailMessage -From $MailFrom -body "$mesg" -Attachments "$file" -smtpServer $SmtpServer -To $Recipients
    }

    Remove-Item $file
}
现在,您每次都可以用一行代码调用它:

Check-NewFiles -Path \\DesignatedNetworkDrive\,\\DesignatedNetworkDrive\Corporateshare\ -CreatedAfter '07/02/2016'
Check-NewFiles -Path \\DesignatedNetworkDrive\Administration\,\\DesignatedNetworkDrive\Administration\_Private\ -CreatedAfter '05/04/2016'
对于具有大量参数的同一调用的许多实例,我喜欢使用参数参数设置哈希表集合-这样我可以轻松地循环整个集合并调用函数,而参数:

$FoldersToWatch = @(
    # Folder: Corporateshare
    @{
        Path = '\\DesignatedNetworkDrive\','\\DesignatedNetworkDrive\Corporateshare\'
        CreatedAfter = "07/02/2016"
        MailFrom = "sysadmin@something.com" 
        Recipients = "jendoe@something.com","johndoe@something.com"
    },

    # Folder: Administration
    @{
        Path = '\\DesignatedNetworkDrive\Administration\','\\DesignatedNetworkDrive\Administration\_Private\'
        CreatedAfter = "05/04/2016"
        Recipients = "jendoe@something.com","johndoe@something.com"
    },

    # Folder: Procurement
    @{
        Path = '\\DesignatedNetworkDrive\Procurement\'
        CreatedAfter = "05/25/2016"
        Subject = "Procurement, IMPORTANT!"
    }
)
现在,将上述内容放入自己的文件中,称之为
FoldersToWatch.ps1

然后,在定义了
Check NewFiles
函数的脚本中,点源
FoldersToWatch.ps1
文件,然后在哈希表中循环并调用该函数:

# function Check-NewFiles goes up here

. .\FoldersToWatch.ps1

$FoldersToWatch |Foreach-Object {
    Check-NewFiles @_
}
就在这里。现在,任何人都可以更新
FoldersToWatch.ps1
中的参数,而不会弄乱脚本本身,也不会忽略正在发生的事情


我还想指出,使用
newobject
addmember
创建新对象,然后将其添加到数组中的方法是完全不必要的。使用
选择对象
并将其直接导入
导出Csv

Get-ChildItem $Path |Where-Object { $_.CreationTime -ge $CreatedAfter } |Select-Object FullName,Length,@{Label='Owner';Expression={(Get-Acl $_.FullName).Owner}},LastAccessTime,LastWriteTime,CreationTime |Export-CSV -notypeinformation "$file"
最终的函数看起来更像:

function Check-NewFiles 
{
    param(
        [Parameter(Mandatory)]
        [string[]]$Path,
        [Parameter(Mandatory)]
        [datetime]$CreatedAfter,
        [string]$Subject = "New files found",
        [string[]]$Recipients = @("jendoe@something.com","johndoe@something.com"),
        [string]$MailFrom = "noreply@something.com",
        [string]$SmtpServer
    )

    $file = "\\DesignatedNetworkDrive\NewFileFinderReport.csv"
    $mesg = "Please see the attached file for a list of files that were created after {0:MMM dd, yyyy}" -f $CreatedAfter

    Get-ChildItem $Path |Where-Object { $_.CreationTime -ge $CreatedAfter } |Select-Object FullName,Length,@{Label='Owner';Expression={(Get-Acl $_.FullName).Owner}},LastAccessTime,LastWriteTime,CreationTime |Export-CSV -notypeinformation "$file"

    if ($(get-item -path "$file").length -gt 0) {
        Send-MailMessage -From $MailFrom -body "$mesg" -Attachments "$file" -smtpServer $SmtpServer -To $Recipients
    }

    Remove-Item $file
}

您需要将过程抽象为一个函数

将PowerShell代码片段转换为有用函数的关键是识别它的可变部分-这些应该转换为参数,然后在调用函数时可以传递给函数

查看您的代码,很少有部分是变量,即:

  • 创建日期
  • 文件夹路径
此外,您可能希望允许对电子邮件收件人、邮件主题和SMTP服务器进行可选更改-这些内容可能会在将来更改,或因特定目的而有所不同

考虑到这一点,我们最终得出如下结论:

function Check-NewFiles 
{
    param(
        [Parameter(Mandatory)]
        [string[]]$Path,
        [Parameter(Mandatory)]
        [datetime]$CreatedAfter,
        [string]$Subject = "New files found",
        [string[]]$Recipients = @("jendoe@something.com","johndoe@something.com"),
        [string]$MailFrom = "noreply@something.com",
        [string]$SmtpServer
    )

    # Folder: Administration
    $arr = @()
    $file = "\\DesignatedNetworkDrive\NewFileFinderReport.csv"
    $mesg = "Please see the attached file for a list of files that were created after {0:MMM dd, yyyy}" -f $CreatedAfter

    Get-ChildItem $Path  | Where-Object { $_.CreationTime -ge $CreatedAfter } | ForEach-Object {
        $obj = New-Object PSObject
        $obj | Add-Member NoteProperty FullName $_.FullName
        $obj | Add-Member NoteProperty Length $_.Length
        $obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
        $obj | Add-Member NoteProperty LastAccessTime $_.LastAccessTime
        $obj | Add-Member NoteProperty LastWriteTime $_.LastWriteTime
        $obj | Add-Member NoteProperty CreationTime $_.CreationTime

        $arr += $obj
    }
    $arr | Export-CSV -notypeinformation "$file"



    if ($(get-item -path "$file").length -gt 0) {
        Send-MailMessage -From $MailFrom -body "$mesg" -Attachments "$file" -smtpServer $SmtpServer -To $Recipients
    }

    Remove-Item $file
}
现在,您每次都可以用一行代码调用它:

Check-NewFiles -Path \\DesignatedNetworkDrive\,\\DesignatedNetworkDrive\Corporateshare\ -CreatedAfter '07/02/2016'
Check-NewFiles -Path \\DesignatedNetworkDrive\Administration\,\\DesignatedNetworkDrive\Administration\_Private\ -CreatedAfter '05/04/2016'
对于具有大量参数的同一调用的许多实例,我喜欢使用参数参数设置哈希表集合-这样我可以轻松地循环整个集合并调用函数,而参数:

$FoldersToWatch = @(
    # Folder: Corporateshare
    @{
        Path = '\\DesignatedNetworkDrive\','\\DesignatedNetworkDrive\Corporateshare\'
        CreatedAfter = "07/02/2016"
        MailFrom = "sysadmin@something.com" 
        Recipients = "jendoe@something.com","johndoe@something.com"
    },

    # Folder: Administration
    @{
        Path = '\\DesignatedNetworkDrive\Administration\','\\DesignatedNetworkDrive\Administration\_Private\'
        CreatedAfter = "05/04/2016"
        Recipients = "jendoe@something.com","johndoe@something.com"
    },

    # Folder: Procurement
    @{
        Path = '\\DesignatedNetworkDrive\Procurement\'
        CreatedAfter = "05/25/2016"
        Subject = "Procurement, IMPORTANT!"
    }
)
现在,将上述内容放入自己的文件中,称之为
FoldersToWatch.ps1

然后,在定义了
Check NewFiles
函数的脚本中,点源
FoldersToWatch.ps1
文件,然后在哈希表中循环并调用该函数:

# function Check-NewFiles goes up here

. .\FoldersToWatch.ps1

$FoldersToWatch |Foreach-Object {
    Check-NewFiles @_
}
就在这里。现在,任何人都可以更新
FoldersToWatch.ps1
中的参数,而不会弄乱脚本本身,也不会忽略正在发生的事情


我还想指出,使用
newobject
addmember
创建新对象,然后将其添加到数组中的方法是完全不必要的。使用
选择对象
并将其直接导入
导出Csv

Get-ChildItem $Path |Where-Object { $_.CreationTime -ge $CreatedAfter } |Select-Object FullName,Length,@{Label='Owner';Expression={(Get-Acl $_.FullName).Owner}},LastAccessTime,LastWriteTime,CreationTime |Export-CSV -notypeinformation "$file"
最终的函数看起来更像:

function Check-NewFiles 
{
    param(
        [Parameter(Mandatory)]
        [string[]]$Path,
        [Parameter(Mandatory)]
        [datetime]$CreatedAfter,
        [string]$Subject = "New files found",
        [string[]]$Recipients = @("jendoe@something.com","johndoe@something.com"),
        [string]$MailFrom = "noreply@something.com",
        [string]$SmtpServer
    )

    $file = "\\DesignatedNetworkDrive\NewFileFinderReport.csv"
    $mesg = "Please see the attached file for a list of files that were created after {0:MMM dd, yyyy}" -f $CreatedAfter

    Get-ChildItem $Path |Where-Object { $_.CreationTime -ge $CreatedAfter } |Select-Object FullName,Length,@{Label='Owner';Expression={(Get-Acl $_.FullName).Owner}},LastAccessTime,LastWriteTime,CreationTime |Export-CSV -notypeinformation "$file"

    if ($(get-item -path "$file").length -gt 0) {
        Send-MailMessage -From $MailFrom -body "$mesg" -Attachments "$file" -smtpServer $SmtpServer -To $Recipients
    }

    Remove-Item $file
}

看起来最简单的方法是让它使用Import CSV从配置文件中提取信息,然后使用ForEach循环。如果你想让它被很好地编码,你可能也应该把它划分成函数——比如看Mathias的答案。最简单的方法似乎是让它使用Import CSV从配置文件中提取信息,然后使用ForEach循环。如果你想让它被很好地编码,你可能也应该把它划分成函数——比如看Mathias的答案,让它从文件中提取参数可能是个好主意-最简单的解决方案是使用导入CSV,然后使用ForEach循环或调用调用命令。@Larkeith我通常为函数调用定义第二个脚本,并为AnswerThank@MathiasR.Jessen添加示例。非常感谢您的全面回复。非常感谢我的学习经历。@MathiasR.Jessen这绝对是另一个不错的选择;我喜欢CSV的主要原因是它可以用Excel编辑,但任何一种方法都是100%可行的,特别是因为splatting表格支持注释。除此之外,让它从文件中提取参数可能是个好主意