Saturday, May 30, 2015

#76 : Using Choice Box in Powershell

I got an interesting requirement to allow users choose from a list. The list will be dynamic and will display all items of the file in a drop down list.

Preparation:
1. Create an empty file called list.txt.
2. Add below entries to the file:
ABC
XYZ
PQR
RST
UVX
123
3. Create script and paste below code:

function showDialog([string]$file) 
{
 [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
 [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 

 $objForm = New-Object System.Windows.Forms.Form 
 $objForm.Text = "Choice-Box"
 $objForm.Size = New-Object System.Drawing.Size(300,200) 
 $objForm.StartPosition = "CenterScreen"

 $objForm.KeyPreview = $True
 $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
  {
   $x=$objListBox.SelectedItem;$objForm.Close()}
  })
  
 $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
  {$objForm.Close()}})

 $OKButton = New-Object System.Windows.Forms.Button
 $OKButton.Location = New-Object System.Drawing.Size(75,120)
 $OKButton.Size = New-Object System.Drawing.Size(75,23)
 $OKButton.Text = "OK"
 $OKButton.Add_Click({$x=$objListBox.SelectedItem;$objForm.Close()})
 $objForm.Controls.Add($OKButton)

 $CancelButton = New-Object System.Windows.Forms.Button
 $CancelButton.Location = New-Object System.Drawing.Size(150,120)
 $CancelButton.Size = New-Object System.Drawing.Size(75,23)
 $CancelButton.Text = "Cancel"
 $CancelButton.Add_Click({$objForm.Close()})
 $objForm.Controls.Add($CancelButton)

 $objLabel = New-Object System.Windows.Forms.Label
 $objLabel.Location = New-Object System.Drawing.Size(10,20) 
 $objLabel.Size = New-Object System.Drawing.Size(280,20) 
 $objLabel.Text = "Please choose any of the below :"
 $objForm.Controls.Add($objLabel) 

 $objListBox = New-Object System.Windows.Forms.ListBox 
 $objListBox.Location = New-Object System.Drawing.Size(10,40) 
 $objListBox.Size = New-Object System.Drawing.Size(260,20) 
 $objListBox.Height = 80

 $items = gc $file | where { $_ -ne "" }
 
 foreach ( $item in $items) 
 {
  [void] $objListBox.Items.Add($item)
  
 } 

 $objForm.Controls.Add($objListBox) 

 $objForm.Topmost = $True

 $objForm.Add_Shown({$objForm.Activate()})
 [void] $objForm.ShowDialog()

 $x

} 


showDialog .\list.txt 


Once your run it, you will get a popup like below:


That's it! You can see the value of $x can be used further in any place of your code.

Hope you liked this article. Send your comments and suggestions to me...
Enjoy!

Friday, May 29, 2015

#75 : How to run Powershell scripts from network location (UNC Path)?

In most of the cases, people ask questions if they can run the Powershell scripts from network location which is shared on multiple machines.

At first sight,  I would not suggest to do it as this is not recommended to run unsigned scripts, but requirement is always a requirement and I have seen people debating in a long mail chain when I say that something is not possible. Sometimes whole group is fighting with me one after another and using google search and all options to make me accept. Believe me, I don't believe in too much argument on any topic, but still I don't like to accept something which cannot be done or something which cannot be done perfectly.

I believe in correct usage of any technology, arguments and debates are other areas are not my areas of expertise. Anyways, for those who have been forced to do something and for those who has to do something because it has to be done.

You can use -ExecutionPolicy "Bypass" in the command line. Something like this :

For example, if you have script located at abc server's c:\abc.ps1, you can run statement like this:
Powershell.exe -ExecutionPolicy bypass \\abc\c$\abc.ps1

This will not ask any questions or input. Keep all such shared script at central location, create a share or map a drive, do whatever suits your environment.

Hope, you liked this article. Please do sent your suggestions and advises.

 

Thursday, May 28, 2015

#74 : How to get IP address from Host Name using Powershell?

There are multiple ways to get it. Some will suggest using ping.exe also. But below is the tested and clean approach to do it.

Replace your host name below and test it at your end :

function GetIPAddress([string] $HostName) 
{
 trap {
  return 0 
 }
 $IP_ADDRESS=$([System.Net.Dns]::GetHostAddresses("$HostName")).IPAddressToString
 return $IP_ADDRESS 

} 

echo $(GetIPAddress "ABCHOSTNAME")


Hope you like this tip, do write your comments and suggestions.
Life is good!

Wednesday, May 27, 2015

#73 : How to list all files in current directory and subdirectories using Powershell?

Sometimes, we need to work with numerous files located in certain location. We might need to perform some action or read some lines with those files. When the requirement is all about reading all files in directory and sub-directories, we can simply use ls in Powershell. (Run Get-Alias ls to know which cmdlet is called in background, skipping this so that you learn something more, those who know this can avoid it ;))

Every experiment starts with a small building block, so let's run ls with recursion :

ls -recurse


You see multiple directories, but this is not useful as you don't have much option to perform any task on them.

    Directory: B:\tst

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         5/26/2015   6:08 AM            A
d----         5/26/2015   6:09 AM            B
-a---         5/26/2015   6:09 AM          0 file4.txt
-a---         5/26/2015   6:09 AM          0 file5.txt

    Directory: B:\tst\A

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         5/26/2015   6:08 AM          0 file1.txt

    Directory: B:\tst\B

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         5/26/2015   6:09 AM          0 file2.txt
-a---         5/26/2015   6:09 AM          0 file3.txt


Now, run the same command with little twist and then you will be able to much from output :

ls -Recurse | foreach { $_.FullName  }

The result is full list of files and you can perform more precise operations on them.
B:\tst\A
B:\tst\B
B:\tst\file4.txt
B:\tst\file5.txt
B:\tst\A\file1.txt
B:\tst\B\file2.txt
B:\tst\B\file3.txt

But, if you see the output above, you can see that directories are also there,  but your requirement might be only related with files or directories. So, let's get separate results for them.

List all Files recursively :
ls -Recurse | where { $_.PSIsContainer -eq $false } |  foreach { $_.FullName }

Output:
B:\tst\file4.txt
B:\tst\file5.txt
B:\tst\A\file1.txt
B:\tst\B\file2.txt
B:\tst\B\file3.txt

List all directories recursively :
ls -Recurse | where { $_.PSIsContainer -eq $true } |  foreach { $_.FullName }

Output:
B:\tst\A
B:\tst\B

So, this concludes today's tip. Always start with small example and keep trying till you get the results. Send your mails and comments and let me know if you have questions.

Enjoy!


 

Tuesday, May 26, 2015

#72 : How to run a program with different credential in Powershell?

There are multiple ways to achieve it. I will suggest using a Get-Credential cmdlet to get the credential and use start-process to run the script or program of your choice. You can also use invoke-command for this purpose to run commands on remote machines of you network, but the approach is not advisable when WinRM is not enabled and I don't want to make it complicated.

So, let's take a look on the script and then we will see how it runs :

$c=Get-Credential
Start-Process c:\windows\notepad.exe -Credential $c

When you run the two lines above, you see a popup which asks your credentials :


Enter credential and then you will see the notepad.exe running with that credential.

This may help you if you are making a program which requires special credentials at some point and user can enter the login and password. Good for any interactive script only. We can also save the credentials and use that. We will see that in next article, till then enjoy!

Wednesday, May 13, 2015

#71 : Pause a Powershell Script

Sometimes, we need to pause scripting where any asynchronous operation is in progress or we have to wait for some file to appear. In all such cases, Start-Sleep can help you achieve that. Let's take a look into syntax and then we will use the same in our example :

Syntax:
Start-Sleep -Milliseconds <int> [<CommonParameters>]
Start-Sleep [-Seconds] <int> [<CommonParameters>]


Example:
Pause the script for 5 seconds:
Start-Sleep -Seconds 5

 

Tuesday, May 12, 2015

#70 : Show statistical information using Powershell

Today' we will talk about Measure-Object cmdlet which helps you peforming average, max, min and other operations. Before we perform some tests, we need to create a file with some data. My file is as follows :

name,age
Som,25
Ravi,30
Akash,60
Jack,89
John,16


Save the above as file.csv. You can use below command to see the statistics :

import-csv C:\engg.demo\file.csv | measure-object age -ave -max -min

Output:
Count    : 3
Average  : 38.3333333333333
Sum      :
Maximum  : 60
Minimum  : 25
Property : age


In measure-object, we mentioned the column name against which you want to run certain operation. After that, you can mention from below :
-ave : Average
-min : Min
-max : Max
-sum : Sum

Enjoy scripting!!

 

Sunday, May 10, 2015

#69 : Formatted output from a number with decimal using Powershell

Sometimes, we need to produce formatted output from a number with decimals. If the output has to be in a designated formatted such as till two places after decimals, we can simply format them using below. It helps specifying the precision correctly :

Below is the function to help you in setting precision till whatever places of decimal you want. If number is limited to only two digits after decimal, it will add zero as suffix, so this might help in some other cases also where you want to show result in money.

Please check the Gist below :



There are several other ways to do it, but I found it more flexible.
Enjoy scripting !!

Saturday, May 9, 2015

#68 : Understanding Try-Catch-Finally Blocks in Powershell

Try-Catch-Finally is language construct introduced in Powershell v2.0. It provides option to error handling in an elegant manner. While a faulty code might stop flow of your code, Try-Catch can be used to handle some of the obvious errors. For example, if you are writing to a file and suddenly disk got full, your script will fail miserably and error could be trapped further. The script will proceed further without having finishing pervious operation correctly. In a simple language, we can say that Try-Catch gives option to handle errors during runtime without impacting the desired flow of script.

(There are so many big articles written on this subject, this article is just a jump start. My intention is not re-invent the wheel.)


Below is a simple example using this language construct :
(It will run a divide-by-error operation and cause failure. The error will be forwarded on screen)



Enjoy developing Powershell scripts!




 

Friday, May 8, 2015

#67 : Get Windows Operating System Name and Version

Sometimes, we need to know the Operating system name and version for troubleshooting and sometimes we need to run specific code for specific version. With Powershell, this is very simple.

$OS_VERSION=$(Get-WmiObject -Class Win32_OperatingSystem).Version
$OS_NAME=$(Get-WmiObject -class Win32_OperatingSystem).Caption

echo "Version : $OS_VERSION"
echo "Version : $OS_NAME"


Hope, this was simple and useful for your scripts.
Enjoy scripting!!

Thursday, May 7, 2015

#66 : Formatted Date and Time Output

Mostly, in course of scripting, we need to display date and time in a qualified format. The format depends on the requirement suggested. Such as, your script log will have timestamp in a format like LOG_201505150732.log, but inside log, you timestamp might be set as 2015-05-15 07:32:03. Based on purpose, we use time in different ways.

Powershell does not require much more effort in playing with format. It is more straight forward than anything in Powershell. Simply, remember the table below to set the format :

SpecifierTypeExample Example Output
ddDay{0:dd}10
dddDay name{0:ddd}Tue
ddddFull day name{0:dddd}Tuesday
f, ff, …Second fractions{0:fff}932
gg, …Era{0:gg}A.D.
hh2 digit hour{0:hh}10
HH2 digit hour, 24hr format{0:HH}22
mmMinute 00-59{0:mm}38
MMMonth 01-12{0:MM}12
MMMMonth abbreviation{0:MMM}Dec
MMMMFull month name{0:MMMM}December
ssSeconds 00-59{0:ss}46
ttAM or PM{0:tt}PM
yyYear, 2 digits{0:yy}02
yyyyYear{0:yyyy}2002
zzTimezone offset, 2 digits{0:zz}-05
zzzFull timezone offset{0:zzz}-05:00
:Separator{0:hh:mm:ss}10:43:20
/Separator{0:dd/MM/yyyy}10/12/2002


Using toString() function, you can do all kinds of formatting you want.

For example, if you have to get the timestamp for a log file, use below :
$FILE_NAME="ABC_$($(get-date).toString("yyyyMMddhhmmss")).log"

If you want to output the time in log file, it must be little more readable. Such as below :
$MSG="$($(get-date).toString("yyyy/MM/dd HH:mm:ss" )) : Program Started"

There are lot many experiments possible with it. This is simple, yet effective way to handle time.
Enjoy scripting!!
 

Tuesday, May 5, 2015

#11 : PowerGUI : A great tool!

-- Still writing this article, I would come up with full details about PowerGUI. The tool is really interesting and I may also include a video on it.

Sorry for making you wait.. Please wait for sometime...

Monday, May 4, 2015

#65 : Error-Handling with Trap

In v1.0 of Windows Powershell, there was no Try-Catch-Finally feature. We had trap construct for the same purpose. I think, Trap was a new concept as it was not there in any of the existing .NET-based languages. But Powershell v1.0 somehow had this unusual feature. In most of the old machines, there will be Powershell v1.0 and we cannot use Try-Catch blocks for those servers. So if you are writing script for all versions of Windows, there is no option left except using Trap.

Let us see the Trap example below :



The above example will call two divide statement which will end up with divide-by-zero. There are two blocks where trap is declared :
1. At script level
2. At function level

You will notice that output will call Function level when it will fail inside function block and it will call script level trap when called outside function.

Hope this simple example will make you learn this correctly. Please send me your questions and suggestion if you have any. Learning from small example is always better if you want to understand something correctly.

That's it for today! Thanks for reading today and keep reading this blog which is updated everyday.


Sunday, May 3, 2015

Tool #4 : Powershell ISE with Powershell v4.0

Powershell ISE comes bundled with Powershell. The editor was useful in previous versions also, but version 4.0 comes with collapsing and expanding of functions and statement blocks. This is very important to have big functions collapsed as it avoids so much scrolling back and forth. Also, it makes script more readable if you are just reviewing someone's code. Syntax highlighting and Intellisense have already been there.

So, those who have not used it for some reasons. I would request them to give a try on this tool. If you do not see it in your newly installed Windows 2008 or 2012, you can try to add it from features.


Remarkable Features:

1. Intellisense feature
2. East of Debugging Code using Breakpoints
3. Collapsing and Expanding of blocks
4. Code and Output windows switching
5. Familiar shortcuts used in all Microsoft products such as F5 etc.

Below are some items which are missing in this version, hope Microsoft will add in future releases :
1. Script parameter passing is not possible.
2. There is no scope of writing GUI based tools.

If you find something interesting about this tool, please let me know.


 

Saturday, May 2, 2015

#64 : Backup Report Server Encryption Key

Report server encryption key is essential in recovering, migrating and troubleshooting. Although, we generally backup it when report server is built, but it is required to take backup time-to-time to avoid any miss-out. Scheduling a SQL Server job on the SQL Server will be sufficient and we can schedule it to run once a week.

Below is a simple Powershell script which can help you scheduling such a job :



You can schedule the job with Powershell subsystem or CMDExec subsystem depending on the standard followed in your organization.

Thanks for reading this article! Please do update me if you have issues running it.



Friday, May 1, 2015

#63 : Open Control Panel Items with Powershell

I don't see any purpose of opening control panel items. I expect you may need if you are something interactive which requires users to set something.

To open the Folder Options:
Show-ControlPanelItem -Name "Folder Options"


To open Internet Options: 
Show-ControlPanelItem -Name "Internet Options"


To open Firewall Settings:
Show-ControlPanelItem -Name "Windows Firewall"


There could be many such items in your control panel which differ from one computer to another. If you want to know the list of control panel items, use the below command :

Get-ControlPanelItem

This will take at least few seconds to get the results. You can play as much these controls.

I would suggest not to use the graphical controls if you are running any automated script which runs with scheduled task or SQL Server job. This may call the program in memory for so long. Such programs can be killed from Task manager or Powershell if started accidentally.

Hope you liked this article! We will see a new article tomorrow.
 

#112: How to handle xml document in Powershell?

 In PowerShell, you can handle XML data using various cmdlets and methods provided by the .NET Framework. Here's a basic guide on how to...