none
WMI Permanent event monitoring - Powerevents syntax problem RRS feed

  • Question

  • Hello,

    I have been trying to come up with nice solution for permanent event monitoring and so far Powerevents seemed like nice way to go.

    However I have a problem with Commandline consumer syntax, where I run another PS script.

    Here is my Consumer command:

    $consumer = New-WmiEventConsumer -Name "Event Consumer for $eventid" -ConsumerType commandline -CommandLineTemplate "powershell.exe -command `". 'c:\skript\monitoring\sql_vklad_eventy.ps1' `"$eventid $popis`""

    Here it calls script that inserts its two parameters into SQL, which in this case are variables $eventid and $popis.

    My problem is that second parameter is long string with event details in it and I can't manage to get it in quotation marks that doesn't screw up whole line. When I run the script, first parameter writes fine and I have only first word from the second one.

    No matter what I do, I just break whole command or get same result.
    Can you please help me ?

    Wednesday, August 6, 2014 3:46 PM

Answers

  • Use the PowerShell-file -args method and your arguments won't get munged.


    ¯\_(ツ)_/¯

    • Marked as answer by David Kucera Thursday, August 7, 2014 12:53 PM
    Thursday, August 7, 2014 12:27 PM

All replies

  • It is just a simple string.

    $cmdline="powershell.exe -command c:\skript\monitoring\sql_vklad_eventy.ps1 $eventid $popis"
    $props=@{ 
         Name="Event Consumer for $eventid" 
         ConsumerType='commandline'
         CommandLineTemplate=$cmdline
    }
    $consumer=New-WmiEventConsumer @props
    
    


    ¯\_(ツ)_/¯

    Wednesday, August 6, 2014 3:59 PM
  • That must be the sun exposure, I cannot overcome this simple thing.

    Your code makes it much more readable thanks, but I am still unable to get $popis to work with quotation marks, I must be missing something...

    I want to add it like below, which is working when I write it manually

    sql_vklad_eventy.ps1 shortparam "long parameter with spaces"

    Thanks again for any help.

    Wednesday, August 6, 2014 5:12 PM
  • This way:

    $cmdline="powershell.exe -command c:\skript\monitoring\sql_vklad_eventy.ps1 $eventid '$popis'"

    You only need single quotes in this case.



    ¯\_(ツ)_/¯

    Wednesday, August 6, 2014 5:17 PM
  • Thanks again for advice.

    Unfortunately it is not working now. Since it is event fired, I have a hard time debugging it, can you please recommend me good approach how to find the error ?

    Wednesday, August 6, 2014 5:26 PM
  • Thanks again for advice.

    Unfortunately it is not working now. Since it is event fired, I have a hard time debugging it, can you please recommend me good approach how to find the error ?

    What error?  You need to just run it as a command until you get it working.

    Remember that events do not run under an account. They run as system so access to database  is forbidden unless that database is set up correctly.

    To trace the event version you need to do file writes to trace the progress and you need to know how to use error management.

    Why not just use an event log task.  They are much easier to set up and work pretty much flawlessly.


    ¯\_(ツ)_/¯

    Wednesday, August 6, 2014 5:30 PM
  • Thank you for your insight.

    There are lot of events we want to watch, and setting them up task by task seemed like lot of work.

    I'm a little confused by now. When I find consumer details in WMI Event Registration tool, copy the commandlinetemplate value and paste it to cmd it works. It is just not working when event starts. Now it looks like this.

    $cmdline="powershell.exe -command c:\skript\monitoring\sql_vklad_eventy.ps1 `"$eventid `'$popis`'`""

    I doubt I have database permission problem, since it writes good for every other script.

    Wednesday, August 6, 2014 6:09 PM
  • Thank you for your insight.

    There are lot of events we want to watch, and setting them up task by task seemed like lot of work.

    I'm a little confused by now. When I find consumer details in WMI Event Registration tool, copy the commandlinetemplate value and paste it to cmd it works. It is just not working when event starts. Now it looks like this.

    $cmdline="powershell.exe -command c:\skript\monitoring\sql_vklad_eventy.ps1 `"$eventid `'$popis`'`""

    I doubt I have database permission problem, since it writes good for every other script.

    Why do you keep adding esacpe character to the commandline.  They are not used in WIndpoowss commandlines.  This is NOT a powershell CmdLet it is a Windows commandline.  It gets saved exactly the way you run it at a prompt CMD prompt.  Not at a PowerShell prompt.

    You can also do this:

    This gets expanded as needed by the system.  because the command is sent to the CreateProcess API of the system and not to PowerShell.

    PS C:\scripts> $eventid=1234
    PS C:\scripts> $popis='this is an example with spaces'
    PS C:\scripts> $cmdline="powershell.exe -command c:\skript\monitoring\sql_vklad_eventy.ps1 $eventid ""$popis"""
    PS C:\scripts> $cmdline
    powershell.exe -command c:\skript\monitoring\sql_vklad_eventy.ps1 1234 "this is an example with spaces"
    PS C:\scripts>

    The Event tasks can be built on a list of event ids. It is much easier to use and more Powerful.

    The other method is to create a custom subscription (which can work across systesm) and place an event the triggers on all records posted to eh subscription. 

    The other thing is to option the subscription to write the events directly to a SQL table and place triggers on the table to manage the evnt arrival.  This I would be the preferred method.


    ¯\_(ツ)_/¯


    • Edited by jrv Wednesday, August 6, 2014 7:03 PM
    Wednesday, August 6, 2014 7:00 PM
  • Thanks again !

    I was confused when quotes didn't work, so that's that escape madness. Well your version looks as it should, but I am back to single word in second parameter for some reason.

    I will try to solve it tomorrow and study more on event tasks, if that can be done with commands too. I don't know sql triggers at all, will look into it.

    Wednesday, August 6, 2014 9:07 PM
  • I really don't see why you keep having issues.  I can run anything I need.

    powershell  -file c:\scripts\test.ps1  -args 1,2,3,'some new arg'

    #Contents of test.ps1
    $args

    It works every time.


    ¯\_(ツ)_/¯

    Wednesday, August 6, 2014 9:14 PM
  • Here is the same filewith -command

    C:\scripts>powershell  -command c:\scripts\test.ps1  1,2,3,'some new arg'
    1
    2
    3
    some new arg


    ¯\_(ツ)_/¯

    Wednesday, August 6, 2014 9:17 PM
  • You also cannot use variables in CommandLineTemplates. It must be converted to a full string before assignment.


    ¯\_(ツ)_/¯

    Wednesday, August 6, 2014 9:21 PM
  • I think variables are converted before, because SQL gets values.

    If you are willing to look into it I will paste both whole scripts that I use, cause I don't even know where I'm wrong now.

    # Script with powerevents
    
    #Jméno PC a název domény
    $jmenopc = $env:COMPUTERNAME
    if ((gwmi win32_computersystem).partofdomain -eq $true) 
    {
    import-module ActiveDirectory
    $dom = get-addomain | select forest -ErrorAction SilentlyContinue
    $domena = $dom.forest
    } 
    else {
        $workgroup = Get-Workgroup
    }
    #domena nebo workgroup
    if (!$domena) { $net = $workgroup}
    else { $net = $domena}
    
    # modul pro WIM eventy - powerevents - je potřeba ho nainstalovat do C:\Program Files\WindowsPowerShell\Modules !!
    # zde je v utilities i program wmieventhelper na mazání záznamů 
    Unblock-File -LiteralPath "C:\Program Files\WindowsPowerShell\Modules\powerevents\install.ps1"
    cd "C:\Program Files\WindowsPowerShell\Modules\powerevents\"
    .\install.ps1
    
    # Pro každé ID ze seznamu kritických ID který ke každému zdroji budeme mít
    $seznam = @("2003" ,"2001")
    foreach ($eventid in $seznam)
    {
    #Create a WMI Query for the event log entry - filtr zajímá nás sourcename a eventcode
    $query = "SELECT * FROM __InstanceCreationEvent WHERE
              TargetInstance ISA 'Win32_NTLogEvent' AND
              TargetInstance.LogFile='Application' AND
              TargetInstance.sourcename='Microsoft-Windows-LocationProvider' AND
              TargetInstance.EventCode=$eventid"            
    
    #Create an event filter - vytvoření filtru
    $filter = New-WmiEventFilter -Name "Event Filter for Event ID $eventid" -Query $query            
    
    #Create an event consumer - consumer je typu SMTP = jen mailuje (možno nastavit na cmd)
    $popis = 'Na $jmenopc udalost s ID $eventid a zprava:%TargetInstance.Message%'
    $cmdline="powershell.exe -command c:\skript\monitoring\sql_vklad_eventy.ps1 $eventid ""$popis"""
    $props=@{ 
         Name="Event Consumer for $eventid" 
         ConsumerType='commandline'
         CommandLineTemplate=$cmdline
    }
    $consumer=New-WmiEventConsumer @props
    
    
    #Bind the filter and consumer together      
    New-WmiFilterToConsumerBinding -Filter $filter -Consumer $consumer
    }

    #### Table into SQL insert ####
    
    #### Parametry ####
    param([string]$p1, [string]$p2)
    
    #### Definice tabulky ####
     
     $ev = "Tabulka eventu"
     $global:eventytab = New-Object system.Data.DataTable “$ev”
     $sloupec1 = New-Object system.Data.DataColumn Název,([string])
     $sloupec2 = New-Object system.Data.DataColumn Popis,([string])
     $sloupec3 = New-Object system.Data.DataColumn Datum,([string])
    $global:eventytab.columns.add($sloupec1)
    $global:eventytab.columns.add($sloupec2)
    $global:eventytab.columns.add($sloupec3)
    
    $radek = $global:eventytab.NewRow()
    $radek.Název = $p1
    $radek.Popis = $p2
    $radek.Datum = get-date -Format "yyyy-MM-ddTHH:mm:ss"
    $global:eventytab.Rows.add($radek)
    
    # Eventy - zapis promenne do SQL
    
    $cn = new-object System.Data.SqlClient.SqlConnection("Data Source=NB21\SQLexpress;Integrated Security=SSPI;Initial Catalog=SYSP");
    $cn.Open()
    
    
    $bc = new-object ("System.Data.SqlClient.SqlBulkCopy") $cn
    $bc.DestinationTableName = "dbo.udalosti"
    $bc.WriteToServer($global:eventytab)
    $cn.Close()
    Hope you can make some sense from it, most of comments are in Czech
    Thursday, August 7, 2014 7:05 AM
  • Use the PowerShell-file -args method and your arguments won't get munged.


    ¯\_(ツ)_/¯

    • Marked as answer by David Kucera Thursday, August 7, 2014 12:53 PM
    Thursday, August 7, 2014 12:27 PM
  • YOu should also be awre that the parameter with spaces should not be an array of lines.  It will break the data column at the first array element.


    ¯\_(ツ)_/¯

    Thursday, August 7, 2014 12:29 PM
  • Finally it works ! Thank you very much for your input !

    I don't really understand -args since it is ignoring first word after it, but when I insert any word, those two parameters are working

    Thursday, August 7, 2014 12:53 PM
  • -args passes a comma separated list as an array.

    Powershell -file <somefile> -args 1,2,3,"text with spaces", simpletext, 1.345

    $args[0] ... $args[$args.count-1]

    If you use a Param statement they are mapped in order:

    Param(
         $p1, #$args[0]
          $p2, #$args[1]
          $p3   #$args[2]
    )

    That is all there is to it.  If you are skipping the first one then there is something that you are doing wrong like passing an array of strings which will be picked up as an array of arguments.  To prevent this do the following:

    $somearg # argument that is an array of strings

    $newarg=$somearg | Out-String

    This will explicitly convert the array into a string and will add the newline characters.  This prevents PowerShell from seeing this array as a list of arguments.

    The returned messages from the eventlog are returned as an array of lines.


    ¯\_(ツ)_/¯

    Thursday, August 7, 2014 1:23 PM
  • It even passes details with more lines correctly.

    Thank You for example and explanation, I will try to get it to behave correctly.

    Thursday, August 7, 2014 2:42 PM