Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

I learned some things while working on this little problem, so I thought I'd share. update: changed $ARGV[0] for @ARGV per discussion.

The first thing is that wmi doesn't necessarily use the same fixed headers on different machines. My first attempt was a simple batch file and worked on my machine:

@echo off wmic process |find /i "Caption" |perl -CS -ne "($caption,$commandline, +$ppid,$pid)=unpack('a[21] a[270] @798a[17] @899a[11]',$_);print '}',$ +caption,'-',$ppid,'-',$pid,'-',$commandline,'{',$/;" |find /i "parent +" wmic process |find /i "%1" |perl -CS -ne "($caption,$commandline,$ppid +,$pid)=unpack('a[21] a[270] @798a[17] @899a[11]',$_);print '}',$capti +on,'-',$ppid,'-',$pid,'-',$commandline,'{',$/;" |find /v /i "find"

but not on either the machine of the admin I was doing this for or on the prod machine he needed it for. The static unpack template was off for the set of fields wmi was using on the other machines (to be semantically honest I didn't investigate enough to blanme this on wmi; it was just off).

So, I ended up turning it inside-out. Instead of using perl in a batch file I used the wmic command in a perl script. I ended up opening a file (well, pipe) like almut suggested, but using BrowserUK's command line option to cover the unicode issue.

#!/usr/bin/perl -WCD use strict; use warnings; use Data::Dumper; $\ = $/; my $debug = 1; #array of fields to display my @processFields = ('Caption','ParentProcessId','ProcessId','CommandL +ine'); #ARGV processing #my $searchfor = $ARGV[0] ? join(' ',@ARGV) : die("I need a process to + look for."); # corrected, per bug in discussion below. You might also check out th +e style discussion not changed here. my $searchfor = @ARGV ? join(' ',@ARGV) : die("I need a process to loo +k for."); #set up handle - note -CD arg, above open (PROCINFO, "wmic process |")||die("Can't open wmic for process in +fo pipe!"); #loop my $template=''; while (<PROCINFO>) { #first time get header, find position of columns, build unpack tem +plate unless ($template) { while (@processFields) { my @allFields = split; my $field = pop @processFields; my $fieldIndex; for ($fieldIndex=0; $fieldIndex<=$#allFields; $fieldIndex+ ++) { if ($allFields[$fieldIndex] eq $field) { last; } #assert: found $field in @allfields with index $fieldI +ndex } pos=undef; /\b$field\b/g or die("Could not find field $field"); my $fieldPos = pos; $fieldPos = $fieldPos - length($field); my $nextFieldPos; if ($fieldIndex+1 <= $#allFields) { pos=undef; /\b$allFields[$fieldIndex+1]\b/g or die("Could not fin +d next field $allFields[$fieldIndex+1]"); $nextFieldPos = pos; $nextFieldPos = $nextFieldPos - length($allFields[$fie +ldIndex+1]); } else { $nextFieldPos = length($_)+1; } my $fieldlength = $nextFieldPos - $fieldPos; $template = '@'.$fieldPos.'a['.$fieldlength.'] '.$template +; } #do it once for the header row my $fieldVal; my $outLine=''; foreach $fieldVal (unpack($template, $_)) { $outLine .= ($outLine?'-':'}').$fieldVal; } $outLine .= '{'; print $outLine; #all other times look for, unpack and display if matches arg } if (/$searchfor/) { my $fieldVal; my $outLine=''; foreach $fieldVal (unpack($template, $_)) { $outLine .= ($outLine?'-':'}').$fieldVal; } $outLine .= '{'; print $outLine; } } close(PROCINFO);

If I were to spend more time on it I would get the common code (to get the position of a field and also to constuct the output lines) out into functions. Also, I've rethunk how to get the length of the fields by looking for something like /\G(\b)/gc, but it's a fairly strightforward little throw-away script, so I'm not going to spend that much more time on it.

Back to lessons learned:
- if you're searching for 'ProcessID' you'll find it in 'ParentProcessID' (duh!); this messed me up for a little bit and drove me to put all that $nextField logic in (again, I've rethunk it and think it would be more elegant with \G).
- -CS worked on the command line, but when I added it to the she-bang (#!/usr/bin/perl -CS -W) it complained about an 'Unknown Unicode option letter'. I finally figured out I had to combine things in the command options as #!/usr/bin/perl -WCS. In retrospect, there are other problems in my past that are explained by this and I never knew it.
- I had to pos=undef; to get the search to reset, since it didn't search backwards from the previous match.
- $#ARGV is 0 whether there are zero or 1 arguments. This led me to the $ARGV[0] ? : solution.
- I was worried about getting the output fields in the order I want and was happy to learn that using @location in the template let me bounce around in the string and still return the fields in the order they appreared in the template.

I'm sure there are other lessons here and many wasy to improve my little script, but as I said, I probably won't spend any more time on it (the script that is; I'll happily spend time learning form any feedback I get here). I hope the lessons learned are helpful.

#my sig used to say 'I humbly seek wisdom. '. Now it says:
use strict;
use warnings;
I humbly seek wisdom.

In reply to Re: unpacking wmic command's unicode output by goibhniu
in thread unpacking wmic command's unicode output by goibhniu

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others rifling through the Monastery: (4)
    As of 2018-08-14 21:05 GMT
    Find Nodes?
      Voting Booth?
      Asked to put a square peg in a round hole, I would:

      Results (155 votes). Check out past polls.