Please find below my powershell script that is used to move files from one folder to another :
$folder = 'C:\test'
$filter = '*.*'
$directory_source = $directory_source = 'C:\test1\*' # <-- set this according to your requirements
$directory_target_cop = 'C:\Folder1'
$directory_target_prop = 'C:\Folder2'
$directory_target_dom = 'C:\Folder3'
$LogTime = Get-Date -Format "MM-dd-yyyy"
$dtNow = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$script:loggingpathpreference = 'C:\PSLogs\'+$LogTime+".log"
Set-PSBreakpoint -Variable Now -Mode Read -Action {Set-Variable Now (get-date -uformat '%Y\%m\%d %H:%M:%S') -Option ReadOnly, AllScope -Scope Global -Force -ErrorAction SilentlyContinue} -ErrorAction SilentlyContinue
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $true # <-- set this according to your requirements
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
Function Write-Log {
[cmdletbinding()]
Param(
[Parameter(Position = 0, ValueFromPipeline = $true)]
[ValidateNotNull()]
$Message,
[switch]$Warning
)
Process{
if($Message -isnot [string]){
$Message = $Message | Out-String
}
Write-Verbose $message
Add-Content -Path $script:LoggingPathPreference -Value "`n$($dtNow) : $($Message)"
if($Warning){
Write-Warning $Message
}
}
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Log "The file '$name' was $changeType at $timeStamp"
try{
$files = $(ls $directory_source)
foreach ($file in $files) {
if ( $(gc $file | Select-String "PROP" -Quiet) ) {
mv -Path $file.Fullname -Destination $directory_target_prop
} elseif ( $(gc $file | Select-String "COP" -Quiet) ) {
mv -Path $file.Fullname -Destination $directory_target_cop
} elseif ( $(gc $file | Select-String "DOM" -Quiet) ) {
mv -Path $file.Fullname -Destination $directory_target_dom
}
}
}catch{
$ErrorMessage = $_.Exception.Message
Write-Log $ErrorMessage
}
}
Now if I remove my Write-Log function then the above script moves the files from test folder to respective three folders, but when I do include the Write-Log function, the above code is not able to move the files.
The above code is doing the logging but not moving the files.
What am I doing wrong here?
Looking forward to your solutions and thanks in advance.
Related
I am trying to copy PDFs from one server to another preserving the folder structure, I have come up with the following script.
I am trying to find the data contained in the variable $Server in another variable $newdes and remove it. However, this fails to happen. If you inspect the variable $newdes you will see that it contains the data stored in $Server, which I need to remove in order for the copy to commence.
As it stands the variable of $newdes contains
C:\Temp\ \file\homedrives\home
It might not show but I see double \ as a UNC file path.
I need it to read C:\temp\homedrives\home.
I am guessing because of the \ \file this fails to start the copy, if this is the case, somebody advise how to get this working.
Amended as requested:
$Criteria = *.pdf
$Trial = c:\temp\folders.txt
$Server = \\file
$Path = homedrives\home
$des = $Path
$safe = Get-Content $Trial
$safe | ForEach-Object {
# find drive-delimeter
$first = $_.IndexOf("\\");
if ($first -eq 1) {
# stripe it
$newdes = Join-Path -Path $des -ChildPath #($_.Substring(0, 1) + $_.Substring(2))[0]
} else {
$newdes = Join-Path -Path $des -ChildPath $_
}
$err = 0
> $folder = Split-Path -Path $newdes -Parent
$err = 0
# check if folder exists"
$void = Get-Item $folder -ErrorVariable err -ErrorAction SilentlyContinue
if ($err.Count -ne 0) {
# create when it doesn't
$void = New-Item -Path $folder -ItemType Directory -Force -Verbose
}
$void = Copy-Item -Path $_ -Destination $des -Force -Verbose
#$void = Copy-Item -Path $_ -Include $Criteria -Destination $Path $Choice -Recurse -Container
#$void = Copy-Item -Path $Files -Include $Criteria -Destination $newdes -Force -Verbose -Recurse -ErrorAction SilentlyContinue
Write-Host $_
}
Write-Host $newdes
Why you don't use the -Recurse switch?
$source = 'C:\source'
$dest = 'C:\dest'
$extensions = #('*.pdf')
Copy-Item -Path $source -Destination $dest -Include $extensions -Force -Recurse
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/copy-item?view=powershell-6
ok, thanks for the assistance, I have now solved the issue, but it has presented another. Will post another question.
The solution to the above is to use
-filter "*.pdf"
Below is a copy of my code
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
Function Select-Server
{
param([string]$Description="Select Folder",[string]$RootFolder="Desktop")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$objForm = New-Object System.Windows.Forms.FolderBrowserDialog
$objForm.Rootfolder = $Server
$objForm.Description = $Description
$objForm.ShowNewFolderButton = $false
$Show = $objForm.ShowDialog()
If ($Show -eq "OK")
{
Return $objForm.SelectedPath + "\"
}
Else
{
Write-Error "Operation cancelled by user."
}
}
Function Select-FolderDialog
{
param([string]$Description="Select Folder",[string]$RootFolder="Desktop")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$objForm = New-Object System.Windows.Forms.FolderBrowserDialog
$objForm.Rootfolder = $RootFolder
$objForm.Description = $Description
$objForm.ShowNewFolderButton = $false
$Show = $objForm.ShowDialog()
If ($Show -eq "OK")
{
Return $objForm.SelectedPath
}
Else
{
Write-Error "Operation cancelled by user."
}
}
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$Server = "\\" + [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a Server to search", "Server Choice")
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$Choice = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a File Path to search", "File Path Choice") + "\"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$Ext = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a File type i.e. *.PST", "Location Choice")
#$Ext.ToUpper()
$Criteria = "*." + $Ext
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
#$FPath = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a path to copy to", "Location Choice")
$Path = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a folder to store the data", "Path Choice") + "\"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
#$Name = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a filename", "File Name Choice")
$Search = $Server +"\"+ $Choice
$FileName = $Path
$Info = $Path + "FileCopy.txt"
$Trial = $Path + "Folders.txt"
$Trial2 = $Path + "Ammended Folders.txt"
$Type = $Path + "$Ext's.txt".ToUpper()
#$Server2 = "\" + $Server
#$File = $Path + $Name
if( -Not (Test-Path -Path $Path ) )
{
New-Item -ItemType directory -Path $Path |out-null
}
Else{
[System.Windows.MessageBox]::Show('The directory already exists','Error','Ok','Error')
}
$properties = #(
'Directory'
' '
'Name'
' '
#{
Label = 'Size'
Expression = {
if ($_.Length -ge 1GB)
{
'{0:F2} GB' -f ($_.Length / 1GB)
}
elseif ($_.Length -ge 1MB)
{
'{0:F2} MB' -f ($_.Length / 1MB)
}
elseif ($_.Length -ge 1KB)
{
'{0:F2} KB' -f ($_.Length / 1KB)
}
else
{
'{0} bytes' -f $_.Length
}
}
}
$result = Get-ChildItem -Path $Search -Recurse -Include $Criteria -ErrorAction SilentlyContinue
) | Out-Null
$Result
#Get-ChildItem -Path $Search -Recurse -Include *.pst -ErrorAction SilentlyContinue |
$Folders = (get-childitem -Path $Search | where-object { $_.PSIsContainer }).Count
If (Test-Path $Search) {
<#Write-Host
Write-Host "Listing All Found In $Path" -ForegroundColor "Yellow"
Write-Host "=========================================" -ForegroundColor "Yellow"#>
Add-Type -assembly System.Windows.Forms
## -- Create The Progress-Bar
$ObjForm = New-Object System.Windows.Forms.Form
$ObjForm.Text = "Progress-Bar of searched folders"
$ObjForm.Height = 100
$ObjForm.Width = 500
$ObjForm.BackColor = "White"
$ObjForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
$ObjForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
## -- Create The Label
$ObjLabel = New-Object System.Windows.Forms.Label
$ObjLabel.Text = "Starting. Please wait ... "
$ObjLabel.Left = 5
$ObjLabel.Top = 10
$ObjLabel.Width = 500 - 20
$ObjLabel.Height = 15
$ObjLabel.Font = "Tahoma"
## -- Add the label to the Form
$ObjForm.Controls.Add($ObjLabel)
$PB = New-Object System.Windows.Forms.ProgressBar
$PB.Name = "PowerShellProgressBar"
$PB.Value = 0
$PB.Style="Continuous"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 500 - 40
$System_Drawing_Size.Height = 20
$PB.Size = $System_Drawing_Size
$PB.Left = 5
$PB.Top = 40
$ObjForm.Controls.Add($PB)
## -- Show the Progress-Bar and Start The PowerShell Script
$ObjForm.Show() | Out-Null
$ObjForm.Focus() | Out-NUll
$ObjLabel.Text = "Starting. Please wait ... "
$ObjForm.Refresh()
Start-Sleep -Seconds 1
Out-Null
## -- Execute The PowerShell Code and Update the Status of the Progress-Bar
$result = Get-ChildItem -Path $Search -Recurse -Include $Criteria -ErrorAction SilentlyContinue
$Counter = 0
ForEach ($Item In $Result) {
## -- Calculate The Percentage Completed
$Counter++
[Int]$Percentage = ($Counter/$Result.Count)*100
$PB.Value = $Percentage
$ObjLabel.Text = "Scanning $Folders Folders For $Criteria in $Search"
#$ObjLabel.Text = "Found $counter $Criteria in $Search"
$ObjForm.Refresh()
Start-Sleep -Milliseconds 150
# -- $Item.Name
#"`t" + $Item.Path
}
$ObjForm.Close()
#Write-Host "`n"
}
Else {
#Write-Host
#Write-Host "`t Cannot Execute The Script." -ForegroundColor "Yellow"
#Write-Host "`t $Search Does Not Exist in the System." -ForegroundColor "Yellow"
#Write-Host
}
Out-Null
Sort-Object -Property DirectoryName |
Format-Table -Property $properties |
out-file $Info
$Search | out-file -Append $Trial
#$Search | Out-File -Append $Trial2
$result | out-file -Append $Info
$result | Select Name | out-file -Append $Type
$des = $Path
#$PDFs= get-content $Type
$safe = Get-Content $Trial
#$Ten = #($Criteria)
$safe | ForEach-Object{
#find drive-delimeter
$first=$_.IndexOf("\\");
if($first -eq 1){
#stripe it
$newdes=Join-Path -Path $des -ChildPath #($_.Substring(0,1)+$_.Substring(2))[0]
}
else{
$newdes=Join-Path -Path $des -ChildPath $_
}
$err=0
$folder=Split-Path -Path $newdes -Parent
$err=0
#check if folder exists"
$void=Get-Item $folder -ErrorVariable err -ErrorAction SilentlyContinue
if($err.Count -ne 0){
#create when it doesn't
$void=New-Item -Path $folder -ItemType Directory -Force -Verbose
}
$void=Copy-Item -Path $_ -destination $newdes -Filter $Criteria -recurse -Container -Force -Verbose -ErrorAction SilentlyContinue
write-host $_
}
write-host $newdes
$void=Copy-Item -Path $_ -destination $newdes -Filter $Criteria -recurse -Container -Force -Verbose -ErrorAction SilentlyContinue
So I am trying to copy all the folders and keep the structure that only contain pdf's. I am not sure if there is a way to do this, I have managed to get some of the script to work.
However, when I run it, it copies all the folders even if they don't have PDFs in them. Also I have noticed that my script fails to check the folder and creates in the next directory down. For example:
C:\temp copied once shows C:\temp.
If I was to run the script again it now shows C:\temp\temp
Below is my Code:
$Criteria = *.pdf
$Trial = c:\temp\folders.txt
$Server = \\file
$Path = homedrives\home
$des = $Path
$safe = Get-Content $Trial
$safe | ForEach-Object {
#find drive-delimeter
$first = $_.IndexOf("\\");
if ($first -eq 1) {
#stripe it
$newdes = Join-Path -Path $des -ChildPath #($_.Substring(0,1)+$_.Substring(2))[0]
} else {
$newdes = Join-Path -Path $des -ChildPath $_
}
$err = 0
$fr = 0
$folder = Split-Path -Path $newdes -Parent
#check if folder exists"
$void = Get-Item $folder -ErrorVariable err -ErrorAction SilentlyContinue
if ($err.Count -ne 0) {
#create when it doesn't
$void = New-Item -Path $folder -ItemType Directory -Force
}
#$void = Copy-Item -Path $_ -destination $newdes -Force -Verbose
$void = Copy-Item -Path $_ -destination $newdes -Filter $Criteria -Recurse -Force -ErrorVariable fr -ErrorAction SilentlyContinue
$CR = "`r`n"
$RR = $fr[0].CategoryInfo.TargetName.ToString()
"List of PDF's that Failed To Copy" + $CR + "--------------------------------------------------------------" + $CR + $RR | Out-file -Append $Er
Write-Host $_
}
Write-Host $newdes
ok, so looks like I have cracked it, for future reference, my code actually uses user input to determine locations, it then selects the criteria the user requested and then copies only files with the extensions defined. It copies the folder structure without duplicating and although the filename limitations of windows still exist, there is an error log that is produced that shows the files that have failed to copy. Thanks for all your assistance in this matter.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null -ErrorAction Stop
$Server = "\\" + [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a Server to search", "Server Choice")
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null -ErrorAction Stop
$Choice = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a File Path to search", "File Path Choice") + "\"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null -ErrorAction Stop
$Ext = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a File type i.e. *.PST", "Location Choice")
#$Ext.ToUpper()
$Criteria = "*." + $Ext
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null -ErrorAction Stop
#$FPath = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a path to copy to", "Location Choice")
$Path = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a folder to store the data", "Path Choice") + "\"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null -ErrorAction Stop
#$Name = [Microsoft.VisualBasic.Interaction]::InputBox("Please choose a filename", "File Name Choice")
$Search = $Server +"\"+ $Choice
$FileName = $Path
$Info = $Path + "FileCopy.txt"
$Trial = $Path + "Folders.txt"
$Type = $Path + "$Ext's.txt"
$Er= $Path + "Failed Copying.txt"
$Trial2 = $Path + "Folders.txt"
#$Server2 = "\" + $Server
#$File = $Path + $Name
if( -Not (Test-Path -Path $Path ) )
{
New-Item -ItemType directory -Path $Path |out-null
}
Else{
[System.Windows.MessageBox]::Show('The directory already exists','Error','Ok','Error')
-ErrorAction SilentlyContinue
}
$properties = #(
'Directory'
' '
'Name'
' '
#{
Label = 'Size'
Expression = {
if ($_.Length -ge 1GB)
{
'{0:F2} GB' -f ($_.Length / 1GB)
}
elseif ($_.Length -ge 1MB)
{
'{0:F2} MB' -f ($_.Length / 1MB)
}
elseif ($_.Length -ge 1KB)
{
'{0:F2} KB' -f ($_.Length / 1KB)
}
else
{
'{0} bytes' -f $_.Length
}
}
}
$result = Get-ChildItem -Path $Search -Recurse -Include $Criteria -ErrorAction SilentlyContinue
) | Out-Null
$Result
#Get-ChildItem -Path $Search -Recurse -Include *.pst -ErrorAction SilentlyContinue |
$Folders = (get-childitem -Path $Search | where-object { $_.PSIsContainer }).Count
If (Test-Path $Search) {
<#Write-Host
Write-Host "Listing All Found In $Path" -ForegroundColor "Yellow"
Write-Host "=========================================" -ForegroundColor "Yellow"#>
Add-Type -assembly System.Windows.Forms
## -- Create The Progress-Bar
$ObjForm = New-Object System.Windows.Forms.Form
$ObjForm.Text = "Progress-Bar of searched folders"
$ObjForm.Height = 100
$ObjForm.Width = 500
$ObjForm.BackColor = "White"
$ObjForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle
$ObjForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
## -- Create The Label
$ObjLabel = New-Object System.Windows.Forms.Label
$ObjLabel.Text = "Starting. Please wait ... "
$ObjLabel.Left = 5
$ObjLabel.Top = 10
$ObjLabel.Width = 500 - 20
$ObjLabel.Height = 15
$ObjLabel.Font = "Tahoma"
## -- Add the label to the Form
$ObjForm.Controls.Add($ObjLabel)
$PB = New-Object System.Windows.Forms.ProgressBar
$PB.Name = "PowerShellProgressBar"
$PB.Value = 0
$PB.Style="Continuous"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 500 - 40
$System_Drawing_Size.Height = 20
$PB.Size = $System_Drawing_Size
$PB.Left = 5
$PB.Top = 40
$ObjForm.Controls.Add($PB)
## -- Show the Progress-Bar and Start The PowerShell Script
$ObjForm.Show() | Out-Null
$ObjForm.Focus() | Out-NUll
$ObjLabel.Text = "Starting. Please wait ... "
$ObjForm.Refresh()
Start-Sleep -Seconds 1
Out-Null
## -- Execute The PowerShell Code and Update the Status of the Progress-Bar
$result = Get-ChildItem -Path $Search -Recurse -Include $Criteria -ErrorAction SilentlyContinue
$Counter = 0
ForEach ($Item In $Result) {
## -- Calculate The Percentage Completed
$Counter++
[Int]$Percentage = ($Counter/$Result.Count)*100
$PB.Value = $Percentage
$ObjLabel.Text = "Scanning $Folders Folders For $Criteria in $Search"
#$ObjLabel.Text = "Found $counter $Criteria in $Search"
$ObjForm.Refresh()
Start-Sleep -Milliseconds 150
# -- $Item.Name
#"`t" + $Item.Path
}
$ObjForm.Close()
#Write-Host "`n"
}
Else {
#Write-Host
#Write-Host "`t Cannot Execute The Script." -ForegroundColor "Yellow"
#Write-Host "`t $Search Does Not Exist in the System." -ForegroundColor "Yellow"
#Write-Host
}
Out-Null
Sort-Object -Property DirectoryName |
Format-Table -Property $properties |
out-file $Info
$Search| out-file -Append $Trial
#$Search | Out-File -Append $Trial2
$result | out-file -Append $Info
$result | Select Name | out-file -Append $Type
$CR = "`r`n"
"List of PDF's that Failed To Copy" + $CR + $CR + "--------------------------------------------------------------" | Out-file $Er
$des = $Path
#$PDFs= get-content $Type
$safe = Get-Content $Trial
#$Ten = #($Criteria)
$safe | ForEach-Object{
#find drive-delimeter
$first=$_.IndexOf("\\");
if($first -eq 0){
#stripe it
$newdes=Join-Path -Path $des -ChildPath #($_.Substring(0,1)+$_.Substring(2))[0]
}
$newdes=Join-Path -Path $des -ChildPath $_
$err=0
$fr=0
$folder=Split-Path -Path $newdes -Parent
$folders=Split-Path -Path $newdes -leaf
#$fy = $folder + "\" +$folders
#check if folder exists"
$void=Get-Item $newdes -ErrorVariable err -ErrorAction SilentlyContinue #-verbose
If(!(Test-Path -Path $newdes) ){
$err=1
}
if($err.Count -ne 0){
#create when it doesn't
$void=New-Item -Path $folder -ItemType Directory #-verbose
}
#$void=Copy-Item -Path $_ -destination $newdes -Force -Verbose
$void=Copy-Item -Path $_ -destination $folder -Filter $Criteria -Recurse -Container -Force -ErrorVariable fr -ErrorAction SilentlyContinue -verbose
write-host "------------------------------------------------------- Break -------------------------------------------------------" -ForegroundColor Green
foreach($re in $fr){
$RR = $re[0].CategoryInfo.TargetName.ToString()
$X5 = $re[0].CategoryInfo.Reason.ToString()
$X6 = $re[0].TargetObject.DirectoryName.ToString()
$X6 + $CR + $X5 + "---" + $RR + $CR | Out-file -Append $Er
}
write-host "`n" $_
}
write-host "`n------------------------------------------------------- End of Script -------------------------------------------------------" -ForegroundColor Blue`
I have a file transformation solution built upon powershell with filesystemwatcher and powershell noexit. The problem I have is that the events don't fire after a while (I have no idea when it stops, I just get a call from the production), and I'm not sure why that is.
The question is basically if/how I can check health of existing active eventwatchers. I tried first by adding control if event object existed so that I could simply execute the powershell script a few times a day, but soon figured out it was powershell session bound and I was not able to fetch it from a new powershell session.
This is the basic structure of the solution.
(Anonymized, so functions etc renamed a bit and the workload logics is stripped out and on the places where it says '...' it is not syntax error)
powershell.exe -NoExit -ExecutionPolicy Bypass -inputformat none -File C:\|...|.ps1 WINDOWSTARTUP="hidden" WAITFORINPUT="NO" DOS="YES"
function Test-FileLock {
param ([parameter(Mandatory=$true)][string]$Path)
$oFile = New-Object System.IO.FileInfo $Path
if ((Test-Path -Path $Path) -eq $false)
{
return $false
}
try
{
$oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
if ($oStream)
{
$oStream.Close()
}
$false
}
catch
{
# file is locked by a process.
return $true
}
}
function ConvertType1($sourceFile, $custno, $destFile)
{
$result = "-1"
try {
$OFS = "`r`n"
$data = ""
$data += "..."
$data += $OFS + "`tType=""..."""
# |...|
$data | Out-File $destFile
$result = "Done"
Write-Host $result
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
$result = "ConvertType1: " + $ErrorMessage + " - " + $FailedItem
Write-Host $result
}
finally
{
}
return $result
}
function ConvertType2($sourceFile, $custno, $destFile)
{
$result = "-1"
try {
$OFS = "`r`n"
$data = ""
$data += "..."
$data += $OFS + "`tType=""..."""
# |...|
$data | Out-File $destFile
$result = "Done"
Write-Host $result
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
$result = "ConvertType2: " + $ErrorMessage + " - " + $FailedItem
Write-Host $result
}
finally
{
}
return $result
}
#$devTest = $true
$devTest = $false
if ($devTest)
{
$logfile = "....LOG"
$monitorFolder = '\\..._transformation\Development\Test\In' # Enter the root path you want to monitor.
$destinationFolder = '\\..._transformation\Development\Test\Out' # Enter the root path you want to monitor.
$filter = '*.*' # You can enter a wildcard filter here.
}
else
{
$logfile = ".....LOG"
$monitorFolder = '\\..._transformation\In' # Enter the root path you want to monitor.
$destinationFolder = '\\..._transformation\Out' # Enter the root path you want to monitor.
$filter = '*.*' # You can enter a wildcard filter here.
}
$fsw = New-Object IO.FileSystemWatcher $monitorFolder, $filter -Property #{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'}
#Check if eventsubcriber already exists, if it does just terminate script. This way we can schedule this script continously to make sure we always have the watcher in place
#Added note: This does not work because the events are per session and we won't be able to see events from previous sessions.
if($devTest)
{
if(Get-EventSubscriber | Where-Object -Property SourceIdentifier -eq "devTest_...FileCreated") {
Exit
}
Register-ObjectEvent $fsw Created -SourceIdentifier devTest_...FileCreated -Action {
$sourceFilename = $Event.SourceEventArgs.Name
$sourcePathFilename = $Event.SourceEventArgs.FullPath
$sourcePath = split-path $sourcePathFilename
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$destinationFile = (join-path $destinationFolder ([system.io.fileinfo]$sourceFilename).BaseName) + ".wli"
Write-Host "$logTime - The file '$sourcePathFilename' was $changeType at $timeStamp" -fore green
try {
$logTime = (Get-Date -format (Get-culture).DateTimeFormat.UniversalSortableDateTimePattern)
Out-File -FilePath $logfile -Append -InputObject "$logTime - The file '$sourceFilename' was $changeType at $timeStamp"
do {
sleep -seconds 1
$fileLockTest = Test-FileLock $sourcePathFilename
} while ($fileLockTest)
switch ($sourceFilename.ToLower())
{
{($_ -like "*hire*") -or ($_ -like "*change*")} { $result = ConvertType1 $sourcePathFilename 123456 $destinationFile }
{($_ -like "*termination*") -or ($_ -like "*...*")} { $result = ConvertType2 $sourcePathFilename 123456 $destinationFile }
default {$result = "Error. File name is not recognized. File name must |...|"}
}
Write-Host "$logTime - Transformation of file '$sourceFilename': $result"
Out-File -FilePath $logfile -Append -InputObject "$logTime - Transformation of file '$sourceFilename': $result"
Move-Item $sourcePathFilename (join-path $sourcePath "Backup") -force
}
Catch
{
$logTime = (Get-Date -format (Get-culture).DateTimeFormat.UniversalSortableDateTimePattern)
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Move-Item $sourcePathFilename (join-path $sourcePath "Error") -force
Write-Host "$logTime - The file '$sourceFilename' encountered an error during transformation. The error message was $ErrorMessage" -fore red
Out-File -FilePath $logfile -Append -InputObject "$logTime - The file '$sourceFilename' encountered an error during transformation. The error message was $ErrorMessage"
}
}
}
else
{
if(Get-EventSubscriber | Where-Object -Property SourceIdentifier -eq "...FileCreated") {
Exit
}
Register-ObjectEvent $fsw Created -SourceIdentifier ...FileCreated -Action {
$sourceFilename = $Event.SourceEventArgs.Name
$sourcePathFilename = $Event.SourceEventArgs.FullPath
$sourcePath = split-path $sourcePathFilename
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$destinationFile = (join-path $destinationFolder ([system.io.fileinfo]$sourceFilename).BaseName) + ".wli"
Write-Host "$logTime - The file '$sourcePathFilename' was $changeType at $timeStamp" -fore green
try {
$logTime = (Get-Date -format (Get-culture).DateTimeFormat.UniversalSortableDateTimePattern)
Out-File -FilePath $logfile -Append -InputObject "$logTime - The file '$sourceFilename' was $changeType at $timeStamp"
do {
sleep -seconds 1
$fileLockTest = Test-FileLock $sourcePathFilename
} while ($fileLockTest)
switch ($sourceFilename.ToLower())
{
{($_ -like "*hire*") -or ($_ -like "*change*")} { $result = ConvertType1 $sourcePathFilename 123456 $destinationFile }
{($_ -like "*termination*") -or ($_ -like "*...*")} { $result = ConvertType2 $sourcePathFilename 123456 $destinationFile }
default {$result = "Error. File name is not recognized. File name must include information about type of file |...|"}
}
Write-Host "$logTime - Transformation of file '$sourceFilename': $result"
Out-File -FilePath $logfile -Append -InputObject "$logTime - Transformation of file '$sourceFilename': $result"
Move-Item $sourcePathFilename (join-path $sourcePath "Backup") -force
}
Catch
{
$logTime = (Get-Date -format (Get-culture).DateTimeFormat.UniversalSortableDateTimePattern)
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Move-Item $sourcePathFilename (join-path $sourcePath "Error") -force
Write-Host "$logTime - The file '$sourceFilename' encountered an error during transformation. The error message was $ErrorMessage" -fore red
Out-File -FilePath $logfile -Append -InputObject "$logTime - The file '$sourceFilename' encountered an error during transformation. The error message was $ErrorMessage"
}
}
}
I'm trying to create a PowerShell program to monitor when a file in a certain path is modified, and only if it now contains the string "loaded successfully", to Write-Host. Eventually an email component will be added if the string is not found in a certain amount of time.
$folder = 'C:\Users\afila\Desktop\TEST' # Enter the root path you want to monitor.
$files = Get-ChildItem $folder
$filter = '*.txt' # You can enter a wildcard filter here.
# In the following line, you can change 'IncludeSubdirectories to $true if required.
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $false;
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
# Function to search folder contents for a string
function Search-Folder {
$SearchTerm = "Loaded successfully"
foreach ( $file in $files) {
$text = Get-Content "$folder\$file"
if ($text | where {$text -like "*$SearchTerm*" }) {
Write-Host "The file '$file succeeded" -fore white
Out-File -FilePath C:\Users\afila\Desktop\SucceededLog.txt -Append -InputObject "The file '$file' completed at $timeStamp"
}
}
}
# Here, all the Changed event is registerd.
Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -Action {
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$searchTerm = "Loaded successfully"
foreach ($file in $files) {
$text = Get-Content "$folder\$file"
if ($text | where {$text -like "*$searchTerm*"}) {
Write-Host "The file '$name' was $changeType at $timeStamp" -fore magenta
Out-File -FilePath C:\Users\afila\Desktop\TestLogItems\TestLog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"
}
}
}
# To stop the monitoring, run the following commands:
Unregister-Event FileChanged
The FileSystemWatcher already gives you the full path to the file via the property $Event.SourceEventArgs.Path, so you don't need to loop over a list of files.
Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -Action {
$path = $Event.SourceEventArgs.Path
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$searchTerm = 'Loaded successfully'
if ((Get-Content $path) -like "*$searchTerm*"}) {
Write-Host "The file '$name' was $changeType at $timeStamp"
}
}
I have a script that watches for files and triggers events on things like change. It works except there are duplicate events triggered for the same file (previous Stackflow question) which I need to handle. I am writing the filename to a logfile and only re-logging it if it is not in there.
The problem is I think the events are being fired synchronously and I am getting 2 entries in the log for 1 file change even though I am checking for dups. I am not sure how to work around this.
Here is the code:
Unregister-Event FW*
$source = 'S:\FIS-BIC Reporting\Report Output Files\IT\'
$filter = '*.*'
$MasterFile = "H:\PS\EmailNotifications.csv"
$LogFile = "H:\EmailNotify.log"
$FilesToCheck = import-csv -path $Masterfile
if (! (Test-Path $Logfile))
{
$Output = "Date|Filename|FilenameSpec|Email"
$Output | Out-File $LogFile
}
function Get-CharRight($str,$chars)
{
return $str.Substring($str.Length – $chars, $chars)
}
function ProcessFile()
{
param ([string]$filename)
Write-Host "file: $filename"
$ext= (Get-CharRight $filename 3)
if ($ext -ne "tmp")
{
foreach($FileToCheck in $FilesToCheck)
{
if($filename -like $FileToCheck.FilenameSpec)
{
Write-Host "Match"
#check log to see if an email was already sent
$Exists = import-csv -path $Logfile -delimiter "|" | where-object {$_.Filename -eq $filename}
Write-Host ($Exists.Count -eq $null)
if ($Exists.Count -eq $null)
{
Write-Host "Not in logfile"
$Date = Get-Date -format G
$Output = $Date + "|" + $filename + "|" + $FileToCheck.FilenameSpec + "|" + $FileToCheck.Email
$Output | Out-File $LogFile -append
}
else
{write-host "duplicate"}
}
}
}
}
$fsw = New-Object IO.FileSystemWatcher $source, $filter -Property #{IncludeSubdirectories = $true; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite, Attributes'}
Register-ObjectEvent $fsw Changed -SourceIdentifier FWFileChanged -Action {
ProcessFile $Event.SourceEventArgs.FullPath
}
Register-ObjectEvent $fsw Created -SourceIdentifier FWFileCreated -Action {
ProcessFile $Event.SourceEventArgs.FullPath
}
while($true) {
start-sleep -s 2
}
`