Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

comment on

( [id://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

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



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-18 12:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found