2 years ago

#7561

test-img

Teknowledgist

Can PowerShell be an ActiveScriptEventConsumer?

I need to continuously watch a particular "drop" folder for (tiny) pdfs and auto-print and delete them. The printing itself is being handled by SumatraPDF (because I don't think there is a built-in, Windows method).

Creating a temporary WMI event monitor in PowerShell is pretty straightforward:

$WQLquery = "SELECT * FROM __InstanceCreationEvent WITHIN 5 " +
            "WHERE TargetInstance ISA 'CIM_DataFile' " +
            "AND TargetInstance.Extension = 'pdf' " +
            "AND TargetInstance.Drive = '$($Drive):' " +
            "AND TargetInstance.Path = '$($Folder.replace('\','\\'))'"

$Action = {
   $TimedOut = $null
   $PrintProcess = Start-Process -FilePath $Sumatra -ArgumentList "-Print-To $Printer `"$($EventArgs.NewEvent.TargetInstance.Name)`""  -PassThru
   $PrintProcess | Wait-Process -Timeout 10 -ErrorAction SilentlyContinue -ErrorVariable TimedOut
   if ($TimedOut) {
      "Printing $($EventArgs.NewEvent.TargetInstance.Name) timed out." | Out-File $ErrorLogPath -Append
      $PrintProcess.kill
   } elseif ($PrintProcess.ExitCode -ne 0) {
      "Error for $($EventArgs.NewEvent.TargetInstance.Name) : $($PrintProcess.ExitCode)" | Out-File $ErrorLogPath -Append
   } else {
      Remove-Item $EventArgs.NewEvent.TargetInstance.Name -Force
   }
}

Register-CimIndicationEvent -Query $wqlquery -SourceIdentifier 'FileCreated' -Action $Action 

When it comes to creating a permanent event subscription, I can replace the Action and Register-CimIndicationEvent with:

# This creates a permanent event monitor that lasts through a reboot
# Step One:  Create a Filter object
$FilterArgs = @{
   ClassName    = '__EventFilter'
   NameSpace    = 'root\subscription'
   Computername = $env:COMPUTERNAME
   ErrorAction  = 'Stop'
   Property     = @{
      Name           = 'PDFCreatedFilter'
      EventNamespace = 'root\CIMV2'
      QueryLanguage  = 'WQL'
      Query          = $WQLQuery
   }
}
$FilterInstance = New-CimInstance @FilterArgs

# Step Two:  Create a Consumer object
$ConsumerArgs = @{
   ClassName    = 'ActiveScriptEventConsumer'
   NameSpace    = 'root\subscription'
   Computername = $env:COMPUTERNAME
   ErrorAction  = 'Stop'
   Property     = @{
      Name           = 'FileCreatedConsumer'
      EventNamespace = 'root\CIMV2'
      ScriptingEngine = ''   # <---- What goes here for PowerShell?
      ScriptFileName  = ''   # <---- What goes here for PowerShell?
   }
}

$ConsumerInstance = New-CimInstance @ConsumerArgs

# Step Three:  Create a Binding object between the Filter and Consumer
$BindingArgs = @{
   ClassName    = '__FilterToConsumerBinding'
   NameSpace    = 'root\subscription'
   Computername = $env:COMPUTERNAME
   ErrorAction  = 'Stop'
   Property     = @{
      Filter   = [Ref]$FilterArgs
      Consumer = [Ref]$ConsumerArgs
   }
}
$BindingInstance = New-CimInstance @BindingArgs

However, and you can see, I am unsure about the ActiveScriptEventConsumer. Microsoft's documentation says it can be "in an arbitrary scripting language", but every example I can find uses VBScript only. I'd really like to use PowerShell.

Is PowerShell a valid Scripting Engine?

If yes, can someone provide the syntax for the ScriptingEngine and ScriptText properties to get it to work?

If no, am I better off hacking together some noob VBScript (yuck!) or using an CommandLineEventConsumer to start a PowerShell script (that I then have to watch/protect)?

Thanks!

windows

powershell

vbscript

event-handling

wmi-query

0 Answers

Your Answer

Accepted video resources