"A device attached to the system is not functioning " error when using robocopy to move folder in sharepoint - powershell

We are using Sharepoint 2010. There is a requirement to archive folders/Subfolders from a given folder to Archive folder which is part of document library. So we used Robocopy from powershell environment. But we're getting error "A device attached to the system is not functioning". ERROR 31 (0x0000001F) Changing File Attributes
Can any one help me what I have to do fix the above error.
Here is my code
$sourceDir = "\\labserver\sites\XXX\YYY Accounts Documents"
$targetDir = "\\labserver\sites\XXXX\Archived YYY Accounts Documents"
$FilePath = "C:\InactiveAccount_SharepointFolder.xlsx"
$sourceDir1= "\\labserver\sites\xxx\yyy Accounts Documents"
$SheetName = "Sheet1"
# Create an Object Excel.Application using Com interface
$objExcel = New-Object -ComObject Excel.Application
# Disable the 'visible' property so the document won't open in excel
$objExcel.Visible = $false
# Open the Excel file and save it in $WorkBook
$WorkBook = $objExcel.Workbooks.Open($FilePath)
$strSheetName = "sheet1"
# Load the WorkSheet 'BuildSpecs'
if ($strSheetName -eq "")
{
$worksheet = $WorkBook.sheets.item(1)
}
else
{
$worksheet = $WorkBook.sheets.item($strSheetName)
}
try {
$intRowMax = ($worksheet.UsedRange.Rows).count
for($intRow = 2 ; $intRow -le $intRowMax ; $intRow++)
{
$isFodlerExists = $worksheet.cells.item($intRow,3).value2
if($isFodlerExists -match "Yes")
{
$accountName = $worksheet.cells.item($intRow,1).value2
#[system.io.directory]::CreateDirectory($tempSource + $accountName)
#write-host $accountName
$sFolder = $sourceDir + "\" + $accountName
$sFolder1 = $sourceDir1 + "\" + $accountName
write-host $sFolder
$tFolder = $targetDir
Add-Content -Path $ErrorLog -Value $sFolder
if((Test-path -Path $sFolder1) -eq $TRUE)
{
try {
#Copy-Item -Path $sFolder -Destination $tFolder -Recurse -force
robocopy $sFolder $tFolder /e /r:2 /log:$ErrorLog /tee
}
Catch {
Add-Content -Path $ErrorLog -Value "Exception write"
$DateTime = (Get-Date).ToShortDateString() + " " + (Get-Date).ToShortTimeString()
$Target = $_.TargetObject
$e = $_
Add-Content -Path $ErrorLog -Value "$DateTime - $e $Target"
#Write-Host "$e $Target"
$ErrorActionPreference = "Continue"
}
if($?)
{
add-content -path $ErrorLog -value ($?)
}
else
{
add-content -path $ErrorLog -value ($?)
}
}
}
#write-host $accountName
}
}
Catch {
Add-Content -Path $ErrorLog -Value "Exception write"
$DateTime = (Get-Date).ToShortDateString() + " " + (Get-Date).ToShortTimeString()
$Target = $_.TargetObject
$e = $_
Add-Content -Path $ErrorLog -force -Value "$DateTime - $e $Target"
#Write-Host "$e $Target"
$ErrorActionPreference = "Continue"
}
$WorkBook.close()
$objExcel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($objExcel)
Can any one help me what I have to do fix the above error.

Related

For loop with list not working as expected Powershell

I'm trying to create a powershell script which checks a log file for lines of text and if the line exists restarts a service and resets/archives the log. I got it working before with 1 "checkstring" if you will, but I've been struggling to get it to work with a list of strings. Could anyone help me figure out where I'm going wrong?
This is the code I'm currently using:
$serviceName = "MySQL80"
$file = "test.txt"
$pwd = "C:\tmp\"
$checkStrings = New-Object System.Collections.ArrayList
# Add amount of checkstrings
$checkStrings.add("Unhandled error. Error message: Error retrieving response.")
$checkStrings.add("Unhandled error. Error message: Error retrieving response. Second")
$logName = "ServiceCheck.log"
$backupFolder = "Archive"
$logString = (Get-Date).ToString("ddMMyyyyHHmmss"), " - The service has been reset and the log moved to backup" -Join ""
Set-Location -Path $pwd
if(Test-Path -Path $file) {
if(Test-Path -Path $backupFolder) {
} else {
New-Item -Path $pwd -Name $backupFolder -ItemType "director"
}
foreach ($element in $checkStrings) {
$containsWord = $fileContent | %{$_ -match $element}
if ($containsWord -contains $true) {
Restart-Service -Name $serviceName
$backupPath = $pwd, "\", $backupFolder, "\", $date, ".log" -join ""
$currentFile = $pwd, "\", $file -join ""
Copy-Item $currentFile -Destination $backupPath
Get-Content $currentFile | select-string -pattern $checkString -notmatch | Out-File $currentFile
if(Test-Path -Path $logName) {
Add-Content $logName $logString
} else {
$logString | Out-File -FilePath $logName
}
}
}
}

Powershell - New-Object System.IO.StreamReader [duplicate]

This question already has answers here:
Powershell StreamReader - how to wait for a new file to be readable
(3 answers)
Closed 1 year ago.
I am trying to write a code to make my daily life easier :)
The code below works if I indicate the file path
$ stream_reader = New-Object System.IO.StreamReader {c:\test.txt}
However it does not work when I use a variable like:
$ stream_reader = New-Object System.IO.StreamReader {$FileIOC}
How to use it:
Create a file text containing md5 entries
Run the script and specify the file.
Normally, a file name like : "randomID.ioc" will be created
Code
try {
$FileIOC = read-host "Where is located the text file containing iOC"
if (Test-Path $FileIOC) {
write-host "File found at:" $FileIOC
} else {
write-host "Unable to file iOC file into: " $FileIOC
}
}
catch {
#Write-Warning $_.Exception.Message
#Write-Host "Unable to find $hotfix"
}
try {
# GUI ID Generation
$GUID = [System.Guid]::NewGuid()
#[guid]::NewGuid()
Write-Host "Generating ID: " $GUID
}
catch {
Write-Warning $_.Exception.Message
}
# Variables
$gdate = Get-Date -format s
$Hostname = "$GUID.ioc"
# Where I am
$Locate = Get-Location
$Folder = "$Locate\"
#write-host "Path :" $Folder
# Create file format GUID.ioc (# create xml)
# `n <== Enter
New-Item -path $Folder -name $Hostname -type "file" -value "<?xml version=""1.0"" encoding=""utf-8""?>"
Add-Content -path $Folder$Hostname -value "`n<ioc xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" id=""$GUID"" last-modified=""$gdate"" xmlns=""http://schemas.mandiant.com/2010/ioc"">"
Add-Content -path $Folder$Hostname -value " <short_description>Custom EDR-O iOC</short_description>"
Add-Content -path $Folder$Hostname -value " <short_description>Custom EDR-O iOC $Hostname $gdate</short_description>"
Add-Content -path $Folder$Hostname -value " <keywords />"
Add-Content -path $Folder$Hostname -value " <authored_by>LEFBE</authored_by>"
Add-Content -path $Folder$Hostname -value " <authored_date>$gdate</authored_date>"
Add-Content -path $Folder$Hostname -value " <links />"
Add-Content -path $Folder$Hostname -value " <definition>"
# For each line in text files
# Generate ID
$GUID1 = [guid]::NewGuid()
Add-Content -path $Folder$Hostname -value " <Indicator operator=""OR"" id=""$GUID1"">"
$stream_reader = New-Object System.IO.StreamReader{"$FileIOC"} #< Here a problem variable was note read by $stream_reader
while (($current_line =$stream_reader.ReadLine()) -ne $null)
{
Write-Host "$current_line"
$line_number++
$GUID2 = [guid]::NewGuid()
Add-Content -path $Folder$Hostname -value " <IndicatorItem id=""$GUID2"" condition=""is"">"
Add-Content -path $Folder$Hostname -value " <Context document=""FileItem"" search=""FileItem/Md5sum"" type=""mir"" />"
Add-Content -path $Folder$Hostname -value " <Content type=""md5"">$current_line</Content>"
Add-Content -path $Folder$Hostname -value " </IndicatorItem>"
}
Add-Content -path $Folder$Hostname -value " </Indicator>"
Add-Content -path $Folder$Hostname -value " </definition>"
Add-Content -path $Folder$Hostname -value "</ioc>"
Write-Host ""
Write-Host "iOC file can be found at this location:" "$Folder$Hostname"
Do you have any idea ?
Thanks to #iRon for his help.
Solution is :
$stream_reader = [System.IO.StreamReader]::new($FileIOC)
# Do some stuff
# Do not forget to close the file and dispose
$stream_reader.Close()
$stream_reader.Dispose()

How to amend a string with a variable?

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

Copying PDFs while keeping folder structure

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`

powershell file system event watcher service

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"
}
}
}