October 2007 - Posts
In my previous blog, I mentioned that Microsoft Virtulization is script extensible using PowerShell, I didn’t give the full picture. Actually PowerShell is the cornerstone features of System Center Virtual Machine Manager (SCVMM). All functions of the SCVMM Admin Console are built on PowerShell the same way as that Exchange 2007 did. It contains >130 task-oriented Cmdlets which provided a very user approachable scripting experience.
Here is an example:
Get-VM-VMMServer Server1 | Select name, processortype, memory
In case you want to dig deeper, you can find more information at
Windows PowerShell Virtual Machine Manager Cmdlet Reference
Looks like the PowerShell train is left the station and in full speed! 
Here is a little chart to compare Microsoft Window Server (2008) Virtualization with VMWare ESX Server
|
Windows Server Virtualization |
VMWare ESX Server |
| Architecture Support |
x86 and x64 |
x86 and x64 |
| Large Memory Support |
32 GB per virtual machine |
16 GB per virtual machine |
| Guest Multiprocessing |
4-core support (Free) |
2/4-core($$) |
| Migration |
Quick Migration WAN Disaster Recovery |
Live Migration($$) Local Disaster Recovery ($$) |
| Management |
unified Physical and Virtual |
Virtual Only |
It seems Microsoft has a couple nice features builtin and free of charge. And for powershell lovers Microsoft Virtualization is script extensible using powershell/wmi.
Let’s say that you have a log folder contain a lot of log.txt files and you want to find out which log file contain a particular “event” or “string”. The below script can accomplish just that
Get-ChildItem c:\log | select-strings “string”
Here are some background knowledge- many components of the Windows OS are implemented as what are called “services”. Among them, a fair number of those services are implemented in DLLs rather than in stand-alone executables. But a DLL is only a library of functions that can be called by running porgrams – it can’t be running on its own. Svchost – a standalone program whose job is to execute services that are implemented in DLLs.
At any single time do a get-process svchost on your computer for svchost – you will get a bunch of them
PS C:\PS> get-process svchost
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
92 4 1744 596 37 0.34 440 svchost
212 6 3304 1808 61 1.26 648 svchost
143 4 2892 2132 39 0.59 772 svchost
490 14 2400 1836 39 2.75 1024 svchost
1682 72 19044 16596 114 42.83 1356 svchost
120 3 2588 600 33 0.20 1592 svchost
101 5 2124 2588 33 0.67 1816 svchost
289 13 8624 5944 47 0.65 1960 svchost
Now, let’s see we know that wuauserv.dll is running under one of them and for whatever reason we need to stop the svchost process related to wuauserv.dll – how we do that?
$svchosts = get-process svchost
foreach ($process in $svchosts)
{$PModules = $process.modules
foreach ($module in $Pmodules)
{if ($module.modulename -eq "wuauserv.dll")
{$process.id}
}
}
and once you identified the pid – you can do a select “kill”.
Here svchost is just an convenient example, you will run into situations where you have multiple instance whatever.exe running and they all associated with different modules. You could do similar trick here.
Here is a powershell script to get the defaultIPGateway information for your vpn connection
$strComputer = "."
$Nics = Get-wmiobject win32_NetworkAdapter -comp $strComputer |where {$_.description -eq "WAN Miniport (IP)"}
foreach ($Nic in $Nics)
{
$Config = Get-Wmiobject win32_NetworkAdapterConfiguration | where {$_.index -eq $Nic.index}
if ($config.IPAddress -ne "$null")
{$VGateway = $config.DefaultIPGateway; $VGateway}
}
Here is a PowerShell script to update DNS Search Order on a particular NIC on multiple remote machines
$cred = get-credential
$strDNSServers = "192.168.1.50", "192.168.1.51","192.168.1.52"
function Update-DNS
{
$Nic = Get-WMIObject Win32_NetworkAdapter -comp $strComputer |where{$_.NetConnectionID -eq "Local Area Connection"}
$Config = Get-WMIObject Win32_NetworkAdapterConfiguration -comp $strComputer |where{$_.MACAddress -eq $Nic.MACAddress}
write-host "The current DNS Search Order is:"
$config.DNSServerSearchOrder
$config.SetDNSServerSearchOrder($strDNSServers) | out-null
}
foreach ($strComputer in get-content c:\temp\ServerList.txt)
{
Update-DNS
}
Again you could remove a line or two from above to just check or verify your changes.
Here is a PowerShell script to udpate WINS settings on a particular NIC on multple remote machines
#You may need to run this under different user context
$cred = get-credential
Function Update-WINS
{
# Here we target a particular NIC of interest
$Nic = Get-WMIObject Win32_NetworkAdapter -comp $strComputer |where{$_.NetConnectionID -eq "Local Area Connection"}
$Config = Get-WMIObject Win32_NetworkAdapterConfiguration -comp $strComputer |where{$_.MACAddress -eq $Nic.MACAddress}
$pri = $config.winsprimaryserver
$sec = $config.winsSecondaryServer
Write-host "The Current Primary WINS Server on $strComputer is $pri"
Write-host "The Current Secondary WINS Server on $strComputer is $sec"
$config.SetWinsServer("192.168.1.10","192.168.1.11") |out-null
}
foreach ($strComputer in get-content c:\temp\ServerList.txt)
{
Update-WINS
}
Once you done with the change, you could run the following slightly different script to verify the changes
$cred = get-credential
Function Check-WINS
{
$Nic = Get-WMIObject Win32_NetworkAdapter -comp $strComputer |where{$_.NetConnectionID -eq "Local Area Connection"}
$Config = Get-WMIObject Win32_NetworkAdapterConfiguration -comp $strComputer |where{$_.MACAddress -eq $Nic.MACAddress}
$pri = $config.winsprimaryserver
$sec = $config.winsSecondaryServer
Write-host "The Current Primary WINS Server on $strComputer is $pri"
Write-host "The Current Secondary WINS Server on $strComputer is $sec"
}
foreach ($strComputer in get-content c:\temp\ServerList.txt)
{
Check-WINS
}
Here is a PowerShell script to delete files(logs) older than however many days you defined.
BECAREFUL, THIS CAN REALLY DO DAMAGE! USE AT YOUR OWN RISK!
Function GetOldFile
{
param ($strComputer = $(Read-Host "Please Enter The Server Name")),
($Dir = $(Read-host "Please Enter The Directory Path"))
($Days = $(Read-Host "How Many Days?"))
$TargetFolder = "\\" + $strComputer + "\" + $Dir
if (Test-Path $TargetFolder)
{
#Warn you the targeted folder, so you can double check
Write-host "The Targeted Folder is:" $TargetFolder -foregroundcolor "Red"
Write-Host `a `a `a `a `a
Write-Host "If This Is Not The Intended Target, Press 'Ctrl + C' To Exit" -foregroundcolor "Yellow"
Start-sleep -s 15
$Now = Get-Date
# Notice the minus sign before $days
$LastWrite = $Now.AddDays(-$days)
$Files = get-childitem $TargetFolder -include *.log -recurse |Where {$_.LastWriteTime -le "$LastWrite"}
foreach ($File in $Files)
#You can add -whatif to see the consequence – Remove-item $File -Whatif
{write-host "Deleting File $File" -foregroundcolor "Red"; Remove-Item $File | out-null}
}
Else
{Write-Host "The Folder $TargetFolder Does Not Exist!"}
}
GetOldFile