Powershell – Scheduled task to run a 32-bit PowerShell Script with three arguments

powershellscheduled-taskwindows-server-2008-r2

TLDR Version

I need to run a 32-bit PowerShell script that takes three arguments as a scheduled task in Windows Server 2008 R2. The script starts a FileSystemWatcher, so I need to keep it alive so that it can keep picking up new files.

You should probably look at the stuff under "Arguments", below if you're skimming.

Background

I've created a PowerShell script that runs fine from the x86 PowerShell console on my Windows Server 2008 R2 box. It creates a FileSystemWatcher, and registers an action for the file creation event. Because I need the FileSystemWatcher to keep watching, I need PowerShell to keep running, not exit immediately after the script is fired:

The script takes three arguments:

  1. The path to the folder to watch
  2. The path to a folder where it will move any new .xlsx files and write an output text file based on the contents of the .xlsx file.
  3. The path to the log file.

I can't get the script to run correctly as a scheduled task, though. I think the issue is the arguments I'm using, but I don't know what arguments would be correct.

Setup

Since I need the script to run in the 32-bit PowerShell, I set the program of the scheduled task to %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe.

I've made sure to set the Execution Policy to RemoteSigned for the local machine in the 32-bit PowerShell.

Arguments

I've tried several different variants for my arguments. The following run in Console, but fail in some way for Task Scheduler:

The task runs, but it doesn't write to the log file, which indicates it probably hasn't even started the FileSystemWatcher. In any case, it doesn't pick up files when they're created:

powershell -Noexit -File "D:\Scripts\myScript.ps1" "\\otherServer\share\folder\subfolder\" "\\someserver.domain.edu\D$\working_directory\" "\\otherServer\share\folder\my_log.txt"

The task exits with code 0xFFFD0000 (see Last Result of 0xFFFD0000 for Powershell Scheduled Task). I am sure the task is running as the appropriate service account, which has access to the network shares used in the arguments.

powershell -Noexit -File 'D:\Scripts\myScript.ps1' '\\otherServer\share\folder\subfolder\' '\\someserver.domain.edu\D$\working_directory\' '\\otherServer\share\folder\my_log.txt'

These variants don't even work in the console (don't so much as make the first write to the log):

powershell -Noexit -File "D:\Scripts\myScript.ps1" "\\otherServer\share\folder\subfolder\ \\server.domain.edu\D$\working_directory\ \\otherServer\share\folder\my_log.txt"
powershell -Noexit -command {"& 'D:\Scripts\myScript.ps1' '\\otherServer\share\folder\subfolder\' '\\server.domain.edu\D$\working_directory\' '\\otherServer\share\folder\my_log.txt'"}

Based on the Scripting Guys blog, I thought I ought to try using the -Command argument instead of -File. These two variants start the File System Watcher in the console and write the corresponding message to the log file, but they don't pick up files on creation:

powershell -Noexit -command "& 'D:\Scripts\myScript.ps1' '\\otherServer\share\folder\subfolder\' '\\server.domain.edu\D$\working_directory\' '\\otherServer\share\folder\my_log.txt'"
powershell -Noexit -command "& D:\Scripts\myScript.ps1 \\otherServer\share\folder\subfolder\ \\server.domain.edu\D$\working_directory\ \\otherServer\share\folder\my_log.txt"

Code

Because the script works in the console, I'm pretty sure that the issue doesn't lie in the code itself. Still, here's some relevant portions from the script itself for those who won't be satisfied unless they see the code. 🙂

Create the FileSystemWatcher

Function startWatcher ($onFolder) {
    try {
        #Create a file watcher
        $filter = "*.xlsx"
        $fsWatcher = New-Object IO.FileSystemWatcher $onFolder, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'}
        $fileWatcherStartDate = (Get-Date -format M.d.yyyy.HH.mm.ss).Tostring()
        log($fileWatcherStartDate)
        log "Started file system watcher on $onFolder for $filter files.`r`n"
        return $fsWatcher
    }
    catch {
        handleError("Error starting file system watcher")
    }
}

Register creation event

Function registerCreationEvent ($watcher) {
    log "Attempting to register creation event..."
    try {
        Register-ObjectEvent $watcher Created -SourceIdentifier FileCreated -Action {
            try {
                #Code to read from Excel file, create an output text file from the 
                #content, and move both to the specified working directory.
            }
            catch {
                handleError("Performing main action on individual file.")
            }
        }
        log "Event creation registered."
    }
    catch {
        handleError("Error registering creation event")
    }
}

Best Answer

By George, I think I've got it!

Ultimately, I reverted to the way I was originally running it in Console (that is, with dot-sourcing), but added the -Noexit flag in front:

Program: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe

Arguments: -Noexit . D:\Scripts\myScript.ps1 \\otherserver\share\folder\subfolder\ \\server.domain.edu\D$\working_dir\ \\otherserver\share\folder\my_log.txt