From be2a5ca582bdd2ea9af8b93f67cd9d60df3e983a Mon Sep 17 00:00:00 2001 From: Adam Bertram Date: Wed, 18 Oct 2017 17:21:09 -0500 Subject: [PATCH] Added Invoke-Process --- File-Folder Management/FileMonitor.psm1 | 29 +++++++++------- Processes/Invoke-Process.ps1 | 46 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 Processes/Invoke-Process.ps1 diff --git a/File-Folder Management/FileMonitor.psm1 b/File-Folder Management/FileMonitor.psm1 index 6810d69..356d008 100644 --- a/File-Folder Management/FileMonitor.psm1 +++ b/File-Folder Management/FileMonitor.psm1 @@ -48,30 +48,35 @@ function New-FileMonitor { param ( [Parameter(Mandatory)] [string]$Name, + [Parameter(Mandatory)] [string]$MonitorInterval, + [Parameter(Mandatory)] [string]$FolderPath, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateSet('Modification', 'Creation')] + [string]$EventType, + [Parameter(Mandatory)] [ValidateScript({ Test-Path -Path $_ -PathType 'Leaf' })] [ValidatePattern('.*\.ps1')] [string]$ScriptFilePath, + [ValidatePattern('.*\.vbs')] [string]$VbsScriptFilePath = "$($env:TEMP)\FileMonitor.vbs" ) process { try { - ## Break apart the drive and path to meet WMI specs - $Drive = $FolderPath | Split-Path -Qualifier - $FolderPath = "$($FolderPath | Split-Path -NoQualifier)\".Replace('\', '\\') - ## Create the event query to monitor only the folder we want. Also, set the monitor interval ## to something like 10 seconds to check the folder every 10 seconds. - $WmiEventFilterQuery = " - SELECT * FROM __InstanceCreationEvent WITHIN $MonitorInterval - WHERE targetInstance ISA 'CIM_DataFile' - AND targetInstance.Drive = `"$Drive`" - AND targetInstance.Path = `"$FolderPath`"" + $WmiEventFilterQuery = @' +SELECT * FROM __Instance{0}Event WITHIN {1} +WHERE targetInstance ISA 'CIM_DirectoryContainsFile' +and TargetInstance.GroupComponent = 'Win32_Directory.Name="{2}"' +'@ -f $EventType, $MonitorInterval, ($FolderPath -replace '\\+$').Replace('\', '\\') ## Subscribe to the WMI event using the WMI filter query created above $WmiFilterParams = @{ @@ -86,7 +91,7 @@ function New-FileMonitor { ## WMI events cannot auto-trigger another PowerShell script. $VbsScript = " Set objShell = CreateObject(`"Wscript.shell`")`r`n - objShell.run(`"powershell.exe -NoProfile -WindowStyle Hidden -executionpolicy bypass -file `"`"$ScriptFilePath`"`"`") + objShell.run(`"powershell.exe -NonInteractive -NoProfile -WindowStyle Hidden -executionpolicy bypass -file `"`"$ScriptFilePath`"`"`") " Set-Content -Path $VbsScriptFilePath -Value $VbsScript @@ -94,7 +99,7 @@ function New-FileMonitor { $WmiConsumerParams = @{ 'Class' = 'ActiveScriptEventConsumer' 'Namespace' = 'root\subscription' - 'Arguments' = @{ Name = $Name; ScriptFileName = $VbsScriptFilePath; ScriptingEngine = 'VBscript' } + 'Arguments' = @{ Name = $Name; ScriptFileName = $VbsScriptFilePath; ScriptingEngine = 'VBScript' } } Write-Verbose -Message "Creating WMI consumer using script file name $VbsScriptFilePath" $WmiConsumer = Set-WmiInstance @WmiConsumerParams @@ -138,7 +143,7 @@ function Get-FileMonitor { $Monitor.Binding = Get-WmiObject @BindingParams $Monitor.Filter = Get-WmiObject @FilterParams $Monitor.Consumer = Get-WmiObject @ConsumerParams - if (@($Monitor.Values | where { $_ }).Count -eq $Monitor.Keys.Count) { + if ($Monitor.Consumer -and $Monitor.Filter) { [pscustomobject]$Monitor } elseif (-not $Monitor.Consumer -and -not $Monitor.Filter) { $null diff --git a/Processes/Invoke-Process.ps1 b/Processes/Invoke-Process.ps1 new file mode 100644 index 0000000..fd856fe --- /dev/null +++ b/Processes/Invoke-Process.ps1 @@ -0,0 +1,46 @@ +function Invoke-Process { + [CmdletBinding(SupportsShouldProcess)] + param + ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$FilePath, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string]$ArgumentList + ) + + $ErrorActionPreference = 'Stop' + + try { + $stdOutTempFile = "$env:TEMP\$((New-Guid).Guid)" + $stdErrTempFile = "$env:TEMP\$((New-Guid).Guid)" + + $startProcessParams = @{ + FilePath = $FilePath + ArgumentList = $ArgumentList + RedirectStandardError = $stdErrTempFile.FullName + RedirectStandardOutput = $stdOutTempFile.FullName + Wait = $true; + PassThru = $true; + NoNewWindow = $true; + } + if ($PSCmdlet.ShouldProcess("Process [$($FilePath)]", "Run with args: [$($ArgumentList)]")) { + $cmd = Start-Process @startProcessParams + $cmdOutput = Get-Content -Path $stdOutTempFile.FullName -Raw + $cmdError = Get-Content -Path $stdErrTempFile.FullName -Raw + if ([string]::IsNullOrEmpty($cmdOutput) -eq $false) { + Write-Output -InputObject $cmdOutput + } + if ($cmd.ExitCode -ne 0) { + throw $cmdError.Trim() + } + } + } catch { + $PSCmdlet.ThrowTerminatingError($_) + } finally { + Remove-Item -Path $stdOutTempFile.FullName, $stdErrTempFile.FullName -Force + $ErrorActionPreference = 'Continue' + } +} \ No newline at end of file