Atle Hanssen
Atle Hanssen

Reputation: 11

Powershell variable getting "lost"

I'm working on a script that monitors an error folder and sends e-mail when an error occurs. For each error we get two files in the folder, one text file and one xml. In the e-mail I want to include the entire content of the text file and part of the content of the xml file.

In the following script I get only the content of the text file. (Lines for sending the email are commented out for testing purposes). I have read about variables and foreach and I guess this may be the problem, but I'm still not sure how to fix this in my script. Or maybe there is a much easier way to do this?

$Foldertowatch = 'C:\lpos\invalidArts' 
$FilterXML = '*.xml' 
$FilterTXT = '*.txt' 

Unregister-Event -SourceIdentifier CreatedEventXML
$fswXML = New-Object System.IO.FileSystemWatcher $Foldertowatch, $FilterXML
$fswXML.EnableRaisingEvents=$true
$fswXML.IncludeSubdirectories=$false

Register-ObjectEvent -InputObject $fswXML -EventName Created -SourceIdentifier CreatedEventXML -Action {
$Filename = $Event.SourceEventArgs.Name
[XML]$XMLFile = (Get-Content $Foldertowatch\$Filename)
$XMLtmp = foreach ($user in $XMLFile.POSLog.POSLogTransaction)
{
$user.RetailStoreID
$user.WorkStationID
$user.OperatorID
$user.SequenceNumber
}
}

Unregister-Event -SourceIdentifier CreatedEventTXT
$fswTXT = New-Object System.IO.FileSystemWatcher $Foldertowatch, $FilterTXT
$fswTXT.EnableRaisingEvents=$true
$fswTXT.IncludeSubdirectories=$false

Register-ObjectEvent -InputObject $fswTXT -EventName Created -SourceIdentifier CreatedEventTXT -Action {
$FilenameTXT = $Event.SourceEventArgs.Name
$ContentTXT = (Get-Content $Foldertowatch\$FilenameTXT) -join "`n"

write-host $user.retailstoreid
Write-Host $contenttxt

<#$From = "[email protected]"
$To = "[email protected]"
$SMTPServer = "mailserver.com"
$subject = $env:COMPUTERNAME + " contains invalid ARTSXML"#>
<#Write-Host "Store:" + $ContentXML.RetailStoreID + "`n" + "Workstation:" + $ContentXML.WorkStationID + "`n" +"Operator:" + $ContentXML.OperatorID + "`n" +"Receiptnumber:" + $ContentXML.sequencenumber + "`n" + "`n" + "Filelocation: $Foldertowatch\$FilenameTXT" + "`n" + "`n" + <#$ContentTXT##>
<#$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer);
$smtp.Send($From, $To, $subject, $body);#>
}

The $ContentXML is from an early try, it should be $user now. I manage to get content from XML if I run first part of script like this:

$Foldertowatch = 'C:\lpos\invalidArts' <# Folder to watch #>
$FilterXML = '*.xml' <# Use *.xml #>
$FilterTXT = '*.txt' <# Use *.txt for poslog2arts, use *.log for POS Reporting #>

Unregister-Event -SourceIdentifier CreatedEventXML
$fswXML = New-Object System.IO.FileSystemWatcher $Foldertowatch, $FilterXML
$fswXML.EnableRaisingEvents=$true
$fswXML.IncludeSubdirectories=$false

Register-ObjectEvent -InputObject $fswXML -EventName Created -SourceIdentifier CreatedEventXML -Action {
$Filename = $Event.SourceEventArgs.Name
[XML]$XMLFile = (Get-Content $Foldertowatch\$Filename)
$XMLtmp = foreach ($user in $XMLFile.POSLog.POSLogTransaction)
{
write-host $user.RetailStoreID
write-host $user.WorkStationID
write-host $user.OperatorID
write-hosts $user.SequenceNumber
}
}

Upvotes: 1

Views: 184

Answers (1)

Swoogan
Swoogan

Reputation: 5558

I'm not sure of your intent, but I see a possible solutions. First, this code:

$XMLtmp = foreach ($user in $XMLFile.POSLog.POSLogTransaction)
{
  $user.RetailStoreID
  $user.WorkStationID
  $user.OperatorID
  $user.SequenceNumber
}

You never seem to use $XMLtmp again. Also, it's just going to contain an array of strings, not something that has properties like $user.RetailStoreID

What you can do is this:

$users = @()

Register-ObjectEvent -InputObject $fswXML -EventName Created -SourceIdentifier CreatedEventXML -Action {
  $Filename = $Event.SourceEventArgs.Name
  [XML]$XMLFile = (Get-Content $Foldertowatch\$Filename)
  foreach ($user in $XMLFile.POSLog.POSLogTransaction) {
    $users += $user
  }
}

Then later you can index that array. Are there more than one user? Do you want to send more than one email?

At that point you can do the following:

$users | % { Write-Host $_.RetailStoreId  }

The $user variable you create in the foreach () {} goes out of scope (aka "disappears") when the } is hit. The $XMLtmp is unnecessary. Declaring $users outside of the scope of the Action and foreach ensures it is global to the entire script.

Upvotes: 1

Related Questions