任务计划程序创建由脚本文件生成的损坏版本

时间:2017-03-15 15:52:07

标签: file powershell task schedule

我一直在为Powershell做一个小项目。 我的任务是创建一个脚本,收集邮件附件中的所有文件,将所有.pdf文件合并为一个文件,然后将生成的文件发送到我的邮箱。
该脚本在Powershell ISE中完全正常,但是当我尝试从任务调度程序运行它时,合并的.pdf文件已损坏而没有任何数据。
请记住,我是这个东西的新手。

这是我执行所有繁重工作的主要代码:

    function getAttachments
    {
    #########################################################
    ##-----------------------------------------------------## 
    ##                GET ATTACHMENTS                      ## 
    ##-----------------------------------------------------## 
    #########################################################

    ##PATH TO CREDENTIAL
    $credpath = "C:\Users\" + $env:UserName + "\Documents\myCred_${env:USERNAME}_${env:COMPUTERNAME}.xml"

    #test variable
    $test = Test-Path $credpath

    ##TEST IF CREDENTIAL EXISTS
    if(!$test){
    ## USER PROMPT PSW  CREDENTIAL ## 
        $cred = Get-Credential 

        #save credential in documents
        $cred | Export-CliXml -Path $credpath
    }else{
    ##READ USER CREDENTIAL FROM FILE
        $cred = Import-CliXml -Path $credpath
    }

    ##url and date variables
    $url = "https://outlook.office365.com/api/v1.0/me/messages" 

    $d = [DateTime]::Today.AddDays(-1)
    $global:date = $d.ToString("yyyy-MM-dd")

    ## Get all messages that have attachments where received date is greater than $date  
    $messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived ge " + $date 
    $messages = Invoke-RestMethod $messageQuery -Credential $cred 

    ## Loop through each results 
    foreach ($message in $messages.value) 
    { 
        # get attachments and save to file system 
        $query = $url + "/" + $message.Id + "/attachments" 
        $attachments = Invoke-RestMethod $query -Credential $cred 

        # in case of multiple attachments in email 
        foreach ($attachment in $attachments.value) 
        { 
            Write-Host “Found File :- ” $attachment.Name
            $path = "c:\Attachments\" + $attachment.Name 

            $Content = [System.Convert]::FromBase64String($attachment.ContentBytes) 
            Set-Content -Path $path -Value $Content -Encoding Byte 
        } 
    } 
}

    function sendAttachments
    {
    #############################################################
    ##---------------------------------------------------------##
    ##          SEND ATTACHMENTS AND DELETE FILES              ##
    ##---------------------------------------------------------##
    #############################################################

    #Connection Details

    #PATH TO CREDENTIAL
    $credpath = "C:\Users\" + $env:UserName + "\Documents\myCred_${env:USERNAME}_${env:COMPUTERNAME}.xml"
    $cred = Import-CliXml -Path $credpath

    $smtpServer = “ smtp.office365.com”

    $msg = new-object Net.Mail.MailMessage 

    #Change port number for SSL to 587
    $smtp = New-Object Net.Mail.SmtpClient($SmtpServer, 25) 

    #Uncomment Next line for SSL  
    $smtp.EnableSsl = $true

    $smtp.Credentials = $cred

    $msg.IsBodyHtml = $true

    #From Address
    $msg.From = $cred.UserName
    #To Address, Copy the below line for multiple recipients
    $msg.To.Add(“email@gmail.com”)

    #Message Body
    $msg.Body=”<h2>Alle attachments samen bevinden zich in de bijlage van did email</h2> <br/><br/>”

    #Message Subject
    $msg.Subject = “no-reply: Email met alle attachments”

    #your file location
    $files=Get-ChildItem “C:\Attachments\”

    #attach the right file
    $file = $global:pname
    Write-Host “Attaching File :- ” $file
    $attachment = New-Object System.Net.Mail.Attachment –ArgumentList C:\Attachments\$file
    $msg.Attachments.Add($attachment)

    #send email
    $smtp.Send($msg)
    $attachment.Dispose();
    $msg.Dispose();

    #delete the files from the folder
    Get-ChildItem -Path C:\Attachments -Include * -File -Recurse | foreach { $_.Delete()}
     }

function mergePDF
{
#############################################################
##---------------------------------------------------------##
##                MERGE ALL PDF FILES                      ##
##---------------------------------------------------------##
#############################################################
    $workingDirectory = "C:\Attachments"
    $itspath = $PSScriptRoot
    $global:pname = $global:date + "_pdfAttachments.pdf"
    $pdfs = ls $workingDirectory -recurse | where {-not $_.PSIsContainer -and $_.Extension -imatch "^\.pdf$"};

    [void] [System.Reflection.Assembly]::LoadFrom([System.IO.Path]::Combine($itspath, 'itextsharp.dll'));

    $output = [System.IO.Path]::Combine($workingDirectory, $pname);
    $fileStream = New-Object System.IO.FileStream($output, [System.IO.FileMode]::OpenOrCreate);
    $document = New-Object iTextSharp.text.Document;
    $pdfCopy = New-Object iTextSharp.text.pdf.PdfCopy($document, $fileStream);
    $document.Open();

    foreach ($pdf in $pdfs) {
        $reader = New-Object iTextSharp.text.pdf.PdfReader($pdf.FullName);
        [iTextSharp.text.pdf.PdfReader]::unethicalreading = $true
        $pdfCopy.AddDocument($reader);
        $reader.Dispose();
    }
    $document.Close()
    $pdfCopy.Dispose();
    $document.Dispose();
    $fileStream.Dispose();
}
getAttachments
Start-Sleep -s 10
mergePDF
Start-Sleep -s 10
sendAttachments

在我在另一个脚本文件中运行的这段代码中,我创建了一个新任务:

#############################################################
##---------------------------------------------------------##
##          SCHEDULE SCRIPTS IN WINDOWS TASKS              ##
##---------------------------------------------------------##
#############################################################

##PATH TO CREDENTIAL
$credpath = "C:\Users\" + $env:UserName + "\Documents\myCred_${env:USERNAME}_${env:COMPUTERNAME}.xml"

#test variable
$test = Test-Path $credpath

##TEST IF CREDENTIAL EXISTS
if(!$test){
## USER PROMPT PSW  CREDENTIAL ## 
    $cred = Get-Credential

    #save credential in documents
    $cred | Export-CliXml -Path $credpath
}

$taskName = "ManageEmailAttachments"
$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }

if($taskExists) 
{
   Get-ScheduledJob ManageEmailAttachments
   Unregister-ScheduledJob ManageEmailAttachments
   $wshell = New-Object -ComObject Wscript.Shell
   $wshell.Popup("Task successfully deleted, run the script again to schedule the task",0,"Done",0x0)
} 
else 
{
    $tt = Get-Date
    $tt = $tt.AddMinutes(1)
    $testtime = $tt.ToString("HH:mm:ss")

    #set trigger
    $trigger = New-JobTrigger -Daily -At "1:00"
    $testtrigger = New-JobTrigger -Daily -At $testtime

    #path to the scripts
    $scriptPath = $PSScriptRoot + "\wps_manage_pdf_attachments.ps1"


    #options(optional)
    $option = New-ScheduledJobOption -WakeToRun: $true

    #create a new task
    Register-ScheduledJob -Name ManageEmailAttachments -FilePath $scriptPath -Trigger  $testtrigger -ScheduledJobOption $option 
}

在Powershell中运行的脚本运行良好,它从邮箱获取所有附件,将它们合并到1 .pdf文件中并将它们发送到请求的电子邮件地址。但是当在Windows任务调度程序中进行调度时,它可以完成第一步,但是在合并时,.pdf文件已损坏而没有任何内容。

我无法弄清楚如何使其工作所以我在论坛上发布了一个问题。 希望你们找到解决问题的方法。

提前致谢

2 个答案:

答案 0 :(得分:0)

使用以下函数获取脚本根目录。     函数Get-ScriptDirectory     {      $ Invocation =(Get-Variable MyInvocation -scope 1).Value      拆分路径$ Invocation.MyCommand.Path     }     $ scriptPath = Join-Path(Get-ScriptDirectory)'wps_manage_pdf_attachments.ps1'

答案 1 :(得分:0)

显然问题嵌套在主代码中。我用过:

Try{...} 
Catch{$_ | Out-File C:\errors.txt}

在mergePDF函数中找出错误是什么。好像我的ITextSharp.dll的路径不正确。我用过的$ PSScriptRoot显示&#34; C:\ windows \ windows32&#34;而不是剧本的实际位置。

所以我做的是在我的批处理文件中添加一行来将itextsharp.dll复制到%Temp%:

xcopy Scripts\itextsharp.dll %Temp% /D >NUL 2>NUL

然后从那里读取文件:

$itsPath = [System.IO.Path]::GetTempPath()

一切都按原样运作。我知道这不是最好的方法,但我之前有这个批处理文件,只需点击它就可以运行脚本。 所以添加一条线就不会受到伤害。

我希望这可以帮助任何有同样问题的人。