Archive

Archive for the ‘Tech Tips’ Category

Quicker copies with Robocopy . .

February 7, 2011 Leave a comment

So I was messing about with Robocopy over the weekend and I decided to re-run an old copy job, using a new Desktop.
Strangely, my copy did not kick off like it did before. The problem – the new version of robocopy has new features and new syntax (yes I know it has been out a while – thanks clever clogs . . . )

anyway, long story short, looking at the updated switches, I noticed :

/MT[:n] :: Do multi-threaded copies with n threads (default 8).
n must be at least 1 and not greater than 128.
This option is incompatible with the /IPG and /EFSRAW opt

How awesome is that! The new robocopy runs Multi threaded and can be ramped up to 128 Threads!!!!!!! (this is Vista onwards I believe. – seems something good actually did come with Vista?)

Categories: Scripting, Tech Tips, Toolbox Tags: , ,

Script of the Day – Powershell Menu Select list

January 26, 2011 2 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
        }
    }
}

‘The terminal server has exceeded the maximum number of allowed connections.’ when trying to remote connect to the server

January 26, 2011 Leave a comment

To query and list the sessions on the remote session, you could use QUser.exe or QWinsta, or Powershell.

Powershell is my usual weapon of choice . .

PSTerminalServices is a PowerShell module that helps you manage Terminal Services (including Remote Desktop connections) sessions and processes.

The module is based on an open source project named Cassia (version 2.0.0.60), a .NET library for accessing the native Windows Terminal Services API.

You’ll need to download the module from  http://code.msdn.microsoft.com/PSTerminalServices and then ‘Import’ the module

What you can do with it

The following operations are supported on local and remote computers:

  • Enumerating terminal sessions and reporting session information including connection state, user name, client name, client display details, client-reported IP address, and client build number.
  • Logging off a session.
  • Disconnecting a session.
  • Displaying a message box in a session.
  • Enumerating all processes or processes for a specified session.
  • Killing a process.

Supported Platforms

Cassia has been tested on Windows Server 2008 R2 beta (RTM?), Windows Server 2008, Windows Server 2003, Windows XP, and Windows Server 2000. It should work on Windows Vista as well.

Functions

The following functions are added to the current session when you import the module:        Disconnect-TSSession – Disconnects any attached user from the session.

Get-TSCurrentSession – Provides information about the session in which the current process is running.

Get-TSServers – Enumerates all terminal servers in a given domain.

Get-TSProcess – Gets a list of processes running in a specific session or in all sessions.

Get-TSSession – Lists the sessions on a given terminal server.

Send-TSMessage – Displays a message box in the specified session ID.

Stop-TSProcess – Terminates the process running in a specific session or in all sessions.

Stop-TSSession – Logs the session off, disconnecting any user that might be connected.

Some Code Examples

For more code examples use Get-Help <cmdletName> –Examples.

# Logs off all the active sessions from remote computer 'Labserv07', no confirmations.
PS> Get-TSSession -ComputerName Labserv07 -State Active | Stop-TSSession –Force
# Gets all Active sessions from remote computer 'Labserv07', made from IP addresses that starts with '10'.
PS> Get-TSSession -ComputerName Labserv07 -Filter {$_.ClientIPAddress -like '10*' -AND $_.ConnectionState -eq 'Active'}
# Displays a message box inside all active sessions of computer name 'Labserv07'.
PS>$Message = "Important`n, the server is going down for maintenance in 10 minutes. Please save your work and logoff."
PS> Get-TSSession -State Active -ComputerName Labserv07 | Send-TSMessage -Message $Message
#Gets all processes connected to session ID 0 from remote computer 'Labserv07'.
PS>Get-TSSession -Id 0 -ComputerName Labserv07 | Get-TSProcess

2. QUser

QUser command comes with all the latest Windows clients and servers. This will list the sessions of the remote server (or local machine).

NOTE: if you are using Windows XP, you need to add this location into your System path: C:\Windows\System32\DLLCache. To do this, in command prompt, type the following.

SET PATH = %PATH%;C:\Windows\System32\DLLCache;

QUser help shows,

C:\Anand>QUser /?
Display information about users logged on to the system.

QUERY USER [username | sessionname | sessionid] [/SERVER:servername]

username Identifies the username.
sessionname Identifies the session named sessionname.
sessionid Identifies the session with ID sessionid.
/SERVER:servername The server to be queried (default is current).

E.g.,

C:\>quser /server:LabServer1
USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME

LabAdmin           rdp-tcp#49          2  Active          .  26/01/2011 1

Logoff the user / session

Logoff command kicks off (logging off) the specified remote session. Log off help shows,

C:\>logoff /?
Terminates a session.

LOGOFF [sessionname | sessionid] [/SERVER:servername] [/V]

sessionname The name of the session.
sessionid The ID of the session.
/SERVER:servername Specifies the Terminal server containing the user
session to log off (default is current).
/V Displays information about the actions performed.

E.g.,

C:\>logoff /server:LabServer1  1 /v
Logging off session ID 1

3. QWinsta

QWinsta is little different and better. It has more features and options. It comes with all flavors of Windows. QWinsta command line help displays as,

C:\>qwinsta /?
Display information about Terminal Sessions.

QUERY SESSION [sessionname | username | sessionid]
[/SERVER:servername] [/MODE] [/FLOW] [/CONNECT] [/COUNTER]

sessionname Identifies the session named sessionname.
username Identifies the session with user username.
sessionid Identifies the session with ID sessionid.
/SERVER:servername The server to be queried (default is current).
/MODE Display current line settings.
/FLOW Display current flow control settings.
/CONNECT Display current connect settings.
/COUNTER Display current Terminal Services counters information.

E.g.,

C:\>qwinsta /server:LabServer1

SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE

console                                     0  Conn    wdcon

rdp-tcp                                 65536  Listen  rdpwd

rdp-tcp#2         admvanwyka                1  Active  rdpwd

RWinsta (Logoff the user sessions)

RWinsta has same parameters and does same thing as log off command. It simply means Reset WINdows STAtion. The help goes as,

C:\>RWinsta /?
Reset the session subsytem hardware and software to known initial values.

RESET SESSION {sessionname | sessionid} [/SERVER:servername] [/V]

sessionname Identifies the session with name sessionname.
sessionid Identifies the session with ID sessionid.
/SERVER:servername The server containing the session (default is current).
/V Display additional information.

E.g.,

C:\>RWinsta /Server:LabServer1 1

Note: RWinsta command does not return anything.

Remember – killing an active session will log off the user – so play nice!

There goes – three different command line methods for logging off sessions . . . (of course if you are the GUI type, you could just use The Terminal Services Session Manager)

Categories: Tech Tips Tags: , ,

Replacing clustered storage for a SQL cluster (EMC CE / MS Clustering)

January 25, 2011 1 comment

So we had a client running a SQL database . . and they ran out of space.
Normally, you’d just expand disks and we’re good . . but in this instance, the SQL server was clustered – and the cluster was Geo-spanned using EMC Cluster Enabler.

The way disk access is handled is as per following diagram
#################
#               #
#   EMC CE      # (Uses Lun / Device ID to identify disks) failover)
#               #(Allows failover of GeoSpan clusters i.e. remote site
#################
       ||
       \/ (Creates a Cluster Resource to handle GeoSpan replication)
##################
#                #
# MS Cluster     # (Uses Signature ID of disk to identify disk)
#   Service      #(Provides ability to failover between 2 Servers seemlessly)
##################
        ||
        \/
#################
#               #
# DiskMgr       # (Uses Disk ID to identify disk)
#               #
#################

So in order for us to expand the disk, we need to at a DiskMgr level, simply replace the disk with a new one containing the same data . . which also happens to carry the same Disk ID, Signature ID and Device / Lun ID. Of course . . the Lun ID will change when your storage guys present new storage and the signature and disk ID can’t change while the resource is in use.

In Simple Terms, what we need to do (once shutting down your SQL services etc)is:
1) Deconfigure Cluster resource (removes the cluster
2) Stop Clustering
3) Present Disk to OS
4) Disk Offset for SQL (format / drive letter etc)
5) Copy data
4) Swap Signatures for Clustering
6) Swap Drive Letters
7) Enable Clustering
8) Configure EMC CE Group

But for those of you who need a little more info (I blog this so I too have a copy) – here is what we do:

Provision new disk(s) and replicate these at a Storage level (clariion / symmetrix etc)

Shut down SQL services (and any other apps that write to this disk)

* EMC CE
Launch EMC Cluster Enabler (screen grab config for reference)
Select Manage cluster
Under storage, make sure disk that has been presented is available to both ends (rescan if needed)
Select Groups -> <Name of Group containing disk to be replaced. -> right click -> Deconfigure Group ** this removes the resource, stopping the EMC replication for all objects in that group – Your disk is still available in the cluster and at this point your Server could in theory continue to operate . . though without the ability to failover to the other cluster Node

Check that both servers see new disks at compmgmt level
Shut down B-Node
In Device Manager, disable ‘cluster Disk driver’ (You’ll have to first right click and select ‘show hidden devices’) * This Driver is the tool that allows the Clustering service to ‘own’ a disk and manage failover etc of whole disks.
Set cluster service to Manual (Services.msc)
Bounce A-Node
At cmd use Diskpar (this is an EMC tool for managing EMC disks)
Run a DumpCfg and capture the output (again an EMC tool)
diskpar (this will list disks – provide Device IDs etc)
* recheck disk IDs and write down disk ID and signature numbers!
diskpar -S<New Disk’s Number> *follow prompts – select offset of 1920 (SQL server) – We are setting the offset of the disk to 1920 as this is for a SQL server (best practice)
Compmgmgt – Assign disk a new drive letter and format **Allocation size must be 64k!! (SQL)
Robocopy old drive to new drive
View registry to capture disk signatures (hklm\system\currentcontrolset\services\clusdisk\parameters\signatures) – new disk will be in ‘available’, old one in ‘signatures’
Dumpcfg (will display signature mappings)
{Now swap signatures} as follows:
Dumpcfg -s<New random signature to allocate old disks> <Old disk number from DeviceMgr> >> Gives new sig to old disk
Dumpcfg -s<Original disk’s old signature ID> <New Disks Device ID>

Swap drive letters in Compmgmt

Enable Cluster disk Driver in Device Manager

At this point, we have reset all identifiers according to above diagram and we need to bring everything back up (so we reverse the process)

Bounce A-Node
Start clustering (If OK, Set Service to Auto)
Verify that your drive is accesible etc.
Start B-Node

EMC CE
NodeNameLevel, right-click -> ‘configure CE cluster’ -> follow wizard

Powershell – function to Query a SQL database

January 21, 2011 Leave a comment

# 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 = <strong>new-object</strong> ('System.Data.SqlClient.SqlConnection')
$connString = "Server=$server;Integrated Security=SSPI;Database=$database;Application Name=$connectionName"
$conn.ConnectionString = $connString
<strong>Write-Debug</strong> ("Function: Query-SQL: $server $database")
if (<strong>test-path</strong> variable:\conn) {
$conn.close()
} else {
$conn = <strong>new-object</strong> ('System.Data.SqlClient.SqlConnection')
}
$conn.Open()
$sqlCmd = <strong>New-Object</strong> 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 = <strong>New-Object</strong> Object
For ($i = 0; $i -le $max; $i++) {
$name = $data.GetName($i)
if ($name.length -eq 0) {
$name = "field$i"
}
$obj | <strong>Add-Member</strong> Noteproperty $name <em>-value</em> $data.GetValue($i) -Force
}
$obj
}
$conn.close()
$conn = $null
}

Authenticating through a proxy when the app has no option to do so

January 20, 2011 1 comment

Sometimes, you work in an environment where all web queries run through a proxy server and the proxy requires authentication . .

Then sometimes, you use apps that need to access the web . . and they don’t have a method of inputting Username and Password for Web connections.

The easy way to fix this is with a Squid Proxy (effectively, run a proxy server locally . . that authenticates to your web proxy)
All you need to do is use the following configuration settings:

# Listen only local interface rc:
http_port 127.0.0.1:3128

# Parent proxy (192.168.1.253:8080) and Authentication settings
cache_peer 192.168.1.253 parent 8080 0 no-query default login=User:Passwd

# No direct access
never_direct allow all

Of course, you may not have a Linux box available for you to run a Squid proxy . . Squid can compile and run on Windows as a system service using the Cygwin emulation environment

Alternatively and more easily, get a compiled version of Squid for Windows like : www.reaper-x.com/2006/07/18/complete-guide-on-installing-and-configuring-squid-proxy-server-for-windows/

Here’s a quick how to:

  1. Download the latest package from the above link
  2. Extract it (I extracted to c:squid for my example)
  3. Rename *.conf.default to *.conf for all files in c:squidetc
  4. Open the file squid.conf (Notepad / VI or whatever you favour)
  5. Amend the file as above – Save and exit . . .or use the file below if you’re battling and just replace the username / password, IP addresses and DNS servers

If you are battling, you could use the following file and simply edit the row starting with dns_nameservers
and the row starting with cache_peer

6. Now from a dos box, just run the following commands:
mkdir c:\squid\var\cache
c:\squid\sbin\squid -D

(this will start the Squid and ignore the DNS check it normally does at startup)

7. At this point your squid server is running. You should be able to point the proxy server for any app at 127.0.0.1:3128 and the authentication will be handled by the squid proxy. As a test I user the “Android SDK and AVD manager” which only allows specifying of Proxy, but not of credentials . . and all downloads ran properly.

Sample File

# [START - Copy from after this]
# HTTP Port (in this tutorial squid will run on localhost at port 3128)
http_port 127.0.0.1:3128
# ICP Port and HTCP Port (we’ll disable this since we are not going to use it)
icp_port 0
htcp_port 0
# Cache Peer (we’ll forward all request into parent proxy)
cache_peer 192.168.1.1 parent 8080 0 no-query default login=username:password #amend these . .the IP is the Proxy, and Username and Password need replacing.
# Cache directory (in this example i was using 30 MB space to store squid cache)
# cache_dir awin32 c:/squid/var/cache 3000 16 256
# access_log
access_log c:/squid/var/logs/access.log squid
# cache_log
cache_log c:/squid/var/logs/cache.log
# cache_store_log
cache_store_log none
# mime_table
mime_table c:/squid/etc/mime.conf
# pid_filename
pid_filename c:/squid/var/logs/squid.pid
# unlinkd_program
unlinkd_program c:/squid/libexec/unlinkd.exe
# refresh_pattern (you can configure this as you like it, to get more hits from a website)
# note: if you change this parameter "refresh_pattern . 1 100% 20160 reload-into-ims ignore-reload” into something else for
# example like "refresh_pattern . 10 100% 20160 reload-into-ims ignore-reload”
# there’ll be some error on some page (Gamefaqs.com for an example) because the page didnt reload correctly after login into Gamefaqs
refresh_pattern ^http://.*.gif$ 1440 50% 20160 reload-into-ims
refresh_pattern ^http://.*.asis$ 1440 50% 20160
refresh_pattern -i .png$ 10080 150% 40320 reload-into-ims
refresh_pattern -i .jpg$ 10080 150% 40320 reload-into-ims
refresh_pattern -i .bmp$ 10080 150% 40320 reload-into-ims
refresh_pattern -i .gif$ 10080 300% 40320 reload-into-ims
refresh_pattern -i .ico$ 10080 300% 40320 reload-into-ims
refresh_pattern -i .swf$ 10080 300% 40320 reload-into-ims
refresh_pattern -i .flv$ 10080 300% 40320 reload-into-ims
refresh_pattern -i .rar$ 10080 150% 40320
refresh_pattern -i .ram$ 10080 150% 40320
refresh_pattern -i .txt$ 1440 100% 20160 reload-into-ims override-lastmod
refresh_pattern -i .css$ 1440 60% 20160
refresh_pattern ^http:// 1 100% 20160 reload-into-ims ignore-reload
refresh_pattern ^ftp:// 240 50% 20160
refresh_pattern ^gopher:// 240 40% 20160
refresh_pattern /cgi-bin/ 0 0% 30
refresh_pattern . 0 100% 20160 reload-into-ims
# Deny requests to unknown ports
# http_access deny !Safe_ports
# Deny CONNECT to other than SSL ports
# http_access deny CONNECT !SSL_ports
# Block access to Malware & ads farm site
# Insert your own rule here by using
# acl blablabla url_regex -i "path to file”
# or
# acl blablabla url_regex "path to file”
acl all src 0.0.0.0/0.0.0.0
http_access allow all
# http_access deny all
cache_mgr Reaper-X
httpd_suppress_version_string on
visible_hostname Reaper
via off
forwarded_for off
log_icp_queries off
client_db off
never_direct allow all
#Some anonymizing
header_access From deny all
#there’s some website which use referer check
#so its better to disable this
#header_access Referer deny all
header_access WWW-Authenticate deny all
header_access Link deny all
header_access Warning deny all
header_access Via deny all
header_access User-Agent deny all
header_access Proxy-Connection deny all
header_access X-Forwarded-For deny all
dns_nameservers 192.168.1.2

#[END – Copy to before here]

What we are doing here in effect is running the Squid proxy as a local proxy, that has the authnetication to your Network Proxy already configured. the squid.conf contains the username and passwpord and any request sent from your cliebt via the squid proxy thus has the request redirected and processed using an authenticated connection.

The added bonus of course is that you can set your local squid proxy to cache your web requests, thus in theory having your own local cahing proxy that never requires manual authentication.

Interestingly, if you are normally prompted for authentication when you access your work proxt, you should now stop seeing the prompt, as you dekstop / laptop will never communicate directly with the proxy anymore (unless of course you tell it to)

Happy Days

Categories: Apps, Tech Tips, Toolbox Tags: , , ,