Labels

Sunday, November 29, 2009

vCenter file copy with virtual floppy disk

n an ESXi or vCenter environment, without network connectivity to a virtual machine from your administrative workstation it's quite hard to bi-directionally transfer files.

This post discusses a simple method I use for small quick file transfer from a secure virtual machine to my administrative workstation, using virtual floppy drives managed from the command-line.

This process uses vfd.exe, but presumably any virtual floppy software on your workstation could be used. The virtual machine also needs to have a floppy drive...

To bi-directionally transfer files from a non-network connected VM to my administrative workstation:

  1. Create a virtual floppy disk on my workstation

  2. Mount that floppy disk file as a virtual floppy drive on my workstation as A:

  3. Through VI client, connect the VM to the A: drive

  4. On the VM, copy files to/from A: drive and disconnect from the floppy

  5. On my workstation, copy files to/from the virtual A:

  6. Close the virtual floppy


Using vfd.exe:
  1. vfd install

  2. vfd open c:\temp\new.flp

  3. Use VI Client to connect to A:

  4. Copy files, then disconnect the VM virtual device

  5. copy a:\*.*

  6. vfd close


The obvious limitation of this is that the size is limited to 1.44MB. I tried with a 2.44MB floppy and the virtual machine didn't recognise this disk.

This doesn’t work with a virtual CD-ROM, as it’s mounted as read-only in the VM, so bi-directional copies aren’t available. You can still use a similar process for creating an ISO to copy files into a VM though. For this I use oscdimg.exe (Microsoft utility) to create my ISO from the command-line.


Read more!

Friday, October 30, 2009

VMware PowerCLI commands

The VMware PowerCLI PowerShell interface provided for managing vSphere systems is a fantastic tool that should be useful for all VMware admins.

I've gathered these commands while implementing and managing ESXi 4.0 clusters, use with caution on any production system.

This is an extension of a previous post:
VMware vSphere PowerCLI commands



Join a cluster by moving an ESX host from one location to the cluster
Move-Inventory -Item (Get-VMHost -Name esxHost) -Destination (Get-Cluster -Name clusterName)

Get the VMware.Vim.ClusterComputeResource MO from the PowerCLI cluster object
$clusterview = get-view $cluster.Id

Reconfigure a host for VMware HA (high availability)
$vmhost = get-vmhost -name esxHost; $hostMO = Get-View -ID $vmhost.ID; $hostMO.ReconfigureHostForDAS()

Find migration events for the last day
$events = Get-VIEvent -Start (Get-Date).AddDays(-1) | where {$_.fullFormattedMessage -match "Migrating.*"}

Find events other than CPU Alarms or user login/logout for the last day
$events = Get-VIEvent -Start (Get-Date).AddDays(-1) | where {$_.fullFormattedMessage -notmatch "Alarm.*CPU.*|User.*logged.*"}

Find events for degraded MPIO path redundancy 
$events = Get-VIEvent -Start (Get-Date).AddDays(-1) | where {$_.fullFormattedMessage -match "Path redundancy to storage.*degraded"}

Report the date, host and description for MPIO path redundancy errors
foreach ($event in $events) {write-output ($event.createdTime.ToString() + "," + $event.host.get_name() + "," + $event.fullFormattedMessage)}

List a table of VI events with only the date and message
$events | format-table -wrap -autosize -property createdTime,fullFormattedMessage

List the physical networks adapters and the current link speed (ESX 4.0)
$hostSystem = get-view -ViewType HostSystem; $hostConfigManager = $hostSystem.get_ConfigManager(); $hostNetworkSystem = $hostConfigManager.get_NetworkSystem(); $netSystem = Get-View $hostNetworkSystem; $netSystem.NetworkConfig.pnic; foreach ($pnic in  $netSystem.NetworkConfig.pnic) {Write-Output ($pnic.Device + "," + $pnic.spec.linkspeed.SpeedMB)}

List the vSwitches and the uplinks currently attached
$hostSystem = get-view -ViewType HostSystem; $hostConfigManager = $hostSystem.get_ConfigManager(); $hostNetworkSystem = $hostConfigManager.get_NetworkSystem(); $netSystem = Get-View $hostNetworkSystem; foreach ($vswitch in  $netSystem.NetworkConfig.vSwitch) {Write-Output ($vSwitch.Name + "," + $vswitch.spec.policy.NicTeaming.NicOrder.ActiveNic)}

Remove snapshots from a group of machines
$VMs = Get-VM -Location (get-folder -name "vmFolder"); foreach ($vm in $vms) {remove-snapshot -snapshot (Get-Snapshot -vm $vm) -confirm:$false}

Take snapshots of a group of machines
$VMs = Get-VM -Location (get-folder -name "vmFolder"); foreach ($vm in $VMs) {New-Snapshot -Name "snapshot 01" -description "Snapshot description" -vm $vm -Quiesce:$false}

Find VM name, description and primary disk datastore
$VMs = get-vm; foreach ($vm in $VMs) {write-output ($vm.Name + ",""" + $vm.Description + """," + $vm.harddisks[0].FileName.Replace(" ", ",")) | out-file -append -filepath c:\temp\VM_Datastores.txt}

Bring a host out of maintenance most
Set-VMHost -VMHost esxHost -State Connected

Generate diagnostic support bundles for all hosts
get-log -vmhost (get-vmhost) -bundle -destinationpath c:\temp\bundles

Find the network adapter type for each VM
$vms = get-vm ; foreach ($vm in $vms) {write-host $vm.Name "-"  $vm.networkadapters[0].type}

Find physical NICs and whether they're set to autonegotiate or hardcoded
foreach ($pnic in $hostNetwork.pnic) {if($pnic.linkSpeed -eq $null) {$ls = "Auto"} else {$ls= $pnic.linkSpeed.speedMB.toString() + ":" + $pnic.linkSpeed.duplex} ;write-output ($pnic.Device + "," + $ls)}

Find host sytem build information
$hostSystems = get-view -ViewType HostSystem; foreach ($hostSystem in $hostSystems) {Write-Output ($hostSystem.Name + "," + $hostSystem.config.product.Fullname)}

Find VMs and whether the VMtools is configured to synchronising time 
$vmSet = Get-VM ; foreach ($vm in $vmSet) { $view = get-view $vm.ID ;$config = $view.config; $tools = $config.tools; Write-Output ($vm.Name + "," + $tools.SyncTimeWithHost) }

Revert to a snapshot
set-vm -vm vmName -snapshot (get-snapshot -vm vmName) -confirm:$false

Remove a virtual machine from inventory and delete from disk
remove-vm -DeleteFromDisk:$true -RunAsync:$true -vm vmName

Shutdown one or more Virtual Machine guests
shutdown-vmguest -vm $vms -confirm:$false

Start one or more Virtual Machine guests
start-vm -vm $vms -confirm:$false

Forcefully power off one or more Virtual Machines
stop-vm $vms -confirm:$false

Get a virtual switch from the specified ESX host
get-virtualswitch -name vSwitch1 -vmhost esxHost

Create a new port group on the specified vSwitch
New-VirtualPortGroup -Name "pgName" -VirtualSwitch $vs

Find ESX memory balloon averages for the last five days
get-stat -entity $hosts -start (Get-Date).AddDays(-5) -finish (Get-Date) -stat mem.vmmemctl.average

Export a list of VMs
$vms | select-object -prop Name | out-file -filepath c:\temp\vms.txt

Export a list of VM guest hostnames 
$vms = get-vm; foreach ($vm in $vms) { write-output $vm.guest.get_HostName()}


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Tuesday, October 13, 2009

Service Control Manager Security for non-admins

Allowing non-administrators rights for service control sounds deceptively simple, but unfortunately it’s not. After Windows Server 2003 SP1, the default rights are very focused on administrator-only access for service control.

This post describes how to view and modify the security descriptor for the Service Control Manager (SCM) and individual services as required.

Show the descriptor for SCM:
sc sdshow SCMANAGER

D:(A;;CC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)


In this case, the output shows that by default, Authenticated Users (AU) only have connect, but not enumerate (LC) for SCM.

If you want to allow a non-administrator to connect to the Service Control Manager and enumerate the services, you can modify the security descriptor by using something like the following command to add enumerate, read control and query lock status for Authenticated Users with SCM:
sc sdset SCMANAGER

D:(A;;CCLCRPRC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)


This allows connecting to the SCM and enumerating services. However, if the DACL on the individual services only allows administrators access to the services, then they still won’t be accessible. You’ll need to run specific 'sc sdset' commands against particular services, or use subinacl to change all services with one command.

Note that the sc.exe version with XP does not support this syntax – use the sc.exe on 2003 server.

For individual services, you could then allow query and interrogate with the following command:

subinacl /service \\server\* /grant=domain\user=QSI

Note that to map the ACE flags to the meaning with regards to service control, I went through the following process:

  1. Find the access rights from the flag, eg CC = SDDL_CREATE_CHILD = ADS_RIGHT_DS_CREATE_CHILD (ACE Strings link below)
  2. Find the constant matching this value, eg. 0x1 (ADS_RIGHTS_ENUM Enumeration link below)
  3. Match this to the SCM access right for the hexadecimal value, eg. 0x1 = SC_MANAGER_CONNECT (Service Security and Access Rights link below)
Map between sdshow output, right, hex value and SC/service meaning:

"CC"  ADS_RIGHT_DS_CREATE_CHILD          = 0x1,    SC_MANAGER_CONNECT, SERVICE_QUERY_CONFIG
"DC"  ADS_RIGHT_DS_DELETE_CHILD          = 0x2,    SC_MANAGER_CREATE_SERVICE, SERVICE_CHANGE_CONFIG
"LC"  ADS_RIGHT_ACTRL_DS_LIST            = 0x4,    SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_STATUS
"SW"  ADS_RIGHT_DS_SELF                  = 0x8,    SC_MANAGER_LOCK, SERVICE_ENUMERATE_DEPENDENTS
"RP"  ADS_RIGHT_DS_READ_PROP             = 0x10,   SC_MANAGER_QUERY_LOCK_STATUS, SERVICE_START, 
"WP"  ADS_RIGHT_DS_WRITE_PROP            = 0x20,   SC_MANAGER_MODIFY_BOOT_CONFIG, SERVICE_STOP
"DT"  ADS_RIGHT_DS_DELETE_TREE           = 0x40,   SERVICE_PAUSE_CONTINUE
"LO"  ADS_RIGHT_DS_LIST_OBJECT           = 0x80,   SERVICE_INTERROGATE
"CR"  ADS_RIGHT_DS_CONTROL_ACCESS        = 0x100   SERVICE_USER_DEFINED_CONTROL
"RC"  READ_CONTROL                       = 0x20000 READ_CONTROL



Access right Description for services and SCM:


SERVICE_QUERY_CONFIG (0x0001) Required to call the QueryServiceConfig and QueryServiceConfig2 functions to query the service configuration. 
SERVICE_CHANGE_CONFIG (0x0002) Required to call the ChangeServiceConfig or ChangeServiceConfig2 function to change the service configuration. Because this grants the caller the right to change the executable file that the system runs, it should be granted only to administrators.  
SERVICE_QUERY_STATUS (0x0004) Required to call the QueryServiceStatusEx function to ask the service control manager about the status of the service. 
SERVICE_ENUMERATE_DEPENDENTS (0x0008) Required to call the EnumDependentServices function to enumerate all the services dependent on the service. 
SERVICE_START (0x0010) Required to call the StartService function to start the service. 
SERVICE_STOP (0x0020) Required to call the ControlService function to stop the service. 
SERVICE_PAUSE_CONTINUE (0x0040) Required to call the ControlService function to pause or continue the service. 
SERVICE_INTERROGATE (0x0080) Required to call the ControlService function to ask the service to report its status immediately. 
SERVICE_USER_DEFINED_CONTROL(0x0100) Required to call the ControlService function to specify a user-defined control code. 
SERVICE_ALL_ACCESS (0xF01FF) Includes STANDARD_RIGHTS_REQUIRED in addition to all access rights in this table. 
READ_CONTROL Required to call the QueryServiceObjectSecurity function to query the security descriptor of the service object. 

SC_MANAGER_CONNECT (0x0001) Required to connect to the service control manager. 
SC_MANAGER_CREATE_SERVICE (0x0002) Required to call the CreateService function to create a service object and add it to the database. 
SC_MANAGER_ENUMERATE_SERVICE (0x0004) Required to call the EnumServicesStatusEx function to list the services that are in the database. 
SC_MANAGER_LOCK (0x0008) Required to call the LockServiceDatabase function to acquire a lock on the database. 
SC_MANAGER_QUERY_LOCK_STATUS (0x0010) 
SC_MANAGER_MODIFY_BOOT_CONFIG (0x0020) Required to call the NotifyBootConfigStatus function. 
SC_MANAGER_ALL_ACCESS (0xF003F) Includes STANDARD_RIGHTS_REQUIRED, in addition to all access rights in this table. 




Directory service object access rights


"RC"  SDDL_READ_CONTROL  READ_CONTROL 
"RP"  SDDL_READ_PROPERTY  ADS_RIGHT_DS_READ_PROP  
"WP"  SDDL_WRITE_PROPERTY  ADS_RIGHT_DS_WRITE_PROP  
"CC"  SDDL_CREATE_CHILD  ADS_RIGHT_DS_CREATE_CHILD  
"DC"  SDDL_DELETE_CHILD  ADS_RIGHT_DS_DELETE_CHILD  
"LC"  SDDL_LIST_CHILDREN  ADS_RIGHT_ACTRL_DS_LIST  
"SW"  SDDL_SELF_WRITE  ADS_RIGHT_DS_SELF  
"LO"  SDDL_LIST_OBJECT  ADS_RIGHT_DS_LIST_OBJECT  
"DT"  SDDL_DELETE_TREE  ADS_RIGHT_DS_DELETE_TREE  
"CR"  SDDL_CONTROL_ACCESS  ADS_RIGHT_DS_CONTROL_ACCESS  



ADS enum:


typedef enum  {
  ADS_RIGHT_DS_CREATE_CHILD          = 0x1,
  ADS_RIGHT_DS_DELETE_CHILD          = 0x2,
  ADS_RIGHT_ACTRL_DS_LIST            = 0x4,
  ADS_RIGHT_DS_SELF                  = 0x8,
  ADS_RIGHT_DS_READ_PROP             = 0x10,
  ADS_RIGHT_DS_WRITE_PROP            = 0x20,
  ADS_RIGHT_DS_DELETE_TREE           = 0x40,
  ADS_RIGHT_DS_LIST_OBJECT           = 0x80,
  ADS_RIGHT_DS_CONTROL_ACCESS        = 0x100 

} ADS_RIGHTS_ENUM;

READ_CONTROL = 0x20000;




References:

Applying Security Descriptors on the Device Object
http://msdn.microsoft.com/en-us/library/ms793368.aspx

Non-administrators cannot remotely access the Service Control Manager after you install Windows Server 2003 Service Pack 1
http://support.microsoft.com/default.aspx?scid=kb;EN-US;907460

Securing a Remote WMI Connection
http://msdn.microsoft.com/en-us/library/aa393266(VS.85).aspx

Configuring a Report Server for Remote Administration
http://msdn.microsoft.com/en-us/library/ms365170(SQL.90).aspx

Service Security and Access Rights
http://msdn.microsoft.com/en-us/library/ms685981(VS.85).aspx

How to grant users rights to manage services in Windows 2000
http://support.microsoft.com/kb/288129

How to troubleshoot WMI-related issues in Windows XP SP2
http://support.microsoft.com/kb/875605

ACE Strings
http://msdn.microsoft.com/en-us/library/aa374928(VS.85).aspx

ADS_RIGHTS_ENUM Enumeration
http://msdn.microsoft.com/en-us/library/aa772285(VS.85).aspx



Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Wednesday, September 30, 2009

VMware Command-Line Interface commands

The Windows command-line interface provided for managing ESX/ESXi systems is an invaluable tool for managing ESX infrastructure at the command-line. When using ESXi without a service console the CLI becomes even more useful.

I've gathered these commands while implementing and managing ESXi 4.0 clusters, use with caution on any production system.

ESXi 4.0 RCLI:


List the NTP servers used by the host
vicfg-ntp.pl --server esx01 --list

Add a Software iSCSI NIC named vmk2
esxcli --server=esx01 swiscsi nic add -n vmk2 -d vmhba33

List the Software iSCSI NICs
esxcli --server=esx01 swiscsi nic list -d vmhba33

List the software iSCSI status on a host
vicfg-iscsi.pl --server esx01 --swiscsi --list

Enable software iSCSI on an ESX host
vicfg-iscsi.pl --server esx01 --swiscsi --enable

List the adapters bound to software iSCSI
esxcli --server=esx01 swiscsi nic list -d vmhba33

List the VMKernel NICs
vicfg-vmknic.pl --server esx01 --list

List the software iSCSI adapters
vicfg-iscsi.pl --server esx01 --adapter --list

Set the iSCSI alias for the specified adapter
vicfg-iscsi.pl --server esx01 --iscsiname --alias esx01 vmhba33

Bind a VMK software iSCSI NIC for MPIO PSA
esxcli --server=esx01 swiscsi nic add -n vmk2 -d vmhba33

Rescan a storage adapter bus
vicfg-rescan.pl --server esx01 vmhba33

Add a dynamic iSCSI discovery target
vicfg-iscsi.pl --server esx01 --discovery --add --ip 10.1.1.10:3260 vmhba33

Add CHAP authentication to an iSCSI discovery target
vicfg-iscsi.pl --server esx01 --authentication --level chapRequired --method CHAP --auth_username esxchap --auth_password chapacc3ss80 --ip 10.2.128.33:3260 vmhba33

Find the current ScratchConfig scratch location
vicfg-advcfg.pl --server esx01 -g ScratchConfig.ConfiguredScratchLocation

Set the scratch location for ESXi
vicfg-advcfg.pl --server esx01 -s "/vmfs/volumes/esxds01/Scratch/esx01" ScratchConfig.ConfiguredScratchLocation

Check if CIM OEM providers are enabled (such as Dell OM)
vicfg-advcfg.pl --server esx01 -g UserVars.CIMOEMProvidersEnabled

Enable CIM OEM Providers (such as Dell OM)
vicfg-advcfg.pl --server esx01 -s "1" UserVars.CIMOEMProvidersEnabled

Query the patches/updates/bulletins/VIBs installed on ESXi
vihostupdate.pl --server esx01 -q

Set the SNMP community for the ESXi host
vicfg-snmp.pl --server esx01 -c public

Enable the SNMP agent on an ESXi host
vicfg-snmp.pl --server esx01 -E

List the iSCSI node name
vicfg-iscsi.pl --server esx01 --list --iscsiname --adapter vmhba36

List the preferred nativte multipathing (NMP) path for a device
 esxcli --server esx01 nmp fixed getpreferred -d naa.6090332880cfdc44fda634b1ca2457b8

Check whether round robin path selection is used for a device
esxcli --server esx01 nmp roundrobin getconfig -d naa.6090a02833cfdc7ffd4434b1ca5457b8 

List the disk NAA/UUIDs known to a host
esxcli --server esx01 nmp device list

List the MPIO path to device mapping
esxcfg-mpath.pl --server esx01 -m

List the SCSI devices known to a host
vicfg-scsidevs.pl --server esx01 --list   

List the available datastores on a host
vifs.pl --server esx01 --listds

List the contents of a datastore
 vifs.pl --server esx01 --dir [datastore]

Upload a local file to a datastore through vifs
vifs.pl --server esx01 --put c:\temp\file.txt dir/file.txt?dsName=datastoreName

List virtual switches, port groups, uplinks and MTU
vicfg-vswitch.pl -l --server esx01

Browse the datastores or local host through ssl
https://esx01/folder or https://esx01/host

Find the vmnic configuration, including driver, current speed
vicfg-nics.pl --server esx01 -l 

Set a vNIC to auto-negotiate
vicfg-nics.pl --server esx01 --vihost esx01 -a vmnic0

List the host-based files on an ESXi client
vifs.pl --server esx01 --dir /host  



A few other useful VMware tips:

Recreate the rui.pfx file for VirtualCenter
openssl pkcs12 -export -in rui.crt -inkey rui.key -name rui -passout pass:testpassword -out rui.pfx

Forcefully power off a suspended VM
Delete the vmss file, and then power on the VM (state is lost)

ESXi 4.0, access unsupported ssh console through the dcui
Press Alt+F1, type unsupported, then the root password


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Sunday, September 20, 2009

More useful command-lines

This is the second edition of useful command lines, adding another 132 commands that I've found useful. Note that many of the command-line calls may require Microsoft utilities (such as dsquery, wmic, dnscmd).

Most of the commands are for the windows-based command interpreter, with a few PowerShell and ESX service console commands creeping in. They range from diagnostics, troubleshooting and simply automating recurring tasks.

Each command-line can be copied and pasted at the command prompt, if you use a batch file you'll need to reference variables with double-percent (%%).

See the original post with another 425 commands http://waynes-world-it.blogspot.com/2008/09/useful-command-lines.html



Given an IP and mask, return the subet the IP belongs to
for /f "tokens=1-8 delims=.- " %i in ('echo 192.168.5.200 255.255.255.0') do set /a Octet1="%i & %m" >nul & set /a Octet2="%j & %n" >nul & set /a Octet3="%k & %o" >nul & set /a Octet4="%l & %p" >nul & Echo %i.%j.%k.%l,!Octet1!.!Octet2!.!Octet3!.!Octet4!,%m.%n.%o.%p

Display the contents of the client DNS resolver cache
ipconfig /displaydns

Find the package source path of a program from SMS
wmic /namespace:\\root\sms\site_%sitecode% /node:"server" path SMS_Package Where "Name like '%programname%'" get Name,ShareName,PkgSourcePath

Find the session associated with a process
wmic path win32_process get name,sessionid

List the local winstation windows objects
objdir \Windows\Windowstations\Winsta0

Query the configuration container for Exchange mailbox stores
dsquery * ",CN=Configuration,DC=domainroot" -filter "(&(objectClass=msExchPrivateMDB)(objectCategory=msExchPrivateMDB))"

Query a Virtual Centre/VC 2.5 database for Virtual Machine details
sqlcmd -S server -d database -W -s "," -Q "select ENT.Name as 'Name', Lower(DNS_Name) as 'DNS Name', Guest_OS as 'OS', Mem_Size_MB as 'Mem', Num_VCPU as 'CPU', Num_NIC as 'NIC', IP_Address as 'IP', NET.MAC_Address as 'MAC Address', VM.FILE_Name as 'VMX location' from vpx_vm VM inner join VPX_NIC NET on VM.ID = NET.ENTITY_ID inner join VPX_ENTITY ENT on VM.ID = ENT.ID Order By ENT.Name"

Query a Virtual Centre/VC 2.5 database for Virtual Machine snapshots (GMT+10)
sqlcmd -S server -d database -W -s "," -Q "select ENT.Name as 'Name', Lower(DNS_Name) as 'DNS Name', Guest_OS as 'OS', Mem_Size_MB as 'Mem', IP_Address as 'IP', VM.FILE_Name as 'VMX location', VM.Suspend_Time as 'Suspend Time', VM.Suspend_Interval as 'Suspend Interval', VMS.Snapshot_Name as 'Snapshot Name', VMS.Snapshot_Desc 'Snapshot Description', DateAdd(Hour, 10, VMS.Create_Time) as 'Snapshot Time', VMS.Is_Current_Snapshot 'Current Snapshot' from vpx_vm VM inner join VPX_NIC NET on VM.ID = NET.ENTITY_ID inner join VPX_ENTITY ENT on VM.ID = ENT.ID inner join VPX_SNAPSHOT VMS on VM.ID = VMS.VM_ID"

Test the password for a domain account (assumes no existing IPC connection)
net use \\server\ipc$ /user:%domain%\%testuser% *

View the last-access, modified, created and MFT entry modified timestampes
timestomp "%fullpathtoFile%" -v

Create a scheduled task escaped with a command containing double-quotes (2003)
schtasks /create /SC Daily /TN "Task" /ST 12:00 /TR "cmd /c echo \"Test\"" /RU System

Create a scheduled task running two commands
schtasks /create /SC Daily /TN "Task" /ST 12:00 /TR "cmd /c echo Test1 & cmd /c echo Test2" /RU System

Check a number of computers to see if hibernation is enabled
for /f %i in (%controlfile%.txt) do @if exist \\%~i\c$\hiberfil.sys (echo %~i,Enabled) else (echo %~i,Disabled)

For each path in a control file, list the 8.3 short equivalent
for /f "tokens=*" %i in (test.txt) do echo %~si

Use if exist and disabled path parsing to bypass max_path
for /f "tokens=*" %i in (test.txt) do if exist "\\?\UNC\%~pnxi" echo File exists

Enumerate a cluster through WMI
wmic /node:"%node%" /namespace:\\root\mscluster path MSCluster_Cluster

Given a path exceeding MAX_PATH, return the 8.3 equivalent of the directories
for /f "tokens=*" %i in (longfiles.txt) do for /d %m in ("\\%~pi") do echo %~sm%~nxi

Given a path you know contains deeper than 260, batch to return the 8.3 subdirs
(3 lines) @for /f "tokens=*" %%i in (c:\temp\longdir1.txt) do @for /d %%m in ("\\%%~pi") do @Call :Process "%%~si" || :process || @if "%~1"=="" (goto :EOF) else (@for /d %%i in ("%~1\*.*") do @echo %%~si & Call :Process "%%~si")

Set a Domain Controller to be a Global Catalog server
dsmod server "%DC_DN%" -isgc yes

Check which network connections (drive mappings) a computer has
wmic /node:"%computer%" path win32_logicaldisk where "DriveType=4" get DeviceID,ProviderName 

Query the current site of a remote computer using nltest
nltest /dsgetsite /server:%computer%

Query the current site of a remote computer using the registry
reg query \\%computer%\hklm\system\currentcontrolset\services\netlogon\parameters /v DynamicSiteName

Check the schema version on a Domain Controller (R2=31)
reg query \\%dc%\hklm\system\currentcontrolset\services\NTDS\parameters /v "Schema Version"

Query the revision of 2003 Update (R2=9)
dsquery * CN=Windows2003Update,CN=ForestUpdates,CN=Configuration,%forestRoot% -attr revision

Check the schema version on a Domain Controller (R2=31)
dsquery * "CN=Schema,CN=Configuration,%forestRoot%" -attr objectVersion -scope base   

Find the disk signature of a disk through diskpart
echo select disk 0 > %temp%\diskpart.txt & echo detail disk >> %temp%\diskpart.txt & diskpart /s %temp%\diskpart.txt | find /i "Disk ID:"

Search a dnscmd export for duplicate IP address references
for /f "tokens=1,5" %i in (DNSExport.txt) do @if "%j" NEQ "" @for /f "tokens=1" %m in ('"findstr /i "%j$" DNSExport.txt find /i /c "%j""') do @if %m GTR 1 @echo %i,%j,%m

Search and report duplicate IPs from a dnscmd export
for /f "tokens=1,4" %i in (DNSExport.txt) do @if "%j" NEQ "" @for /f "tokens=1" %m in ('"findstr /i "%j$" DNSExport.txt find /i /c "%j""') do @if %m GTR 1 (@echo %j,%m: & findstr /i "%j$" DNSExport.txt & echo.)

Dump the dfsr config from the active directory
dfsrdiag dumpadcfg

Remove Outlook 2003 prevention of PST usage
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\11.0\Outlook /v DisablePST /t reg_dword /d 0x0 

Set the command prompt to include the time of the last command
prompt $t $p$g

Create a zero byte file
echo file 2>zero.txt

Given a list of files, echo those that are zero bytes in size
for %i in (%source%\*) do @if %~zi == 0 @echo %i

From a dnscmd export, find duplicate IP addresses
echo. > DuplicateIPs.txt & (for /f "tokens=1,4" %i in (DNSRecords.txt) do @if "%j" NEQ "" @find /i "%j" DuplicateIPs.txt >nul & if errorlevel 1 for /f "tokens=1" %m in ('"findstr /i "%j$" DNSRecords.txt | find /i /c "%j""') do @if %m GTR 1 (@echo %j,%m: & findstr /i "%j$" DNSRecords.txt & echo.) >> DuplicateIPs.txt) & type DuplicateIPs.txt

Start xperf performance tracing using the 'Diag' group
xperf -start -on Diag -f %temp%\tracing.etl 

Open an xperf trace, exporting context switching for threads and processes
xperf -i %temp%\tracing.etl -a cswitch -thread -process

Check whether VMware VMFS partitions are block aligned to 128
/sbin/fdisk -lu

Query a Virtual Centre/VC 2.5 database for Consolidation performance stats
sqlcmd -S server -d virtualcenter -W -s "," -Q "Select Top 6 ip_address as 'IP', cpu_mhz_avg/1000 as 'CPU', mem_mb_avg/1000 as 'RAM' , disk_percent_avg/1000 as 'Disk' from vpx_csl_system_perf vPERF inner join vpx_csl_system_ip_address vIP on vPERF.System_ID = vIP.system_ID order by sample_time desc"

Identify Virtual Machines that are currently powered on
/usr/sbin/vcbVmName -h %server% -u username -s powerstate:on

Find OCS 2007 classes/attributes in AD
dsquery * "CN=Schema,CN=Configuration,DC=forestRoot" -filter "(&((cn=*rtc*)(|(objectCategory=classSchema)(objectCategory=attributeSchema))))"

Find OCS 2007 server from DNS service records
nslookup -type=srv _SipInternalTLS._tcp.{FQDN}

Find OCS 2007 Pools published in the current directory
dsquery * -filter "(objectClass=msRTCSIP-Pools)"

Find OCS 2007 SCPs from the local domain
dsquery * "CN=Pools,CN=RTC Service,CN=Microsoft,CN=System,DC=domainRoot" -attr *

Export config from OCS 2007 from a remote server
lcscmd /config /action:export /level:machine /configfile:config.xml /fqdn:%server%

IIS Authentication and Access Control Diagnostics
authdiag.exe

Find the number of VMs per datastore from the VC database
sqlcmd -S server -d virtualcenter -W -s "," -Q "select DS.name, Count(VMDS.VM_ID) as 'VMs' from vpxv_vm_datastore VMDS inner join vpx_datastore DS on VMDS.DS_ID = DS.ID group by DS.name" 

Find detail on the VMs per datastore from the VC database
sqlcmd -S server -d virtualcenter -W -s "," -Q "select DS.name, VMS.Name from vpxv_vm_datastore VMDS inner join vpx_datastore DS on VMDS.DS_ID = DS.ID inner join vpxv_vms VMS on VMDS.VM_ID = VMS.VMID order by DS.Name"

Unattended install of IIS (assuming INF created with relevant [components])
Sysocmgr.exe /i:%windir%\inf\sysoc.inf /u:%iisComponents%.inf

Find the Exchange 2003 organization from AD
dsquery * forestroot -filter "(&(objectCategory=msExchOrganizationContainer))"

Mount a virtual floppy
vfd install & vfd start & vfd open

Send an SMTP mail using blat
blat -f smtprelay@relay.local -to user@domain.com -subject Test -body "Test body" -server smtprelay

Create MAPI profiles with an Exchange connection on a server without Outlook
profman2.exe

Find mailboxes that are excluded from Recipient Update Policies
dsquery * -filter "(&(objectClass=User)(objectCategory=Person)(msExchPoliciesExcluded=*))" -attr cn msExchPoliciesExcluded | find /i "{26491CFC-9E50-4857-861B-0CB8DF22B5D7}"

Export a connector space from MIIS/IIFP to XML
csexport %maName% maExport.xml

IIFP permissions, write proxyAddresses to user objects, inherited to subobjects
dsacls "OU=%targetOU%,%domainRoot%" /I:S /G %DOMAIN%\%GROUP%:WP;proxyAddresses;user

IIFP permissions, create and delete contact objects, inherited to subobjects
dsacls "OU=%targetOU%,%domainRoot%" /I:S /G %DOMAIN%\%GROUP%:CCDC;contact

IIFP permissions, read/write all properties, inherited to subobjects
dsacls "OU=%targetOU%,%domainRoot%" /I:S /G %DOMAIN%\%GROUP%:RPWP;;contact

Find extended rights in the directory that apply to schema classes
dsquery * "CN=Extended-Rights,CN=Configuration,dc=forestRoot" -attr displayName CN

Trigger the SD propagator adminsdholder process in a domain
admod -rootdse "FixUpInheritance::1"

Set interrupt processor affinity for PnP drivers
intfiltr.exe

Set interrupt processor affinity for processes persistent across reboots
imagecfg.exe -a 0xF calc.exe (the mask to use the first four logical processors)

Start an executable with the specified processor affinity
start /affinity f calc.exe (the mask to use the first four logical processors)

Modify a server to use only one processor
boot.ini, add /onecpu switch

Query DC/DNS servers and find unconditional non-ds forwarders
for /f %i in ('dsquery server -domain %userdnsdomain% -o rdn') do @for /f "tokens=1,3" %m in ('"dnscmd %i /info > DNS_%i.txt & tail -5 DNS_%i.txt | find /i "addr[" | find /i "addr""') do @echo %~ni,%m,%n

Create an Active Directory integrated DNS conditional forwarder (5.2.3790.0)
dnscmd /ZoneAdd %targetDomain% /DsForwarder %targetDomainNSIP%

Find DNS forwarder zones
dnscmd %server% /enumzones /forwarder

Find DNS forwarder targets
for /f %i in ('"dnscmd %server% /enumzones /forwarder | find /i "forwarder""') do dnscmd %server% /zoneinfo %i | find /i "master"

Find AdminSDHolder groups with GROUP_TYPE_SECURITY_ENABLED
dsquery * domainroot -filter "(&(objectCategory=Group)(objectClass=Group)(groupType:1.2.840.113556.1.4.803:=2147483648))"

Query an MIIS/IIFP database to find the management agent AD configuration
select ma_name, private_configuration_xml from mms_management_agent

Check the MIIS/IIFP GALSync.xml file to find the management agent AD config
Extensions\GALSync.xml

Query an MIIS/IIFP database to find the management agent AD containers to sync
select filter_xml from mms_partition MMSP inner join mms_management_agent MMSA on MMSP.ma_id = MMSA.ma_id where ma_name = 'MA-NAME' and partition_name = 'DC=domainRoot'

Set the IP address of a machine using netsh
netsh interface ip set address name="Local Area Connection" source=static addr=192.168.0.10 mask=255.255.255.0 gateway=192.168.0.1 1

Set local DNS client primary using netsh
netsh interface ip add dns name="Local Area Connection" addr=192.168.0.10 index=1

Set local DNS client secondary using netsh
netsh interface ip add dns name="Local Area Connection" addr=192.168.0.11 index=2

Set local WINS client primary using netsh
netsh interface ip add wins name="Local Area Connection" addr="192.168.0.10" index=1

Set local WINS client secondary using netsh
netsh interface ip add wins name="Local Area Connection" addr="192.168.0.11" index=2

Modify service DACLs to allow service start stop (assumes query already exists)
subinacl /service schedule /grant=builtin\users=TO

User cmdkey to add a stored credential when connecting to a remote server
cmdkey /add:remote.domain.com /user:domain\user /pass:*

Find the holders of the specified NT right / privilege
showpriv SeProfileSingleProcessPrivilege

Query the privileges the current user holds
whoami /priv

Delete the policy restriction to run adsiedit.msc
reg delete "HKCU\Software\Policies\Microsoft\MMC\{1C5DACFA-16BA-11D2-81D0-0000F87A7AA3}"

Stop and then restart the ESX software iSCSI initiator
/usr/sbin/esxcfg-swiscsi -d | /usr/sbin/esxcfg-swiscsi -e

Reset a computer account secure channel
nltest /sc_reset:%domain%[\%dc%]

Reset the password for a computer account
nltest /sc_change_pwd:%domain%

CSV directory export of one or more subcontainers of a container
for /f %i in ('"dsquery ou OU=People,DC=domainRoot -scope onelevel -o rdn"') do csvde -f UserExport-%~i.csv -l givenName,sn,displayname,mail,targetAddress,proxyAddresses,mailnickname -d "OU=%~i,OU=People,DC=domainRoot" -r "(&(objectClass=Contact)(objectCategory=Person))"

Query VMFS volume information from the service console
/usr/sbin/vmkfstools -P /vmfs/volumes/%GUID%

Change the volume label of a disk
label %drive%: %newlabel%

Find VMware CDP info from the service console
esxcfg-info | grep -C 18 '\==+CDP Summary'

Add a non expiring enabled user account to the Active Directory
dsadd user "CN=user,OU=Users,DC=test,DC=com" -pwd "password" -pwdneverExpires yes -disabled no -desc "Description"

Clear local DNS client settings using netsh
netsh interface ip delete dns name="Local Area Connection" addr=ALL

From an ESX service console, scan for updates from a depot for UpdateManager
/usr/sbin/esxupdate --HA --flushcache -d http://esx01/vci/hostupdates/hostupdate/esx/esx-3.5.0 scan

Check the VI35 Legato AAM HA agent
cat /var/log/vmware/aam/aam_config_util_addnode.log

VMware VI35 HA Legato AAM, list the cluster manager
/opt/vmware/aam/bin/ftcli -domain vmware -timeout 60 -cmd "listrules"

VMware VI35 HA Legato AAM, list the cluster nodes
/opt/vmware/aam/bin/ftcli -domain vmware -connect esx01 -port 8042 -timeout 60 -cmd "listnodes"

VMware ESX VI35 List the software iSCSI targets
/usr/sbin/vmkiscsi-tool -L -l vmhba32

Mount a local volume inside a local folder
mountvol c:\temp\mount1 \\?\Volume{f856ff87-70ae-11dc-8b8d-806d6172696f}\

Remove a mount point
mountvol C:\temp\mount1\ /d

List junctions or mount points
junction -s c:\temp

Find the boot device for an ESX installation
esxcfg-info -s | grep -A10 "Diagnostic Partition"

Find the boot device for an ESX installation
esxcfg-info -s | egrep -A4 "Parallel SCSI Interface|Block SCSI Interface"

Use vSphere RCLI to list an ESXi host filesystem
vifs.pl --server %server% --username %username% --password %password% -D /host

Use vSphere RCLI to backup an ESXi host (esxcfg-cfgbackup.pl)
vicfg-cfgbackup.pl --server %server% --username %username% --password %password% -s server.tgz

ESX VI35 list the virtual machines and their disks for performance analysis
/usr/lib/vmware/bin/vscsiStats -l

ESX VI35 gather disk statistics and display the latency histogram in CSV
/usr/lib/vmware/bin/vscsiStats -s; /usr/lib/vmware/bin/vscsiStats -x; /usr/lib/vmware/bin/vscsiStats -p latency -c;

Get Windows Remote Management config on the local machine
winrm get winrm/config

Windows Remote Management quick configuration to create a listener
winrm quickconfig

Test Windows Remote Management listener on the local host
winrm id

Create a Windows Remote Management https listener on the local host
winrm quickconfig -transport:https

Create a self-signed certificate
makecert" -r -pe -n -r 30/12/2039 -eku 1.3.6.1.5.5.7.3.1 -ss my-sr localMachine -sky Exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 c:\temp\test.cer

Query the SNTP servers a comptuer is using for time synchronisation
net time \\server /querysntp   

Set the SNTP servers used for w32time synchronistaion
net time \\server /setsntp:"192.168.0.10 192.168.0.11"

Convert time from 100 nanosecond intervals since epoch 01/01/1601
w32tm /ntte 127076450620627215

Install the w32time Windows Time service
w32tm /register

Enable NTP Server for a w32time service
reg add \\server\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer /v Enabled /t reg_dword /d 0x1 /f

Find the error description given a win32 error number
net helpmsg 2

Delete the policy value controlling whether recently run programs are recorded
reg delete HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer /v NoRecentDocsHistory

Set registry permissions (subinacl 5.2.3790.1180 or later)
subinacl /keyreg "\\server\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /grant=domain\group=F

Set service DACLs (Q : Query SC, S: status, I: interrogate, T: Start, O: Stop)
subinacl /service \\server\schedule /grant=domain\group=TOQSI

Rename a LAN interface name (ncpa.cpl)
netsh interface set int name="Local Area Connection 2" newname="Local Area Connection"

Find all network devices
devcon findall =net

Find all network adapters for the Net class
devcon listclass net

Remove an old VMware VI3 PCNET Flexible/VLance/VMXNET adapter instance (@)
devcon remove "@PCI\VEN_1022&DEV_2000&SUBSYS_20001022&REV_10\3&61AAA01&0&88"

Find where a file is in the path
for %i in (calc.exe) do echo %~$PATH:i

Find the physical disk sector size
wmic path win32_diskdrive get BytesPerSector

Find the current amount of memory used by the file system virtual cache
wmic path Win32_PerfFormattedData_PerfOS_Memory get SystemCacheResidentBytes

Use robocopy in backup mode to take a copy of folder-level permissions
Robocopy \\server\source c:\temp\copy zxcvsadfqwer /E /B /COPYALL /R:1 /W:1

Find remote shares and paths using WMI
wmic /node:%server% path win32_share get Name,Path,Description

Find total memory, free memory and used paging file
wmic /node:%server% path Win32_OperatingSystem Get FreePhysicalMemory,FreeSpaceInPagingFiles,TotalVirtualMemorySize,TotalVisibleMemorySize

Search a remote computer's registry for a string
regfind -m \\%server% -y -b -n search_string

Set a computer to use a specified number of available processors
modify boot.ini, use the /NUMPROC=x switch or /ONECPU switch

Check the Exchange ESE buffer cache size
dsquery * "CN=InformationStore,CN=exchserver01,CN=Servers,CN=AdminGroup01,CN=Administrative Groups,CN=organisation,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domainRoot" -attr msExchESEParamCacheSizeMax -scope base

Query the start of authority record for a DNS zone
dnscmd %server% /enumrecords %fqdn% @ /type SOA


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Tuesday, August 11, 2009

VMware PowerCLI - Reconfigure cluster options

The following script contains a simple example of how to modify the configuration of a cluster – in this case to add two advanced options to the HA settings. This uses the new ClusterConfigSpecEx object, which can be used with the more generic function to reconfigure a resource – ReconfigureComputeResource().

The options set in this example are the das.allowNetworkX options, configuring HA to set specific management networks/service consoles that are used for HA communication and heartbeats.

Consider the following scenario for a reason why you might want to use these options:

  1. Software iSCSI with ESX 3.x – using the service console for authentication, meaning you need a service console on your iSCSI network (or routes between your corporate network and iSCSI). The standard result is that HA could be used across this interface.
  2. You are progressing with an upgrade to ESXi 4.0, still using software iSCSI, which is improved to remove the need for a management interface on your iSCSI network
  3. You put an ESX 3.5 and ESXi 4.0 host in the same cluster, HA no longer works because your iSCSI service console on ESX 3.5 can’t talk to your ESXi 4.0 host.
  4. Adding the two options above (with names changed appropriately) would force HA to use the service console on ESX 3.5 and the equivalent management network on ESXi 4.0, ignoring the iSCSI service console on 3.5 - resolving HA issues.



# http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.ComputeResource.html#reconfigureEx
# http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.cluster.DasConfigInfo.html#field_detail

param (
    $vcServerName = ""
)

$viServer = Connect-VIServer -server $vcServerName

$optionValue = New-Object Vmware.Vim.OptionValue
$optionValue.Key = "das.allowNetwork0"
$optionValue.Value = "Service Console"

$optionValue2 = New-Object Vmware.Vim.OptionValue
$optionValue2.Key = "das.allowNetwork1"
$optionValue2.Value = "Management Network"

[Vmware.Vim.OptionValue[]]$optionValues = $optionvalue, $optionValue2  # Create the array of the two new option values

$cluster = get-cluster -Name 'Cluster01'     # Get the cluster
$clusterview = get-view $cluster.Id      # Get the SDK object from the PowerCli object MO

$spec = New-Object Vmware.Vim.ClusterConfigSpecEx
$spec.dasConfig = New-Object Vmware.Vim.ClusterDasConfigInfo   # New VMware HA config

$spec.dasConfig.option = $optionValues      # Add the array of optionValues
$clusterview.ReconfigureComputeResource($spec, $true)    # Modify the configuration. When configuring clusters, can be a ClusterConfigSpecEx object


# Check the settings were saved

$cluster = get-cluster -Name 'Cluster01'     # Get the cluster
$clusterview = get-view $cluster.Id      # Get the SDK object from the PowerCli object MO

$clusterview.Configuration.dasConfig.Option | format-list   # Retrieve the advanced options


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

VMware PowerCLI - Backup ESXi 4.0 firmware

The following script contains a simple function to use the VMware vSphere PowerCLI to connect to a vCenter and/or ESXi 4.0 host and backup the 'firmware' - the configuration of the ESX host. I don’t think this functionality is exposed directly through the PowerCLI, so a call to the very useful Get-View function is used to get the VI SDK object to call the appropriate method.

From what I can tell all this command does is generate a config dump on the server and return the HTTP URL to access the file download, which I’m then using the .Net web client object to download the file and store as the filename returned with a unique date suffix.

This certainly isn’t original, all I did was look at the vicfg-backup.pl perl RCLI script and (badly) translate to PowerCLI from there.


#
# Description:
#  Backup the firmware configuration on an ESXi 4.0 host
#
# Limitations:
#  -
#
# Assumptions, this script works on the assumption that:
#  The caller provides credentials with permissions to connect to the specified host
#
# Arguments:
#  esxServer, the ESX host to connect to, eg. esx01
#  vcServerName, The vCenter Server to connect to, eg vc01
#  outputDir, The directory to write the backup file to, defaults to %temp%
#  username, The username to use when connecting to the vCenter server (if specified), defaults to %username%
#  password, The password to use for the connection to vCenter, secure string prompt by default
#
# Usage:
#  PowerShell . .\BackupFirmware.ps1 -esxServer 'esx01'
#  PowerShell . .\BackupFirmware.ps1 -esxServer 'esx01' -vcServer vc01 -u domain\username
#
# References:
#  http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.host.FirmwareSystem.html
#
# Changes:
#  04/07/2009, Wayne Martin, initial version

#$ErrorActionPreference = "Continue"


param (
    $esxServer = "",
    $vcServerName = "",

    $outputDir = $env:Temp,

    $username = $env:username,
    $password = ""
)

if ($password -eq "" -and !($pass)) {
    write-output "No password specified from the command-line"
    $pass = Read-Host "Password?" -assecurestring
    $credential = new-object System.Management.Automation.PSCredential($username,$pass)    
}

if ($esxServer -eq "" -OR ($vcServerName -eq "" -and $esxServer -eq "")) {
    Write-Output "Please specify either a standalone host, or a host and a cluster"
    Exit 2
}

$viServer = $null


function BackupConfiguration([string] $vcServerName, [string] $esxServer, [string] $outputDir){
    $hostSystem = get-view -ViewType HostSystem -Filter @{"Name" = $esxServer}    # Find the .Net view of the specified host

    $hostConfigManager = $hostSystem.get_ConfigManager()      # Get the config manager
    $hostfirmwareSystem = $hostConfigManager.get_firmwareSystem()     # Find the MOR of the host firmware system

    $hostfirmware = Get-View $hostfirmwareSystem        # Get the VMware.Vim.HostFirmwareSystem object from the MOR

    $backupDownload = $hostfirmware.BackupFirmwareConfiguration()     # Call the backup method to generate the config bundle

    $backupDownload = $backupDownload.Replace("*", $esxServer)      # Replace '*' with the server name

    Write-Output "Backup saved to $backupDownload on the ESX host"
    $fileName = $backupDownload.SubString($backupDownload.LastIndexOf("/")+1)    # Extract the filename to reuse
    $fileType = $fileName.SubString($fileName.LastIndexOf("."))      # Find the extension (.tgz in this case)

    $Now = [DateTime]::Now.ToString("yyyyMMddTHHmmss")          # Unique identifier for the filename
    $file = $fileName.SubString(0, $fileName.Length - $fileType.Length)     # File name without extension
    $outputFile = $outputDir + "\" + $file + "_" + $Now + $fileType     # Construct the full filename path\bundle_date.tgz

    $wc = new-object system.net.WebClient        # use the .Net web client
    $wc.DownloadFile($backupDownload, $outputFile)       # Download the file from the URL returned

    if (test-path -path $outputFile) {         # Does the output file exist?
        Write-Output "$outputFile downloaded"
    } else {
        Write-Output "Error: $outputFile was not downloaded from $backupDownload"
    }

}

if ($vcServerName -ne "") {
    $viServer = Connect-VIServer -server $vcServerName -Credential $credential
} elseif ($esxServer -ne "") {
    $esxServer = Connect-VIServer -server $esxServer       # connect to VC
}


$results = ""
$results = BackupConfiguration $vcServerName $esxServer $outputDir

$results

if ($vcServerName -ne "") {
    Disconnect-VIServer -confirm:$false
}

Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Thursday, August 6, 2009

VMware vSphere PowerCLI commands

The commands below are PowerCLI commands used to automate VMware ESX and VirtualCenter at the command prompt. Most of these commands were built on 3.5 with vSphere PowerCLI, and the majority have been tested against ESXi 4.0 and vCenter 4.0 infrastructure.

Each command-line can be copied and pasted at a PowerCLI command prompt, and most commands assume you already have a connection to the target, be it vCenter or ESX.

Note that most of these commands use OBN - Object By Name - instead of using the get* command to get the object. This is supported with all but a few of the commands I've come across.



List the vSphere PowerCLI commands
Get-VICommand

Connect to a ESX or VirtualCenter instance
connect-viserver -server %server%

List the currently available datastores
Get-Datastore | sort

List the currently available datastores filtered and sorted
Get-Datastore | where {$_.Name -like '*pr*'} | sort

Find the VMs attached to one or more datastores
foreach ($prodDatastore in $prodDatastores) { write-output $prodDatastore.Name; get-vm -datastore $proddatastore; write-output ''}

Get a Virtual Machine
$vm = get-vm -name '%vm%'

Get the virtual harddisk for the specified VMs
Get-HardDisk -vm $vm

Move a virtual machine to another container
Move-VM -Destination $prodApps -VM $vm

Update the VM description for a list of CSV entries
foreach ($virtualServer in $virtualservers) {$arr = $virtualServer.split(","); $desc = $arr[1]; $vmName = $arr[0]; write-output $vmName; $desc; $vm = get-vm -name $vmName; Set-VM -VM $vm -description $desc}

Query for a list of VMs and output in ANSI format
get-vm | sort-object | format-table -property Name | out-file -encoding ASCII -filepath c:\temp\vms_20090625.txt

Find VMware machine performance statistics
 get-stat -entity $vm -disk -start 01/01/2009 -finish ([DateTime]::Now.ToString("dd/MM/yyyy"))

For a group of VMs, report performance statistics and save to file
foreach ($vm in $devVMs) {get-stat -entity $vm -disk -start 01/01/2009 -finish ([DateTime]::Now.ToString("dd/MM/yyyy")) | out-file -filepath ("c:\temp\" + $vm.Name + "DiskPerformance.txt")}

Find VM datastore disk usage
$devVMs = get-vm -name '*dv*'; foreach ($vm in $devvms) {$vm.harddisks}

Find VM datastore disk usage
$testVMs = Get-VM -Location (get-folder -name "Test") ;foreach ($vm in $testVMs) {$vm.harddisks | format-table -hideTableHeaders -wrap -autosize | findstr /i /c:per}

Find SCSI devices attached to an ESX server
get-scsilun -vmhost (Get-VMHost -Location "cluster")[0]

Rescan HBAs on an ESX server
get-VMHostStorage -VMHost (Get-VMHost -Location "cluster")[0] -RescanAllHba

Storage vMotion a virtual machine to a new datastore
Move-VM -vm "vmName" -datastore "NewDatastore"

Storage vMotion a group of machines from a CSV input file
$servers = get-content -path inputfile.txt; foreach ($server in $servers) {move-vm -vm $server.split(",")[0] -datastore $server.split(",")[1]}

Remove a snapshot and child snapshots, reporting how long the operation took
measure-command -expression {remove-snapshot -snapshot $snapshots[0] -removechildren}

Find datastore space, usage and number of VMs per datastore
$datastores = get-datastore | sort-object; write-output "Name,Size,Used,Free,% Used,#VMs"; foreach ($datastore in $datastores) { write-output ($datastore.Name + "," + [math]::round($datastore.CapacityMB/1024) + "," + [math]::round(($datastore.CapacityMB/1024)-($datastore.FreeSpaceMB/1024)) + "," + [math]::round($datastore.FreeSpaceMB/1024) + "," + [math]::round(((($datastore.CapacityMB/1024) - ($datastore.FreeSpaceMB/1024)) / ($datastore.CapacityMB/1024)) * 100) + "," + (get-vm -datastore $datastore).count)}

From a set of VMs, find which have snapshots
foreach ($testvm in $testvms) {if (get-snapshot -vm $testvm){write-output $testvm.Name}}

Find the size of the first hard disk in each VM
foreach ($vm in $vms) {$vm.harddisks[0] | format-table -hideTableHeaders -wrap -autosize | findstr /i /c:per }

Find disk information for VMs in the specified datastore
 $VMs = Get-VM ;foreach ($vm in $VMs) {$vm.harddisks | where {$_.FileName -like '*clusterpr*'} | format-table -hideTableHeaders -wrap -autosize | findstr /i /c:per}

Find VMs in the specified datastore
$VMs = Get-VM | where {$_.harddisks[0].FileName -like '*clusterpr*'}

Get VM guest information, including virtual OS
get-vm | get-vmguest | format-table -wrap -autosize

Find virtual machines and their description/notes
$vms = get-vm ; $vms | format-table -wrap -autosize -property Name,Description

Create an associative array containing VM names and descriptions
$vmdesc = @{}; foreach ($vm in $vms) {$vmdesc.add($vm.Name, $vm.Description)}

Migrate a virtual machine to another host in a VMware ESX cluster
move-vm -vm %vmName% -destination %hostname%

Find the host a VM is currently located on
get-vmhost -vm %vnName%

Add a new harddisk to a virtual machine
New-HardDisk -vm %vmName% -CapacityKB 20971520

Retrieve details on the resource pools from the currently connected datacenter
Get-ResourcePool | format-table -wrap -autosize -property Name,Id,CpuExpandableReservation,CpuLimitMHz,CpuReservationMHz,CpuSharesLevel,CustomFields,MemExpandableReservation,MemLimitMB,MemReservationMB,MemSharesLevel,Name,NumCpuShares,NumMemShares

Find virtual machines and if they have a CD-ROM
get-vm | format-table -wrap -autosize -property Name,CDDrives

Find the last 100 events that aren't alarm related
$events = Get-VIEvent -MaxSamples 100 | where {$_.fullFormattedMessage -notmatch "Alarm*"}

Find all events for machine deployments from templates
$events = Get-VIEvent | where {$_.fullFormattedMessage -match "Deploying (.*) on host (.*) in (.*) from template (.*)"}

Create a resource pool with high CPU and memory shares
New-ResourcePool -location (get-cluster -name 'cluster') -Name ResPool1 -CpuSharesLevel [VMware.VimAutomation.Types.SharesLevel]::High -MemSharesLevel [VMware.VimAutomation.Types.SharesLevel]::High

Create a folder from the root of the tree
New-Folder -Name Workstations -location (get-folder -name 'vm')

Move one or more VMs to a resource pool (or other destination)
$vms = get-vm -name vmNames*; move-vm -vm $vms -destination (Get-ResourcePool -name 'ResPool1')

Get an OS customization specification, and list the properties in wide format
Get-OSCustomizationSpec -name "SpecName" | format-list

Take a snapshot of a virtual machine
New-Snapshot -Name "Snapshot 01" -description "Snapshot description" -vm vmName -Quiesce:$true

Convert a virtual machine to a template
$vmView = get-vm -name vm01 | Get-View; $vmView.MarkAsTemplate()

Find Datastore usage (custom written function)
get-datastoreusage

Get an ESX log bundle using PowerCLI
Get-Log -VMHost esxhostname -Bundle -DestinationPath c:\temp

Query for snapshots
Get-VM | Get-Snapshot | export-csv -path c:\temp\VMsnapshots.csv

Query for snapshot information
Get-VM | Get-Snapshot | foreach-object {$out=  $_.VM.Name + "," + $_.Name + "," + $_.Description + "," + $_.PowerState; $out}


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Resetting Computer Account Passwords

I was trying to tell from a workstation point of view when the computer account password was last set. I'm sure this information is stored locally somewhere, but in the end it was easier to query the AD and find when the password for the computer account was last set.

This is used for Virtual Machine templates - we use nltest to reset the computer account password, such that we can maintain a single template image and turn it on periodically for updates without having to rejoin to the domain because of mismatched computer accounts.

Forcefully reset the computer account password:



nltest /SC_CHANGE_PWD:%domain%



Query the workstation in the domain and find when the password was last set - returns the number of 100 nanosecond intervals since 01/01/1601.



dsquery computer -name ws01
dsquery * "CN=ws01,OU=Computers,DC=domain,DC=com" -attr pwdlastset
pwdlastset
128934012123005000


Use PowerShell to convert the number to a human readable date format:



powershell [datetime]::FromFileTime(128934012123005000)

Thursday, 30 July 2009 2:20:12 PM


Use w32tm to convert the number to a human readable date format:



w32tm /ntte 128934012123005000

149229 04:20:12.3005000 - 30/07/2009 2:20:12 PM



Use VBScript to convert the number to a human readable date format:



cscript ConvertFileTime.vbs 128934012123005000

30/07/2009 2:20:12 PM


' ConvertFileTime.vbs
' VBScript doesn't support 64-bit integers, so it can't handle the number of 100 nanosecond intervals since 01/01/1601
' http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnclinic/html/scripting09102002.asp

' Either use ADSI provider and the IADs/IADsLargeInteger object
' LargeIntValue = objLargeInt.HighPart * 2^32 + objLargeInt.LowPart

' http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/iadslargeinteger.asp'
' Or WMI, which handles the conversion between 64-bit datetime structure / UTC / and VB var datetime

If Wscript.Arguments.UnNamed.Count > 0 Then 
        strDateTime = Wscript.Arguments.UnNamed(0)
        Set objDateTime = CreateObject("WbemScripting.SWbemDateTime")
        If IsDate(strDateTime) Then
                Call objDateTime.SetVarDate(strDateTime, False)
                wscript.echo objDateTime.GetFileTime
        Else
                Call objDateTime.SetFileTime(strDateTime, False)
                wscript.echo objDateTime.GetVarDate
        End If
        intReturn = 0
Else
        WScript.Echo "Specify a filetime or a date to convert, eg 127076450620627215, or ""11/04/2006 11:17:10 AM"""
        intReturn = 2
End If
WScript.Quit(intReturn)


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Monday, July 27, 2009

PowerCli Relocate VM storage with VI35 / VI4

This post provides a script to help with storage vMotion – migrating a VMware virtual machine from one VMFS datastore to another with no downtime. It’s a great tool, but in VI35 at least it’s not exposed through the GUI or VC scheduled tasks, so I’ve written a script to perform a few checks and allow for very simplistic 'scheduling' (delay).

I’ve only tested this with VI3.5 and PowerCLI 1.0, but I have no reason to think this wouldn’t with with vSphere vCenter and VI 4.0 hosts.

There are a few caveats with storage vMotion (in VC 2.5/ESX 3.5) at least, you can’t:
- Move the storage of a VM that has a snapshot if the VM is powered on
- Move the storage of a VM that has a snapshot (in any power state) if the VM has disks in a different location than the config file.

Based on these caveats, if instructed the script will suspend a VM with snapshots in order to move the storage, then power the VM back on. Use this with caution, as this may cause an outage of your VMs.


#
# Description:
#   Relocate a virtual machine from one datastore to another.
#
# Limitations:
#  -
#
# Assumptions, this script works on the assumption that:
#   The caller provides credentials with permissions to perform the operations
#
# Arguments:
#  vmName, lowecase short name for the virtual machine, eg pibutepr03
#  dataStoreName, the new datastore to migrate the VM to
#  suspend, Whether or not to suspend a VM and move if the VM has snapshots (which prevent live storage vMotion vi VI35)
#  username, The username to connect with, default to the current username environment variable
#  password, The Password to use for the connection, not specifying a password will result in a prompt to enter a secure string
#  delay, The optional number of seconds to delay before starting the operation
#
#
# Usage:
#   PowerShell . .\RelocateVM.ps1 -vmName "vm01" -datastore 'ds02'
#   PowerShell . .\RelocateVM.ps1 -vmName "vm01" -datastore 'ds02' -suspend yes -username domain\user
#
# Changes:
#  07/04/2009, Wayne Martin, Initial version
#

param (

    $vmName = "",
    $dataStoreName = "",
    $suspendIfRequired = $false,
    $username = $env:username,
    $password = "",
    $delay = 0
)


$ErrorActionPreference = "Continue"

 $invalidArgs = $false
if ($dataStoreName -eq "") { write-output "Please specify the datastore target for the VM, eg. ds02"; $invalidArgs = $true}
if ($vmName -eq "") { write-output "Please specify the virtual machine to move, eg vm01"; $invalidArgs = $true}
if ($account -eq "") { write-output "Please specify a user account to connect with, eg domain\user"; $invalidArgs = $true}

if ($invalidArgs) { write-output "Invalid Arguments, terminating"; exit}


Write-Output "Moving VM '$vmName' to the '$dataStoreName' datastore"

if ($delay -gt 0) {
    $hours = $delay / 60 /60
    Write-Output "Delaying $delay seconds before beginning ($hours hours)"
    Sleep -seconds $delay
}


if ($suspendIfRequired) {
    Write-Output "The virtual machine will be suspended if snapshots are preventing storage vMotion"
} else {
    Write-Output "If the virtual machine has snapshots and is powered on the storage vMotion will not work"
}

if ($password -eq "" -and !($pass)) {
    write-output "No password specified from the command-line"
    $pass = Read-Host "Password?" -assecurestring
}
$credential = new-object System.Management.Automation.PSCredential($username,$pass)    


$viServer = $null
$suspend = $false
$poweredOn = ""
$snapshot = $null
$hasSnapshot = $null

$viServer = Connect-VIServer -server $vcServerName -Credential $credential


if ($viServer) {
    Write-Output (Get-Date -format "dd/MM/yyyy HH:mm:ss")
    write-output ("Connected to server " + $viServer.Name + " on port " + $viServer.Port)

    $vm = get-vm -name $vmName
    if ($vm -and $vm -isnot [object[]]) {
        Write-Output ("Found " + $vm.Name)

        $hardDisks = $vm.hardDisks
        $vmSize = 0
        $vmSizeMB = 0
        foreach ($harddisk in $vm.hardDisks) {
            $vmSize += $hardDisk.CapacityKB
        }
        $vmSizeMB = $vmSize /1024

        $datastore = get-datastore -name $dataStoreName
        if ($datastore) {
            $freeSpace = $datastore.FreeSpaceMB
        
            if ($freeSpace -gt $vmSizeMB)
            {
                Write-Output "The datastore $datastoreName has $freeSpace MB available, the VM has disks totalling $vmSizeMB MB"
            
                switch ($vm.PowerState)
                {
                    ([VMware.VimAutomation.Types.PowerState]::PoweredOn)
                    {
                        Write-Output "The virtual machine is currently powered on"
                        $poweredOn = $true
                    }

                    ([VMware.VimAutomation.Types.PowerState]::PoweredOff)
                    {
                        Write-Output "The virtual machine is currently powered off"
                    }

                    ([VMware.VimAutomation.Types.PowerState]::Suspended)
                    {
                        Write-Output "The virtual machine is currently suspended"
                    }
            
                    default
                    {
                        write-output "Virtual machine power state unknown"
                    }
                }

                [object[]]$snapshot = get-snapshot -vm $vm
                if ($snapshot) 
                {
                    $hasSnapshot = $true
                    $numSnapshots = $snapshot.Count
                    Write-Output "$vmName currently has $numSnapshots snapshot(s)"
                    if ($poweredOn) {
                        if ($suspendIfRequired) {
                            Write-Output "$vmName is powered on and has a snapshot, and will be suspended during the move"
                            $suspend = $true
                        } else {
                            Write-Output "Error: $vmName is powered on and has a snapshot, but will not be suspended, process aborted"
                            $suspend = $false
                            exit 2
                        }
                    }
                } else {
                    $suspend = $false
                    $hasSnapshot = False
                    Write-Output "No snapshots currently found for $vmName"

                }

                if ($suspend) {
                    Write-Output "Suspending $vmName"
                    Suspend-VM -vm $vm -confirm:$false
                }

                Write-Output "Moving $vmName to $datastoreName"
                Move-VM -vm $vmName -datastore $datastoreName

                if ($suspend) {
                    Write-Output "Bringing $vmName out of suspension"
                    Start-VM -vm $vm -confirm:$false
                }
                Write-Output "$vmName migrated to $datastoreName"

            } else {
                Write-Output "The datastore only has $freeSpace MB available, but the VM has disks totalling $vmSizeMB MB"
            }
        } else {
            Write-Output "Error: datastore $datastoreName not found"
        }
    } else {
        if ($vm -is [object[]])
        {
            Write-Output "Multiple objects returned for $vmname, please specify a single VM"
        } else {
            write-output "VM Not found - $vmName"
        }
    }
} else {
    write-output "ERROR: VI server not found - $viServer"
}

Write-Output (Get-Date -format "dd/MM/yyyy HH:mm:ss")

Disconnect-VIServer -confirm:$false
exit 0


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Wednesday, July 1, 2009

PowerShell - vSphere VMKernel NIC MTU

I came across a problem with VI4 (vSphere) on ESXi, where I was unable to create a vmkernel NIC for iSCSI with the vicfg-vmknic.pl script to set a custom MTU of 9000. This post provides a method using the GUI/perl script, and a PowerShell vSphere PowerCLI script to modify an existing VMKernel NIC.

It seems there is a bug in the perl script doesn't allow you to create a VMKernel NIC, however it does work if you create one through the GUI, and then use the script to delete and re-create the virtual NIC.

This was using a standalone ESXi server with a normal vSwitch - it wasn't managed by VC and it wasn't a DVS.

The GUI/PL script method:

  1. Create a VMKernel NIC in an existing vSwitch through the VI Client, with a port group called iSCSI1 in this example.
  2. Using the CLI, run the following commands, the first to delete the existing NIC, and then another to re-create the same NIC, but with an increased MTU:
    vicfg-vmknic.pl -d iSCSI1
    vicfg-vmknic.pl -a -i x.x.x.x -n x.x.x.x -m 9000 iSCSI1
  3. Run 'vicfg-vmknic.pl –l' to list the VMK NICs, which should show the adjusted MTU

I wasn't particularly happy with this method, so I looked at using the vSphere PowerCLI to set the MTU. For whatever reason, VMware chose not to expose the MTU property, which leaves only the SDK.

Luckily the PowerCLI makes it much easier to use the .Net SDK than previously possible with the Get-View cmdlet, so the script below is a combination of standard PowerCLI with a hook into the vNIC collection and the UpdateVirtualNic method to change a virtual NIC spec.


param (

    $MTU = 9000, 
    $nicName = vmk1, 
    $vcServer = "vcServer", 
    $vmServerName = "esx01"
)

#
#
# Description:
#  Update the MTU of a vmkernel NIC used for iSCSI
#
# Limitations:
#  DVS untested
#
# Assumptions, this script works on the assumption that:
#  The caller provides credentials with permissions to change the specified NIC
#
# Arguments:
#  MTU, The new MTU size, eg. 9000
#  nicName, The vmkernel NIC, eg. vmk1.  Note that this differs from the port group (eg. iSCSI1, with a NIC name of vmk1)
#  vcServer, the VC instance to connect to, eg. vcServer
#  vmServerName, The server name controlled by the VC instance (or direct), eg. esx01
#
# Usage:
#  PowerShell . .\UpdateVMKMTU.ps1 -MTU 9000 -nicName 'vmk1' -vcServer 'vcServer' -vmServerName 'esx01'
#
# References:
#  http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.host.VirtualNic.Specification.html
#
# Changes:
#  26/06/2009, Wayne Martin, initial version

#$ErrorActionPreference = "Continue"


Connect-VIServer -server $vcServer        # connect to VC
$hostSystem = get-view -ViewType HostSystem -Filter @{"Name" = $vmServerName}   # Find the .Net view of the specified host
$hostConfigManager = $hostSystem.get_ConfigManager()      # Get the config manager
$hostNetworkSystem = $hostConfigManager.get_NetworkSystem()     # Find the MOR of the host network system
$netSystem = Get-View $hostNetworkSystem       # Get the object from the reference for the update method later

$hostconfig = $hostSystem.Config        # Get the current host config
$hostNetwork = $hostconfig.Network        # Get the current network host config
$hostvNIC = $hostNetwork.vNic         # Get the virtual NICs

$nicBeingUpdated = $null
foreach ($hostVirtualNIC in $hostvNIC) {       # For each virtual NIC
    if ($hostVirtualNIC.Device -eq $nicName) {        # Is this the device specified?
        $nicBeingUpdated = $hostVirtualNIC       # Yes, copy the object
    }
}

if ($nicBeingUpdated) {          # Was something found?
    $nicSpec = $nicBeingUpdated.Spec        # Yes, get the current spec
    $currentMTU = $nicSpec.MTU         # Get the current MTU from the spec

    if ($currentMTU -ne $MTU) {         # Is the MTU different?
        $nicSpec.set_Mtu($MTU)         # Yes, update the MTU on the copy of the spec of the existing NIC
        $netSystem.UpdateVirtualNic($nicName, $nicSpec)             # Call the update method from the netsystem, to update the NIC with the modified device spec

        write-output "MTU for $nicName updated from $currentMTU to $MTU"
        (get-vmhostnetwork).VirtualNic        # Output updated information
    } else {
        write-output "MTU for $nicName already set to $MTU, no changes made"
    }

} else {

    write-output "NIC $nicName not found, no changes made"

}


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Sunday, June 28, 2009

Processor affinity on Windows server 2003/2008

This post describes a few methods of setting the processor affinity mask for a service, process or executable on a Windows Server 2003/2008 machine. There are several reasons to do this; increasingly as software becomes licensed per socket or even per core, but also separating or tuning the performance of applications on multi-core and hyper-threaded processors, i.e. to force usage of shared cache.

Of course this can be done through the task manager GUI (taskmgr.exe), but following the theme of command-line automation and scripting, I’ve found a few other methods that may be more efficient. The options below have different advantages/disadvantages and really depend on what you’re trying to achieve and how the process gets started.

In no particular order:

WSRM

Use Windows System Resource Manager, which among other things can be used for persistent application to processor mappings. This requires 2003 enterprise, 2003 datacenter or server 2008. WSRM is useful when trying to run multiple applications on a single physical box, allowing granular control through a GUI (the configuration of which is persistent across reboots). WSRM also has a command-line interface, and can be used for accounting and to set per-processor utilisation, not just processor affinity.

Note that when I was testing WSRM, it detected calc.exe and matched it against a rule to limit 50% CPU usage, but using factorial of a large number still resulted in 100% CPU. WSRM uses soft caps apparently, only constraining usage when there is contention (I didn’t do any more testing to confirm). There is also a note about WSRM only supporting management of non-OS processes (I’m unsure of whether it would detect calc.exe as such).

PowerShell

Use PowerShell to set the processor affinity for one or more running processes. There’s an example script below, setting the processor mask of calc.exe to the first 4 processors. I like this method because the script is simple, it would be easy to schedule, works on x86 and x64, supports multiple processes of the same name and at least partly because it highlights just how easy administration with PowerShell is.

Note that if you use factorial of a large number with calc.exe (n!) you’ll generate100% CPU which can be useful for testing. The mask below is 0xf = 1111 – a mask allowing use of only the first four processors:

$calcSet = Get-Process -ProcessName "calc"
foreach ($calc in $calcSet) {$calc.ProcessorAffinity=0xF}

Start or psexec

Use a wrapper to launch the process, including either ‘start /affinity’ or ‘psexec -a’ to launch the application, setting affinity as required. Note that ‘start /affinity’ is available on 2003 server, Vista and 2008 server, but not XP.

psexec /a 0,1 calc.exe
start /affinity 1 calc.exe


If you’re trying to control a service, you could use instsrv/srvany to create a service that wraps the start or psexec command around the real service binary. For example, the commands below create another version of the spooler service that will only run on the first processor.

instsrv Test c:\util\srvany.exe
reg add hklm\system\currentcontrolset\services\test\Parameters
reg add hklm\system\currentcontrolset\services\test\Parameters /v Application /t reg_sz /d cmd.exe
reg add hklm\system\currentcontrolset\services\test\Parameters /v AppParameters /t reg_sz /d "/c start /affinity 1 C:\WINDOWS\system32\spoolsv.exe"

ImageCfg

Use imagecfg.exe - a Windows Server 2000 Resource Kit Supplement utility - to modify the binary to set the processor affinity. This actually modifies the .exe – changing the initialisation section of the executable, and will ensure the affinity whenever the executable is run. Note that in my testing, modifying an x64 binary with this utility did not set the affinity correctly, only x86 binaries were successful (running on x64 or x86 OS). If you’re using calc.exe to test this – use a copy in another folder, otherwise windows file protection will replace the updated binary, undoing any change you make.

The mask below is 0xf = 1111 – a mask allowing use of only the first four processors:

imagecfg -a 0x0F c:\temp\calc.exe

ProcAff.exe

Use procaff.exe (a third-party utility) to set the processor affinity of a running process. This could be run as startup scheduled task, setting the mask of any process started as a service (you might need to build in some logic to wait for the processes to start). Note that this utility worked on both x86 and x64 systems while testing, but it’s limited in that if there are multiple processes with the same name, it requires a PID. This is easy enough to script using a ‘for’ loop and pslist to identify the PIDs and then call procaff.

procaff /set 1 calc.exe

Boot.ini and HAL options

Some rather more severe options – reducing the OS to only one CPU:

  1. The /NUMPROC switch in boot.ini on the server. This will set the number of processes Windows will see when booted. I assume this will just apply a mask at startup, but in a multi-CPU multi-core server I haven't tested to confirm the cores are paired or whether the first core from each CPU is presented.
  2. The /ONECPU switch in boot.ini on the server. This will tell Windows to use only one CPU, limiting any application running on the OS. On a multi-core server, the OS would use only one core of one package. I successfully tested this on 2003 enterprise OS.
  3. Downgrade the OS from a multiprocessor HAL to a uniprocessor HAL, removing support for multiple CPUs from the OS. I didn’t actually test this method, but it’s something I used to do on NT4, and I don’t see why it wouldn’t work on 2003/2008.



Plug-and-Play device interrupts

Use Intfilter.exe - allowing you to perform similar functionality to drivers – binding interrupts to a particular processor, useful to control plug-and-play driver-level CPU binding.

References

Procaff
http://www.stefan-kuhr.de/cms/index.php?option=com_content&view=article&id=60&Itemid=77

Boot INI Options Reference
http://technet.microsoft.com/en-us/sysinternals/bb963892.aspx

HAL options after Windows XP or Windows Server 2003 Setup
http://support.microsoft.com/kb/309283

Available Switch Options for Windows NT Boot.ini File
http://support.microsoft.com/kb/170756

How to Manually Add Support for a Second Processor
http://support.microsoft.com/kb/156358

Windows System Resource Manager: Frequently Asked Questions
http://www.microsoft.com/windowsserver2003/techinfo/overview/wsrmfaq.mspx

Windows System Resource Manager
http://www.microsoft.com/downloads/details.aspx?FamilyID=848306EF-F57E-4B3F-984D-50E9BCA44383&displaylang=en

Best Practices for Managing Applications with Process Control
http://technet.microsoft.com/en-us/library/bb742469.aspx

The Context Switch Action (xperf)
http://msdn.microsoft.com/en-us/library/cc305227.aspx

Monitoring Context Switches and Threads
http://technet.microsoft.com/en-us/library/cc938639.aspx

Analyzing Processor Activity
http://technet.microsoft.com/en-us/library/cc958310.aspx

Monitoring Activity on Multiprocessor Systems
http://technet.microsoft.com/en-us/library/cc938649.aspx

Windows Performance Toolkit x86 and x64 v4.1.1
http://download.microsoft.com/download/e/2/7/e2700369-d072-4fdc-a451-c3355eab0613/xperf_x86.msi

http://download.microsoft.com/download/e/2/7/e2700369-d072-4fdc-a451-c3355eab0613/xperf_x64.msi

Windows Performance Toolkit
http://msdn.microsoft.com/en-us/library/cc305187.aspx

Intfilter to manage drivers:
http://support.microsoft.com/default.aspx?scid=KB;en-us;252867


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Monday, June 1, 2009

Calling CPUID from PowerShell for Intel VT

I was trying to work out whether the Intel VT (VMX) extensions had been enabled on a server and whether the server support the SSE4.1 and SSE4.2 processor instructions - without having to reboot the server to check the BIOS. I ended up 'writing' a PowerShell script that compiles some C# to call a DLL written in assembler which has run the CPUID instruction and returned the results. Note that I didn't really write any of this, the PowerShell script compiling and running the C# is from the reference below, as is the actual C$ and asm dll.

Does this seem like a lot of effort? Sure does, but unfortunately the simple method - using Win32_Processor.ProcessorID was useless in this example, as for some reason MS chose to only return the EAX and EDX registers, whereas the bits I was after were returned in ECX. There may also be other ways to achieve this through PowerShell/.Net framework, rather than compiling c# to call unmanaged code.

Below is the PowerShell script, which contains the inline C# that is compiled and executed, which in turn requires the dll, using the EFLAGS register to confirm support and the CPUID instruction with eax=1 (if further supported) to query feature information from the CPU.

The original c# and asm dll: (see below for the hex text stream)
http://devpinoy.org/blogs/cvega/archive/2006/04/07/2658.aspx

The compile-csharp function: (adding the -unsafe parameter to allow pointer use)
http://monadblog.blogspot.com/2005/12/calling-win32-api-functions-through.html



#
# Description:
#  Call the CPUID function from an external DLL through C# inline code.
#  Report whether Intel VT (VMX) is supported, bit 5 of the ECX register returned from CPUID eax=1 call.
#  Note that WMI Win32_Processor:ProcessID contains the results of a call to CPUID - except that it only contains EAX and EDX, Intel VT (what I was after) is in ECX
#
# Author:
#  Wayne Martin, note that I didn't write any of this code, the inline C# was from the monad reference below, and the CPUID DLL and C# was from the first reference

#References:
# cpuid.dll and the namespace from: http://devpinoy.org/blogs/cvega/archive/2006/04/07/2658.aspx
# Intel cpuid: http://www.intel.com/Assets/PDF/appnote/241618.pdf
# http://monadblog.blogspot.com/2005/12/calling-win32-api-functions-through.html
# http://msdn.microsoft.com/en-us/library/aa394373.aspx


function Compile-Csharp ([string] $code, $FrameworkVersion="v2.0.50727",
[Array]$References)
{
    $cp = new-object Microsoft.CSharp.CSharpCodeProvider
    $cpar = New-Object System.CodeDom.Compiler.CompilerParameters
    $cpar.CompilerOptions = "-unsafe"      # unsafe to compile the code which uses pointers in the DLL call
    $cpar.GenerateInMemory = $true
    $cpar.GenerateExecutable = $false
    $cpar.OutputAssembly = "custom"
    # $cpar.ReferencedAssemblies.AddRange($refs)
    $cr = $cp.CompileAssemblyFromSource($cpar, $code)

    if ( $cr.Errors.Count)
    {
        $codeLines = $code.Split("`n");
        foreach ($ce in $cr.Errors)
        {
            write-host "Error: $($codeLines[$($ce.Line - 1)])"
            write-host $ce
           # $ce out-default
        }
        Throw "INVALID DATA: Errors encountered while compiling code"
    }
}



$code = @'
namespace CPUID
{
 using System;
 using System.Runtime.InteropServices;
 using System.Text;

 public class cpuid
 {
  private cpuid()
  {
  }

  [DllImport("cpuid.dll")]
     public static extern bool CPUIDIsSupported();

  [DllImport("cpuid.dll")]
     private unsafe static extern bool __cpuid
            (uint function, 
             int* eax, 
             int* ebx, 
             int* ecx, 
             int* edx);

  // Invoke __cpuid function
  public unsafe static bool Invoke
      (uint level, 
       out int eax, 
       out int ebx, 
       out int ecx, 
       out int edx)
  {
   int __eax = 0;
   int __ebx = 0;
   int __ecx = 0;
   int __edx = 0;

   if (__cpuid(level, &__eax, &__ebx, &__ecx, &__edx))
   {
    eax = __eax;
    ebx = __ebx;
    ecx = __ecx;
    edx = __edx;

    return true;
   }
   else
   {
    eax = 0;
    ebx = 0;
    ecx = 0;
    edx = 0;

    return false;
   }
  }
 }
}


'@


compile-CSharp $code
$eax = ""
$ebx = ""
$ecx = ""
$edx = ""
[CPUID.CPUID]::Invoke(1, [ref]$eax, [ref]$ebx, [ref]$ecx, [ref]$edx) 

$INTEL_CPUID_VT_FLAG = 0x0020                                                           # bit 5 of ECX returned from CPUID EAX=1
$INTEL_CPUID_SSE41 = 0x80000                                                            # bit 19 of ECX returned from CPUID EAX=1
$INTEL_CPUID_SSE42 = 0x100000                                                           # bit 20 of ECX returned from CPUID EAX=1
$INTEL_CPUID_XD = 0x00100000

write-output ("Intel VT: " + ($ecx -band $INTEL_CPUID_VT_FLAG) )                        # Does this processor support Intel VT / VMX?
write-output ("SSE 4.1: " + ($ecx -band $INTEL_CPUID_SSE41) )                           # Does this processor support SSE 4.1?
write-output ("SSE 4.2: " + ($ecx -band $INTEL_CPUID_SSE42) )                           # Does this processor support SSE 4.2?
write-output ("eXecute Disable: " + ($edx -band $INTEL_CPUID_XD) )                      # Does this processor support XD?




Note that in a previous post, I have written two powershell scripts, one to convert binary to a hex string, and vice versa. The following stream is the cpuid.dll file, if you write it to cpuid.txt and run the following command it will create the dll:



Powershell . .\HexStringToBinary.ps1 cpuid.txt cpuid.dll

4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000c00000000e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f742062652072756e20696e20444f53206d6f64652e0d0d0a240000000000000071d4f7db35b5998835b5998835b59988c9958b8834b59988bbaa8a8834b599885269636835b59988000000000000000000000000000000000000000000000000504500004c0103006a793a440000000000000000e0000e210b01050c00020000000400000000000000100000001000000020000000000010001000000002000004000000040000000400000000000000004000000004000070fa000002000000000010000010000000001000001000000000000010000000002000005f0000000000000000000000000000000000000000000000000000000000000000000000003000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e746578740000006c000000001000000002000000040000000000000000000000000000200000602e726461746100005f000000002000000002000000060000000000000000000000000000400000402e72656c6f6300000c000000003000000002000000080000000000000000000000000000400000420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000558becb801000000c9c20c005352b8000000009c588bc83500002000509d9c5b33c325000020007507b801000000eb0233c0519d5a5bc3558bec5357e8cbffffff48740433c0eb1e8b45080fa28b7d0c89078b7d14890f8b7d1889178b7d10891fb8010000005f5bc9c214000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a793a44000000003c2000000100000002000000020000002820000030200000382000000c1000003710000046200000572000000000010063707569642e646c6c0043505549444973537570706f72746564005f5f6370756964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin. 


Read more!

Saturday, May 30, 2009

Extending a server 2003 VM system/boot disk

Whether using basic or dynamic disks, Windows Server 2003 doesn’t provide a method to extend the size of the system or boot disk. In VI35, I have used the following process to extend the system/boot disk of 2003 server virtual machines. Note that this is for the system/boot disk only, data volumes can be grown and extended live.

This process requires the VM to be shutdown, then a small outage while the disk is extended, then a reboot once the OS is first started.

The process I used in VI 3.5 U4, with a 2003 SP2 virtual machine:

  1. Turn the VM off - VM1 in this example
  2. Use VC to increase the size of the boot/system disk of VM1 by xGB (6 in my test)
  3. Use VC to attach the disk inside another running VM that can be shutdown, eg. VM2
  4. On VM2, load diskmgmt.msc, rescan disks (or run diskpart rescan)
  5. On VM2, start diskpart:
    1. List vol (get a list of volumes)
    2. Select vol x (where x is the number of the newly added disk)
    3. Extend
  6. Shutdown VM2 and detach the disk (don’t delete it!)
  7. Start VM1
  8. On my test, after logon, a setupapi message ‘Windows has finished installing new devices. Do you want to restart your computer now?’.
  9. Said yes and the server restarted, diskmgmt.msc shows correctly sized disk.
  10. Ran chkdsk c: to verify no corruption

Step 8 has a matching event ID 271 from PlugPlayManager and setupapi.log entry:

The Plug and Play operation cannot be completed because a device driver is
preventing the device from stopping. The name of the device driver is listed as
the vetoing service name below.
Vetoed device:
STORAGE\VOLUME\1&30A96598&0&SIGNATURE6AF3AEFAOFFSET7E00LENGTH53FD06C00
Vetoing device:
STORAGE\Volume\1&30a96598&0&Signature6AF3AEFAOffset7E00Length53FD06C00
Vetoing service name: FileSystem\Ntfs
Veto type 6: PNP_VetoDevice
When Windows attempts to install, upgrade, remove, or reconfigure a device,
it queries the driver responsible for that device to confirm that the operation
can be performed. If any of these drivers denies permission (query-removal
veto), then the computer must be restarted in order to complete the operation.
User Action
Restart your computer.


Setupapi.log driver logging showing the first vetoed attempt at installation and then the shadow copy volume snapshot install:
[2009/05/06 08:45:46 404.3 Driver Install]
#-019 Searching for hardware ID(s): storage\volume
#-198 Command line processed: C:\WINDOWS\system32\services.exe
#I393 Modified INF cache "C:\WINDOWS\inf\INFCACHE.1".
#W383 "volume.PNF" migrate: PNF Language = 0409, Thread = 0c09.
#I022 Found "STORAGE\Volume" in C:\WINDOWS\inf\volume.inf; Device: "Generic volume"; Driver: "Generic volume"; Provider: "Microsoft"; Mfg: "Microsoft"; Section name: "volume_install".
#I023 Actual install section: [volume_install.NTx86]. Rank: 0x00000000. Driver date: 10/01/2002. Version: 5.2.3790.3959.
#-166 Device install function: DIF_SELECTBESTCOMPATDRV.
#I063 Selected driver installs from section [volume_install] in "c:\windows\inf\volume.inf".
#I320 Class GUID of device remains: {71A27CDD-812A-11D0-BEC7-08002BE2092F}.
#I060 Set selected driver.
#I058 Selected best compatible driver.
#-166 Device install function: DIF_INSTALLDEVICEFILES.
#I124 Doing copy-only install of "STORAGE\VOLUME\1&30A96598&0&SIGNATURE6AF3AEFAOFFSET7E00LENGTH53FD06C00".
#-166 Device install function: DIF_REGISTER_COINSTALLERS.
#I056 Coinstallers registered.
#-166 Device install function: DIF_INSTALLINTERFACES.
#-011 Installing section [volume_install.NTx86.Interfaces] from "c:\windows\inf\volume.inf".
#I054 Interfaces installed.
#-166 Device install function: DIF_INSTALLDEVICE.
#I123 Doing full install of "STORAGE\VOLUME\1&30A96598&0&SIGNATURE6AF3AEFAOFFSET7E00LENGTH53FD06C00".
#W100 Query-removal during install of "STORAGE\VOLUME\1&30A96598&0&SIGNATURE6AF3AEFAOFFSET7E00LENGTH53FD06C00" was vetoed by "STORAGE\Volume\1&30a96598&0&Signature6AF3AEFAOffset7E00Length53FD06C00" (veto type 6: PNP_VetoDevice).
#W104 Device "STORAGE\VOLUME\1&30A96598&0&SIGNATURE6AF3AEFAOFFSET7E00LENGTH53FD06C00" required reboot: Query remove failed (install) CfgMgr32 returned: 0x17: CR_REMOVE_VETOED.
#I121 Device install of "STORAGE\VOLUME\1&30A96598&0&SIGNATURE6AF3AEFAOFFSET7E00LENGTH53FD06C00" finished successfully.
[2009/05/06 08:55:18 400.3 Driver Install]
#-019 Searching for hardware ID(s): storage\volumesnapshot
#-198 Command line processed: C:\WINDOWS\system32\services.exe
#W383 "volsnap.PNF" migrate: PNF Language = 0409, Thread = 0c09.
#I022 Found "STORAGE\VolumeSnapshot" in C:\WINDOWS\inf\volsnap.inf; Device: "Generic volume shadow copy"; Driver: "Generic volume shadow copy"; Provider: "Microsoft"; Mfg: "Microsoft"; Section name: "volume_snapshot_install".
#I023 Actual install section: [volume_snapshot_install.NTx86]. Rank: 0x00000000. Driver date: 10/01/2002. Version: 5.2.3790.3959.
#-166 Device install function: DIF_SELECTBESTCOMPATDRV.
#I063 Selected driver installs from section [volume_snapshot_install] in "c:\windows\inf\volsnap.inf".
#I320 Class GUID of device remains: {533C5B84-EC70-11D2-9505-00C04F79DEAF}.
#I060 Set selected driver.
#I058 Selected best compatible driver.
#-166 Device install function: DIF_INSTALLDEVICEFILES.
#I124 Doing copy-only install of "STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT1".
#-166 Device install function: DIF_REGISTER_COINSTALLERS.
#I056 Coinstallers registered.
#-166 Device install function: DIF_INSTALLINTERFACES.
#-011 Installing section [volume_snapshot_install.NTx86.Interfaces] from "c:\windows\inf\volsnap.inf".
#I054 Interfaces installed.
#-166 Device install function: DIF_INSTALLDEVICE.
#I123 Doing full install of "STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT1".
#I121 Device install of "STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT1" finished successfully.

References

How to extend a data volume in Windows Server 2003, in Windows XP, in Windows 2000, and in Windows Server 2008
http://support.microsoft.com/kb/325590


Wayne's World of IT (WWoIT), Copyright 2009 Wayne Martin.


Read more!

All Posts

printQueue AD objects for 2003 ClusterVirtualCenter Physical to VirtualVirtual 2003 MSCS Cluster in ESX VI3
Finding duplicate DNS recordsCommand-line automation – Echo and macrosCommand-line automation – set
Command-line automation - errorlevels and ifCommand-line automation - find and findstrBuilding blocks of command-line automation - FOR
Useful PowerShell command-line operationsMSCS 2003 Cluster Virtual Server ComponentsServer-side process for simple file access
OpsMgr 2007 performance script - VMware datastores...Enumerating URLs in Internet ExplorerNTLM Trusts between 2003 and NT4
2003 Servers with Hibernation enabledReading Shortcuts with PowerShell and VBSModifying DLL Resources
Automatically mapping printersSimple string encryption with PowerShellUseful NTFS and security command-line operations
Useful Windows Printer command-line operationsUseful Windows MSCS Cluster command-line operation...Useful VMware ESX and VC command-line operations
Useful general command-line operationsUseful DNS, DHCP and WINS command-line operationsUseful Active Directory command-line operations
Useful command-linesCreating secedit templates with PowerShellFixing Permissions with NTFS intra-volume moves
Converting filetime with vbs and PowerShellDifference between bat and cmdReplica Domain for Authentication
Troubleshooting Windows PrintingRenaming a user account in ADOpsMgr 2007 Reports - Sorting, Filtering, Charting...
WMIC XSL CSV output formattingEnumerating File Server ResourcesWMIC Custom Alias and Format
AD site discoveryPassing Parameters between OpsMgr and SSRSAnalyzing Windows Kernel Dumps
Process list with command-line argumentsOpsMgr 2007 Customized Reporting - SQL QueriesPreventing accidental NTFS data moves
FSRM and NTFS Quotas in 2003 R2PowerShell Deleting NTFS Alternate Data StreamsNTFS links - reparse, symbolic, hard, junction
IE Warnings when files are executedPowerShell Low-level keyboard hookCross-forest authentication and GP processing
Deleting Invalid SMS 2003 Distribution PointsCross-forest authentication and site synchronizati...Determining AD attribute replication
AD Security vs Distribution GroupsTroubleshooting cross-forest trust secure channels...RIS cross-domain access
Large SMS Web Reports return Error 500Troubleshooting SMS 2003 MP and SLPRemotely determine physical memory
VMware SDK with PowershellSpinning Excel Pie ChartPoke-Info PowerShell script
Reading web content with PowerShellAutomated Cluster File Security and PurgingManaging printers at the command-line
File System Filters and minifiltersOpsMgr 2007 SSRS Reports using SQL 2005 XMLAccess Based Enumeration in 2003 and MSCS
Find VM snapshots in ESX/VCComparing MSCS/VMware/DFS File & PrintModifying Exchange mailbox permissions
Nested 'for /f' catch-allPowerShell FindFirstFileW bypassing MAX_PATHRunning PowerSell Scripts from ASP.Net
Binary <-> Hex String files with PowershellOpsMgr 2007 Current Performance InstancesImpersonating a user without passwords
Running a process in the secure winlogon desktopShadow an XP Terminal Services sessionFind where a user is logged on from
Active Directory _msdcs DNS zonesUnlocking XP/2003 without passwords2003 Cluster-enabled scheduled tasks
Purging aged files from the filesystemFinding customised ADM templates in ADDomain local security groups for cross-forest secu...
Account Management eventlog auditingVMware cluster/Virtual Center StatisticsRunning scheduled tasks as a non-administrator
Audit Windows 2003 print server usageActive Directory DiagnosticsViewing NTFS information with nfi and diskedit
Performance Tuning for 2003 File ServersChecking ESX/VC VMs for snapshotsShowing non-persistent devices in device manager
Implementing an MSCS 2003 server clusterFinding users on a subnetWMI filter for subnet filtered Group Policy
Testing DNS records for scavengingRefreshing Computer Account AD Group MembershipTesting Network Ports from Windows
Using Recovery Console with RISPAE Boot.ini Switch for DEP or 4GB+ memoryUsing 32-bit COM objects on x64 platforms
Active Directory Organizational Unit (OU) DesignTroubleshooting computer accounts in an Active Dir...260+ character MAX_PATH limitations in filenames
Create or modify a security template for NTFS perm...Find where a user is connecting from through WMISDDL syntax in secedit security templates

About Me

I’ve worked in IT for over 20 years, and I know just about enough to realise that I don’t know very much.