[PowerShell] Scheduled Task als user niet ingelogd is

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Livvie
  • Registratie: December 2018
  • Laatst online: 04-12-2023
Mijn vraag:
Voor een klant heb ik een script geschreven die een Outlook folder uitleest.
Elke mail in deze folder wordt gecontroleerd op bijlagen, indien er PDF's in de bijlage zitten worden deze op locatie X opgeslagen. De mail zelf wordt verplaatst naar een "verwerkt"-folder.

Omdat IMAP en POP3 niet gebruikt mag worden spreekt het script de Outlook client aan.
Outlook dient geinstalleerd te zijn op het systeem, anders werkt het script dan ook niet.

Het script werkt.

Maar zodra ik een scheduled task aan maak, dan werkt het alleen als ik kies voor "Run only when a user is logged on".
Uiteraard wil ik dat niet, want bij iedere server reboot moet die user (schedule user) weer ingelogd worden. En ik heb geen zin om dat elke dag te controleren, dan kan ik namelijk ook handmatig het script starten.

Ik weet niet wat ik anders moet doen om het werkend te krijgen, heeft iemand hier tips of wellicht de oplossing voor mij?

Relevante software en hardware die ik gebruik:
PowerShell
Outlook 2010
Server 2012 R2

Wat ik al gevonden of geprobeerd heb:
De schedule user heeft full controll rechten op de betreffende mailbox
Het script zelf werkt
Alle overige scheduled task instellingen staan goed

Het script:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#= Bronscript: https://meneer.depuydt.eu/outlook-attachments-automatisch-opslaan/   =
#=                                                                                  =
#= Vereisten:  Via Outlook > Bestand > Opties > Vertrouwenscentrum >                =
#= Instellingen voor het Vertrouwenscentrum > Toegang op programmeerniveau:         =
#= "Waarschuw mij nooit voor verdachte activiteiten (niet aanbevolen)"              =
#= moet aangevinkt staan anders werkt het script niet                               =
#=                                                                                  =
#= Vereist:    Outlook moet geïnstalleerd staan op de server waar dit script draait =
#=                                                                                  =
#= Uitleg:     Het script doorzoekt één folder in Outlook en controleert alle       =
#=             e-mail items op bijlagen. Alle PDF-bijlagen worden opgeslagen        =
#=             in een opgegeven locatie. Vervolgens wordt de e-mail verplaatst.     =
#=                                                                                  =
#====================================================================================

$EmailAddress = "facturen@mail.loc"                                                               #Het e-mail account wat het script gaat controleren
$RootFolder = "Postvak IN"                                                                                   #De hoofdmap van het e-mail account (Standaard: Postvak IN")
$SearchFolder = "1 PDF uitpakken"                                                                            #De zoekfolder, het script doorzoekt uitsluitend deze map
$filepath = "\\domain.loc\dfs\folder\folder\Fact_import"                                                #Het pad waar de bijlages opgeslagen gaan worden
$numberOfMails = 1                                                                                           #Start variabele om de While($numberOfMails) loop te kunnen starten

#============================ HIERONDER NIETS AANPASSEN =============================

function getMailObjects {
    $Mails = $null                                                                                               #Leeg het $Mails-object, om onverklaarbare fouten te voorkomen
    Add-Type -assembly "Microsoft.Office.Interop.Outlook" -Verbose
    $Outlook = New-Object -ComObject Outlook.Application
    $namespace = $Outlook.GetNameSpace("MAPI")
    $Account = $namespace.Folders | ? { $_.Name -eq $EmailAddress };
    $Inbox = $Account.Folders | ? { $_.Name -eq $RootFolder };
    $Folder = $Inbox.Folders | ? { $_.Name -eq $SearchFolder };
    $Mails = $Folder.Items
    $Root = $namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)      #Deze variable is nodig om een path te bouwen naar de $archiveFolder
    $archiveFolder = $Root.Folders['1 PDF uitpakken VERWERKT']                                                   #Hiermee wordt het path gebouwt om de mail naartoe te verplaatsen na behandeling
                                                                                                                 #[1/2] Geef alle mail berichten in de $SearchFolder terug als een object.
    return $Mails,$archiveFolder                                                                                 #[2/2] Geef $archiveFolder terug omdat deze variabele anders niet beschikbaar is in de parseMailObjects functie
}

function parseMailObjects ([Object]$Mails, $archiveFolder) {                                                     #Functie parseMailObjects, parameters -Mails en -archiveFolder opgeven
    foreach ($Mail in $Mails) {                                                                                  #De functie krijgt een object mee die alle mails bevat. Voor elke losse mail moet de loop doorlopen worden
        if ($Mail.Attachments.Count -gt 0) {                                                                     #Heeft een e-mail bericht een bijlage
            $Mail.attachments | foreach {                                                                        #Voor elke gevonden attachment moet de loop doorlopen worden
                $fileExt = $($_.FileName.toString())                                                             #Filename object omzetten naar String zodat er en IF-statement op los gelaten kan worden
                if ($fileExt -like "*.pdf") {                                                                    #Alleen PDF bestanden hoeven opgeslagen te worden                                                                       
                    $mailDate = ($Mail.CreationTime).ToString("yyyyMMdd")                                        #De datum waarop de mail is binnengekomen
                    $filename = "$mailDate - $($_.filename.toString())"                                          #Creert de bestandsnaam van de bijlage(s) en plakt de $mailDate ervoor
                    $saveFileAs = (Join-Path $filepath -ChildPath "Productie" | Join-Path -ChildPath $filename)  #Samenvoegen van pad en bestandsnaam
                    if (-not (Test-Path($saveFileAs))) {
                        $_.saveasfile($saveFileAs)                                                               #Slaat de PDF op in $filepath 
                    }
                }
            }
            try {
                $Mail.Move($archiveFolder) | Out-Null                                                            #PROBEER: Verplaatst de mail na behandeling naar $archiveFolder
            } catch {      
                Write-Error "Error tijdens het uitvoeren van Mail.Move(): $($PSItem.ToString())"                 #CATCH: Als de try fout gaat, dan wordt hier de reden gegeven
            }
        }
    }
}

While ($numberOfMails -ne 0) {                                                                                   #Het script stopt na een aantal mails zonder geldige reden. Deze While-loop zorgt ervoor dat het script echt alle mails verwerkt
    $currentMails = getMailObjects                                                                               #Roep functie getMailObjects aan en sla het resultaat op in $currentMails (let op: Array!)
    $numberOfMails = $currentMails[0].Count                                                                      #Sla de Count op in de variabele $numberOfMails om de While loop succesvol te kunnen gebruiken
    if ($numberOfMails -gt 0) {                                                                                  #Zo lang er mails zijn (waarde groter dan 0) is deze IF-statement TRUE
        parseMailObjects -Mails $currentMails[0] -archiveFolder $currentMails[1]                                 #Roep functie parseMailObjects aan en geef vereiste parameters mee (resultaat van functie getMailObjects)
    }
}

[ Voor 0% gewijzigd door Livvie op 14-12-2018 11:27 . Reden: taalkundig ]

Beste antwoord (via Livvie op 16-12-2018 11:25)


  • Killah_Priest
  • Registratie: Augustus 2001
  • Laatst online: 10:22
Even voor de duidelijkheid : je kunt normaal gesproken de Office Interop objecten niet non-interactive aanroepen (sowieso moet je dit niet willen, met de Office COM objecten werken wat dat betreft).

Staan de mails toevallig op een Exchange server (Office 365 is overigens ook Exchange)? In dat geval kun je namelijk de EWS API gebruiken (Exchange Web Services), dit kan dmv SOAP of door de managed DLL van Microsoft te gebruiken (ik heb in het verleden tientallen scripts geschreven om items uit mailboxen te processen hiermee).
Voordeel is dat dit echt retesnel werkt vergeleken met de Outlook COM objecten, het een stuk sneller is en je geen last krijgt van vreemde bijverschijnselen (COM objecten dienen namelijk ALLEMAAL eerst opgeschoond te worden, anders wilt bv Outlook nog weleens blijven draaien na het aanroepen van de quit() method).

Mocht je met EWS willen werken, dan kun je op het blog van Glen Scales een heleboel informatie vinden hierover : https://gsexdev.blogspot.com/

[ Voor 14% gewijzigd door Killah_Priest op 14-12-2018 14:35 ]

Alle reacties


Acties:
  • 0 Henk 'm!

  • Marber
  • Registratie: Juni 2014
  • Laatst online: 24-09 17:40
Wat als je het script laat draaien onder de eigenaar van de mailbox?

Acties:
  • Beste antwoord
  • +2 Henk 'm!

  • Killah_Priest
  • Registratie: Augustus 2001
  • Laatst online: 10:22
Even voor de duidelijkheid : je kunt normaal gesproken de Office Interop objecten niet non-interactive aanroepen (sowieso moet je dit niet willen, met de Office COM objecten werken wat dat betreft).

Staan de mails toevallig op een Exchange server (Office 365 is overigens ook Exchange)? In dat geval kun je namelijk de EWS API gebruiken (Exchange Web Services), dit kan dmv SOAP of door de managed DLL van Microsoft te gebruiken (ik heb in het verleden tientallen scripts geschreven om items uit mailboxen te processen hiermee).
Voordeel is dat dit echt retesnel werkt vergeleken met de Outlook COM objecten, het een stuk sneller is en je geen last krijgt van vreemde bijverschijnselen (COM objecten dienen namelijk ALLEMAAL eerst opgeschoond te worden, anders wilt bv Outlook nog weleens blijven draaien na het aanroepen van de quit() method).

Mocht je met EWS willen werken, dan kun je op het blog van Glen Scales een heleboel informatie vinden hierover : https://gsexdev.blogspot.com/

[ Voor 14% gewijzigd door Killah_Priest op 14-12-2018 14:35 ]


Acties:
  • 0 Henk 'm!

  • Livvie
  • Registratie: December 2018
  • Laatst online: 04-12-2023
Dankjewel Killah_Priets, ga ik zeker bekijken en proberen. Ik zal het script hier plaatsen als het me gelukt is.

Acties:
  • 0 Henk 'm!

  • Killah_Priest
  • Registratie: Augustus 2001
  • Laatst online: 10:22
Livvie schreef op zondag 16 december 2018 @ 11:26:
Dankjewel Killah_Priets, ga ik zeker bekijken en proberen. Ik zal het script hier plaatsen als het me gelukt is.
Laat het maar even weten als je ergens op vastloopt (dan kan ik altijd ff kijken of ik kan helpen).