INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

How to do this in PowerShell

How to do this in PowerShell

(OP)
Hi all,

I'm used to cmd scripting, and struggle to find Powershell counterparts for some common scripting techniques.

Let's examine the following example:

CODE

C:\Windows\System32\inetsrv>appcmd.exe list vdir

VDIR "Default Web Site/" (physicalPath:C:\inetpub\wwwroot)
VDIR "Webshop/" (physicalPath:C:\InetPub\Webshop)
VDIR "Webshop/App0/" (physicalPath:C:\Inetpub\Webshop\App0)
VDIR "Webshop/App1/" (physicalPath:C:\Inetpub\Webshop\App1)
VDIR "Webshop/App2/" (physicalPath:C:\Inetpub\Webshop\App2)
VDIR "Webshop/App3/" (physicalPath:C:\Inetpub\Webshop\App3)
VDIR "Webshop/App4/" (physicalPath:C:\Inetpub\Webshop\App4)
VDIR "Webshop/App5/" (physicalPath:C:\Inetpub\Webshop\App5)
VDIR "Webshop/App6/" (physicalPath:C:\Inetpub\Webshop\App6)

Let's say I want to show just the custom 'App' vdirs, and the 2nd property of them (logical path). In cmd I'd do something like:

CODE

C:\Windows\System32\inetsrv>for /f "tokens=2" %i in ('"appcmd.exe list vdir | find "App""') do @echo %i

"Webshop/App0/"
"Webshop/App1/"
"Webshop/App2/"
"Webshop/App3/"
"Webshop/App4/"
"Webshop/App5/"
"Webshop/App6/"

How can I do this in PowerShell? (putting the result in an array of strings)

RE: How to do this in PowerShell

(OP)
To be more specific, let's examine the following .ps1 script

CODE

$tl=(& tasklist)
$tl

This will create an array identified by $tl which contains strings, one string object per line returned. The second line will output the contents of the array to screen:

CODE

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
System Idle Process              0 Services                   0         24 K
System                           4 Services                   0        308 K
smss.exe                       280 Services                   0      1.228 K
csrss.exe                      468 Services                   0      4.772 K
wininit.exe                    548 Services                   0      4.656 K
csrss.exe                      568 Console                    1     14.664 K
services.exe                   604 Services                   0     14.240 K
...etc...

Now, how do I filter on lines containing '.exe', and then just store the PID per match in a new array (containing strings)?

RE: How to do this in PowerShell

PowerShell actually has a native command for getting process information, Get-Process. Since it returns objects, it's a little easier to work with than parsing the strings. For things that don't have native PowerShell equivalents, there are commands such as Select-String for the equivalent of Find and operators such as -match that can use regular expressions to pull information out of strings.

The following gets all processes, filters to get ones with a value in MainModule (which cuts out ones such as System), selects only the PID, and then assigns all of those to the variable $p. Note that in this case $p is an object with all the IDs assigned to it (instead of an array of strings).

CODE

$p = Get-Process | Where {$_.MainModule -ne $null} | Select ID
$p

Does that help?
 

RE: How to do this in PowerShell

(OP)
Thanks for the Select-String suggestion!

Been googling for some time, but I can't find an example of how to use the -match operator with regular expressions in order to split a string in separate fields, delimited by some char.

Also, I think it's weird having to resort to regexps for something this simple and common. I just want the n-th field of a 'tokenized' string. Isn't there an easier approach then regexps?

RE: How to do this in PowerShell

Something like this seems to work:

CODE

# Run from command line:
# powershell -ExecutionPolicy RemoteSigned .\find_exe_task.ps1

$tl = tasklist | sort-object

# writing all lines
echo "* Lines containing .EXE:"
foreach($line in $tl){
  if ($line -match ".exe") {
    echo $line
  }
}

echo ""

# writing only first column -i.e EXE name
echo "* Tasks containing .EXE (case sensitive):"
foreach($line in $tl){
  # split line into array
  $line_arr = [regex]::split($line,"\s+")
  # if first array element contains EXE, then print it
  if ($line_arr[0] -cmatch ".EXE") {
    echo $line_arr[0]
  }
}
Output:

CODE

C:\_mikrom\Work\PowerShell>powershell -ExecutionPolicy RemoteSigned .\find_exe_task.ps1
* Lines containing .EXE:
amswmagt.exe                1796 Console                 0      5.860 K
ati2evxx.exe                 548 Console                 0      4.752 K
...
...
winlogon.exe                1156 Console                 0      7.552 K
wmiprvse.exe                3992 Console                 0      6.004 K
xtagent.exe                 1416 Console                 0      3.748 K

* Tasks containing .EXE (case sensitive):
DWRCS.EXE
DWRCST.EXE
TOTALCMD.EXE

RE: How to do this in PowerShell

Yes, I tried the function split() before but I think it didn't work as I expected: $line_arr[0] was ok, but $line_arr[1] was wrong.

RE: How to do this in PowerShell

The example below is the comparision of string split and the regex split function.
This is what I found wrong with string split function:

CODE

# Run from command line:
# powershell -ExecutionPolicy RemoteSigned .\split_example.ps1

$tl = tasklist | sort-object

echo "* Processing output of command:"
foreach($line in $tl){
  echo $line
}

echo ""

echo "* Using string split function:"
foreach($line in $tl){
  # split line into array
  $line_arr = $line.split()
  # array elements
  $e01 = $line_arr[0]
  $e02 = $line_arr[1]
  $e03 = $line_arr[2]
  echo "e01 = '$e01', e02= '$e02' , e03 = '$e03'"
}

echo ""

echo "* Using regex split function:"
foreach($line in $tl){
  # split line into array
  $line_arr = [regex]::split($line,"\s+")
  # array elements
  $e01 = $line_arr[0]
  $e02 = $line_arr[1]
  $e03 = $line_arr[2]
  echo "e01 = '$e01', e02= '$e02' , e03 = '$e03'"
}
Output:

CODE

* Processing output of command:

========================= ====== ================ ======== ============
amswmagt.exe                1288 Console                 0      5.860 K
ati2evxx.exe                 552 Console                 0      4.748 K
ati2evxx.exe                1448 Console                 0      3.176 K
avp.exe                     1916 Console                 0    211.432 K
avp.exe                     3632 Console                 0      4.528 K
avp.exe                     5868 Console                 0     14.484 K
CAF.exe                     2236 Console                 0     15.124 K
cam.exe                     1948 Console                 0      3.548 K
capmuamagt.exe              2100 Console                 0      4.660 K
...
...
wmiprvse.exe                2448 Console                 0      6.004 K
xtagent.exe                 1432 Console                 0      3.748 K

* Using string split function:
e01 = '', e02= '' , e03 = ''
e01 = '=========================', e02= '======' , e03 = '================'
e01 = 'amswmagt.exe', e02= '' , e03 = ''
e01 = 'ati2evxx.exe', e02= '' , e03 = ''
e01 = 'ati2evxx.exe', e02= '' , e03 = ''
e01 = 'avp.exe', e02= '' , e03 = ''
e01 = 'avp.exe', e02= '' , e03 = ''
e01 = 'avp.exe', e02= '' , e03 = ''
e01 = 'CAF.exe', e02= '' , e03 = ''
e01 = 'cam.exe', e02= '' , e03 = ''
e01 = 'capmuamagt.exe', e02= '' , e03 = ''
...
...
e01 = 'wmiprvse.exe', e02= '' , e03 = ''
e01 = 'xtagent.exe', e02= '' , e03 = ''

* Using regex split function:
e01 = '', e02= '' , e03 = ''
e01 = '=========================', e02= '======' , e03 = '================'
e01 = 'amswmagt.exe', e02= '1288' , e03 = 'Console'
e01 = 'ati2evxx.exe', e02= '552' , e03 = 'Console'
e01 = 'ati2evxx.exe', e02= '1448' , e03 = 'Console'
e01 = 'avp.exe', e02= '1916' , e03 = 'Console'
e01 = 'avp.exe', e02= '3632' , e03 = 'Console'
e01 = 'avp.exe', e02= '5868' , e03 = 'Console'
e01 = 'CAF.exe', e02= '2236' , e03 = 'Console'
e01 = 'cam.exe', e02= '1948' , e03 = 'Console'
e01 = 'capmuamagt.exe', e02= '2100' , e03 = 'Console'
...
...
e01 = 'wmiprvse.exe', e02= '2448' , e03 = 'Console'
e01 = 'xtagent.exe', e02= '1432' , e03 = 'Console'
I really don't understand how the string split function works, because the array elements $line_arr[1], $line_arr[2],.. etc seems to be empty.
IMHO, the regex split function is ok, but the string split function is wrong.  

RE: How to do this in PowerShell

Now I understand: string split function splits by default only by one space, i.e the following code

CODE

$tl = tasklist | sort-object

foreach($line in $tl){
  echo $line
  # split line into array
  #$line_arr = [regex]::split($line,"\s+")
  $line_arr = $line.split(" ")
  # array elements
  $i=0
  foreach ($elem in $line_arr){
    echo "elem[$i] = $elem"
    $i++
  }
}
delivers this result

CODE

...
amswmagt.exe                1288 Console                 0      6.280 K
elem[0] = amswmagt.exe
elem[1] =
elem[2] =
elem[3] =
elem[4] =
elem[5] =
elem[6] =
elem[7] =
elem[8] =
elem[9] =
elem[10] =
elem[11] =
elem[12] =
elem[13] =
elem[14] =
elem[15] =
elem[16] = 1288
elem[17] = Console
elem[18] =
elem[19] =
elem[20] =
elem[21] =
elem[22] =
elem[23] =
elem[24] =
elem[25] =
elem[26] =
elem[27] =
elem[28] =
elem[29] =
elem[30] =
elem[31] =
elem[32] =
elem[33] =
elem[34] = 0
elem[35] =
elem[36] =
elem[37] =
elem[38] =
elem[39] =
elem[40] = 6.280
elem[41] = K
...
But I still don't understand this behaviour of the string split function.

For example using similar function in perl:  

CODE

$line="amswmagt.exe                1288 Console                 0      5.860 K";
@line_arr = split(" ", $line);
$i=0;
foreach my $elem (@line_arr) {
  printf "elem[%d] = %s\n", $i, $elem;
  $i++;
}
delivers this result

CODE

elem[0] = amswmagt.exe
elem[1] = 1288
elem[2] = Console
elem[3] = 0
elem[4] = 5.860
elem[5] = K

and Python delivers the same:

CODE

>>> s = "amswmagt.exe                1288 Console                 0      5.860 K"
>>> print s.split()
['amswmagt.exe', '1288', 'Console', '0', '5.860', 'K']

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close