Powershell - 观看多个文件夹,使用文件运行多个进程

时间:2016-04-18 13:50:53

标签: powershell foreach hashtable filesystemwatcher multiple-instances

所以我有一个设置用于以下目的的脚本:

  1. 如果文件夹中出现文件,只需将其移动到其出现的子文件夹上方的文件夹中。*例如:从c:\ My_Documents \ a>移动c:\ My_Documents *
  2. 每次发生上述情况时,文件名和尝试号都存储在哈希表中。一旦同一文件出现3次,文件就会从结构中移动到完全不同的文件夹,并且会向适当的收据发送电子邮件。 *例如:c:\ My_Documents \ a> c:\ FailedFolder \ *
    1. 然后删除哈希表中文件的记录。整个哈希表每10分钟清除一次。
  3. 这是有效的,我现在的问题是我需要扩展它,以便脚本为多个文件夹执行此操作,这些文件夹以完全相同的方式设置但不重叠。 *例如:c:\ My_Documents \ a> c:\ My_Documents \&& c:\ randomFolder \ a> c:\ randomFolder \&& c:\ AnotherRandomFolder \ a> c:\ AnotherRandomFolder \ *

    有人可以帮助我实现这个目标吗?

    请参阅我目前的代码:

    $global:folder = 'C:\Users\random\Documents\IUR Test\r' # Enter the root   path you want to monitor. 
    $global:origin = 'C:\Users\random\Documents\IUR Test'
    $filter = '*.*'  # You can enter a wildcard filter here. 
    $global:Failedfolder = 'C:\Users\random\Documents\Failed' 
    $global:Files = @{}
    $timer = New-Object Timers.Timer
    $timer.Interval = 600000     # fire every 10 minutes
    $timer.AutoReset = $true  # Enable the event again after its been fired
    $timer.Enabled = $true
    
    # In the following line, you can change 'IncludeSubdirectories to $true if required.                           
    $fsw = New-Object IO.FileSystemWatcher $global:folder, $filter -Property @{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName,LastWrite'} 
    
    Register-ObjectEvent -InputObject $timer -EventName Elapsed -SourceIdentifier HashMapClear -Action {
        $global:Files.clear()
    }
    
    Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
        ForEach ($file in (gci $global:folder)) 
        {
            $fName = $file.Name
    
            if(-not $global:Files.ContainsKey($fName))
            {
                $global:Files.Add($fName,1)             
                Move-Item $File.Fullname $global:origin -force
    
            }
            Elseif($global:Files.Get_Item($fName) -lt 3)
            {
                $global:Files.Set_Item($fName,++$global:Files.Get_Item($fName))             
                Move-Item $File.Fullname $global:origin -force
            }
            Else
            {
                $global:Files.Remove($fName) 
                Move-Item $File.Fullname $global:Failedfolder -force
    
                #### Send error email
            }
        }
    } 
    
    # To stop the monitoring, run the following commands: 
    # Unregister-Event FileCreated 
    # Unregister-Event HashMapClear 
    

2 个答案:

答案 0 :(得分:0)

没有必要自己实施这样的事情。您可以使用非常容易使用的PowershellGuard。你也可以尝试使用红宝石原装防护装置,如果你也适合使用它,它也带有一堆插件。

PowershellGuard基本上可以满足您的需求,因此如果您想以自己的方式重新实现,可以查看其源代码以获取详细信息。

答案 1 :(得分:0)

不知道您想要实现的目标,为您提供具体指导可能有点困难!但是,您可能希望查看可以使用您需要的任何参数调用的Powershell函数(参见下文)

警告:尚未运行或测试:D

$files = @{}

$timer = New-Object Timers.Timer
$timer.Interval = 600000     # fire every 10 minutes
$timer.AutoReset = $true  # Enable the event again after its been fired
$timer.Enabled = $true

$email:From = 'thisisanexample@test.com'
$email:to = 'thisisanexample@test.com'
$email:Subject = 'Failed SJPM File'
$email:SMTPServer = 'thisisatest.qa.test.com'
$email:SMTPPort = 25

function sendFailureEmail([string]$filename, [string]$folder)
{
    $message = 'The file' + $filename + ' located in ' + $folder + ' has failed to process after 3 attempts, please review the file.'
    send-MailMessage -From $email:From -to $email:to -Subject $email:Subject -Body $message -SmtpServer $email:SMTPServer -port $email:SMTPPort -Cc $email:From
}

function monitorDirectory([string]$sourceDirectory, [string]$targetDirectory, [string]$failureDirectory, [string]$filter="*.*")
{
    # In the following line, you can change 'IncludeSubdirectories to $true if required.                           
    $fsw = New-Object IO.FileSystemWatcher $sourceDirectory, $filter -Property @{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName,LastWrite'} 

    Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
        ForEach ($file in (gci $sourceDirectory)) 
        {
            $fName = $file.FullName

            if(-not $files.ContainsKey($fName))
            {
                # We have not seen this file before
                $files.Add($fName, 1)               
                Move-Item $File.Fullname $targetDirectory -force

            }
            Elseif($files.Get_Item($fName) -lt 3)
            {
                # We have seen this file once or twice before
                $files.Set_Item($fName, ++$files.Get_Item($fName))              
                Move-Item $File.Fullname $targetDirectory -force
            }
            Else
            {
                # This is the third time we've seen this file, there an error has occurred
                $files.Remove($fName) 
                Move-Item $File.Fullname $failureDirectory -force

                sendFailureEmail $fName $failureDirectory
            }
        }
    } 

    $fsw
}

Register-ObjectEvent -InputObject $timer -EventName Elapsed -SourceIdentifier HashMapClear -Action {
    # Clear the file list every x minutes
    $files.clear()
}

$f1 = monitorDirectory 'C:\Users\random\Documents\IUR Test\r' 'C:\Users\random\Documents\IUR Test' 'C:\Users\random\Documents\Failed'
$f2 = monitorDirectory 'C:\Users\random\Documents\Test2\z' 'C:\Users\random\Documents\Test2' 'C:\Users\random\Documents\Failed'

# can unregister filewatching and timers if necessary