Archive

Posts Tagged ‘Script of the day’

Script of the Day – Creating AD groups without QAD cmdlets

February 10th, 2011 No comments

We’re automating some server builds and need to create AD groups to manage resource access to each Server (company policy)
We use SCCM for deployment and I wanted to automate the groups (at build time)
Also, I did not want to have any dependencies on external Modules (so I want to do this without the quest tools)

I found a few documents online for creating AD groups that went without the quest tools, but found that most did not work.

You see, our key problem was that we wwanted to create Domain Local Security Groups.
In VBScript, this was pretty simple, as on the ‘put’ portion of group creation, you just told the script to apply both Group type constants, using an or statement.
The theory was that this would work in Powershell too (and many online script seemed to indicate that it would) – but the group types being created were inconsistent.

Below are the constants for the different group types:

Value GroupType
2 Global distribution group
4 Domain local distribution group
8 Universal distribution group
-2147483646 Global security group
-2147483644 Domain local security group
-2147483640 Universal security group

So creating a Domain Local Security group is as simple as:

$groupType = -2147483644
$objOU = [ADSI]"LDAP://localhost:389/OU=YourOUName,DC=Example,DC=com"
$GroupName = "MyNewGroup"
$objGroup = $objOU.Create("group", "CN=" + $GroupName)
$objGroup.Put("groupType", $groupType )
$objGroup.Put("sAMAccountName", $GroupName )
$objGroup.SetInfo()

Of course you can change the LDAP binding to a DC (rather than localhost) and you can change the GroupType by amending the value of $GroupType
Even better, you could wrap it into a Function, with a switch statement to take care of Group type selection.

Happy days.

Monitoring VM Logs – Nearly real time monitoring – Script of the day

February 9th, 2011 No comments

Today’s Script of the day is not one of my own, but one I have used a few times in the past few weeks – and I figured I should post here as a reminder for when I next need it.

Written by the scripting wizard LucD, it is a tool that basicall ymonitors and displays VM logs . . almost as they happen.

http://www.lucd.info/2010/10/08/nearly-real-time-monitoring/

A great and very effective script for troubleshooting realtime VM issues.

Script of the Day – shutdown your VMware ESX estate with PowerCLI

February 7th, 2011 No comments

The following script is straight from
http://www.virtu-al.net/2010/01/06/powercli-shutdown-your-virtual-infrastructure/

I have used it a few times and it is very effective and easy to use.


Connect-VIServer MyVIServer

# Get All the ESX Hosts
$ESXSRV = Get-VMHost

# For each of the VMs on the ESX hosts
Foreach ($VM in ($ESXSRV | Get-VM)){
# Shutdown the guest cleanly
$VM | Shutdown-VMGuest -Confirm:$false
}

# Set the amount of time to wait before assuming the remaining powered on guests are stuck
$waittime = 200 #Seconds

$Time = (Get-Date).TimeofDay
do {
# Wait for the VMs to be Shutdown cleanly
sleep 1.0
$timeleft = $waittime - ($Newtime.seconds)
$numvms = ($ESXSRV | Get-VM | Where { $_.PowerState -eq "poweredOn"}).Count
Write "Waiting for shutdown of $numvms VMs or until $timeleft seconds"
$Newtime = (Get-Date).TimeofDay - $Time
} until ((@($ESXSRV | Get-VM | Where { $_.PowerState -eq "poweredOn" }).Count) -eq 0 -or ($Newtime).Seconds -ge $waittime)

# Shutdown the ESX Hosts
$ESXSRV | Foreach {Get-View $_.ID} | Foreach {$_.ShutdownHost_Task($TRUE)}

Write-Host ";Shutdown Complete"

BE WARNED – IF YOU TEST THIS ON YOUR LIVE ENVIRONEMT, YOU’RE GOING TO GET IN TROUBLE!!!!

Script of the Day – import all VMs from a Datastore to VMWare ESX / ESXi

February 3rd, 2011 No comments

So your DC fell over . . but you have a copy of all your vmdks etc and would like to import them to a new ESX host . .

The following script will run you through a series of prompt and then import all VMs from a DS to the specified ESX cluster


# Code by Alan van Wyk
# This script prompts for a Cluster and a Datastore and imports all VMs from the DS to the Cluster (to be used in DR emergencies etc)

# Simple function to tidy display at prompt screen
Function Selections () # Refresh screen at top of page, shows user selections
{
cls
cls
Write-Host ("Virtual Center: ") -ForegroundColor Blue -NoNewLine; Write-Host (" " + $vc)
Write-Host ("Destination Data Center: ") -ForegroundColor Blue -NoNewLine; Write-Host (" "  + $DC2)
Write-Host ("Destination Cluster: ") -ForegroundColor Blue -NoNewLine; Write-Host (" "  + $Cluster2)
Write-Host ("Destination Datastore: ") -ForegroundColor Blue -NoNewline; Write-Host (" "  + $Datastore2)
Write-Host
}
Function quit #quits script
{
exit
}
Function Pause ($Message="Press any key to continue...") #pause and wait for user to hit key to continue
{
Write-Host -NoNewLine $Message
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Write-Host ""
}

$vc = Read-Host "Please specify your Virtual Center"
Write-Host "Connecting to Virtual Center... "
 Connect-VIServer $vc

selections
#Select DC
 $x = @(0) * 20 # initialize the array
 $i=0 # intialize the indexer
 Get-Datacenter `
 | select -first 20 `
 | % { $x[$i]=$_.Name; "{0} {1}" -f $i++, $_.Name } # store the DCs into an array and display the array
 Write-Host ("`n Please select Destination DataCenter from index above:`n") -ForegroundColor Yellow -BackgroundColor Red
 $index = read-host index # ask for an index
 $dc2 = $x[$index] # select index

 Selections
 # Select cluster
 $x = @(0) * 20 # initialize the array
 $i=0 # intialize the indexer
 Get-Datacenter $dc2    | Get-Cluster `
 | select -first 20 `
 | % { $x[$i]=$_.Name; "{0} {1}" -f $i++, $_.Name } # store the Clusters into an array and display the array
 Write-Host ("`n Please select Destination Cluster from index above:`n")    -ForegroundColor Yellow -BackgroundColor Red

 $index = read-host index # ask for an index
 $Cluster2 = $x[$index] # select index
 Selections

 $x = @(0) * 20 # initialize the array
 $i=0 # intialize the indexer
 get-cluster $cluster2 | get-vmhost | Get-Datastore `
 | select -first 20 `
 | % { $x[$i]=$_.Name; "{0} {1}" -f $i++, $_.Name } # store the Datastores into an array and display the array
 Write-Host ("`n Please select Destination Datastore from index above:`n")    -ForegroundColor Yellow -BackgroundColor Red
 $index = read-host index # ask for an index
 $Datastore2 = $x[$index] # select index
 Selections

 #Prompt for confirmation

 $confirmation = Read-Host "Type CONTINUE to confirm that you would like to import all VMs from $Datastore2 to $cluster2"
 If ($confirmation -cne "CONTINUE")
 {
 Write-Host ("Settings not confirmed - disconnecting from Virtual Center") -BackgroundColor Red -ForegroundColor Yellow
 disconnect-viserver -confirm:$false
 Pause
 Quit
 }

 $dsname = $Datastore2
 $datacenter = $dc2
 $cluster = $cluster2

#####################################################################################################
# Code below by LucD

$ESXname = Get-Cluster $cluster | Get-VMHost | select -First 1
$dsBrowser = Get-View (Get-View (Get-VMHost -Name $ESXname).ID).DatastoreBrowser
$folder = Get-View (Get-Datacenter -Name $datacenter | Get-Folder -Name "vm").ID
$pool = Get-View (Get-Cluster -Name $cluster | Get-ResourcePool -Name "Resources").ID
cls

foreach($dsImpl in $dsBrowser.Datastore){
 $ds = Get-View $dsImpl
 if($ds.Summary.Name -ne $dsname){continue}

 $datastorepath = "[" + $ds.Summary.Name + "]"

 $searchspec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
 $searchSpec.matchpattern = "*.vmx"

 Write-Host "Searching in path" $datastorepath

 $task = Get-View ($dsBrowser.SearchDatastoreSubFolders_Task($datastorePath, $searchSpec))
 while ($task.Info.State -eq "running" -or $task.Info.State -eq "queued"){
 $task.UpdateViewData()
 sleep 5
 }
 if($task.info.result -ne $null){
 foreach ($file in $task.info.Result){

 if($file.FolderPath -match ".snapshot"){continue}
 $found = $FALSE
 foreach($vmx in $vms){
 if(($file.FolderPath + $file.File[0].Path) -eq $vmx){
 Write-Host "`tVM is registered"
 $found = $TRUE
 }
 }
 if (-not $found -and $task.Info.Result[0].File -ne $null){
 $vmx = $file.FolderPath + $file.File[0].Path
 $params = @($vmx,$null,$FALSE,$pool.MoRef,$null)
 Write-Host "Registering" $vmx
 $folder.GetType().GetMethod("RegisterVM_Task").Invoke($folder, $params)
 }

 }
 }
}

Script of the Day – changing ESX NTP servers

February 2nd, 2011 No comments

The following script will amend the NTP server settings for all ESX hosts in your VC

$ntp1 = <ipaddress>"
$ntp2 = "<ipaddress>"
$oldntp = "<ipaddress>"
$oldntp2 = "<ipaddress>"

Add-PSSnapin VMware.VimAutomation.Core
connect-viserver -server <vcentername> -credential (Get-Credential)

$vmhosts = Get-VMHost

foreach ($element in $vmhosts)
{
Remove-VMHostNtpServer -NtpServer $oldntp -VMHost $element
Remove-VMHostNtpServer -NtpServer $oldntp2 -VMHost $element
Add-VmHostNtpServer -NtpServer $ntp1 -VMHost $element
Add-VmHostNtpServer -NtpServer $ntp2 -vmhost $element

$ntpd = Get-Vmhostservice -VMHost $element | where {$_.key -eq 'ntpd'}
Restart-VMHostService $ntpd -Confirm:$false
}

Script of the day – writing to a cell in Excel

January 31st, 2011 No comments

Ever needed to inject info to a cell in an Excel spreadsheet – repeatedly . . . you can do so from Powershell . . like so:

Function write-excel ($ExcelFile, $WorkSheet, $Column, $Row, $Value)
{
<#
	.SYNOPSIS
	 Write value(s) to Excel cells
	.DESCRIPTION
	 No return - Updates an Excel Cell
	.PARAMETER
		e.g. Specify the requested parameter, if not specified this will be prompted
	.EXAMPLE
		PS C:\> write-excel $ExcelFile $WorkSheet $Column $Row $Value
#>
	$File = (ls $ExcelFile).FullName
	# Open Excel
	$Excel = New-Object -Com Excel.Application

	# Prevent Overwrite and Macro Prompt
	$Excel.displayalerts=$False

	# Open Template File

	$WorkBook = $Excel.Workbooks.Open($File)
	$WorkSheet = $WorkBook.Worksheets.Item("$WorkSheet")
	$Worksheet.Cells.Item($Row,$Column) = $Value

	# Setting All Variables to Null

	$WorkBook.SaveAs($ExcelFile,1)
	$Excel.Quit()
 	$WorkBook = $Null
	$WorkSheet = $Null
	$Excel = $Null

	# Releasing Object Wrapper

	[GC]::Collect()
}

Script of the day – ping a range of IP addresses

January 28th, 2011 No comments

Friday today, so just a quick and easy script . . nothing clever

In PowerShell, ping functionality can be handled by using the ‘test-connection’ cmdlet, or simply using .Net

A ping using test-connection is just:

$object = New-Object system.Net.NetworkInformation.Ping
$object.Send('127.0.0.1')

You can wrap it as function to get even more out of this:

function ping-ip {
param( $ip )
trap {$false; continue}
$timeout = 1000
$object = New-Object system.Net.NetworkInformation.Ping
(($object.Send($ip, $timeout)).Status -eq 'Success')
}
ping-ip 127.0.0.1
ping-ip "news.bbc.com"

You can use this function to ping IP addresses or hostnames and will get either TRUE or FALSE as a return . . so you can use this in an if statement or similar

e.g.

If (Ping-IP "labserver001.local"){write-host "Lab domain appears to be online"}

You can add a loop to create your own network segment scan:

0..255 | % { $ip = "192.168.2.$_"; "$ip = $(ping-ip $ip)" }

Powershell – Script of the Day – Menu-Plus

January 27th, 2011 No comments

Yesterday, we created a simple Powershell menu

http://www.get-virtual.info/2011/01/26/script-of-the-day-powershell-menu-select-list/

Today’s script is a feeder for the menu, that allows you use any filed of an object as your menu source and return a different field of it as your return value.

For Example:
the following query will give you a list of the filenames in the current directory, once you select an item, it will return that ‘LastWriteTime’ of that file. – Simple

PS:8 >menu-plus -object (gci) -displayfield "name" -menuTitle Please select a file -returnfield "LastWriteTime"
Function menu-plus ($object, $displayfield, $menuTitle, $returnfield)

{
<#
.SYNOPSIS
Feeder object to Menu Function to Enable return of different field in Object

.DESCRIPTION
Requires:Menu Function
Creates a menu that allows return of a different object field.

.PARAMETER
$object - the array that we're sselecting from
$Displayfield : Name of the field that will be displayed for selection
$MenuTitle : The prompt to included at top of menu
$Returnfield : Field to be returned - defauilts to all fields

.EXAMPLE

PS: >$a = gci
PS: >$b=menu-plus -object $a -displayfield "name" -menuTitle Please select a file -returnfield "LastWriteTime"
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦ Please select a file ¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
CDB

Compare
Decom
edit-table
temp.csv
PS:87 >$b.LastWriteTime
25 March 2010 15:20:53
#>
$menulist = @()
ForEach ($item in $object){$menulist += $item.$displayfield}
$returnval = menu $menulist $menuTitle $returnfield
$output = $object | where {$_.$displayfield -eq $returnval} | Select $returnfield
return $output
}

Script of the Day – Powershell Menu Select list

January 26th, 2011 No comments

Sometimes you’d like to prompt a user to select an option from a list in Powershell . .

try this:


Function menu
{
<#
	.SYNOPSIS
	 Generate a small "DOS-like" menu.
	.DESCRIPTION
	  Allows you to pick  a menuitem using up and down arrows, select by pressing ENTER
  	.PARAMETER
		e.g. Specify the requested parameter, if not specified this will be prompted
	.EXAMPLE
		C:\> $Options = "Option1", "Option2", "Option3", "Option4", "Option5"
		C:\> $selection = Menu $Options "Please select an Option?"

		****************************
		* Please select an Option? *
		****************************

		Option1
		Option2
		Option3
		Option4
		Option5

		write-host $selection
		Option1

#>
    param ([array]$menuItems, $menuTitle = "MENU", [switch]$quit)
    $vkeycode = 0
    $pos = 0
	If ($quit){$menuItems += "Quit"}
    DrawMenu $menuItems $pos $menuTitle
    While ($vkeycode -ne 13) {
        $press = $host.ui.rawui.readkey("NoEcho,IncludeKeyDown")
        $vkeycode = $press.virtualkeycode
        Write-host "$($press.character)" -NoNewLine
        If ($vkeycode -eq 38) {$pos--}
        If ($vkeycode -eq 40) {$pos++}
        if ($pos -lt 0) {$pos = 0}
        if ($pos -ge $menuItems.length) {$pos = $menuItems.length -1}
        DrawMenu $menuItems $pos $menuTitl
    }
	If ($($menuItems[$pos]) -eq 'Quit'){return}
	Else
	{Write-Output $($menuItems[$pos])}
}



function DrawMenu {
    ## supportfunction to the Menu function above
    param ($menuItems, $menuPosition, $menutitle)
    $fcolor = $host.UI.RawUI.ForegroundColor
    $bcolor = $host.UI.RawUI.BackgroundColor
    $l = $menuItems.length + 1
    cls
    $menuwidth = $menutitle.length + 4
    Write-Host "`t" -NoNewLine
    Write-Host ("#" * $menuwidth) -fore $fcolor -back $bcolor
    Write-Host "`t" -NoNewLine
    Write-Host "# $menutitle #" -fore $fcolor -back $bcolor
    Write-Host "`t" -NoNewLine
    Write-Host ("#" * $menuwidth) -fore $fcolor -back $bcolor
    Write-Host ""
    Write-debug "L: $l MenuItems: $menuItems MenuPosition: $menuposition"
    for ($i = 0; $i -le $l;$i++) {
        Write-Host "`t" -NoNewLine
        if ($i -eq $menuPosition) {
            Write-Host "$($menuItems[$i])" -fore $bcolor -back $fcolor
        } else {
            Write-Host "$($menuItems[$i])" -fore $fcolor -back $bcolor
        }
    }
}

Powershell – function to Query a SQL database

January 21st, 2011 2 comments

# Today’s quick and easy function is a simple one that I regularly use to query a SQL database.

It will return an object containing the result of your query – so makes SQL access very simply from Powershell

Function QuickQuery-SQL {
## Performs a T-SQL query against an SQL 2000/2005/2008
## with the result returned as as a PowerShell object.
## QuickQuery-SQL "server" "database" "t-sql query"
##Usage:
## Find NodeID from FindIt DB
## $output = QuickQuery-SQL "MySqlServername" "MyDatabase" "SELECT * FROM MyTable WHERE name = 'MySearchValue'"
Param ($server = "MyServer\MyInstance",
$database = "master",
$query = "SELECT * FROM sysdatabases",
$connectionName = "PS QuickQuery SQL",
$commandTimeout = 15)
$conn =new-object ('System.Data.SqlClient.SqlConnection')
$connString = "Server=$server;Integrated Security=SSPI;Database=$database;Application Name=$connectionName"
$conn.ConnectionString = $connString
Write-Debug ("Function: Query-SQL: $server $database")
if (test-path variable:\conn) {
$conn.close()
} else {
$conn =new-object ('System.Data.SqlClient.SqlConnection')
}
$conn.Open()
$sqlCmd =New-Object System.Data.SqlClient.SqlCommand
$sqlCmd.CommandTimeout = $CommandTimeout
$sqlCmd.CommandText = $query
$sqlCmd.Connection = $conn
$data = $sqlCmd.ExecuteReader()
while ($data.read() -eq $true) {
$max = $data.FieldCount -1
$obj =New-Object Object
For ($i = 0; $i -le $max; $i++) {
$name = $data.GetName($i)
if ($name.length -eq 0) {
$name = "field$i"
}
$obj |Add-Member Noteproperty $name -value $data.GetValue($i) -Force
}
$obj
}
$conn.close()
$conn = $null
}