0

This is my remote computer file transfer PowerShell script:

#--------------------------------------------------------[Initialisations]-------------------------------------------------------

#Clears the contents of the DNS client cache
Clear-DnsClientCache

#Loading script configuration
$configuration = Get-Content '.\Resources\Remote Computer File Transfer Configuration.cfg' | Select-Object | ConvertFrom-StringData

#Initializing report file
New-Item -Path $configuration.ReportFile -ItemType File

$fileList = Get-Content -Path $configuration.FileList
$computerList = Get-Content -Path $configuration.ComputerList

#Initializing file counters
$successfulTransfers = 0
$failedTransfers = 0

#---------------------------------------------------------[Functions]----------------------------------------------------------

function Write-Log
{
    param
    (
        [Parameter(Position = 0, Mandatory = $false)]
        [String]
        $OperationSuccessful,

        [Parameter(Position = 1, Mandatory = $false)]
        [String]
        $Message,

        [Parameter(Position = 2, Mandatory = $false)]
        [String]
        $LogSeparator
    )
    if($null -eq $LogSeparator)
    {
        $timestamp = Get-Date -Format "yyyy.MM.dd. HH:mm:ss:fff"
        $logEntry = $timestamp + " - " + $Message
    }
    else
    {
            $logEntry = $LogSeparator
    }

    
    if($OperationSuccessful -eq "Successful")
    {
            Write-Host $logEntry -ForegroundColor Green -BackgroundColor Black
    }
    elseif($OperationSuccessful -eq "Failed")
    {
            Write-Host $logEntry -ForegroundColor Red -BackgroundColor Black
    }
    elseif($OperationSuccessful -eq "Partial")
    {
            Write-Host $logEntry -ForegroundColor Blue -BackgroundColor Black
    }
    else
    {
        Write-Host $logEntry -ForegroundColor Yellow -BackgroundColor Black
    }
    
        Add-content -Path $configuration.LogFile -Value $logEntry
    
        Add-content -Path $configuration.ReportFile -Value $logEntry
}

function Send-Report
{
    param
    (
        [Parameter(Position = 0, Mandatory = $true)]
        [string]
        $FinalMessage
    )

    if($configuration.SendReport -eq "true")
    {
        $body = $configuration.Body + "`n" + $FinalMessage

        Send-MailMessage -SmtpServer $configuration.SmtpServer `
                         -Port $configuration.Port `
                         -To $configuration.To `
                         -From $configuration.From `
                         -Subject $configuration.Subject `
                         -Body $body `
                         -Attachments $configuration.ReportFile
                         
        Remove-Item -Path $configuration.ReportFile
    }
}

#---------------------------------------------------------[Execution]----------------------------------------------------------

Write-Log -LogSeparator $configuration.LogTitle
Write-Log -LogSeparator $configuration.LogSeparator

#Get credential from user input
$credential = Get-Credential

$message = "User " + $credential.UserName + " entered credentials"
Write-Log -Message $message

foreach($file in $fileList)
{
    if((Test-Path -Path $file) -eq $true)
    {
        $message = "Successfully checked " + $file + " file - ready for transfer."
        Write-Log -OperationSuccessful "Successful" -Message $message
    }
    else
    {
        $message = "Failed to access " + $file + " file. It does not exist."
        Write-Log -OperationSuccessful "Failed" -Message $message
        $message = "Script stopped - MISSING FILE ERROR"
        Write-Log -OperationSuccessful "Failed" -Message $message
        Write-Log -Message $configuration.LogSeparator
        Send-Report -FinalMessage $message
        Exit
    }
}
$message = "Successfully accessed all files - ready for transfer"
Write-Log -OperationSuccessful "Successful" -Message $message

#Start file transfer
Write-Log -Message "Started file transfer"
foreach($computer in $computerList)
{
    #Mapping network drive
    if((Test-Connection -TargetName $computer -Quiet -Count 1) -eq $true)
    {
        $message = "Successfully accessed " + $computer + " remote computer"
        Write-Log -OperationSuccessful "Successful"-Message $message

        #Network path creation to D partition on the remote computer
        $partition = "\D$"
        $networkPath = "\\" + $computer + $partition

        #Try to create network drive to D partition on the remote computer
        if(New-PSDrive -Name "T" -PSProvider "FileSystem" -Root $networkPath -Credential $credential)
        {
            $message = "Successfully mapped network drive to D partition on the " + $computer + " remote computer"
            Write-Log -OperationSuccessful "Successful" -Message $message
            $driveMappingSuccessful = $true
        }
        else
        {
            $message = "Failed to map network drive to D partition on the " + $computer + " remote computer"
            Write-Log -OperationSuccessful "Failed" -Message $message

            #Network path creation to C partition on the remote computer
            $partition = "\C$"
            $networkPath = "\\" + $computer + $partition
            
            #Try to create network drive to C partition on the remote computer
            if(New-PSDrive -Name "T" -PSProvider "FileSystem" -Root $networkPath -Credential $credential)
            {
                $message = "Successfully mapped network drive to C partition on the " + $computer + " remote computer"
                Write-Log -OperationSuccessful "Successful" -Message $message
                $driveMappingSuccessful = $true
            }
            else
            {
                $message = "Failed to map network drive to C partition on the " + $computer + " remote computer - Credential not valid"
                Write-Log -OperationSuccessful "Failed" -Message $message
                $driveMappingSuccessful = $false
            }
        }
    }
    else
    {
        $message = "Failed to access " + $computer + " remote computer - OFFLINE"
        Write-Log -OperationSuccessful "Failed" -Message $message
        $driveMappingSuccessful = $false
    }

    if($driveMappingSuccessful)
    {
        $path = "T:\" + $configuration.TransferFolder

        if((Test-Path $path) -eq $true)
        {
            $message = "Successfully accessed " + $path + " folder"
            Write-Log -OperationSuccessful "Successful" -Message $message
            $deployingFolderSuccessful = $true
        }
        else
        {
            $message = "Failed to access " + $path + " folder - MISSING FOLDER ERROR"
            Write-Log -OperationSuccessful "Failed" -Message $message

            try
            {
                New-Item -Path $path -ItemType "Directory"
            }
            catch
            {
                Write-Log -OperationSuccessful "Failed" -LogSeparator $_.Exception
            }

            if((Test-Path $path) -eq $true)
            {
                $message = "Successfully created " + $path + " folder"
                Write-Log -OperationSuccessful "Successful" -Message $message
                $deployingFolderSuccessful = $true
            }
            else
            {
                $message = "Failed to create " + $path + " folder"
                Write-Log -OperationSuccessful "Failed" -Message $message
                $deployingFolderSuccessful = $false
            }
        }

        if($deployingFolderSuccessful)
        {
            $fileList = Get-Content -Path $configuration.FileList

            foreach($file in $fileList)
            {
                #File name extraction from file full path
                $fileName = Split-Path $file -leaf
        
                try
                {
                    Copy-Item -Path $file -Destination $path -Force
                }
                catch
                {
                    Write-Log -OperationSuccessful "Failed" -LogSeparator $_.Exception
                }

                $transferDestination = Join-Path -Path $path -ChildPath $file

                if(Test-Path -Path $transferDestination)
                {
                    $message = "Successfully transferred " + $fileName + " file to " + $transferDestination + " folder"
                    Write-Log -OperationSuccessful "Successful" -Message $message
                    $successfulTransfers ++
                }
                else
                {
                    $message = "Failed to transfer " + $fileName + " file to " + $path + " folder"
                    Write-Log -OperationSuccessful "Failed" -Message $message
                    $failedTransfers ++
                }
            }
        }
        else
        {
            $message = "Canceld file transfer to " + $computer + " remote computer"
            Write-Log -OperationSuccessful "Failed" -Message $message
        }
    }
    else
    {
        $message = "Canceld file transfer to " + $computer + " remote computer"
        Write-Log -OperationSuccessful "Failed" -Message $message
    }

    #Network drive removal
    if($driveMappingSuccessful)
    {
        Remove-PSDrive -Name "T"
    }
}

$message = "Completed Remote Computer File Transfer PowerShell Script"
Write-Log -Message $message

if($successfulTransfers -gt 0)
{
    $message = "Successfully transferred " + $successfulTransfers + " files to " + $Destination + " folder"
    Write-Log -OperationSuccessful "Successful" -Message $message
}

if($failedTransfers -gt 0)
{
    $message = "Failed to transfer " + $failedTransfers + " files to " + $Destination + " folder"
    Write-Log -OperationSuccessful "Failed" -Message $message
}

if(($successfulTransfers -gt 0 ) -and ($failedTransfers -eq 0))
{
    $message = "Successfully transferred all files to " + $Destination + " folder"
    Write-Log -OperationSuccessful "Successful" -Message $message
}
elseif(($successfulTransfers -gt 0 ) -and ($failedTransfers -gt 0))
{
    $message = "Successfully transferred some files to " + $Destination + " folder with some failed"
    Write-Log -OperationSuccessful "Partial" -Message $message
}
elseif(($successfulTransfers -eq 0 ) -and ($failedTransfers -gt 0))
{
    $message = "Failed to transfer any file to " + $Destination + " folder"
    Write-Log -OperationSuccessful "Failed" -Message $message
}

Write-Log -Message $configuration.LogSeparator

#Sends email with detailed report and deletes temporary report log file
Send-Report -FinalMessage $message

This is .cfg file:

LogTitle = ***********************************************  Remote Computer File Transfer PowerShell Script Log  ************************************************
LogSeparator = ******************************************************************************************************************************************************

SendReport = true

LogFile = .\\Resources\\Remote Computer File Transfer Log.log
ReportFile = .\\Resources\\Report.log
FileList = .\\Resources\\File-Paths.txt
ComputerList = .\\Resources\\Computer-List.txt
TransferFolder = _INSTALL

SmtpServer = smtp.mail.com
Port = 25
To = [email protected]
From = [email protected]
Subject = Remote Computer File Transfer Report
Body = This is an automated message sent from PowerShell script. Remote Computer File Transfer PowerShell Script has finished executing.

Something is wrong with logging. It must be a problem with Write-Log function. The script actually does the job but nothing is written on the console by Write-Log function, and it just writes this in the picture and I can't figure out why.

enter image description here

Grateful in advance!

7
  • 1
    PLEASE could you edit the question and remove all <# .SYNOPSIS stuff. Commented Jul 30, 2020 at 13:02
  • 1
    Please reformat the question so that it correctly formats code as code. Also, reduce the amount of code down into a minimal reproducible example, don't post your whole script. Commented Jul 30, 2020 at 13:07
  • 1
    Change if($null -eq $LogSeparator) into if(!$LogSeparator) or if([string]::IsNullOrWhiteSpace($LogSeparator)). Since you declared this parameter as string, if unused, the value will be an empty string, not $null. Commented Jul 30, 2020 at 19:15
  • 1
    Well this [$configuration = Get-Content 'D:\Temp\Remote Computer File Transfer Configuration.cfg' | Select-Object | ConvertFrom-StringData] is not providing you what you think it is. This read does not allow you to do the dotted notation you are using. If you just ran that section and then try dot the variable/values, you'll see what is being returned. [$configuration.LogFile The property 'LogFile' cannot be found on this object.] Commented Jul 30, 2020 at 19:49
  • 1
    @postanote It works for me (tested locally), although I would use the Raw switch and leave out the | Select-Object which has no reason to be there. Of course in the Execution part of the code, there is nothing to actually get the files listed in the $configuration.FileList, but that's a different question.. Commented Jul 30, 2020 at 20:13

1 Answer 1

1

As commenten, the if($null -eq $LogSeparator) test will never succeed, because if not given, the parameter $LogSeparator will be an empty string, not $null.

The function you have would work if you change that to if(!$LogSeparator) or if([string]::IsNullOrWhiteSpace($LogSeparator))

The function could be simplified by using a parameter that validates to a certain set of possible values. Extra advantage is that you get autocompletion in the editor aswell so you don't have to worry about sending a parameter value with a typo.

Something like this perhaps:

function Write-Log {
    param (
        [Parameter(Position = 0, Mandatory = $false)]
        [ValidateSet('Success', 'Fail', 'Partial', 'None')]
        [String]$OperationResult = 'None',

        [Parameter(Position = 1, Mandatory = $false)]
        [String]$Message
    )

    $timestamp = Get-Date -Format "yyyy.MM.dd. HH:mm:ss:fff"
    $logEntry = $timestamp + " - " + $Message
    switch ($OperationResult) {
        'Success'  { $fg = 'Green'; $bg = 'Black'; break }
        'Fail'     { $fg = 'Red'; $bg = 'Black'; break }
        'Partial'  { $fg = 'Blue'; $bg = 'Black'; break }  # Cyan would be easier to read I think
        default    { $logEntry = $Message
                     $fg = 'Yellow'; $bg = 'Black' }
    }
    Write-Host $logEntry -ForegroundColor $fg -BackgroundColor $bg
    Add-content -Path $configuration.LogFile -Value $logEntry
    Add-content -Path $configuration.ReportFile -Value $logEntry
}

Testing:

Write-Log -Message $configuration.LogTitle
Write-Log -Message $configuration.LogSeparator

$message = "Successfully checked file - ready for transfer."
Write-Log -OperationResult Success -Message $message

$message = "Script stopped - MISSING FILE ERROR"
Write-Log -OperationResult Fail -Message $message

$message = "Script did not complete"
Write-Log -OperationResult Partial -Message $message

Write-Log -Message $configuration.LogSeparator

Result in console:

***********************************************  Remote Computer File Transfer PowerShell Script Log  ************************************************
******************************************************************************************************************************************************
2020.07.30. 21:34:53:959 - Successfully checked file - ready for transfer.
2020.07.30. 21:34:53:959 - Script stopped - MISSING FILE ERROR
2020.07.30. 21:34:53:959 - Script did not complete
******************************************************************************************************************************************************
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you all for your answers, but I figured it out two hours before you posted the solution of the problem, But now I am interested to see the refactored version of the script. I am still learning PowerShell and I can see that my code is hideous. I would like to improve my self.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.