Archive

Archive for the ‘Scripting’ Category

Adding permissions on printers using powershell

I needed to add a group of users to the ACL of all our printers. As we currently have about 100 printers; I looked if I could use powershell for this.
Currently on Windows server 2008 there are no built in cmdlets to administrate printers. But I did find a useful powershell script with everything I needed.

I ended up with only executing one line of code to add the group to all the printers.

Get-printer printserver | add-printerpermission -user “domain\groupname” -AceType Allow -accessmask ManagePrinters

The script can be found here, I’m posting the google translation link as my Russian isn’t that good;-)

Categories: PowerShell, Scripting

Split CSV to TXT

Question: How to split a csv file in one txt file per line? The first column in the CSV provides the name for the TXT-file and the second one the contents.

SetLocal EnableDelayedExpansion
for /f %%i in (inp.csv) do set var=%%i& set name=!var:~0,6!& set phone=!var:~7,4!& echo !phone!>>!name!.txt
EndLocal
Categories: Scripting Tags:

ADFind Oneliners

I’m very fond of the powerful AdFind command line utility from joeware.net. Here’s a little list I’m keeping for my own reference:

Find the user behind a GUID:

adfind -binenc -gc -s subtree -b dc=test,dc=com -f "objectGUID={{GUID:????????-????-????-????-????????????}}" displayName

Likewise, you can use the same tool to find the e-mail address of a certain user:

adfind -gc -b dc=???,dc=??? -nodn -nolabel -f "sAMAccountName=??????" mail

The command above is actually part of script, so I used the “-nodn” and “-nolabel” parameters to have the tool only return the e-mail address. You obviously need to replace the question marks with something meaningful in the examples above.

List all distribution groups:

adfind -csv -nodn -f "(&(objectcategory=group)(mail=*))" displayname

List all contacts:

adfind -csv -nodn -f "(&(&(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=contact)) ))))" displayname

List all mailbox-enabled users:

adfind -csv -nodn -f "(&(&(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*))) ))))" displayname

Run a query against another domain:

adfind -h %servername% -u %domain%\%username% -up %password% -csv -nodn -f "displayname=John Doe" displayname

List all the members of a DL (and optionally use the resulting dn to retrieve some more readable information):

adfind -list -f "DisplayName=%displayname%" member
adfind -list -f "DisplayName=%displayname%" member | adfind -csv -nodn mailnickname displayname mail

Report on the usage of Extension Attributes:

adfind -csv -nodn -f "(|(ExtensionAttribute1=*)(ExtensionAttribute2=*)(ExtensionAttribute3=*)(ExtensionAttribute4=*)(ExtensionAttribute5=*)(ExtensionAttribute6=*)(ExtensionAttribute7=*)(ExtensionAttribute8=*)(ExtensionAttribute9=*)(ExtensionAttribute10=*)(ExtensionAttribute11=*)(ExtensionAttribute12=*)(ExtensionAttribute13=*)(ExtensionAttribute14=*)(ExtensionAttribute15=*))" displayname ExtensionAttribute1 ExtensionAttribute2 ExtensionAttribute3 ExtensionAttribute4 ExtensionAttribute5 ExtensionAttribute6 ExtensionAttribute7 ExtensionAttribute8 ExtensionAttribute9 ExtensionAttribute10 ExtensionAttribute11 ExtensionAttribute12 ExtensionAttribute13 ExtensionAttribute14 ExtensionAttribute15

Count the number of mailboxes on an exchange server:

adfind -c -f "msExchHomeServerName=/o=EMS/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=%servername%"

Imagine you’re working as a consultant/contractor for a large organisation and you want to know the end date of you contract:

adfind -tdcs -f "samaccountname=%UserName%" accountExpires

The “tdcs” parameter converts the time in a human readable format.

Somebody called you on your mobile phone and you want to know who:

adfind -list -f "telephoneNumber=*%extension%" displayname

More info

Categories: Active Directory, Scripting Tags: ,

Automating a powershell demo using AutoHotKey

I gave a custom Exchange 2007 course to one of our customers yesterday. Not unsurprisingly, it also included a demo of Exchange Management Shell (EMS). These demos tend to end up in a quest for the exact command, which is quite annoying if you’re in front of an audience (even a small one). Think about:

  • about_regular_expressions or about_regular_expression?
  • $_. or $._?
  • Why is -Confirm $False not working?

This time I decided to try and automate that demo by using the autoreplace feature (Hotstring) in AutoHotKey. The main goal is avoiding typo’s by using tried and true commands in a working order. A poor man’s Start-Demo script if you wish ;-)

The script starts of with a bunch of commands controlling the overall functionallity (the first 3 come with the default template):

#NoEnv

Recommended for performance and compatibility with future AutoHotkey releases.

SendMode Input

Recommended for new scripts due to its superior speed and reliability.

SetWorkingDir %A_ScriptDir%

Ensures a consistent starting directory.

#Hotstring EndChars `n

Limit the hotstring end characters to ENTER only

#Hotstring O

Don’t actually type the end character. (I want to launch the command myself after/during my explanation.)

#Hotstring R

Type replacement text in raw mode. (To prevent AHK from interpreting e.g. “{“)

The remainder of the script is actually a long list of hotstring definitions like these ones

::ems01::Get-Help
::ems02::Get-Help About
::ems03::Get-Help About_Regular_Expression
::ems04::Get-Command *mailbox
::ems05::Get-Help New-Mailbox
::ems06::Get-Help New-Mailbox -Detailed
::ems07::Get-Help New-Mailbox -Full

and so on.

Seems stupid with these simple examples, but the advantage becomes clear for more complex commands. Lets take “ems26″ for example;

::ems26::1..10 | Foreach-Object { new-mailbox -Database “Mailbox Database 2″ -Name (“User” + $_) -UserPrincipalName (“User” + $_ + “@exchange2007.lab”) -Password $Pwd }

When I type “ems26″+ENTER in EMS AutoHotKey executable automatically replaces this string with “1..10 | Foreach-Object { new-mailbox -Database “Mailbox Database 2″ -Name (“User” + $_) -UserPrincipalName (“User” + $_ + “@exchange2007.lab”) -Password $Pwd }” and waits. I do my talking and then hit ENTER again to execute the command.

It worked nicely actually. People were impressed with my typing skills ;-) I only encountered one error because I didn’t delete some manually after a test the day before. It even works with shell running inside a VM while the AutoHotKey script is running on my physical computer.

Categories: Scripting Tags: ,

Closing open Lotus Notes file

The users at a certain customer have a problem with reopening Lotus Notes if their session is not closed properly (e.g. because of a crash of a terminal server). They keep receiving the error message “Domino Server still running” until we close the open files.

I’ve been writing a script over time to automate this process which becomes quickly annoying after you’ve done it a couple of times.

More specifically, the script will:

  1. Connect to a GC to get domain and display name (ADFind)
  2. Connect to a DC to get home directory (ADFind)
  3. Derive server name from the previous query via string manipulation (Set)
  4. Kill PsExec if it’s already running (SC)
  5. Find the physical disk (PsExec)
  6. List open Notes files and ask if you whan to close them (PsFile)
  7. Close the files if after you confirmed you wanted to do so (PsFile)
  8. Quit
  9. Last but not least, it will put a comment on the clipboard for easy pasting in the incident management tool ;-)

Prerequisites are both ADFind and PsTools.

Well, here it is:

   1: ::========================================================================================================
   2: :: AUTHOR
   3: ::    Koen Vermoesen
   4: ::    koen.vermoesen@nospam.com
   5: ::    2008-04-24
   6: ::========================================================================================================
   7: :: SCRIPT
   8: ::    Close open lotus notes files
   9: ::========================================================================================================
  10: :: PREREQUISITES
  11: ::    ADFind    http://www.joeware.net/freetools/tools/adfind/index.htm
  12: ::    PsTools    http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx
  13: ::========================================================================================================
  14: :: CHANGE HISTORY:
  15: ::    2008-04-24 Initial version
  16: ::    2008-04-25 Use %temp% to avoid writing to a network share all the time
  17: ::    2008-05-07 Added a todo for the script
  18: ::    2008-05-13 Call another script to verify & close psexec if it's already running
  19: ::    2008-05-13 Goto end (skip closing)  when no open files found
  20: ::    2008-05-13 Print user's diplay name as a means to cross check
  21: ::    2008-05-14 Removed last reference to temporary file
  22: ::    2008-07-31 Started using ADFind to make script work across domains
  23: ::    2008-07-31 Removed dependency on other scripts for easy sharing with colleagues
  24: ::    2008-09-16 Goto end after closing files + use variable for Title
  25: ::    2008-10-06 Provide some help when no parameters are being passed
  26: ::    2008-10-07 Used hardcoded path for DFS
  27: ::    2008-10-07 Check if very first query returns a valid resullt. Jump to help (skip remainder of script) if not
  28: ::    2008-10-07 Update Help: hardcoded DFS values + for loop example for running against a batch of users
  29: ::    2008-10-27 Use clip.exe to store some comment on the clipboard for easy pasting in the incident
  30: ::========================================================================================================
  31: :: TO DO
  32: ::    Integrate logic for working on a batch of users.
  33: ::========================================================================================================
  34:  
  35: @echo off
  36: setlocal EnableDelayedExpansion
  37:  
  38: :: Setting some variables
  39: Set StrTitle=Close open Lotus Notes files
  40: Set strHomeDirAB=FileServer01
  41: Set strHardDiskAB=E:
  42:  
  43: Cls
  44: Title %StrTitle%
  45:  
  46: ::Saving the input parameter to variable
  47: Set StrUserName=%1
  48: If "[%strUserName%]"=="[]" Goto Help
  49: Set Return=return1
  50: Goto SubEcho
  51: :return1
  52:  
  53: :: Looking up Distinguished Name & Display Name
  54: For /F "tokens=1,2 delims=;" %%I in ('adfind -nodn -csv -nocsvheader -csvnoq -csvdelim ^; -gc -s subtree -b dc^=domain^,dc^=tld -f ^"sAMAccountName^=%StrUserName%^" distinguishedName displayName') Do Set StrDistingName=%%I & Set StrDisplayName=%%J
  55: If "[%StrDisplayName%]"=="[]" Echo. & Echo No valid user object found; please check the username. & Echo. & Goto Help
  56: Set StrBaseDN=%StrDistingName:~-26%
  57: Set Return=return2
  58: Goto SubEcho
  59: :return2
  60:  
  61: :: Looking up Home Directory
  62: Set StrTLD=%StrBaseDN:~22,3%
  63: Set StrRoot=%StrBaseDN:~15,3%
  64: Set StrDomain=%StrBaseDN:~3,8%
  65: For /F %%I in ('adfind -nodn -csv -nocsvheader -csvnoq -s subtree -b dc^=%StrDomain%^,dc^=%StrRoot%^,dc^=%StrTLD% -f ^"sAMAccountName^=%StrUserName%^" homeDirectory') Do Set StrHomeDirectory=%%I
  66: Set Return=return3
  67: Goto SubEcho
  68: :return3
  69:  
  70: :: Looking up Home Server
  71: IF /I "%StrDomain%"=="subdomain3" (Set StrHomeServer=%strHomeDirAB%) Else (For /F "tokens=1 delims=\" %%I in ("%StrHomeDirectory%") Do Set StrHomeServer=%%I)
  72: Set Return=return4
  73: Goto SubEcho
  74: :return4
  75:  
  76: :: Ensuring PsExec is not running on Home Server
  77: echo.
  78: For /F "Tokens=2" %%I in ('sc \\%StrHomeServer% query psexesvc ^| find "SERVICE_NAME"') Do Set StrPsexecExists=%%I
  79: If /I "%StrPsexecExists%"=="psexesvc" (echo PsExec running on the remote host; killing it. & sc \\%StrHomeServer% stop psexesvc & sc \\%StrHomeServer% delete psexesvc) else (echo PsExec is not running on the remote host.)
  80:  
  81: :: Looking up Physical Disk
  82: echo.
  83: IF /I "%StrDomain%"=="subdomain3" (Set StrHardDisk=%strHardDiskAB%) Else (For /F "tokens=2 delims=\ " %%I in ('psexec \\%StrHomeServer% net share ^| find /i "%StrUserName%"') Do Set StrHardDisk=%%I)
  84: Set Return=return5
  85: Goto SubEcho
  86: :return5
  87:  
  88: :: Listing open Lotus Notes Files
  89: IF /I "%StrDomain%"=="subdomain1" (set StrNotesPath=%StrHardDisk%\folder\%StrUserName%\windows\NotesR6)
  90: IF /I "%StrDomain%"=="subdomain2" (set StrNotesPath=%StrHardDisk%\folder\folder\%StrUserName%\notes\data)
  91: IF /I "%StrDomain%"=="subdomain3" (set StrNotesPath=%StrHardDisk%\folder\%StrUserName%\WINDOWS\NotesR6)
  92: Set StrOpenFiles=
  93: For /F "tokens=2 delims=] " %%I in ('psfile \\%StrHomeServer% %StrNotesPath% ^| find /i "] %StrNotesPath%"') Do Set StrOpenFiles=!StrOpenFiles!%%I   
  94: Set Return=return6
  95: Goto SubEcho
  96: :return6
  97: echo.
  98: IF /I "%StrOpenFiles%"=="" (Echo No open files found. & goto :end)
  99: echo Open Files:
 100: For %%I in (%StrOpenFiles%) do echo %%I
 101:  
 102: :: Closing open Lotus Notes Files
 103: echo.
 104: Set /P StrConfirmClose="Press <c> to close these files, <enter> key will SKIP this step."
 105: IF /I "%StrConfirmClose%"=="c" (psfile \\%StrHomeServer% %StrNotesPath% -c) ELSE Goto end
 106: Set Return=return7
 107: Goto SubEcho
 108: :return7
 109: echo.
 110: echo Open Lotus Notes files closed!
 111: echo Open Lotus Notes files for user %StrUserName% on server %StrHomeServer% closed. | clip
 112: Goto End
 113:  
 114: :: Procedure printing the different values determined by script
 115: :SubEcho
 116: cls
 117: Title %StrTitle%
 118: Echo User:        %StrUserName%
 119: Echo Name:        %StrDisplayName%
 120: Echo BaseDN:        %StrBaseDN%
 121: Echo TLD:        %StrTLD%
 122: Echo Root:        %StrRoot%
 123: Echo Domain:        %StrDomain%
 124: Echo HomeDir:    %StrHomeDirectory%
 125: Echo Server:        %StrHomeServer%
 126: Echo Disk:        %StrHardDisk%
 127: Echo Path:        %StrNotesPath%
 128: Goto %Return%
 129:  
 130: :Help
 131: Title %strTitle%
 132: Echo You should call this script from the command line passing the name of the user to unblock as a parameter. (e.g. "killnotes user1980"). The script will then fetch some data, list the open lotus notes files and ask you wheter or not you want to close them.
 133: Echo.
 134: Echo More specifically, the script will:
 135: Echo   1. Connect to GC to get domain and display name (ADFind)
 136: Echo   2. Connect to DC to get home directory (ADFind)
 137: Echo   3. Get servername via string manipulation (Set)
 138: Echo   4. Kill PsExec if it's already running (SC)
 139: Echo   5. Find the physical disk (PsExec)
 140: Echo   6. List open Notes files and ask if you whan to close them (PsFile)
 141: Echo   7. Close the files if you confirmed you wanted to do so (PsFile)
 142: Echo   8. Quit
 143: Echo.
 144: Echo If you want to apply this script on a number of users then I recommend saving them in a file "userlist.txt" (1 user per line). You can then use a for loop to launch the script:
 145: Echo.
 146: Echo   for /F %%i in (userlist.txt) do killnotes %%i
 147: Echo.
 148: Echo IMPORTANT: Physical Disk (%strHardDiskAB%) and Server Name (%strHomeDirAB%) for AB are HARDCODED. These values need to be adopted in the script if the design ever changes.
 149: Echo.
 150: Echo PS1: The script will print the values of the different variables to allow you to monitor the progress.
 151: Echo PS2: If the script halts for a moment it's because of number of connections being made using PsTools.
 152: Echo.
 153:  
 154: ::Deleting variables
 155: :END
 156: Echo.
 157: Echo Quitting...
 158: Endlocal

There’s still some room for improvement obviously. The hard coded DFS information, for instance, should be replaced with some decent logic (there are very few users on this infra however, so I didn’t invest to much time in that part).

http://www.robvanderwoude.com/ proved very helpful while writing this script.

Categories: Scripting Tags: ,

Hooking up SQLite and PowerShell

I’ve been playing around with SQLite on the command line (cmd that is) a bit. I immediately started wondering if it would be possible to combine this portable SQL engine with PowerShell, but I couldn’t find any working samples on the internet.

After some more research I discovered the SQLite ADO.net 2.0 Provider but I couldn’t get it to work immediately.

It took me a couple of days to find the blog post Database Queries with Windows Powershell. (This blog seems to have moved recently as most of the hyperlinks/search results are still referring to Typepad). The post is nicely commented, so I could rather easily translate the MySQL to SQLite statements with some assistance from the included help file.

[void][System.Reflection.Assembly]::LoadFrom("D:\DATA\Tools\System.Data.SQLite.dll")

$cn = New-Object -TypeName System.Data.SQLite.SQLiteConnection
$cn.ConnectionString = "Data Source=D:\DATA\Tools\koen.sqlite"
$cn.Open()

$cm = New-Object -TypeName System.Data.SQLite.SQLiteCommand
$sql = "SELECT FirstName, LastName FROM tblKoen"
$cm.Connection = $cn
$cm.CommandText = $sql
$dr = $cm.ExecuteReader()

while ($dr.Read())
{
    write-host $dr.GetString(0) " " $dr.GetString(1)
}

$cn.Close()

Some more interesting links I came across:

Categories: Scripting Tags: ,

VI Toolkit scripting contest winners announced.

Carter Shanklin announced the winners of the contest.

1st prize: The guest provisioning system of LucD. This application lets you provision your VMs in an easy way. You can set the options from one screen no clicking around to configure everything manually.

2nd prize: VI Power Documenter by tzamora. This script generates reports about your virtual infrastructure.

3rd prize: PowerVDI script by Dan Baskette. It let you deploy multiple VDI instances on an EMC celera using snapshots and AD integration.

I’m sure there are other contributions that are very useful.

Congrats to the winners. Nice job guys.

Categories: Scripting, Virtualization Tags:

PowerGui integrates with VI Client

Dmitri over at Dmitry’s PowerBlog just posted about the integration between PowerGui and the VI client. I had already installed the PowerGUI 1.5.1 version but hadn’t noticed the plugin for the VI Client.

This makes managing your VMware environment using  Powershell even more easier. PowerGUI lets you write your own Powershell scripts and the VMware PowerPack is also compatible with the VI client plugin. The plugin uses your current connection to the VC. You don’t need to make a separate connection for every script.

VI Toolkit 1.0 Released

Last week VMware officially released the VI Toolkit for Windows.

  • They replaced get-viserver with connect-viserver. get-viserver is now an alias for connect-viserver.
  • disconnect-viserver was added which allows you to do a clean disconnect. Hence the rename of the get-viserver cmdlet.
  • VMware also added cmdlets for managing the VMware Update Manager.
Categories: Scripting Tags: ,

Pimp My PowerShell

Jeffrey Snover posted a solution for speeding up the PowerShell start-up long time ago. I only noticed it lasted week :-(

Check it out: http://blogs.msdn.com/powershell/archive/2007/11/08/update-gac-ps1.aspx

Categories: Scripting Tags: