使用三个参数运行 32 位 PowerShell 脚本的计划任务

jon*_*bot 5 powershell scheduled-task windows-server-2008-r2

TLDR 版本

我需要运行一个 32 位 PowerShell 脚本,该脚本采用三个参数作为Windows Server 2008 R2 中的计划任务。该脚本启动一个 FileSystemWatcher,所以我需要让它保持活动状态,以便它可以继续接收新文件。

如果您要略读,您可能应该查看下面“参数”下的内容。

背景

我创建了一个 PowerShell 脚本,它可以在我的 Windows Server 2008 R2 机器上的 x86 PowerShell 控制台中正常运行。它创建一个 FileSystemWatcher,并为文件创建事件注册一个动作。因为我需要 FileSystemWatcher 继续观察,所以我需要 PowerShell 继续运行,而不是在脚本被触发后立即退出:

该脚本采用三个参数:

  1. 要观看的文件夹的路径
  2. 将移动任何新的 .xlsx 文件并根据 .xlsx 文件的内容写入输出文本文件的文件夹的路径。
  3. 日志文件的路径。

但是,我无法让脚本作为计划任务正确运行。我认为问题在于我使用的参数,但我不知道哪些参数是正确的。

设置

由于需要脚本在32位PowerShell中运行,我将定时任务的程序设置为%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe。

我已确保在 32 位 PowerShell 中将本地计算机的执行策略设置为 RemoteSigned。

参数

我为我的论点尝试了几种不同的变体。以下在 Console 中运行,但在Task Scheduler 中以某种方式失败:

任务运行,但它没有写入日志文件,这表明它可能甚至没有启动 FileSystemWatcher。在任何情况下,它在创建文件时都不会拾取文件:

powershell -Noexit -File "D:\Scripts\myScript.ps1" "\\otherServer\share\folder\subfolder\" "\\someserver.domain.edu\D$\working_directory\" "\\otherServer\share\folder\my_log.txt"
Run Code Online (Sandbox Code Playgroud)

任务以代码 0xFFFD0000 退出(请参阅Powershell 计划任务的 0xFFFD0000 的最后结果)。我确信该任务正在作为适当的服务帐户运行,该帐户可以访问参数中使用的网络共享。

powershell -Noexit -File 'D:\Scripts\myScript.ps1' '\\otherServer\share\folder\subfolder\' '\\someserver.domain.edu\D$\working_directory\' '\\otherServer\share\folder\my_log.txt'
Run Code Online (Sandbox Code Playgroud)

这些变体甚至不能在控制台中工作(不要第一次写入日志):

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'"}
Run Code Online (Sandbox Code Playgroud)

根据脚本专家的博客,我认为我应该尝试使用-Command参数而不是-File. 这两个变体在控制台中启动文件系统观察器并将相应的消息写入日志文件,但它们不会在创建时获取文件:

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"
Run Code Online (Sandbox Code Playgroud)

代码

因为脚本在控制台中工作,所以我很确定问题不在于代码本身。不过,这里有一些来自脚本本身的相关部分,供那些除非看到代码才会满意的人使用。:)

创建文件系统观察者

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

注册创建事件

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

jon*_*bot 3

乔治,我想我已经明白了!

最终,我恢复了最初在控制台中运行它的方式(即使用dot-source),但在前面添加了 -Noexit 标志:

程序: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe

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