0

I've written a Powershell script to zip up my files and copy them to a USB drive and it's working as intended. However, I decided to update the script and add an error log, should something occur, and store into a text file.

My Code:

[string]$zipPath="C:\Users\someuser\7z.exe"
[string]$drive="E:\"
[string]$securityBackup="Security"
[string]$tempSecurity="temp_security"
[string]$keepasscopy="keepass_copy"
[string]$setDate
[string]$userPath="C:\Users\someuser\"
[string]$errorReport
[string]$errorText="C:\Users\someuser\errorLog.txt"
$dateVar = Get-Date

function createErrorReport($writeError){

   $writeError += " " + $dateVar.ToString()

   if(Test-Path ($errorText)){

        $writeError | Add-Content $errorText
    }
    else
    {
        $writeError | Set-Content $errorText
    }

}




<#Checking to see if the E:\ Drive exists, if it doesn't exit the script, if it does proceed#>

if(Test-Path ($drive)){
    Write-Output ($drive + " Drive Exists")
}
Else{

  #  Write-Output ($drive + " Drive Doesn't Exist")
   # $errorReport= ($drive + " Drive Doesn't Exist")
   # createErrorReport($errorReport)
    exit
}



[string]$buildDay=($dateVar.day.ToString())
[string]$buildMonth=($dateVar.Month.ToString())
[string]$buildYear=($dateVar.Year.ToString())
[string]$buildHour=($dateVar.Hour.ToString())
[string]$buildMinute=($dateVar.Minute.ToString())
[string]$buildSecond=($dateVar.Second.ToString())


[int]$checkDay = 0
[int32]::TryParse($buildDay,[ref]$checkDay)

[int]$checkMonth = 0
[int32]::TryParse($buildMonth,[ref]$checkMonth)

<#Checking to see if the day/month is less than 10, so that a zero could be applied#>

if($checkNum -le 10){
  ($buildDay="0"+$buildDay)
}

if($checkMonth -le 10){
    ($buildMonth="0"+$buildMonth)
}
 <#Creating the setDate variable which is used as the name. That way the script can be run without user interaction anytime
   Using the current day, month, year hour, minute and second we construct a name to apply to our zip file. #>
$setDate = $buildDay + "-" + $buildMonth + "-" + $buildYear + "-" + $buildHour + $buildMinute + $buildSecond


<#Create a temporary security directory in the user's path to store the KeePass files#>
md ("C:\Users\someuser\" + $tempSecurity)

<#If statement to check to see if the above directory was created. If it evaluates to true proceed #> 
if(Test-Path ($userPath + $tempSecurity)){

    <#Copy all the items in the security folder to the temporary folder that was created#>
    <#Recurse: Ensures all files and folders are copied, not just the top level folder #>
    Copy-Item ($userPath + $securityBackup+"\*") ($userPath + $tempSecurity) -Recurse

    md ($userPath + $keepasscopy+"\"+$setDate)

    <#Check to see if the above folder, KeePass\setDate has been created #>
    if(Test-Path ($userPath + $keepasscopy+"\"+$setDate)){

        <#Copy all the items in the Security folder where KeePass is stored to the newly created directory of KeePass\setDate#>
        Copy-Item ($userPath + $securityBackup+"\*") ($userPath + $keepasscopy+"\"+$setDate) -Recurse

        <#Call the 7-zip .exe and create a zip archive of the KeePass folder in the KeePass\setDate Directory#>
        $invokeCommand = ($zipPath + (" a -tzip") + (" "+$drive + $setDate + ".zip") + (" " + $userPath + $keepasscopy+"\"+$setDate))

        <#Calls the command to be started#>
        Invoke-Expression $invokeCommand

        <#Provided that the zip file is created on the USB drive remove the KeePass copy and the temporary copy from the user directory#>
        if(Test-Path ($drive + $setDate + ".zip")){


        Remove-item ($userPath + $keepasscopy) -Recurse
        Remove-Item ($userPath + $tempSecurity) -Recurse

    }   <#If the script is unable to create a copy on the USB drive, then tell the user that a backup copy exists on the current user directory#>
    else{
        Write-Output ("Unable to create backup of KeePass in " +$drive +  " A backup copy exist " + $userPath + $keepasscopy+"\"+$setDate)
         $errorReport= ("Unable to create backup of KeePass in " +$drive +  " A backup copy exist " + $userPath + $keepasscopy+"\"+$setDate)
         createErrorReport($errorReport)
        exit
    }
  }
  else
  {
    Write-Output ("Unable to create KeePass copy in " + $userPath)
      $errorReport= ("Unable to create KeePass copy in " + $userPath)
      createErrorReport($errorReport)
    exit
  }

}
else{
    Write-Output ("Unable to create temporary folder in " +$userPath)
     $errorReport= ("Unable to create temporary folder in " +$userPath)
     createErrorReport($errorReport)
    exit
}

Problem:

My issue is the first if statement, it checks to see if the USB drive I'm copying to exists, now even if the drive does exist it will print to the screen that it doesn't and right below it, it will print it does and continue on as normal, even if I comment out the Write-Output $drive doesn't exist, for some reason it still prints it to the screen. In other words it prints the drive doesn't exist even if it's plugged in and the Windows Explorer can see and access it. Even if it says the drive doesn't exist, and below it, it says it does, the rest of the ELSE statement won't execute, meaning it doesn't create the log report.

  • First thing: `$errorText` is not in scope for the function `createErrorReport`. If you are doing this in ISE save, close and reopen and start again. Your variables/functions are saved between runs so you might be having odd behaviour. Does that drive exist _BEFORE_ the powershell script is executed? – Matt Feb 08 '15 at 15:56
  • @Matt - I think you did it! How do I fix this behavior? –  Feb 08 '15 at 15:59
  • Which behavior are you referring to? – Matt Feb 08 '15 at 16:00
  • the errorText out of scope for the function. How do I fix it, so that everytime I run the ISE I don't see drive doesn't exist even if it does. –  Feb 08 '15 at 16:01
  • Does `Get-PSDrive` help out here at all? https://technet.microsoft.com/en-us/library/hh849796.aspx – cristobalito Feb 08 '15 at 16:02
  • @cristobalito - Thanks for the help but I don't think so, because I'm testing the path before I execute any code. The problem I believe is my test path, but it might be something else. –  Feb 08 '15 at 16:03
  • @Matt - Sorry for the long delay in my answer, I was unaware you asked a question. Yes the drive does exist, I made sure it does, I can see it in windows explorer and access it on my own. The behavior only happens when I execute in the ISE not when I do it directly from Powershell –  Feb 08 '15 at 16:09
  • for the errortext the easiest thing to do is pass it to the function so that it is in scope. `createErrorReport($writeError,$errortext)` you will have some reability issues if you use the same variable names in different scopes but it would work – Matt Feb 08 '15 at 16:28
  • @Matt - Thanks. I just tested my script again, this time without the function, just exit if there was an error, and it worked as intended, it didn't print drive doesn't exist twice. –  Feb 08 '15 at 16:32
  • So do you still have an issue or was your problem just related to the scope of that function? – Matt Feb 08 '15 at 16:54
  • @Matt - The problem was related to the scope of the function –  Feb 08 '15 at 17:14

1 Answers1

0

You first if statement has a scope issue. Inside the function you have scope is with the variable $errorText which is declared outside the function.

[string]$errorText="C:\Users\someuser\errorLog.txt"

function createErrorReport($writeError){
       $writeError += " " + $dateVar.ToString()
        if(Test-Path ($errorText)){
            $writeError | Add-Content $errorText
        }
        else{
            $writeError | Set-Content $errorText
        }
}

You have a few ways to address this. Which one you pick boils down to preference and need.

You could use the $global scope keyword like in this answer

A better coding practice would be to declare the variable inside the function ( especially if it is not used anywhere else)

function createErrorReport($writeError){
    [string]$errorText="C:\Users\someuser\errorLog.txt"
    if(Test-Path ($errorText)){

    }
}

Or pass it as a parameter to the function

function createErrorReport($writeError, $errorText){
    if(Test-Path ($errorText)){
    }
}

createErrorReport "Some Error" "C:\Users\someuser\errorLog.txt"
Community
  • 1
  • 1
Matt
  • 45,022
  • 8
  • 78
  • 119