Saturday, August 8, 2009

Unix / Linux find equivalent in Powershell Find-ChildItem Cmdlet

Find is one of the most often used commands in day to day work life. Unix find command provides lot of features and options that enable users to find files/directories more effectively

In Powershell, we can use Get-ChildItem cmdlet to search for files. But it doesn't give you all the fun. So I have developed Find-ChildItem Powershell cmdlet which is equivalent to Unix find command.

Download Find-ChildItem for both 32 bits and 64 bits

Note: For 64 bit operating system, you will have to use different InstallUtil.exe. See below for details

Syntax:
Find-ChildItem [-Name <String>] [-Type <String>] [-MaxDepth <Int32>] [-MinDepth <Int32>] [-CMin <String>]
[-AMin <String>] [-WMin <String>] [-CTime <String>] [-ATime <String>] [-WTime <String>] [-Size <String>]
[-Empty] [-Exec <String>] [-Delete] [-OutObject] [[-Path] <String>] [<CommonParameters>]

ParameterDescription
NameAccepts .Net regular expression to match FileName
Typed - directory, f - file
MaxDepthDescend at most levels (a non-negative integer) levels of directories below the command line arguments
MinDepthDo not apply any tests or actions at levels less than specified mindepth level (a non-negative integer)
CMinFile was created n minutes ago
CTimeFile was created n*24 hours ago
AMinFile was last accessed n minutes ago
ATimeFile was last accessed n*24 hours ago
WMinFile was last changed/written n minutes ago
WTimeFile was last changed/written n*24 hours ago
SizeFile uses n units of space
EmptyFile is empty
ExecExecute Cmdlets in the given argument.
DeleteDelete file or directory
OutObjectWrite Objects in output instead of just Directory/File Names


Find-ChildItem Cmdlet Installation Instructions:
  1. Extract Find-ChildItem.zip files to C:\Windows\Microsoft.NET\Framework\ Directory
  2. Open Powershell with Administrator Privileges
  3. Now, lets install the cmdlet using InstallUtil.exe utility which is available as part of Microsoft Windows SDK.

    For 32 Bit Operating System:
    C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe "C:\Windows\Microsoft.NET\
    Framework\Find-ChildItem.dll"
    For 64 Bit Operating System:
    C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe "C:\Windows\Microsoft.NET\
    Framework\Find-ChildItem.dll"
  4. Type Get-PSSnapin -Registered and press enter. If it displays FindChildItemPSSnapIn01 SnapIn, then our installation is successful
  5. Now, before we can use Find-ChildItem Cmdlet, we need to add FindChildItemPSSnapIn01 using Add-PSSnapin FindChildItemPSSnapIn01
  6. To permanently add the Snapin, Add-PSSnapin FindChildItemPSSnapIn01 Cmdlet need to be added to Windows Powershell Profile file
  7. See the below window, to get clear picture on Cmdlet Installation on Windows 7 32 Bits


PS C:\Users\Jagadish\> cd "C:\Windows\Microsoft.NET\Framework"
PS C:\Windows\Microsoft.NET\Framework> Get-ChildItem .\Find-ChildItem*

Directory: C:\Windows\Microsoft.NET\Framework

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 6/8/2009 1:13 PM 12288 Find-ChildItem.dll
-a--- 6/8/2009 1:14 PM 21298 Find-ChildItem.dll-Help.xml

PS C:\Windows\Microsoft.NET\Framework> C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe .\Find-ChildItem.dll
Microsoft (R) .NET Framework Installation utility Version 2.0.50727.3521
Copyright (c) Microsoft Corporation. All rights reserved.

Running a transacted installation.
.
.
.
The Commit phase completed successfully.

The transacted install has completed.

PS C:\Windows\Microsoft.NET\Framework> Get-PSSnapin -Registered

Name : FindChildItemPSSnapIn01
PSVersion : 2.0
Description : This is Powershell SnapIn that includes Find-ChildItem Cmdlet, developed by Jagadish <http://windows-powershell-scripts.blogspot.com/>

PS C:\Windows\Microsoft.NET\Framework> Add-PSSnapin FindChildItemPSSnapIn01

PS C:\Windows\Microsoft.NET\Framework> Find-ChildItem G:\Jagadish\Cmdlets
G:\Jagadish\Cmdlets\Test
G:\Jagadish\Cmdlets\Test\1
G:\Jagadish\Cmdlets\Test\1\2
G:\Jagadish\Cmdlets\Test\1\file2

If you don't have windows powershell profile file, follow the below steps to create a new one and add "Add-PSSnapin FindChildItemPSSnapIn01" entry to it


PS C:\Users\Jagadish\Desktop\Find-ChildItem> New-Item $profile -ItemType file -Force ; Write-Output "Add-PSSnapin FindChildItemPSSnapIn01" > $profile

Directory: C:\Users\Jagadish\Documents\WindowsPowerShell

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 6/8/2009 6:28 PM 0 Microsoft.PowerShell_profile.ps1


That's it. You added the Add-Snapin entry permanently. Now, Lets have some fun with new Find-ChildItem Cmdlet

List all the files and directories in the current directory


PS G:\Jagadish\Test> Find-ChildItem
G:\Jagadish\Test\Docs
G:\Jagadish\Test\Docs\101_Popular_Interview_Questions.doc
G:\Jagadish\Test\Docs\echosend_1500.c
G:\Jagadish\Test\Downloads
G:\Jagadish\Test\Downloads\VLC
G:\Jagadish\Test\Downloads\VLC\vlc-0.8.6-win32.exe
G:\Jagadish\Test\Downloads\VLC\vlc_src-0.8.5.tar.gz
G:\Jagadish\Test\Downloads\ethereal-setup-0.10.13.exe
G:\Jagadish\Test\Downloads\TeamViewer_Setup.exe
G:\Jagadish\Test\Songs
G:\Jagadish\Test\Songs\Green Day
G:\Jagadish\Test\Songs\Green Day\American Idiot- Boulevard Of Broken Dreams.mp3
G:\Jagadish\Test\Songs\akon-sorry.mp3
G:\Jagadish\Test\msvcp71.dll
PS G:\Jagadish\Test>

List ".exe" files only


PS G:\Jagadish\Test> Find-ChildItem -Type f -Name ".*.exe"
G:\Jagadish\Test\Downloads\VLC\vlc-0.8.6-win32.exe
G:\Jagadish\Test\Downloads\ethereal-setup-0.10.13.exe
G:\Jagadish\Test\Downloads\TeamViewer_Setup.exe
PS G:\Jagadish\Test>

Search for ".c" files only and display no of lines, words, characters in that file


PS G:\Jagadish\Test> Find-ChildItem -Type f -Name "\.c$" -Exec "Get-Content {} | Measure-Object -Line -Character -Word"

Lines Words Characters Property
----- ----- ---------- --------
162 500 3703

PS G:\Jagadish\Test>

You can use the below command to find Empty files in a directory and its sub directories


PS E:\Jagadish\Test> Find-ChildItem -Type f -Empty
E:\Jagadish\Test\Docs\Attachment
E:\Jagadish\Test\Docs\Report.txt
E:\Jagadish\Test\Docs\sample_logs
E:\Jagadish\Test\testing

Use -OutObject parameter to write file objects to powershell


PS E:\Jagadish\Test> Find-ChildItem -Type f -Empty -OutObject

Directory: Microsoft.PowerShell.Core\FileSystem::E:\Jagadish\Test\Docs

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 8/11/2009 10:16 PM 0 Attachment
-a--- 8/11/2009 10:16 PM 0 Report.txt
-a--- 8/11/2009 10:16 PM 0 sample_logs

Directory: Microsoft.PowerShell.Core\FileSystem::E:\Jagadish\Test

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 8/11/2009 10:16 PM 0 testing

Now, If we want to delete all the empty files, we can easily do that with the help of Find-ChildItem cmdlet
Find-ChildItem -Type f -Empty -Delete


PS E:\Jagadish\Test> Find-ChildItem -Type f -Empty -Delete
PS E:\Jagadish\Test> Find-ChildItem -Type f -Empty -OutObject
PS E:\Jagadish\Test>

Now, list all the files with size greater than 9 MB


PS E:\Jagadish\Test> Find-ChildItem -Type f -Size +9M -OutObject

Directory: Microsoft.PowerShell.Core\FileSystem::E:\Jagadish\Test\Downloads\VLC

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 12/13/2006 3:26 PM 9451515 vlc-0.8.6-win32.exe
-a--- 1/25/2007 3:00 PM 81510400 vlc-binary-fc4.tar.gz
-a--- 7/7/2006 5:46 PM 15680081 vlc-binary.tar.gz
-a--- 11/8/2006 5:45 PM 12461262 vlc_src-0.8.5.tar.gz

Directory: Microsoft.PowerShell.Core\FileSystem::E:\Jagadish\Test\Downloads

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 11/9/2006 7:24 PM 11348769 ethereal-setup-0.10.13.exe

If you want more details and usage information on this Find-ChildItem Cmdlet, type Get-Help Find-ChildItem -Full in your Powershell

Let me know if you need any other information or if you encounter any bugs/issues with Find-ChildItem Cmdlet

Saturday, July 4, 2009

Change to Previous Working Directory in Powershell (cd -)

One of the cool features of linux bash is the ability to go to the previous working directory. In Bash, we can go to the previous working directory using "cd -" command.

Unfortunately, we do not have an equivalent of "cd -" in Powershell. So I just wrote a simple powershell cd function for this cool feature

Powershell CD function:

1function cd {
2
3 if ($args[0] -eq '-') {
4 $pwd=$OLDPWD;
5 } else {
6 $pwd=$args[0];
7 }
8
9 $tmp=pwd;
10
11 if ($pwd) {
12 Set-Location $pwd;
13 }
14
15 Set-Variable -Name OLDPWD -Value $tmp -Scope global;
16}


Now lets see, how to install the above function in your powershell

Step 1: Remove Alias for cd

   cd is actually not a powershell cmdlet. It is an *alias* to Set-Location cmdlet. To install our new cd function, first we need to remove this alias


PS C:\Scripts> Get-Command cd

CommandType Name Definition
----------- ---- ----------
Alias cd Set-Location

PS C:\Scripts> Remove-Item Alias:cd
PS C:\Scripts>

Step 2: Install Powershell cd function

   We have removed the alias for cd. Now we can just go ahead and install our new powershell cd function which is very easy. Just paste the complete function in one line.

Powershell CD function in one line:


function cd { if ($args[0] -eq '-') { $pwd=$OLDPWD; } else { $pwd=$args[0]; } $tmp=pwd; if ($pwd) { Set-Location $pwd; } Set-Variable -Name OLDPWD -Value $tmp -Scope global; }



PS C:\Scripts> function cd { if ($args[0] -eq '-') { $pwd=$OLDPWD; } else { $pwd=$args[0]; } $tmp=pwd; if ($pwd) { Set-Location $pwd; } Set-Variable -Name OLDPWD -Value $tmp -Scope global; }
PS C:\Scripts>
PS C:\Scripts> Get-Item function:cd

CommandType Name Definition
----------- ---- ----------
Function cd if ($args[0] -eq '-') { $pwd=$OLDPWD; } else { ...

Ready to go, Lets see this cool feature in action


PS C:\Scripts> cd C:\Users\Jagadish\Desktop
PS C:\Users\Jagadish\Desktop> cd -
PS C:\Scripts> cd -
PS C:\Users\Jagadish\Desktop> cd ..\Documents
PS C:\Users\Jagadish\Documents> cd C:\Scripts
PS C:\Scripts> dir

Directory: C:\Scripts

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 6/6/2009 12:14 PM 279 test.ps1
-a--- 6/20/2009 8:27 PM 69 test1.ps1

PS C:\Scripts> cd -
PS C:\Users\Jagadish\Documents>

Hope you like it :)

Note: Powershell will not save any functions/aliases by default. So if you close your powershell and reopen it, this function will not be available. To make it permanent, it should be added in the Windows Powershell Profile file

Saturday, June 20, 2009

Unix Equivalents in Powershell

I come from Linux background which I really like . There are lot more utilities in Unix/Linux which provide more convenient way of doing some work. They are really very useful in speeding up the work and automating repetitive tasks.

Since the release of Windows Powershell, it has proven to be one of the most powerful shells available now.

As I started using Powershell, I find myself most of the times searching for UNIX equivalents in windows powershell. Here are a few which i came across

wc in Powershell: Measure-Object


[jagadish.g@localhost Scripts]$ cat test.csv | wc
4 13 277
[jagadish.g@localhost Scripts]$ cat test.csv | wc -l
4


PS C:\Scripts> Get-Content test.csv | Measure-Object -line -word -character

Lines Words Characters Property
----- ----- ---------- --------
4 13 273

PS C:\Scripts> Get-Content test.csv | Measure-Object -line

Lines Words Characters Property
----- ----- ---------- --------
4

time in Powershell: Measure-Command


[jagadish.g@localhost Scripts]$ time sleep 5

real 0m5.003s
user 0m0.000s
sys 0m0.001s


PS C:\Scripts> Measure-Command { Sleep 5 }

Days : 0
Hours : 0
Minutes : 0
Seconds : 4
Milliseconds : 999
Ticks : 49996681
TotalDays : 5.78665289351852E-05
TotalHours : 0.00138879669444444
TotalMinutes : 0.0833278016666667
TotalSeconds : 4.9996681
TotalMilliseconds : 4999.6681

GREP in Powershell: Select-String


[jagadish.g@localhost Scripts]$ cat test.csv | grep "Tony Passaquale"
1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up


PS C:\Scripts> Get-Content test.csv | Select-String "Tony Passaquale"

1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up

NOTE, Select-String is Case-Insensitive by default. Use -CaseSensitive switch parameter to make it case sensitive.

Now lets try to get one line after the line with the match


[jagadish.g@localhost Scripts]$ cat test.csv | grep -A1 "Tony Passaquale"
1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity


PS C:\Scripts> Get-Content test.csv | Select-String "Tony Passaquale" -Context 0,1

> 1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity

The -Context parameter in the Select-String cmdlet is used to capture the specified number of lines before and after the line with the match. If you look at the above code window, I have passed '0,1' value to the -Context parameter. The first integer specifies the number of lines to print before the match (in this case, it is 0) and the next integer specifies the number of lines to print after the match (in this case, it is 1)

Select-String cmdlet is using regular expression matching by default. So you can use use regex patterns to select the required lines.


[jagadish.g@localhost Scripts]$ cat test.csv | grep "y$"
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity
4,Allen James,95140,20090405 16:31:00,1000,9.99,9990,New-Opportunity


PS C:\Scripts> Get-Content test.csv | Select-String "y$"

2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity
4,Allen James,95140,20090405 16:31:00,1000,9.99,9990,New-Opportunity

AWK in Powershell

Powershell has lot of features and abilities for text parsing. AWK is one of very powerful commands available for text parsing in Unix/Linux. We do not have a Awk like cmdlet in Powershell. But we can do everything in Powershell that can be done with Awk.

Powershell combined with .Net Classes provide very powerful regular expressions for text parsing. read more...

cd - in Powershell

One of the cool features of linux bash is the ability to go to the previous working directory. In Bash, we can go to the previous working directory using "cd -" command.

Unfortunately, we do not have an equivalent of "cd -" in Powershell. So I just wrote a simple powershell function for this cool feature. read more...

find command in Powershell

Find is one of the most often used commands in day to day work life. Unix find command provides lot of features and options that enable users to find files/directories more effectively

In Powershell, we can use Get-ChildItem cmdlet to search for files. But it doesn't give you all the fun. So I have developed Find-ChildItem Powershell cmdlet which is equivalent to Unix find command. read more...

Saturday, June 13, 2009

Regular Expressions in Powershell

Regular Expressions are the most powerful pattern matching techniques available for text parsing. Almost all programming languages have regular expressions. Perl has very powerful regex engine and it provides more features.

Windows Powershell carries excellent regular expression support from .Net Framework

Regex Pattern matching in Powershell is so easy. We will go though some examples on Regular Expressions in Windows Powershell

Prerequisite: Some knowledge on regular expression would be good


PS C:\Scripts> 'Hello World' -match '^H'
True
PS C:\Scripts> 'ello World' -match '^H'
False

Powershell returns True if the match is found, otherwise False is returned

Let's see one more example


PS C:\Scripts> '2009-Jun-13' -match '\d{4}-[A-z]{3}-\d{2}'
True
PS C:\Scripts> '2009-June-13' -match '\d{4}-[A-z]{3}-\d{2}'
False

-replace operator is used for Search and Replace in Powershell


PS C:\Scripts> '2009-June-13' -replace "2009", "2010"
2010-June-13

How do you capture the pattern and use it in Search and Replace in Powershell? Lets see how,


PS C:\Scripts> '2009-Jun-13' -replace "(\d{4})-([A-z]{3})-(\d{2})", "$2 $3 $1"

PS C:\Scripts> '2009-Jun-13' -replace "(\d{4})-([A-z]{3})-(\d{2})", '$2 $3 $1'
Jun 13 2009

In Search and Replace, Powershell stores captured patterns in special variables $1, $2, etc. But if you use those special variables inside double-quoted replacements, they will be considered as normal variables. That's the reason, we didn't get expected result in first statement in the above code window. To make it work, you need to use single-quoted replacements like above.

To get more idea on this, let's see another example


PS C:\Scripts> $1="How"
PS C:\Scripts> $2="are"
PS C:\Scripts> $3="you"
PS C:\Scripts>
PS C:\Scripts> '2009-Jun-13' -replace "(\d{4})-([A-z]{3})-(\d{2})", "$2 $3 $1"
are you How
PS C:\Scripts> '2009-Jun-13' -replace "(\d{4})-([A-z]{3})-(\d{2})", '$2 $3 $1'
Jun 13 2009

Now let's see how to use captured patterns with -match operator. If you capture patterns using -match, unlike Search and Replace, the captured patterns will be stored in a special array variable called $matches.


PS C:\Scripts> '2009-Jun-13' -match '(\d{4}).*'
True
PS C:\Scripts> $matches

Name Value
---- -----
1 2009
0 2009-Jun-13

PS C:\Scripts> $matches[1]
2009
PS C:\Scripts>

Regular Expressions in Powershell are case-insensitive by default. For case-sensitive pattern matching, we can use the following operators

1. -cmatch
2. -creplace


PS C:\Scripts> 'HELLO' -match '[A-Z]'
True
PS C:\Scripts> 'HELLO' -match '[a-z]'
True
PS C:\Scripts>
PS C:\Scripts> 'HELLO' -cmatch '[A-Z]'
True
PS C:\Scripts> 'HELLO' -cmatch '[a-z]'
False
PS C:\Scripts>

Saturday, June 6, 2009

AWK equivalent in Windows Powershell

Powershell has lot of features and abilities for text parsing. AWK is one of very powerful commands available for text parsing in Unix/Linux. We do not have a Awk like cmdlet in Powershell. But we can do everything in Powershell that can be done with Awk.

Powershell combined with .Net Classes provide very powerful regular expressions for text parsing.

Now, lets play with Bash Awk and Powershell. I'm going to create a test.csv file for our testing and use that through out this topic.

Content of test.csv for our testing

1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity
3,Selma Cooper,97455,20090405 16:31:00,1000,9.99,9990,Pre-Approach
4,Allen James,95140,20090405 16:31:00,1000,9.99,9990,New-Opportunity


So, Lets jump in

Display second field in test.csv


[jagadish.g@localhost Scripts]$ cat test.csv | awk -F, '{print $2}'
Tony Passaquale
Nigel Shan Shanford
Selma Cooper
Allen James


PS C:\Scripts> Get-Content .\test.csv | %{ $_.Split(',')[1]; }
Tony Passaquale
Nigel Shan Shanford
Selma Cooper
Allen James

Now, lets try getting the total value of third field in all the records in test.csv


[jagadish.g@localhost Scripts]$ cat test.csv | awk -F, '{total+=$3} END {print "Total: "total}'
Total: 230831


PS C:\Scripts> Get-Content .\test.csv | %{ [int]$total+=$_.Split(',')[2]; } ; Write-Host "Total: $total"
Total: 230831

Get no of fields in each record


[jagadish.g@localhost Scripts]$ cat test.csv | awk -F, '{print "No of fields in record "$1" = "NF }'
No of fields in record 1 = 8
No of fields in record 2 = 8
No of fields in record 3 = 8
No of fields in record 4 = 8


PS C:\Scripts> Get-Content .\test.csv | %{ $a=$_.Split(','); Write-Host "No of fields in record"$a[0]"="$a.length; }
No of fields in record 1 = 8
No of fields in record 2 = 8
No of fields in record 3 = 8
No of fields in record 4 = 8

Regular Expression matching in Awk and Powershell. Print a record if the last field contains any of these lowercase characters (a, b or c)


[jagadish.g@localhost Scripts]$ cat test.csv | awk -F, '{if ($NF ~ "[a-c]") print}'
3,Selma Cooper,97455,20090405 16:31:00,1000,9.99,9990,Pre-Approach


PS C:\Scripts> Get-Content .\test.csv | %{ if ($_.Split(',')[-1] -match "[a-c]") { $_; } }
3,Selma Cooper,97455,20090405 16:31:00,1000,9.99,9990,Pre-Approach

Monday, June 1, 2009

Working with Registry in Powershell

Microsoft has made registry accessing very simple using powershell. You can access the system registry just like any other drive in powershell.

For example, you can easily list all the registry entries in HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry key with Get-ItemProperty cmdlet


PS C:\> cd HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run> Get-ItemProperty .

RTHDCPL : RTHDCPL.EXE
Alcmtr : ALCMTR.EXE
IgfxTray : C:\WINDOWS\system32\igfxtray.exe
HotKeysCmds : C:\WINDOWS\system32\hkcmd.exe
Persistence : C:\WINDOWS\system32\igfxpers.exe

PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run>

You can add a new entry to registry key using New-ItemProperty cmdlet

I have just added a entry to HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run to autostart notepad.exe on the windows boot-up


PS C:\> New-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -name "Notepad" -value "C:\WINDOWS\NOTEPAD.EXE" -type string

Notepad
-------
C:\WINDOWS\NOTEPAD.EXE

PS C:\> Get-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

RTHDCPL : RTHDCPL.EXE
Alcmtr : ALCMTR.EXE
IgfxTray : C:\WINDOWS\system32\igfxtray.exe
HotKeysCmds : C:\WINDOWS\system32\hkcmd.exe
Persistence : C:\WINDOWS\system32\igfxpers.exe
Notepad : C:\WINDOWS\NOTEPAD.EXE

As you might have noticed in the above code window, i have used PropertyType as 'String'. Below is the list of PropertyType Values available for Registry Entries

PropertyType ValueMeaning
BinaryBinary data
DWordA number that is a valid UInt32
ExpandStringA string that can contain environment variables that are dynamically expanded
MultiStringA multiline string
StringAny string value
QWord8 bytes of binary data

A registry entry can be removed from a registry key with the help of Remove-ItemProperty cmdlet


PS C:\> Remove-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -name "Notepad"
PS C:\> Get-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

RTHDCPL : RTHDCPL.EXE
Alcmtr : ALCMTR.EXE
IgfxTray : C:\WINDOWS\system32\igfxtray.exe
HotKeysCmds : C:\WINDOWS\system32\hkcmd.exe
Persistence : C:\WINDOWS\system32\igfxpers.exe

Sunday, May 3, 2009

How to run windows powershell scripts

Running Powershell Scripts on local machine is so easy. You just need to change ExecutionPolicy in the Powershell. Powershell Execution Policies are used to prevent unauthorized scripts from running. They provide security for the scripting environment.

In Unix-like machines, we need to set the executable bit for shell scripts to run them (chmod +x <scriptname>)

Windows Powershell Execution Policies


Restricted
- Default execution policy.
- Permits individual commands, but scripts cannot
run.

AllSigned
- Scripts can run.
- Requires a digital signature from a trusted
publisher on all scripts and configuration files,
including scripts that you write on the local
computer.
- Prompts you before running scripts from trusted
publishers.
- Risks running signed, but malicious, scripts.

RemoteSigned
- Scripts can run.
- Requires a digital signature from a trusted
publisher on scripts and configuration files that
are downloaded from the Internet (including
e-mail and instant messaging programs).
- Does not require digital signatures on scripts run
from the local computer.
- Does not prompt you before running scripts from
trusted publishers.
- Risks running signed, but malicious, scripts.

Unrestricted
- Unsigned scripts can run.
- Scripts and configuration files that are downloaded
from the Internet (including Microsoft Outlook,
Outlook Express and Windows Messenger) run after
warning you that the file originated on the Internet.
- Risks running malicious scripts.

For us to learn, we will use the ExecutionPolicy "RemoteSigned" to run Powershell scripts without digital signatures on the local machine.

I have written a script to display first 5 running services. Let's see how to run that script (List_5_Running_Services.ps1)


PS C:\Users\Jagadish\Documents\Scripts> Get-ExecutionPolicy
Restricted

PS C:\Users\Jagadish\Documents\Scripts> Get-Content List_5_Running_Services.ps1
Get-Service | Where-Object { $_.Status -eq "Running" } | Select-Object -First 5

PS C:\Users\Jagadish\Documents\Scripts> .\List_5_Running_Services.ps1
File C:\Users\Jagadish\Documents\Scripts\List_5_Running_Services.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.
At line:1 char:14
+ .\Testing.ps1 <<<<
+ CategoryInfo : NotSpecified: (:) [], PSSecurityException
+ FullyQualifiedErrorId : RuntimeException

PS C:\Users\Jagadish\Documents\Scripts>

As you can see in the above code, the current ExecutionPolicy is "Restricted". "Restricted" ExecutionPolicy is the most secure policy, and is the default. It permits individual commands, but does not permit scripts to run.

So to run our scripts without digital signatures, we need to change it to "RemoteSigned" Policy.


PS C:\Users\Jagadish\Documents\Scripts> Get-ExecutionPolicy
Restricted
PS C:\Users\Jagadish\Documents\Scripts> Set-ExecutionPolicy RemoteSigned
Set-ExecutionPolicy : Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell' is denied.
At line:1 char:20
+ Set-ExecutionPolicy <<<< RemoteSigned
+ CategoryInfo : NotSpecified: (:) [Set-ExecutionPolicy], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand

PS C:\Users\Jagadish\Documents\Scripts>

If you get the above error while changing ExecutionPolicy to RemoteSigned, then probably you are running the Windows Powershell without Administrator Privileges. You can easily start Windows Powershell with Administrator Privilege just by right-clicking on the Powershell icon and selecting "Run as Administrator" as shown in below picture

Users running Windows XP or Windows Server 2003, may not get the above error as most users login with administrative privileges. In Windows Vista/7, this changed with the advent of User Account Control. Unless explictly requested, processes started by an Administrator account will run as a standard user and not Administrator.



After starting Windows Powershell with Administrator Privileges, lets try changing the ExecutionPolicy and running the script


PS C:\Users\Jagadish\Documents\Scripts> Get-ExecutionPolicy
Restricted
PS C:\Users\Jagadish\Documents\Scripts> Set-ExecutionPolicy RemoteSigned
PS C:\Users\Jagadish\Documents\Scripts> Get-ExecutionPolicy
RemoteSigned

PS C:\Users\Jagadish\Documents\Scripts> .\List_5_Running_Services.ps1

Status Name DisplayName
------ ---- -----------
Running AntiVirSchedule... Avira AntiVir Scheduler
Running AntiVirService Avira AntiVir Guard
Running Appinfo Application Information
Running AudioEndpointBu... Windows Audio Endpoint Builder
Running Audiosrv Windows Audio

PS C:\Users\Jagadish\Documents\Scripts>


More details can be found in http://www.microsoft.com/technet/scriptcenter/topics/winpsh/manual/run.mspx

Let me know if you have any questions or comments please