PowerCLI Profile

This is a cleaned up version of my PowerCLI profile that I use for everything. I can’t confirm everything works as I add and remove items often, but you can test in your environment. I tried documenting everywhere where I found the inspiration. Many things needed adjusted to work correctly and may have broken as I removed personal information.

# Use ". $profile" to reload

Add-PSSnapin Quest.ActiveRoles.ADManagement
Add-PSSnapin Quest.Defender.AdminTools
Import-Module ActiveDirectory
#Import-Module VMWare*
Import-Module BitsTransfer

#Connect to server
connect-viserver -server vdiserver.domain.com


# Properties from http://www.lucd.info/viproperties/
New-VIProperty -Name ToolsVersion -ObjectType VirtualMachine -ValueFromExtensionProperty 'Config.tools.ToolsVersion' -Force 
New-VIProperty -Name ToolsVersionStatus -ObjectType VirtualMachine -ValueFromExtensionProperty 'Guest.ToolsVersionStatus' -Force
New-VIProperty -Name NumberOfVMs -ObjectType Datastore ` -Value {param($ds) $ds.ExtensionData.VM.Length} ` -Force
New-VIProperty -Name FreeGB -ObjectType Datastore ` -Value {param($ds) [Math]::Round($ds.FreeSpaceMb/1KB,1)} ` -Force
New-VIProperty -Name UsedGB -ObjectType Datastore ` -Value {param($ds) [Math]::Round(($ds.CapacityMB-$ds.FreeSpaceMb)/1KB,1)} ` -Force
New-VIProperty -Name PercentFree -ObjectType Datastore -Value {  param($ds)   "{0:P2}" -f ($ds.FreeSpaceMB/$ds.CapacityMB)} -Force
New-VIProperty -Name ProvisionedGB -ObjectType Datastore `  -Value {    param($ds)     [Math]::Round(($ds.ExtensionData.Summary.Capacity - $ds.ExtensionData.Summary.FreeSpace + $ds.ExtensionData.Summary.Uncommitted)/1GB,1)  } `  -BasedONextensionProperty 'Summary' `  -Force
New-VIProperty -Name Datastore -ObjectType Harddisk -Value {  param($hd)   $hd.Filename.Split(']')[0].TrimStart('[')} -Force

function Invoke-SCCMDCMEvaluation
{
    param (
        [Parameter(Mandatory=$true, HelpMessage="Computer Name",ValueFromPipeline=$true)] $ComputerName
           )
$Baselines = Get-WmiObject -ComputerName $ComputerName -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration
# echo $baselines

 $name = Get-WmiObject -ComputerName $ComputerName -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration | Where-Object {$_.DisplayName -match "<baselineName>"} | Select-Object -ExpandProperty Name
 write-host $name 

 $version = Get-WmiObject -ComputerName $ComputerName -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration | Where-Object {$_.DisplayName -match "<baselineName>"} | Select-Object -ExpandProperty Version
 Write-Host $version

 $MC = [WmiClass]"\\$ComputerName\root\ccm\dcm:SMS_DesiredConfiguration"
 Write-Host $MC

 $Method = "TriggerEvaluation"
 $InParams = $mc.psbase.GetMethodParameters($Method)
 $InParams.IsEnforced = $true
 $InParams.IsMachineTarget = $false
 $InParams.Name = "$name"
 $InParams.Version = "$version"
 $inparams.PSBase.properties | select Name,Value | format-Table
 $R = $MC.InvokeMethod($Method, $InParams, $null)
 $R | Format-Table
}

Function DatastoreStatus
{
Get-DataStore | where-object {$_.Name -notlike "*vdi0*"} | Sort DataCenter,Name | Select DataCenter,Name,NumberOfVMs,FreeGB,UsedGB,PercentFree,ProvisionedGB | Format-Table -AutoSize
} #DatastoreStatus


Function KillVMs
{
#Stop-VM [-Kill] [-RunAsync] [-VM] <VirtualMachine[]> 
#From <https://www.vmware.com/support/developer/PowerCLI/PowerCLI41U1/html/Stop-VM.html> 

Clear-Host
Write-Host "`n`n`n`n`n`n`n`n`n"

$VMs = $args | foreach {get-vm $($_)} | Sort Name
$VMs | ForEach-Object {$VMCount++}
$CurrentVMNumber = 0

foreach ($VM in $VMs){
    $CurrentVMNumber++
    Stop-VM -Kill -VM $VM
    $Countdown = 20
   	for($SecondsRemaining = $Countdown; $SecondsRemaining -ge 0; $SecondsRemaining–-)
     {
      Write-Progress -Activity “Powering Off VMs” -PercentComplete (((($VMCount-$CurrentVMNumber)*20+$SecondsRemaining)/($VMCount*20))*100) -Status “Next machine poweroff in $SecondsRemaining seconds, $($VMCount-$CurrentVMNumber) machines remaining” -secondsRemaining (($VMCount-$CurrentVMNumber)*20+$SecondsRemaining);Sleep -Seconds 1;
     }
    Write-Progress -Activity “Killing” -completed
  }

VMInfo $args
}


Function VMsNotMigrated
{

$VMs = Get-Datacenter | Get-Datastore | where-object {$_.Name -notlike "*vdi*"} | Foreach-Object {
    $ds = $_.Name
    $_ | Get-VM | Sort VMHost,PowerState,Name | Select Name, PowerState, VMHost, @{N="DataStore";E={@((Get-Harddisk $_).Datastore)}} }

$VMs | Format-Table

Write-Host "`n`nMachines left to migrate: $($VMs.Count)`n`n`n"


} #VMsNotMigrated



Function MoveVMsNotMigrated
{

$allvms = @()

#$vms = Get-Vm | Where {$_.Guest.OSFullName -match "Windows"}

$vms = Get-Datacenter | Get-Datastore | where-object {$_.Name -notlike "*vdi*"} | Foreach-Object {
    $ds = $_.Name
    $_ | Get-VM }

$countvm = 1

foreach($vm in $vms){
  $vmstat = "" | Select VmName, CPU, Datastore
  $vmstat.VmName = $vm.name
  $vmview = get-vm $vm.name | Get-View
  $vmstat.CPU = $vmview.Summary.QuickStats.OverallCpuUsage
  $vmstat.Datastore = $((Get-Harddisk $vm.name).Datastore)
  $allvms += $vmstat
  Write-Host "Gathering data for $vm with CPU usage at $($vmstat.CPU) MHz ($countvm of $($vms.count))"
  $countvm++
  } 

$VMs = $allvms | Sort CPU | Select VmName, CPU, Datastore

#seed with first datastore
$datastore = "VDI_001"
$countvm = 1

foreach($vm in $VMs)
 {
  Write-Host "Moving VM $countvm of $($VMs.Count) named $($vm.VmName) to $datastore from $($vm.Datastore)"
  Write-Host "Logged on users = $((Get-WMILoggedOnUser -ComputerName $vm.VmName -Logontype 2,10).Count)"
  
  #This should allow 4 to move at all times
  If((Get-Task -Status Running).Count -ge 4){Write-Host "Waiting for running tasks to complete. Currently $((Get-Task -Status Running).Count) running"}

  While((Get-Task -Status Running).Count -ge 4)
  {Write-Host -NoNewline "$((Get-Task -Status Running).Count)..."
  Start-Sleep 60}

  #Break the count and indent
  Write-Host ""
  Write-Host -NoNewLine "    "

  If($datastore -eq "VDI_001")
  {
  #If VDI_001 then start move and contine script
  Move-VM -Datastore $datastore -RunAsync -VM $vm.VmName
  $datastore = "VDI_002"}
  Else
  {
  #If VDI_002 then start move and wait to complete
  Move-VM -Datastore $datastore -RunAsync -VM $vm.VmName
  $datastore = "VDI_001"}
  $countvm++
 }

} #MoveVMsNotMigrated


## Get-RemoteRegistry
## From http://poshcode.org/615
########################################################################################
## Version: 2.1
##  + Fixed a pasting bug 
##  + I added the "Properties" parameter so you can select specific registry values
## NOTE: you have to have access, and the remote registry service has to be running
########################################################################################
## USAGE:
##   Get-RemoteRegistry $RemotePC "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP"
##     * Returns a list of subkeys (because this key has no properties)
##   Get-RemoteRegistry $RemotePC "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727"
##     * Returns a list of subkeys and all the other "properties" of the key
##   Get-RemoteRegistry $RemotePC "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727\Version"
##     * Returns JUST the full version of the .Net SP2 as a STRING (to preserve prior behavior)
##   Get-RemoteRegistry $RemotePC "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727" Version
##     * Returns a custom object with the property "Version" = "2.0.50727.3053" (your version)
##   Get-RemoteRegistry $RemotePC "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727" Version,SP
##     * Returns a custom object with "Version" and "SP" (Service Pack) properties
##
##  For fun, get all .Net Framework versions (2.0 and greater) 
##  and return version + service pack with this one command line:
##
##    Get-RemoteRegistry $RemotePC "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP" | 
##    Select -Expand Subkeys | ForEach-Object { 
##      Get-RemoteRegistry $RemotePC "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\$_" Version,SP 
##    }
##
########################################################################################
# 

Function Get-RemoteRegistry {

param(
    [string]$computer = $(Read-Host "Remote Computer Name")
   ,[string]$Path     = $(Read-Host "Remote Registry Path (must start with HKLM,HKCU,etc)")
   ,[string[]]$Properties
   ,[switch]$Verbose
)

if ($Verbose) { $VerbosePreference = 2 } # Only affects this script.

   $root, $last = $Path.Split("\")
   $last = $last[-1]
   $Path = $Path.Substring($root.Length + 1,$Path.Length - ( $last.Length + $root.Length + 2))
   $root = $root.TrimEnd(":")

   #split the path to get a list of subkeys that we will need to access
   # ClassesRoot, CurrentUser, LocalMachine, Users, PerformanceData, CurrentConfig, DynData
   switch($root) {
      "HKCR"  { $root = "ClassesRoot"}
      "HKCU"  { $root = "CurrentUser" }
      "HKLM"  { $root = "LocalMachine" }
      "HKU"   { $root = "Users" }
      "HKPD"  { $root = "PerformanceData"}
      "HKCC"  { $root = "CurrentConfig"}
      "HKDD"  { $root = "DynData"}
      default { return "Path argument is not valid" }
   }

Write-Output $computer

   #Access Remote Registry Key using the static OpenRemoteBaseKey method.
   Write-Verbose "Accessing $root from $computer"
   $rootkey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($root,$computer)
   if(-not $rootkey) { Write-Error "Can't open the remote $root registry hive" }

   Write-Verbose "Opening $Path"
   $key = $rootkey.OpenSubKey( $Path )
   if(-not $key) { Write-Error "Can't open $($root + '\' + $Path) on $computer" }

   $subkey = $key.OpenSubKey( $last )
   
   $output = new-object object

   if($subkey -and $Properties -and $Properties.Count) {
      foreach($property in $Properties) {
         Add-Member -InputObject $output -Type NoteProperty -Name $property -Value $subkey.GetValue($property)
      }
      Write-Output $output
   } elseif($subkey) {
      Add-Member -InputObject $output -Type NoteProperty -Name "Subkeys" -Value @($subkey.GetSubKeyNames())
      foreach($property in $subkey.GetValueNames()) {
         if($subkey.GetValue($property) -like "*.otf"){Add-Member -InputObject $output -Type NoteProperty -Name $property -Value $subkey.GetValue($property)}
      }
      Write-Output $output
   }
   else
   {
      $key.GetValue($last)
   }
 }




Function FindOpenTypeFonts
{
#$args | ForEach {$($_)} | Out-File -Append c:\temp\Fonts.log
$args | ForEach {Get-RemoteRegistry $($_) "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts\"} | Out-File -Append c:\temp\Fonts.log
}






Function GetAppVMembers
{
$groups = Get-ADGroup -Filter {Name -like "AENTVS*"} | Select Name
 foreach ($group in $groups){
    $members = Get-ADGroupMember -identity $group.Name | select name,SamAccountName 
  foreach ($member in $members)
    {$output = $output + $group.name + "," + $member.name + "," + $member.SamAccountName + "`n"} 
}
$output | out-file C:\Temp\Groupmembers.csv
}

Function PowerUpVMs
{

Clear-Host
Write-Host "`n`n`n`n`n`n`n`n`n"

$VMs = $args | foreach {get-vm $($_)} | Sort Name
$VMs | ForEach-Object {$VMCount++}
$CurrentVMNumber = 0

foreach ($VM in $VMs){
    $CurrentVMNumber++
    Start-VM -VM $VM
    $Countdown = 600
   	for($SecondsRemaining = $Countdown; $SecondsRemaining -ge 0; $SecondsRemaining–-)
     {
      Write-Progress -Activity “Powering On VMs” -PercentComplete (((($VMCount-$CurrentVMNumber)*600+$SecondsRemaining)/($VMCount*600))*100) -Status “Next machine powerup in $SecondsRemaining seconds, $($VMCount-$CurrentVMNumber) machines remaining” -secondsRemaining (($VMCount-$CurrentVMNumber)*600+$SecondsRemaining);Sleep -Seconds 1;
     }
    Write-Progress -Activity “Building” -completed
  }

VMInfo $args

}

Function PowerUpVMsQuick
{

Clear-Host
Write-Host "`n`n`n`n`n`n`n`n`n"

$VMs = $args | foreach {get-vm $($_)} | Sort Name
$VMs | ForEach-Object {$VMCount++}
$CurrentVMNumber = 0

foreach ($VM in $VMs){
    $CurrentVMNumber++
    Start-VM -VM $VM
    $Countdown = 300
   	for($SecondsRemaining = $Countdown; $SecondsRemaining -ge 0; $SecondsRemaining–-)
     {
      Write-Progress -Activity “Powering On VMs” -PercentComplete (((($VMCount-$CurrentVMNumber)*300+$SecondsRemaining)/($VMCount*300))*100) -Status “Next machine powerup in $SecondsRemaining seconds, $($VMCount-$CurrentVMNumber) machines remaining” -secondsRemaining (($VMCount-$CurrentVMNumber)*300+$SecondsRemaining);Sleep -Seconds 1;
     }
    Write-Progress -Activity “Building” -completed
  }

VMInfo $args

} #End powerupvmsquick

Function PowerUpVMsVeryQuick
{

Clear-Host
Write-Host "`n`n`n`n`n`n`n`n`n"

$VMs = $args | foreach {get-vm $($_)} | Sort Name
$VMs | ForEach-Object {$VMCount++}
$CurrentVMNumber = 0

foreach ($VM in $VMs){
    $CurrentVMNumber++
    Start-VM -VM $VM
    $Countdown = 20
   	for($SecondsRemaining = $Countdown; $SecondsRemaining -ge 0; $SecondsRemaining–-)
     {
      Write-Progress -Activity “Powering On VMs” -PercentComplete (((($VMCount-$CurrentVMNumber)*20+$SecondsRemaining)/($VMCount*20))*100) -Status “Next machine powerup in $SecondsRemaining seconds, $($VMCount-$CurrentVMNumber) machines remaining” -secondsRemaining (($VMCount-$CurrentVMNumber)*20+$SecondsRemaining);Sleep -Seconds 1;
     }
    Write-Progress -Activity “Building” -completed
  }

VMInfo $args


} #End powerupvmsveryquick


function AcknowledgeAlarms
{

$alarmMgr = Get-View AlarmManager

Get-VM | where {$_.ExtensionData.TriggeredAlarmState} | %{
  $vm = $_ 
  $vm.ExtensionData.TriggeredAlarmState | %{
        $alarmMgr.AcknowledgeAlarm($_.Alarm,$vm.ExtensionData.MoRef)
    }
}

} # End AcknowledgeAlarms


function ExportNetworkAdapters
{
# Get the Virtual Network Adapter  

$VMs = Get-VM | where-object {$_.Folder -match "AM US PAM"} | Sort Name
$Data = @()  
foreach ($VM in $VMs){  
$NICs = $VM.NetworkAdapters  
foreach ($NIC in $NICs) {  
$into = New-Object PSObject  
Add-Member -InputObject $into -MemberType NoteProperty -Name VMname $VM.Name  
Add-Member -InputObject $into -MemberType NoteProperty -Name NICtype $NIC.Type 
$Data += $into 
}  
}  

$Data | Export-Csv -Path c:\temp\VM_NICs.csv -NoTypeInformation 
} # End ExportNetworkAdapters


function GetVMHostCapacity
{
  $VMHosts = Get-VMHost |Sort Name | Get-View
  $VMServers = @()

  ForEach ($VMHost in $VMHosts)
  {
    Write-Host "Getting Information for $($VMHost.Name)"
    $VMServer = [PSCustomObject]@{		
      Name = $VMHost.Name
      Type = $VMHost.Hardware.SystemInfo.Vendor+ “ “ + $VMHost.Hardware.SystemInfo.Model
      CPU = 	$VMHost.Hardware.CpuPkg[0].Description
      CPUPackages = $VMHost.Hardware.CpuInfo.NumCpuPackages
      CPUCores = $VMHost.Hardware.CpuInfo.NumCpuCores
      CPUMhz = [math]::round($VMHost.Hardware.CpuInfo.Hz / 1000000, 0)
      TotalHostMhz = 0
      MemGB = [math]::round($VMHost.Hardware.MemorySize / 1GB, 0)
      NumVMs = (Get-View -ViewType "VirtualMachine" -Property Name -Filter @{"Runtime.PowerState"="PoweredOn"} -SearchRoot $(Get-View -ViewType "HostSystem" -Filter @{"Name"="$($VMHost.Name)"} -Property Name).MoRef | Measure-Object).Count
      GuestCPUs = (Get-VMHost $($VMHost.Name) | Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | Measure-Object "NumCpu" -Sum).Sum
      GuestMem = [math]::round((Get-VMHost $($VMHost.Name) | Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | Measure-Object "MemoryGB" -Sum).Sum,0)
      MhzPerVM = 0
      MhzPervCPU = 0
      GBRAMPerVM = 0
    }
    $VMServer.TotalHostMhz = $VMServer.CPUPackages * $VMServer.CPUCores * $VMServer.CPUMhz
    $VMServer.MhzPerVM   = [math]::round($VMServer.TotalHostMhz / $VMServer.NumVMs,0)
    $VMServer.MhzPervCPU = [math]::round($VMServer.TotalHostMhz / $VMServer.GuestCPUs,0)
    $VMServer.GBRAMPerVM = [math]::round($VMServer.MemGB/$VMServer.NumVMs,0)
      
    $VMServers += $VMServer
  }
  $VMServers | ft -auto
  $VMServers | Export-CSV -NoTypeInformation c:\temp\vm_capacity.csv
} #End GetVMHostCapacity


function ExportAllVMInformation
{


#Variables
$Date = get-date
$Datefile = ( get-date ).ToString(‘yyyy-MM-dd-hhmmss’)
$ErrorActionPreference = "SilentlyContinue"
# Variable to change
$CreateCSV= "yes"
$GridView = "no"
$HTML = "yes"
$DisplayHTMLOnScreen = "yes"
$EmailHTML = "yes"
$SendEmail = "yes"
$EmailFrom = "email@address.com"
$EmailTo = "email@address.com"
$EmailSubject = "VMs settings information"
$EmailSMTP = "mail.domain.com"
$FileHTML = New-Item -type file "C:\temp\VMInfo_$datefile.html"
$FileCSV = New-Item -type file "C:\temp\VMInfo_$datefile.csv"
 
#Add Text to the HTML file 
Function Create-HTMLTable
{
param([array]$Array)
$arrHTML = $Array | ConvertTo-Html
$arrHTML[-1] = $arrHTML[-1].ToString().Replace(‘</body></html>’,"")
Return $arrHTML[5..2000]
}
 
$output = @()
$output += ‘<html><head></head><body>’
$output += 



‘<style>table{border-style:solid;border-width:1px;font-size:8pt;background-color:#ccc;width:100%;}th{text-align:left;}td{background-color:#fff;width:20%;border-style:so 
lid;border-width:1px;}body{font-family:verdana;font-size:12pt;}h1{font-size:12pt;}h2{font-size:10pt;}</style>’
$output += ‘<H1>VMware VM information</H1>’
$output += ‘<H2>Date and time</H2>’,$date 

#Gathering VM settings
Write-Host "Gathering VM statistics"
$Report = @()
Get-VM | Sort Name -Descending | %{
  
  $vm = Get-View $_.ID
    $vms = "" | Select-Object VMName, Folder, Hostname, IPAddress, OS, Boottime, VMState, TotalCPU, CPUAffinity, CPUHotAdd, CPUShare, CPUlimit, OverallCpuUsage, CPUreservation, TotalMemory, MemoryShare, MemoryUsage, MemoryHotAdd, MemoryLimit, MemoryReservation, Swapped, Ballooned, Compressed, TotalNics, ToolsStatus, ToolsVersion, HardwareVersion, TimeSync, CBT
    $vms.VMName = $vm.Name
    $vms.VMFolder = $vm.Folder
    $vms.Hostname = $vm.guest.hostname
$vms.IPAddress = $vm.guest.ipAddress
$vms.OS = $vm.Config.GuestFullName
$vms.Boottime = $vm.Runtime.BootTime
$vms.VMState = $vm.summary.runtime.powerState
    $vms.TotalCPU = $vm.summary.config.numcpu
    $vms.CPUAffinity = $vm.Config.CpuAffinity
$vms.CPUHotAdd = $vm.Config.CpuHotAddEnabled
$vms.CPUShare = $vm.Config.CpuAllocation.Shares.Level
$vms.TotalMemory = $vm.summary.config.memorysizemb
    $vms.MemoryHotAdd = $vm.Config.MemoryHotAddEnabled
$vms.MemoryShare = $vm.Config.MemoryAllocation.Shares.Level
$vms.TotalNics = $vm.summary.config.numEthernetCards
$vms.OverallCpuUsage = $vm.summary.quickStats.OverallCpuUsage
    $vms.MemoryUsage = $vm.summary.quickStats.guestMemoryUsage
    $vms.ToolsStatus = $vm.guest.toolsstatus
    $vms.ToolsVersion = $vm.config.tools.toolsversion
$vms.TimeSync = $vm.Config.Tools.SyncTimeWithHost
$vms.HardwareVersion = $vm.config.Version
    $vms.MemoryLimit = $vm.resourceconfig.memoryallocation.limit
    $vms.MemoryReservation = $vm.resourceconfig.memoryallocation.reservation
    $vms.CPUreservation = $vm.resourceconfig.cpuallocation.reservation
    $vms.CPUlimit = $vm.resourceconfig.cpuallocation.limit
$vms.CBT = $vm.Config.ChangeTrackingEnabled
$vms.Swapped = $vm.Summary.QuickStats.SwappedMemory
$vms.Ballooned = $vm.Summary.QuickStats.BalloonedMemory
$vms.Compressed = $vm.Summary.QuickStats.CompressedMemory
$Report += $vms
}
 
#Output
if ($GridView -eq "yes") {
$report | Out-GridView }
 
if ($CreateCSV -eq "yes") {
$report | Export-Csv $FileCSV -NoTypeInformation }
 
if ($HTML -eq "yes") {
$output += ‘<p>’
$output += ‘<H2>VMware VM information</H2>’
$output += ‘<p>’
$output += Create-HTMLTable 


$report
$output += ‘</p>’
$output += ‘</body></html>’ 
$output | Out-File $FileHTML }
 
if ($DisplayHTMLOnScreen -eq "yes") {
ii $FileHTML}
 
if ($SendEmail -eq "yes") {
Send-MailMessage –From $EmailFrom –To $EmailTo –Subject $EmailSubject –SmtpServer $EmailSMTP -Attachments $FileHTML } 


} #End ExportAllVMInformation




Function Get-HostMemory 
{

param([switch]$refresh,$hostname=”*”)

$vmhosts=Get-vmhost $hostname

Function get-memory{
 $output=@()
 ForEach($vmhost in $vmhosts)
 {
 $stat=get-stat -entity $vmhost -stat mem* -realtime
 $Objects = New-Object PSObject -Property ([ordered]@{
 Name=$vmhost.name
 TotalGB=”{0:N2}” -f ($vmhost.memorytotalGB)
 GrantedGB=$granted=”{0:N2}” -f (($stat |Where-Object{$_.metricid -like  “mem.granted.average”}|select -expand value -first 1)/1MB)
 ConsumedGB=”{0:N2}” -f (($stat |Where-Object{$_.metricid -like “mem.consumed.average”}|select -expand value -first 1)/1MB)
 ActiveGB=$active=”{0:N4}” -f (($stat |Where-Object{$_.metricid -like “mem.active.average”}|select -expand value -first 1)/1MB)
 Usage =”{0:P0}” -f (($stat |Where-Object{$_.metricid -like “mem.usage.average”} |select -expan value -first 1)/100)
 })
 $objects|add-member –MemberType NoteProperty -Name UsageActive -value (“{0:P0}” -f ($active/$granted))
 $output+= $objects
 }
 $output | Format-table -auto
 }

IF ($refresh)
 {
 while(0 -ne 1)
 {get-memory
 sleep 15}
 }
 Else {Get-memory}

} # End Get-HostMemory 




#These all use this class http://msdn.microsoft.com/en-us/library/system.security.cryptography.aspx
#Why we still do MD5 hash in Config Manager as the SHA1 hash has not been used for content security since SMS 2003 RTM?

#We use this value as a quick integrity check as it's very fast. Something to note is that the older MD5 Hashes are always 32 characters in length and corresponds to the "Hash" column in the SQL Database. Newer (as of SMS 2003 SP1 and Config Mgr) and more secure SHA1 hashes are always 40 characters in length and correspond to the "New Hash" column in the SQL DB.

function Get-SHAFolderHash ($folder) 
{
 dir $folder -Recurse | ?{!$_.psiscontainer} | %{[Byte[]]$contents += [System.IO.File]::ReadAllBytes($_.fullname)}
 $hasher = [System.Security.Cryptography.SHA1]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
}

function Get-MD5FolderHash ($folder)
{
 dir $folder -Recurse | ?{!$_.psiscontainer} | %{[Byte[]]$contents += [System.IO.File]::ReadAllBytes($_.fullname)}
 $hasher = [System.Security.Cryptography.MD5CryptoServiceProvider]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
}

function Get-AllFolderHash ($folder)
{
 #dir $folder -Recurse | ?{!$_.psiscontainer} | %{[Byte[]]$contents += [System.IO.File]::ReadAllBytes($_.fullname)}

dir $folder -Recurse | %{[Byte[]]$contents += [System.IO.File]::ReadAllBytes($_.fullname)}

Write-Host "KeyedHashAlgorithm"
 $hasher = [System.Security.Cryptography.KeyedHashAlgorithm]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "MD5"
 $hasher = [System.Security.Cryptography.MD5]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "MD5Cng"
 $hasher = [System.Security.Cryptography.MD5Cng]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "HMACMD5"
 $hasher = [System.Security.Cryptography.HMACMD5]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "RIPEMD160"
 $hasher = [System.Security.Cryptography.RIPEMD160]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "SHA1Managed"
 $hasher = [System.Security.Cryptography.SHA1Managed]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "SHA1"
 $hasher = [System.Security.Cryptography.SHA1]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "SHA256"
 $hasher = [System.Security.Cryptography.SHA256]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "SHA384"
 $hasher = [System.Security.Cryptography.SHA384]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "SHA512"
 $hasher = [System.Security.Cryptography.SHA512]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "HMACRIPEMD160"
 $hasher = [System.Security.Cryptography.HMACRIPEMD160]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "HMACSHA1"
 $hasher = [System.Security.Cryptography.HMACSHA1]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "HMACSHA256"
 $hasher = [System.Security.Cryptography.HMACSHA256]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "HMACSHA384"
 $hasher = [System.Security.Cryptography.HMACSHA384]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))
Write-Host "HMACSHA512"
 $hasher = [System.Security.Cryptography.HMACSHA512]::Create()
 [string]::Join("",$($hasher.ComputeHash($contents) | %{"{0:x2}" -f $_}))



}

Function GetVMFolderSizes
{
$searchSpec1 = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpec1.details = New-Object VMware.Vim.FileQueryFlags
$searchSpec1.details.fileSize = $true
$searchSpec1.query += New-Object VMware.Vim.FolderFileQuery

$searchSpec2 = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpec2.details = New-Object VMware.Vim.FileQueryFlags
$searchSpec2.details.fileSize = $true
$searchSpec2.query += New-Object VMware.Vim.FileQuery

$report = @()

Get-Datastore | Get-View | % {
  $browser = Get-View -Id ($_.Browser)

  $dsPath = "[" + $_.Summary.Name + "] /"
  
  $folderList = $browser.SearchDatastore($dsPath, $searchSpec1)

  foreach($folder in $folderList.File){

    $folderPath = $dsPath + $folder.Path

    $fldresult = $browser.SearchDatastore($folderPath, $searchSpec2)
    $fldSize = 0
    foreach($file in $fldresult.File){
      $fldSize += $file.FileSize
    }
    $row = "" | select DSName, FolderName, FolderSize
    $row.DSName = $folderList.FolderPath
    $row.FolderName = $folder.Path
    $row.FolderSize = $fldSize
    $report += $row
  }
}

$report | Export-Csv "c:\Temp\VMFoldersizes.csv" -noTypeInformation
Write-Host "Wrote output to c:\temp\VMFoldersizes.csv"

}

Function GetVMBuildInfo
{

$VM = $args[0]
Get-VIEvent -maxsamples 100000 -Start (Get-Date).AddDays(-30) | where {($_.Gettype().Name-eq "VmCreatedEvent" -or $_.Gettype().Name-eq "VmBeingClonedEvent" -or $_.Gettype().Name-eq "VmBeingDeployedEvent") -and ($_.FullFormattedMessage -match $($VM)) } |Sort CreatedTime -Descending |Select CreatedTime, UserName,FullformattedMessage | ft -Autosize

}


Function UpdateVMInformation
{
connect-viserver -server vdiserver.domain.com
get-vm | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | Export-CSV -NoTypeInformation -Append c:\temp\all_VMS.csv
Get-ADComputer -Filter "Name -like '*'" -SearchBase "DC=test,DC=test,DC=com" -Server "test" |  Select Name, DistinguishedName, DNSHostName, Enabled | Export-CSV -NoTypeInformation -append c:\temp\AD_VMs.csv
}

function VMInfo
{

$args | foreach {get-vm $($_)} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

}



function VMInfoDetails
{

$args | foreach {get-vm $($_)} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}},@{N="Host";E={([string]($_.Host)).Split("\.")[0]}},@{N="DataStore";E={@(Get-HardDisk -VM $($_.Name))[0].Filename.Split(" ")[0]}},PowerState | ft -Autosize

}

function ExportVMInfoDetails
{

Get-VM | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}},@{N="Host";E={([string]($_.Host)).Split("\.")[0]}},@{N="DataStore";E={@(Get-HardDisk -VM $($_.Name))[0].Filename.Split(" ")[0]}},PowerState,NumCpu,MemoryGB | Export-CSV -NoTypeInformation c:\temp\VMInfoDetails.csv

}


function VMInfoExportSQL
{

get-vm | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}},@{N="Host";E={([string]($_.Host)).Split("\.")[0]}},@{N="DataStore";E={@(Get-HardDisk -VM $($_.Name))[0].Filename.Split(" ")[0]}},PowerState | ft -Autosize

}



function ExportVMInfo
{

$args | foreach {get-vm $($_)} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | Export-CSV -NoTypeInformation c:\temp\VMInfo.csv

}

function ExtendTo100GB
{

$args | foreach {Get-HardDisk -VM $($_)} | Sort Name | Set-HardDisk -CapacityGB 100 -Confirm:$false

}

function GetVHDInfo
{

$args | foreach {Get-HardDisk -VM $($_)} | Sort Name

}

function VMBuildInfo
{

$args | foreach {get-vm $($_)} | Sort Name | select Name,Folder,NumCpu,MemoryGB,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

}

function VMFolderBuildInfo
{

get-vm | where-object {$_.Folder -match $($args[0])} | Sort Name | select Name,Folder,NumCpu,MemoryGB,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

}

function ReleaseIPAndPowerOffVMs
{

#Setup credentials
$VMAdminCreds = New-Object System.Management.Automation.PsCredential("username", (ConvertTo-SecureString "password" -AsPlainText -Force))

#Setup VM List
Write-Host "Getting list of VMs to use"
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

#List VMS
$VMs | foreach {get-vm $_.Name} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

ForEach ($vm in $VMs)
{

$vmname = $vm.Name

Write-Host "Release IP on $vmname"
$script = 'c:\Windows\System32\ipconfig.exe /release'
Invoke-VMScript -ToolsWaitSecs 240 -ScriptText $script -VM $vmname -GuestCredential $VMAdminCreds -RunAsync:$true -ScriptType Bat

If ($vm.OSName -match "Microsoft Windows 7")
{
$script = 'c:\Windows\System32\ipconfig.exe /release6'
Invoke-VMScript -ToolsWaitSecs 240 -ScriptText $script -VM $vmname -GuestCredential $VMAdminCreds -RunAsync:$true -ScriptType Bat
}

#Shutdown VM
Shutdown-VMGuest -VM $vmname -Confirm:$false

}

}


function ApplyCustomization
{

#setup customization scripts
$Win7spec = Get-OSCustomizationSpec -name 'WIN7'
$WinXPspec = Get-OSCustomizationSpec -name 'VDIXP'

#Get VMs
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{
  $VM_NAME = Get-VM -Name $vm.Name

#	If ($vm.OSName -match "Microsoft Windows 7"){
    $VM_NAME | set-vm -OSCustomizationSpec $Win7spec -Confirm:$false
#		}
#	If ($vm.OSName -match "Microsoft Windows XP Professional"){
#		$VM_NAME | set-vm -OSCustomizationSpec $WinXPspec -Confirm:$false
#		}
}
} #end ApplyCustomization


function SetVMTo4GBRAM
{

#Get VMs
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{
  $VM_NAME = Get-VM -Name $vm.Name
  $VM_NAME | set-vm -MemoryGB 4 -Confirm:$false
}

} #end SetVMTo4GBRAM

function SetVMTo3GBRAM
{

#Get VMs
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{
  $VM_NAME = Get-VM -Name $vm.Name
  $VM_NAME | set-vm -MemoryGB 3 -Confirm:$false
}

} #end SetVMTo4GBRAM


function SetVMTo2Processors
{

#Get VMs
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{
  $VM_NAME = Get-VM -Name $vm.Name
  $VM_NAME | set-vm -NumCpu 2 -Confirm:$false
}

} #end SetVMTo2Processors


function RebootVMs
{
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{
$vmname = $vm.Name
Restart-VMGuest -VM $vmname
}
}

function UpdateVMTools
{

#$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

#$VMs = Get-Cluster "CR VDI Cluster 01" | get-vm | where {$_.powerstate -ne "PoweredOff" } | where {$_.name -like "V01PRD*"} | where {$_.Guest.ToolsVersionStatus -ne "guestToolsCurrent"} | % { get-view $_.id } | select Name, @{ Name="ToolsVersion"; Expression={$_.config.tools.toolsVersion}}, @{ Name="ToolStatus"; Expression={$_.Guest.ToolsVersionStatus}}

$VMs = Get-Cluster "CR VDI Cluster 01" | get-vm | where {$_.powerstate -ne "PoweredOff" } | % { get-view $_.id } | where {$_.Guest.ToolsStatus -eq "toolsOld" -or $_.Guest.ToolsStatus -eq "toolsNotInstalled" -or $_.Guest.ToolsStatus -eq "toolsNotRunning"} | select Name

#, @{ Name="ToolsVersion"; Expression={$_.config.tools.toolsVersion}}, @{ Name="ToolStatus"; Expression={$_.Guest.ToolsVersionStatus}}, @{ Name="ToolState"; Expression={$_.Guest.ToolsStatus}}

Clear-Host
Write-Host "`n`n`n`n`n`n`n`n`n"

$VMs | ForEach-Object {$VMCount++}
$CurrentVMNumber = 0

foreach ($VM in $VMs){
    $CurrentVMNumber++
    $vmname = $vm.Name
    Write-Host "$CurrentVMNumber of $VMCount : Updating tools on $vmname"
    Update-Tools -VM $vmname -NoReboot:$True
    $Countdown = 10
   	for($SecondsRemaining = $Countdown; $SecondsRemaining -ge 0; $SecondsRemaining–-)
     {
      Write-Progress -Activity “Updating VM tools” -PercentComplete (((($VMCount-$CurrentVMNumber)*10+$SecondsRemaining)/($VMCount*10))*100) -Status “Next machine update in $SecondsRemaining seconds, $($VMCount-$CurrentVMNumber) machines remaining” -secondsRemaining (($VMCount-$CurrentVMNumber)*10+$SecondsRemaining);Sleep -Seconds 1;
     }
    Write-Progress -Activity “Update” -completed
  }

Get-Cluster "CR VDI Cluster 01" | get-vm | where {$_.powerstate -ne "PoweredOff" } | % { get-view $_.id } | where {$_.Guest.ToolsStatus -eq "toolsOld"} | select Name, @{ Name="ToolsVersion"; Expression={$_.config.tools.toolsVersion}}, @{Name="ToolStatus"; Expression={$_.Guest.ToolsVersionStatus}}, @{ Name="ToolState"; Expression={$_.Guest.ToolsStatus}} | Sort Name

}



function DeleteVMs
{

$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{

$vmname = $vm.Name
#get-vm $vmname | where {$_.powerstate -ne "PoweredOff" } | Shutdown-VMGuest -VM $_.Name -Confirm:$false
Remove-VM $vmname -DeletePermanently -Confirm:$false

}

} #End DeleteVMs


function PowerOffVMs
{

$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{

$vmname = $vm.Name
#Shutdown VM
Shutdown-VMGuest -VM $vmname -Confirm:$false

}
} #End PoweroffVMs

function PowerOnVMs
{

$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{

$vmname = $vm.Name
#Start VM
Start-VM -VM $vmname -Confirm:$false

}
} #End poweronVMS


function RebootVMs
{

$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

ForEach ($vm in $VMs)
{

$vmname = $vm.Name
#Start VM
Restart-VM -VM $vmname -Confirm:$false

}
} #End RebootVMs


function MoveVMToProduction
{

#Setup credentials
$VMAdminCreds = New-Object System.Management.Automation.PsCredential("username", (ConvertTo-SecureString "password" -AsPlainText -Force))

#Setup VM List
Write-Host "Getting list of VMs to use"
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

#List VMS
$VMs | foreach {get-vm $_.Name} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

ForEach ($vm in $VMs)
{

$vmname = $vm.Name

Write-Host "Working with the VM: $vmname"

Write-Host "Change Network if needed"
$ProdNetworkSwitch = "vm12345"
$DRNetworkSwitch = "vm23456"
Get-NetworkAdapter -VM $vmname | Where {$_.NetworkName -eq $DRNetworkSwitch } | Set-NetworkAdapter -NetworkName $ProdNetworkSwitch -Confirm:$false

Start-Sleep -s 10

#Start Computer
Start-VM -VM $vmname -Confirm:$false

}

Write-Host "Sleep 300 seconds while last machine powers up"
Start-Sleep -s 300

#List VMs Again with new IPs
$VMs | foreach {get-vm $_.Name} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

} #End MoveVMToProduction


# May need to implement Set-VirtualPortGroup
# https://www.vmware.com/support/developer/PowerCLI/PowerCLI41U1/html/Set-VirtualPortGroup.html

function MoveVMToSecondNetwork
{


#Setup VM List
Write-Host "Getting list of VMs to use"
$VMs = $args | foreach {get-vm $($_)} | Sort Name | select Name, @{N="OSName";E={$_.guest.OSFullName}}

#List VMS
$VMs | foreach {get-vm $_.Name} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

#switch network
ForEach ($vm in $VMs)
{

$vmname = $vm.Name

$ProdNetworkSwitch = "vm12345"
$SecondsNetworkSwitch = "vm23456"
Get-NetworkAdapter -VM $vmname | Where {$_.NetworkName -eq $ProdNetworkSwitch } | Set-NetworkAdapter -NetworkName $SecondsNetworkSwitch -Confirm:$false
Start-Sleep -s 10
Start-VM -VM $vmname -Confirm:$false

}

Write-Host "Sleep 300 seconds while last machine powers up"
Start-Sleep -s 300

#List VMs Again with new IPs
$VMs | foreach {get-vm $_.Name} | Sort Name | select Name,Folder,@{N="IP Address";E={@($_.guest.IPAddress[0])}},@{N="OS Name";E={$_.guest.OSFullName}} | ft -Autosize

} #End MoveVMToSecondNetwork


function history
{
ghy | Select CommandLine,Id, @{n='ExecutionTime';e={$_.EndExecutionTime - $_.StartExecutionTime}} | Sort ExecutionTime -Desc
}


function GetADGroupMembers
{

$MemberList = New-Item -Type file -Force “c:\temp\GroupMembers.csv”
$groups = Get-ADGroup -Filter "Name -like 'AENT*'"
foreach ($group in $groups){
  $members = Get-ADGroupMember -Identity $($group.DistinguishedName) | Select distinguishedName, name
  foreach ($member in $members){
    
    $group.Name + "," + $member.name | Out-File $MemberList -Encoding ASCII -Append
    $nl = [Environment]::NewLine | Out-File $MemberList -Encoding ASCII -Append
  }
}

}



function GetADGroupMemberDetails
{

$MemberList = New-Item -Type file -Force “c:\temp\GroupMembers.csv”

$groups = Get-ADGroup -Filter "Name -like 'SomeGroupName'"
foreach ($group in $groups){
  $members = Get-ADGroupMember -Identity $($group.DistinguishedName) | Select distinguishedName, name
  foreach ($member in $members){
    $memberdetail = Get-QADUser $member.distinguishedName
    $group.Name + "," + $memberdetail.LogonName + "," + $memberdetail.DisplayName + "," + $memberdetail.LogonScript | Out-File $MemberList -Encoding ASCII -Append
    #$group.Name + "," + $member.name | Out-File $MemberList -Encoding ASCII -Append
    $nl = [Environment]::NewLine | Out-File $MemberList -Encoding ASCII -Append
  }
}

}

function LongestPath 
{

$PathToCheck = $args[0]

#Clear variables to be used for comparison
#Clear-Variable m
#Clear-Variable n

#check every path against the longest so far
Get-ChildItem -Recurse -Force $PathToCheck | %{$m=$_.fullname;if($m.length -gt $n.length){$n=$m}};

Write-Host "The longest path length is $($n.length) characters"
Write-Host "The path location is:"
Write-Host $($n)

Remove-Variable m
Remove-Variable n

}


function GetPathsOverLength
{
#http://blogs.technet.com/b/mwiles/archive/2011/10/07/path-is-too-long.aspx
#http://technet.microsoft.com/en-us/library/bb680872.aspx

$PathToCheck = $args[0]
$LengthToCheck = $args[1]
$OutputLocation = $args[2]

#Clear variables to be used for comparison
#Clear-Variable m
#Clear-Variable n

#check every path against the longest so far
Get-ChildItem -Recurse -Force $PathToCheck | 
  Where {$_.FullName.Length -gt $LengthToCheck} | 
  Select FullName, @{N="Path Length";E={$_.FullName.Length}} | Export-CSV -NoTypeInformation $OutputLocation

}

function GetProfiles
{

#setup input
$Computer = $args[0]
#If ($Computer -eq $null){$Computer = "localhost"}

#Setup names to exclude
$NamesToExclude = @(
      "systemprofile",
      "LocalService",
      "NetworkService",
      "DefaultAppPool",
      "Administrator",
      "Public",
      "All Users"
      )
$NamesToExclude = ($NamesToExclude | foreach {$_}) -join '|'

#Find OS Build Number
$OS = Gwmi -Class Win32_OperatingSystem -Computer $Computer | select $_.BuildNumber

#List profiles
If ($OS.BuildNumber -ge 6000)
  {Get-ChildItem \\$computer\c$\users | Where-Object { $_.psIsContainer -eq $true } | Where {$_.BaseName -notmatch $NamesToExclude} | Sort-Object -Property LastWriteTime -Descending | Select -First 5 FullName, LastWriteTime, CreationTime}
Else 
  {Get-ChildItem \\$computer\c$\windows\profiles | Where-Object { $_.psIsContainer -eq $true } | Where {$_.BaseName -notmatch $NamesToExclude}  | Sort-Object -Property LastWriteTime -Descending | Select -First 5 FullName, LastWriteTime, CreationTime}

} #GetProfiles




function GetProfilesForAllVMs
{

#setup input
$VMs = get-vm | select Name,Folder,@{N="IPAddress";E={@($_.guest.IPAddress[0])}},@{N="OSName";E={$_.guest.OSFullName}} 

#Setup names to exclude
$NamesToExclude = @(
      "systemprofile",
      "LocalService",
      "NetworkService",
      "DefaultAppPool",
      "Administrator",
      "Public",
      "Temp",			
      "All Users"
      )
$NamesToExclude = ($NamesToExclude | foreach {$_}) -join '|'

#Write to CSV file
$Header = "FullName, LastWriteTime, CreationTime" 
$Header | OutFile "C:\Temp\all_vm_profiles.csv"
$numVMs = $VMs.Length

for($counter=0;$counter -lt $numVMs;$counter++)
{
  $vm = $VMs[$counter].Name
  $vmOS = $VMs[$counter].OSName
  
  Write-Host "Working with $vm as $vmOS, number $counter OF $numVMs"

  If ($vmOS -match "Microsoft Windows XP Professional"){
    Get-ChildItem \\$vm\c$\windows\profiles | Where-Object { $_.psIsContainer -eq $true } | Where {$_.BaseName -notmatch $NamesToExclude}  | Sort-Object -Property LastWriteTime -Descending | Select -First 5 FullName, LastWriteTime, CreationTime | Export-CSV -Append -NoTypeInformation "C:\Temp\all_vm_profiles.csv"
  }

  If ($vmOS -match "Microsoft Windows 7"){
    Get-ChildItem \\$vm\c$\users | Where-Object { $_.psIsContainer -eq $true } | Where {$_.BaseName -notmatch $NamesToExclude} | Sort-Object -Property LastWriteTime -Descending | Select -First 5 FullName, LastWriteTime, CreationTime | Export-CSV -Append -NoTypeInformation "C:\Temp\all_vm_profiles.csv"
  }

  If ($vmOS -match "Microsoft Windows 8"){
    Get-ChildItem \\$vm\c$\users | Where-Object { $_.psIsContainer -eq $true } | Where {$_.BaseName -notmatch $NamesToExclude} | Sort-Object -Property LastWriteTime -Descending | Select -First 5 FullName, LastWriteTime, CreationTime | Export-CSV -Append -NoTypeInformation "C:\Temp\all_vm_profiles.csv"
  }

}


} #GetProfilesForAllVMs


function GetProfilesForMachines
{

#This is ported for physical machines so some variable names reference a VM script

#setup input
$VMs = $args

#Setup names to exclude
$NamesToExclude = @(
      "systemprofile",
      "LocalService",
      "NetworkService",
      "DefaultAppPool",
      "Administrator",
      "Public",
      "Temp",			
      "All Users",
      "Classic .NET AppPool"
      )
$NamesToExclude = ($NamesToExclude | foreach {$_}) -join '|'

#Write to CSV file
$Header = "FullName, LastWriteTime, CreationTime" 
$Header | OutFile "C:\Temp\all_machine_profiles.csv"
$numVMs = $VMs.Length

for($counter=0;$counter -lt $numVMs;$counter++)
{
  $vm = $VMs[$counter].ToString()
  
  Write-Host "Working with $vm , number $($counter+1) OF $numVMs"

#WinXP
# Disabled assuming all are Windows 7
#		Get-ChildItem \\$vm\c$\windows\profiles | Where-Object { $_.psIsContainer -eq $true } | Where {$_.BaseName -notmatch $NamesToExclude}  | Sort-Object -Property LastWriteTime -Descending | Select -First 5 FullName, LastWriteTime, CreationTime | Export-CSV -Append -NoTypeInformation "C:\Temp\all_machine_profiles.csv"

#Win7 and up
    Get-ChildItem \\$vm\c$\users | Where-Object { $_.psIsContainer -eq $true } | Where {$_.BaseName -notmatch $NamesToExclude} | Sort-Object -Property LastWriteTime -Descending | Select -First 5 FullName, LastWriteTime, CreationTime | Export-CSV -Append -NoTypeInformation "C:\Temp\all_machine_profiles.csv"

}


} #GetProfilesForMachines


function getOrphanVM
{
# Purpose : List all orphaned vmdk on all datastores in all VC's
# Version : v2.0
# Author  : J. Greg Mackinnon, from original by HJA van Bokhoven
# Change  : v1.1  2009.02.14  DE  angepasst an ESX 3.5, Email versenden und Filegrösse ausgeben
# Change  : v1.2  2011.07.12 EN  Updated for ESX 4, collapsed if loops into single conditional
# Change  : v2.0  2011.07.22 EN: 
  # Changed vmdk search to use the VMware.Vim.VmDiskFileQuery object to improve search accuracy
  # Change vmdk matching logic as a result of VmDiskFileQuery usage
  # Pushed discovered orphans into an array of custom PS objects
  # Simplified logging and email output
      
#Initialize the VIToolkit:
#add-pssnapin VMware.VimAutomation.Core
#[Reflection.Assembly]::LoadWithPartialName("VMware.Vim")

#Main

[string]$strVC = "vdiserver.domain.com"								# Virtual Center Server name
[string]$logfile = "c:\temp\getOrphanVMDK.log"
[string]$SMTPServer = "mail.domain.com"							# Change to a SMTP server in your environment
[string]$mailfrom = "email@address.com"	# Change to email address you want emails to be coming from
[string]$mailto = "email@address.com"							# Change to email address you would like to receive emails
[string]$mailreplyto = "email@address.com"						# Change to email address you would like to reply emails

[int]$countOrphaned = 0
[int64]$orphanSize = 0

# vmWare Datastore Browser query parameters
# See http://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.host.DatastoreBrowser.SearchSpec.html
$fileQueryFlags = New-Object VMware.Vim.FileQueryFlags
$fileQueryFlags.FileSize = $true
$fileQueryFlags.FileType = $true
$fileQueryFlags.Modification = $true
$searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpec.details = $fileQueryFlags
#The .query property is used to scope the query to only active vmdk files (excluding snaps and change block tracking).
$searchSpec.Query = (New-Object VMware.Vim.VmDiskFileQuery)
#$searchSpec.matchPattern = "*.vmdk" # Alternative VMDK match method.
$searchSpec.sortFoldersFirst = $true

if ([System.IO.File]::Exists($logfile)) {
    Remove-Item $logfile
}

#Time stamp the log file
(Get-Date –f "yyyy-MM-dd HH:mm:ss") + "  Searching Orphaned VMDKs..." | Tee-Object -Variable logdata
$logdata | Out-File -FilePath $logfile -Append
#Connect to vCenter Server
Connect-VIServer $strVC

#Collect array of all VMDK hard disk files in use:
[array]$UsedDisks = Get-View -ViewType VirtualMachine | % {$_.Layout} | % {$_.Disk} | % {$_.DiskFile}
#The following three lines were used before adding the $searchSpec.query property.  We now want to exclude template and snapshot disks from the in-use-disks array.
# [array]$UsedDisks = Get-VM | Get-HardDisk | %{$_.filename}
# $UsedDisks += Get-VM | Get-Snapshot | Get-HardDisk | %{$_.filename}
# $UsedDisks += Get-Template | Get-HardDisk | %{$_.filename}

#Collect array of all Datastores:
#$arrDS is a list of datastores, filtered to exclude ESX local datastores (all of which end with "-local1" in our environment), and our ISO storage datastore.
[array]$allDS = Get-Datastore | select -property name,Id | ? {$_.name -notmatch "-local1"} | ? {$_.name -notmatch "-iso$"} | Sort-Object -Property Name

[array]$orphans = @()
Foreach ($ds in $allDS) {
  "Searching datastore: " + [string]$ds.Name | Tee-Object -Variable logdata
  $logdata | Out-File -FilePath $logfile -Append
  $dsView = Get-View $ds.Id
  $dsBrowser = Get-View $dsView.browser
  $rootPath = "["+$dsView.summary.Name+"]"
  $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)
  foreach ($folder in $searchResult) {
      foreach ($fileResult in $folder.File) {
      if ($UsedDisks -notcontains ($folder.FolderPath + $fileResult.Path) -and ($fileResult.Path.length -gt 0)) {
        $countOrphaned++
        IF ($countOrphaned -eq 1) {
          ("Orphaned VMDKs Found: ") | Tee-Object -Variable logdata
          $logdata | Out-File -FilePath $logfile -Append
        }
        $orphan = New-Object System.Object
        $orphan | Add-Member -type NoteProperty -name Name -value ($folder.FolderPath + $fileResult.Path)
        $orphan | Add-Member -type NoteProperty -name SizeInGB -value ([Math]::Round($fileResult.FileSize/1gb,2))
        $orphan | Add-Member -type NoteProperty -name LastModified -value ([string]$fileResult.Modification.year + "-" + [string]$fileResult.Modification.month + "-" + [string]$fileResult.Modification.day)
        $orphans += $orphan
        $orphanSize += $fileResult.FileSize
        $orphan | ft -AutoSize | out-string -Width 4096 | Tee-Object -Variable logdata
        $logdata | Out-File -FilePath $logfile -Append
        [string]("Total Size of orphaned files: " + ([Math]::Round($orphanSize/1gb,2)) + " GB") | Tee-Object -Variable logdata
        $logdata | Out-File -FilePath $logfile -Append
        Remove-Variable orphan
      }
    }
  }
}
(Get-Date –f "yyyy-MM-dd HH:mm:ss") + "  Finished (" + $countOrphaned + " Orphaned VMDKs Found.)" | Tee-Object -Variable logdata
$logdata | Out-File -FilePath $logfile -Append

if ($countOrphaned -gt 0) {
  $orphans | Export-CSV -NoTypeInformation c:\temp\orphan.csv
  [string]$body = "Orphaned VMDKs Found: `n"
  $body += $orphans | Sort-Object -Property LastModified | ft -AutoSize | out-string -Width 4096
  $body += [string]("Total Size or orphaned files: " + ([Math]::Round($orphanSize/1gb,2)) + "GB")

    #$SmtpClient = New-Object system.net.mail.smtpClient
    #$SmtpClient.host = $SMTPServer
    #$MailMessage = New-Object system.net.mail.mailmessage
    #$MailMessage.from = $mailfrom
    #$MailMessage.To.add($mailto)
    #$MailMessage.replyto = $mailreplyto
    #$MailMessage.IsBodyHtml = 0
    #$MailMessage.Subject = "Info: VMware orphaned VMDKs"
    #$MailMessage.Body = $body
#	"Mailing report... " | Tee-Object -Variable logdata
#	$logdata | Out-File -FilePath $logfile -Append

    $emailattachment = "c:\temp\orphan.csv"
    $subject = "Info: VMware orphaned VMDKs"

    #$attachment = New-Object System.Net.Mail.Attachment($emailattachment, 'text/plain')
    #$mailmessage.Attachments.Add($attachment)
   
    Send-MailMessage -To $mailto -From $mailfrom -Subject $subject -Body $body -Attachments $emailattachment -SmtpServer $SMTPServer -Encoding ([System.Text.Encoding]::UTF8)

    	#$SmtpClient.Send($MailMessage)
  #$attachment.Dispose()
  #$emailattachment.Dispose()
  #$mailmessage.Dispose()
  
}
}

Function CheckSCCMHealth
{

#taken from:
#http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Script-SCCM-19e8299c

###############################################
## SCCM 2007 R2 HEALTH CHECK
##
## By: Brenton Blawat
## Website Reference: Http://www.bittangents.com
##
##
## Please note that sccm.xml needs to be in the same directory as this script.
##
## Please also note that `r`n means "return -- new line" for the email formatting.
##
###############################################

#To run the script and Email Warning AND Critical Messages:
# 
#(What we use every 7am in the morning)
# 
#powershell.exe directory\sccm_health.ps1 –reporttype “MorningReport”
# 
#To run the script and Email Critical Messages:
# 
#(What we use every hour at the top of every hour)
# 
#powershell.exe directory\sccm_health.ps1
# 
#To send all results regardless of report type:
# 
#Modify SCCM_Health.ps1 line 18 to be if (-not $debug) { $debug = 1 }
# 
#Alternatively you can run:
# 
#powershell.exe directory\sccm_health.ps1 –debug 1

#Get Computer Name For Email Generation
#$CmpName = [System.Net.DNS]::GetHostName()
#Set to SCCM Server instead
$CmpName = "SCCMServer"

# Take any input triggers as the report type MorningReport
# param($reporttype,$debug)

$reporttype = "MorningReport"

#To Turn On Debugging Level Emails Change From 0 to 1 or use the above trigger
if (-not $debug) { $debug = 0 }

# If the report does not contain the following triggers, only output the debugging level and/or on Critical Issues.
if ($reporttype -notcontains "MorningReport") { 
    $reporttype = ""
}



#Function to create a new email
function send-email { param($emailFrom,$emailTo,$subject,$body)
    #Specify the Server Name
    $smtpServer = "mail.domain.com"
    #Setup the Email Connection Object
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    #Send the Email as Specified
    $smtp.Send($emailFrom, $emailTo, $subject, $body)
}

# This function will count the files in the directories specified in the XML document.
Function get-filecount { param($inbox, $directory)
  # Generate the count of the child item.
    $count = (Get-Childitem $directory).count
  
    # If the Count is less than 1000 AND
    # If the script is being run as a MorningReport or in debug mode Return Informational.
    If ($count -lt 1000) { if ($reporttype -eq "MorningReport" -or $debug -eq "1") { return "Informational: $inbox File Count is: $Count `r`n" } }
  # If the count is greater than 1000
  If ($count -gt 1000) { 
        # If the count is greater than 10000 Return a Critical Message
    If ($count -gt 10000) { 
      return "***** CRITICAL *****: $inbox File Count is: $Count `r`n"
    }		
    #if it is less than 10000, Return a Warning Message
        Else { if ($reporttype -eq "MorningReport" -or $debug -eq "1") { return "***** WARNING *****: $inbox File Count is: $Count `r`n"  } }
  }
}

# This Function Will Get the Service Status of a service on a computer. It will determine what the startup type
# is and what the current status of the service is.
function get-servicestatus { param($CmpName,$name,$service,$health)
    
    #Create the Result Array Variable
    $serviceresult = @()
    
    # Query the Service Startup Mode of the local computer
    $servicestart = Get-WmiObject -Computername $CmpName -Query "Select StartMode From Win32_Service Where Name='$service'" -ErrorVariable Err -ErrorAction SilentlyContinue
    #if there is an error -- report it here -- This is useful if RPC is not functional or the service is not responding
    if ($err) { 
        $serviceresult += "***** CRITICAL *****: Error Getting Service Start Information: $err `r`n"
        [string]$servicemode = "(Cannot Determine Start Mode)"
    }
    #This will ensure that the service startup type IS what is specified in the SCCM File. If not -- Throw an error.
    if (-not $servicestart) { 
        $serviceresult += "***** CRITICAL *****: Error Getting Service Start Information: $err `r`n"
        [string]$servicemode = "(Cannot Determine Start Mode)"
    }
    # If it is functional, Return the start mode.
    Else { [string]$servicemode = $servicestart.StartMode }
    
    # This query will get the current running state of the service.    
    $service = get-service -Computername $CmpName -name $service -ErrorVariable Err -ErrorAction SilentlyContinue
    # This is the error handling. If the service is not responding -- it will report the error here.
    if ($err) { 
        $serviceresult += "***** CRITICAL *****: Error Getting Service Status Information: $err `r`n"
        [string]$service = "(Cannot Determine Service Running Status)"
    }    
    # If it is functional, Return the running mode.
    Else { [string]$servicestatus = $service.status }
 
    
       
    # If the XML File Reads Started/Automatic for the Service to be Healthy Proceed with the following
    if ($health -eq "Started/Automatic") {
        # Is the current State Set to Auto as expected? If not -- throw Exception
        if ($servicemode -notmatch "Auto") {
            $serviceresult += "***** CRITICAL *****: $Name Service Start Mode Set to: $servicemode and Expecting to be $health `r`n"
        }
        #Report Healthy for MorningReport and Debug.
        else {
            if ($reporttype -eq "MorningReport" -or $debug -eq "1") { $serviceresult += "Informational: $Name Service Start Mode Set to: $servicemode `r`n" }
        }
        ### Phase 2 ###
        # Is the service currently running as expected? If Not -- throw Exception    
        if ($servicestatus -notmatch "Running") {
            $serviceresult += "***** CRITICAL *****: $Name Service Running Status is currently: $servicemode and Expecting to be $health `r`n"
        }
        #Report Healthy for MorningReport and Debug.
        else {
            if ($reporttype -eq "MorningReport" -or $debug -eq "1") { $serviceresult += "Informational: $Name Service Running Status is currently: $servicestatus `r`n" }
        }
    }
    
    #If the XML File Reads Manual Startup for Service to be Healthy Proceed with the following
    if ($health -eq "Manual") {
            # If the service is not set to manual -- throw exception.
            if ($servicemode -notmatch "Manual") {
                $serviceresult += "***** CRITICAL *****: $Name Service Start Mode Set to: $servicemode and Expecting to be $health `r`n"
            }
            #Report Healthy for MorningReport and Debug.
            else {
                if ($reporttype -eq "MorningReport" -or $debug -eq "1") { $serviceresult += "Informational: $Name Service Start Mode Set to: $servicemode `r`n" }
            }
    } 
    
    #If the XML File Reads Disabled Startup for Service to be Healthy Proceed with the following
    if ($health -eq "Disabled") {
        # If the service is not set to disabled -- throw exception.
        if ($servicemode -notmatch "Disabled") {
            $serviceresult += "***** CRITICAL *****: $Name Service Start Mode Set to: $servicemode and Expecting to be $health `r`n"
        }
        #Report Healthy for MorningReport and Debug.        
        else {
            if ($reporttype -eq "MorningReport" -or $debug -eq "1") { $serviceresult += "Informational: $Name Service Start Mode Set to: $servicemode `r`n" }
        }
    }
    return $serviceresult	
}

# This function will read the XML data
function Get-XMLData { param($XMLExtract,$XMLvar)
  
  #Result Variable
  $dataresult = @()
    
    # Get the content from the sccm.xml file
  $xml = [xml] (get-content "c:\temp\sccm.xml")
    
    # Start the DOT Notation Loop for the data specified to extract
  ForEach($node in $xml.GetElementsByTagName("$xmlextract")) {
    $id = $node.Id
    ForEach($item in $node) {
      #Grab the SCCM Path Data if Requested
            if ($xmlextract -eq "SCCMPATH") {
                $xmlpath = $item.objloc
                return $xmlpath
            }
            # Start the File Check Process if Requested
            if ($xmlextract -eq "filecheck") {
                $xmlname = $item.name
                $xmldirpath = $installdir + $item.objloc
                $dataresult += get-filecount $xmlname $xmldirpath
            
            }
            # Start the Service Check Process if Requested
            if ($xmlextract -eq "servicecheck") {
                $xmlname = $item.name
                $xmlservice = $item.service
                $xmlhealth = $item.healthy
                $dataresult += get-servicestatus $CmpName $xmlname $xmlservice $xmlhealth
                    
            }
    }
  }
#Return Results
return $dataresult
}

#Create the Report Variable and header
$report = @()

#Header to Email
$report += "------------------------------------------`r`n"
$report += "-------------SCCM HEALTH CHECK------------`r`n"
$report += "---------------$CmpName---------------`r`n"
$report += "------------------------------------------`r`n"

$report += "`r`n"

#Get the Installation Directory From XML File
$installdir = Get-XMLData SCCMPATH

$report += "-------$installdir--------`r`n"

#Header to Email
$report += "`r`n"
$report += "-------------SCCM HEALTH CHECK [File Check]------------`r`n"
$report += "`r`n"

# Execute the File Check Process and store in the report variable
$report += Get-XMLData filecheck

$report += "`r`n"
$report += "-------------SCCM HEALTH CHECK [Services Check]------------`r`n"
$report += "`r`n"

# Execute the Service Check Process and Store the report in variable
$report += Get-XMLData servicecheck

# If the report contains a warning or critical item, Send Email.
if ($report -MATCH "WARNING" -OR $report -MATCH "CRITICAL") {

  #Send A New Email. Format: new-email From To Subject Body
  $cpuemail = $CmpName + "@domain.com"
  send-email $cpuemail "enail@address.com" "$CmpName Health Summary Report (Errors Detected)" $report
}

# List out Report for Visual Effect
$report

} #End function check SCCM Heath

function get-localadmin {  
param ($strcomputer)  
  
$admins = Gwmi win32_groupuser –computer $strcomputer   
#$admins = $admins |? {$_.groupcomponent –like '*"Administrators"'}  
  
$admins |% {  
$_.partcomponent –match “.+Domain\=(.+)\,Name\=(.+)$” > $nul  
$matches[1].trim('"') + “\” + $matches[2].trim('"')  
}  

Write-Host $admins | FL * -Auto
}


function get-localadministrators {
    param ([string]$computername=$env:computername)

    $computername = $computername.toupper()
    #$ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'""" | % {$_.partcomponent}
    #$ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'"""
   $ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser"
    # $ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername'""" | % {$_.partcomponent}
    $ADMINS | fl *
    foreach ($ADMIN in $ADMINS.partcomponent) {
                $admin = $admin.replace("\\$computername\root\cimv2:Win32_UserAccount.Domain=","") # trims the results for a user
                $admin = $admin.replace("\\$computername\root\cimv2:Win32_Group.Domain=","") # trims the results for a group
                $admin = $admin.replace('",Name="',"\")
                $admin = $admin.REPLACE("""","")#strips the last "

                $objOutput = New-Object PSObject -Property @{
                    Machinename = $computername
        GroupName = $ADMINS.GroupComponent.split(",")[1].replace("""","").split("=")[1]
                    Fullname = ($admin)
                    DomainName  =$admin.split("\")[0]
                    UserName = $admin.split("\")[1]
                }#end object

    $objreport+=@($objoutput)
    }#end for

    return $objreport
}#end function



Function AddSCCMBoundary
{
[Threading.Thread]::CurrentThread.CurrentCulture = 'en-US'
$XLSX = New-Object -ComObject "Excel.Application"
 
$BoundariesXLSXFile = "C:\temp\CM_Boundaries.xlsx"
$Path = (Resolve-Path $BoundariesXLSXFile).Path
$SavePath = $Path -replace ".xl\w*$",".csv"
 
$WorkBook = $XLSX.Workbooks.Open($Path)
$WorkBook.SaveAs($SavePath,6)
$WorkBook.Close($False)
$XLSX.Quit()
 
$Boundaries = Import-Csv $SavePath
 
foreach($Item in $Boundaries)
{
    Switch($item.'Boundary Type')
    {
 
        "IP Subnet" {$Type = 0}
        "Active Directory Site" {$Type = 1}
        "IPv6" {$Type = 2}
        "Ip Address Range" {$Type = 3}
 
    }

    $Arguments = @{DisplayName = $Item.'Display Name'; BoundaryType = $Type; Value = $Item.'Value';SiteCode=$Item.'SiteCode'}
   Write-Host $Item.'Display Name'
  Write-Host $Item.Value
  Write-Host $Type
  Write-Host $Item.SiteCode

  Write-Host $Arguments.DisplayName
  Write-Host $Arguments.BoundaryType
  Write-Host $Arguments.Value
  Write-Host $Arguments.SiteCode
  Set-WmiInstance -Namespace "ROOT\SMS\Site_TOP" -Class SMS_Boundary -Arguments $Arguments -ComputerName CRASSDSCSS01

#Method2
#$WMIConnection = [WMICLASS]"\\SCCMServer\ROOT\SMS\Site_TOP:SMS_Boundary"
#$NewIPSubetNetBoundary = $WMIConnection.psbase.CreateInstance()
#$NewIPSubetNetBoundary.DisplayName = $Item.'Display Name'
#$NewIPSubetNetBoundary.BoundaryType = $Type
#$NewIPSubetNetBoundary.Value = $Item.Value
#$NewIPSubetNetBoundary.Put()


}

} #End AddSCCMBoundaryRange

function Get-VMEvents {
 <#
   .Synopsis

    Get events for an entity or for query all events.

   .Description

    This function returns events for entities. It's very similar to 
  get-vievent cmdlet.Note that get-VMEvent can handle 1 vm at a time.
  You can not send array of vms in this version of the script.

  .Example

    Get-VMEvents 0All -types "VmCreatedEvent","VmDeployedEvent","VmClonedEvent"

    This will receive ALL events of types "VmCreatedEvent","VmDeployedEvent",
  "VmClonedEvent". 
  
   .Example

    Get-VMEvents -name 'vm1' -types "VmCreatedEvent"

    Will ouput creation events for vm : 'vm1'. This was is faster than piping vms from
  get-vm result. There is no need to use get-vm to pass names to get-vmevents.
  Still, it is ok when you will do it, it will make it just a little bit slower <img src="http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif?m=1129645325g" alt=";)" class="wp-smiley" /> 
  
   .Example

    Get-VMEvents -name 'vm1' -category 'warning'

    Will ouput all events for vm : 'vm1'. This was is faster than piping names from
  get-vm cmdlet. Category will make get-vmevent to search only defined category
  events. 
  
   .Example

    get-vm 'vm1' | Get-VMEvents -types "VmCreatedEvent","VmMacAssignedEvent"

    Will display events from vm1 which will be regarding creation events,
  and events when when/which mac address was assigned


  .Parameter VM

    This parameter is a single string representing vm name. It expects single vm name that
  exists in virtual center. At this moment in early script version it will handle only a case
  where there is 1 instance of vm of selected name. In future it will handle multiple as 
  well.
  
   .Parameter types

    If none specified it will return all events. If specified will return
  only events with selected types. For example : "VmCreatedEvent",
  "VmDeployedEvent", "VmMacAssignedEvent" "VmClonedEvent" , etc...
  
  .Parameter category

    Possible categories are : warning, info, error. Please use this parameter if you
  want to filter events.
  
  .Parameter All

    If you will set this parameter, as a result command will query all events from
  virtual center server regarding virtual machines. 

   .Notes

    NAME:  VMEvents

    AUTHOR: Grzegorz Kulikowski

    LASTEDIT: 11/09/2012
  
  NOT WORKING ? #powercli @ irc.freenode.net 

   .Link

http://psvmware.wordpress.com

 #>

param(
[Parameter(ValueFromPipeline=$true)]
[ValidatenotNullOrEmpty()]
$VM,
[String[]]$types,
[string]$category,
[switch]$All
)
    $si=get-view ServiceInstance
    $em= get-view $si.Content.EventManager
    $EventFilterSpec = New-Object VMware.Vim.EventFilterSpec
  $EventFilterSpec.Type = $types
  if($category){
  $EventFilterSpec.Category = $category
  }
  
  if ($VM){
  $EventFilterSpec.Entity = New-Object VMware.Vim.EventFilterSpecByEntity
  switch ($VM) {
  {$_ -is [VMware.Vim.VirtualMachine]} {$VMmoref=$vm.moref}
  {$_ -is [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]}{$VMmoref=$vm.Extensiondata.moref}
  default {$vmmoref=(get-view -ViewType virtualmachine -Filter @{'name'=$VM}).moref }
  }
  $EventFilterSpec.Entity.Entity = $vmmoref
        $em.QueryEvents($EventFilterSpec) 
  }
  if ($All) {
  $em.QueryEvents($EventFilterSpec)
  }
}

function get-vmcreationdate {
<#
   .Synopsis

    Gets where possible vm creation date.

   .Description

    This function will return object with information about  creation time, method, month,
  creator for particular vm. 
  VMname         : SomeVM12
  CreatedTime    : 8/10/2012 11:48:18 AM
  CreatedMonth   : August
  CreationMethod : Cloned
  Creator         : office\greg
  
  This function will display NoEvent value in properties in case when your VC does no
  longer have information about those particular events, or your vm events no longer have
  entries about being created. If your VC database has longer retension date it is more possible
  that you will find this event. 

  .Example

    Get-VMCreationdate -VMnames "my_vm1","My_otherVM"

    This will return objects that contain creation date information for vms with names
  myvm1 and myvm2
  
   .Example

    Get-VM -Location 'Cluster1' |Get-VMCreationdate

    This will return objects that contain creation date information for vms that are
  located in Cluster1
  
   .Example

    Get-view -viewtype virtualmachine -SearchRoot (get-datacenter 'mydc').id|Get-VMCreationDate

    This will return objects that contain creation date information for vms that are
  located in datacenter container 'mydc'. If you are using this function within existing loop where you
  have vms from get-view cmdlet, you can pass them via pipe or as VMnames parameter.

  .Example

    $report=get-cluster 'cl-01'|Get-VMCreationdate
  $report | export-csv c:\myreport.csv
    Will store all reported creationtimes object in $report array variable and export report to csv file.
  You can also filter the report before writing it to csv file using select
  $report | Where-Object {$_.CreatedMonth -eq "October"} | Select VMName,CreatedMonth
  So that you will see only vms that were created in October.


  .Example
  get-vmcreationdate -VMnames "my_vm1",testvm55
  WARNING: my_vm1 could not be found, typo?
  VMname         : testvm55
  CreatedTime    : 10/5/2012 2:24:03 PM
  CreatedMonth   : October
  CreationMethod : NewVM
  Creator        : home\greg
  In case when you privided vm that does not exists in yor infrastructure, a warning will be displayed.
  You can still store the whole report in $report variable, but it will not include any information about
  missing vm creation dates. A warning will be still displayed only for your information that there was
  probably a typo in the vm name.
  
  .Parameter VMnames

    This parameter should contain virtual machine objects or strings that represents vm
  names. It is possible to feed this function wiith VM objects that come from get-vm or
  from get-view. 


   .Notes

    NAME:  Get-VMCreationdate

    AUTHOR: Grzegorz Kulikowski

    LASTEDIT: 27/11/2012
  
  NOT WORKING ? #powercli @ irc.freenode.net 

   .Link

http://psvmware.wordpress.com

 #>
 
param(
[Parameter(ValueFromPipeline=$true,Mandatory = $true)]
[ValidateNotNullOrEmpty()] 
[Object[]]$VMnames
)
process {
foreach ($vm in $VMnames){
$ReportedVM = ""|Select VMname,CreatedTime,CreatedMonth,CreationMethod,Creator
if ($CollectedEvent=$vm|Get-VMEvents -types 'VmBeingDeployedEvent','VmRegisteredEvent','VmClonedEvent','VmBeingCreatedEvent' -ErrorAction SilentlyContinue)
  {
  if($CollectedEvent.gettype().isArray){$CollectedEvent=$CollectedEvent|?{$_ -is [vmware.vim.VmRegisteredEvent]}}
  $CollectedEventType=$CollectedEvent.gettype().name
  $CollectedEventMonth = "{0:MMMM}" -f $CollectedEvent.CreatedTime
  $CollectedEventCreationDate=$CollectedEvent.CreatedTime
  $CollectedEventCreator=$CollectedEvent.Username
    switch ($CollectedEventType)
    {
    'VmClonedEvent' {$CreationMethod = 'Cloned'} 
    'VmRegisteredEvent' {$CreationMethod = 'RegisteredFromVMX'} 
    'VmBeingDeployedEvent' {$CreationMethod = 'VmFromTemplate'}
    'VmBeingCreatedEvent'  {$CreationMethod = 'NewVM'}
    default {$CreationMethod='Error'}
    }
  $ReportedVM.VMname=$CollectedEvent.vm.Name
  $ReportedVM.CreatedTime=$CollectedEventCreationDate
  $ReportedVM.CreatedMonth=$CollectedEventMonth
  $ReportedVM.CreationMethod=$CreationMethod
  $ReportedVM.Creator=$CollectedEventCreator
  }else {
    if ($?) {
      if($vm -is [VMware.Vim.VirtualMachine]){$ReportedVM.VMname=$vm.name} else {$ReportedVM.VMname=$vm.ToString()}
      $ReportedVM.CreatedTime = 'NoEvent'
      $ReportedVM.CreatedMonth = 'NoEvent'
      $ReportedVM.CreationMethod = 'NoEvent'
      $ReportedVM.Creator = 'NoEvent'
      
    } else {
      $ReportedVM = $null
      Write-Warning "$VM could not be found, typo?"
    }
  }
  $ReportedVM
}
}
}




function Remove-OrphanedData {
<# http://www.lucd.info/2011/04/25/orphaned-files-and-folders-spring-cleaning/
.SYNOPSIS   Remove orphaned folders and VMDK files
.DESCRIPTION   The function searches orphaned folders and VMDK files
   on one or more datastores and reports its findings.
   Optionally the function removes  the orphaned folders   and VMDK files
.NOTES   Author:  Luc Dekens
.PARAMETER Datastore
   One or more datastores.
   The default is to investigate all shared VMFS datastores
.PARAMETER Delete
   A switch that indicates if you want to remove the folders
   and VMDK files
.EXAMPLE
   PS> Remove-OrphanedData -Datastore ds1
.EXAMPLE
  PS> Get-Datastore ds* | Remove-OrphanedData
.EXAMPLE
  PS> Remove-OrphanedData -Datastore $ds -Delete
#>
 
  [CmdletBinding(SupportsShouldProcess=$true)]
 
  param(
  [parameter(Mandatory=$true,ValueFromPipeline=$true)]
  [PSObject[]]$Datastore,
  [switch]$Delete
  )
 
  begin{
    $fldList = @{}
    $hdList = @{}
 
    $fileMgr = Get-View FileManager
  }
 
  process{
    foreach($ds in $Datastore){
      if($ds.GetType().Name -eq "String"){
        $ds = Get-Datastore -Name $ds
      }
      if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess){
        Get-VM -Datastore $ds | %{
          $_.Extensiondata.LayoutEx.File | where{"diskDescriptor","diskExtent" -contains $_.Type} | %{
            $fldList[$_.Name.Split('/')[0]] = $_.Name
            $hdList[$_.Name] = $_.Name
          }
        }
        Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{
          $_.Extensiondata.LayoutEx.File | where{"diskDescriptor","diskExtent" -contains $_.Type} | %{
            $fldList[$_.Name.Split('/')[0]] = $_.Name
            $hdList[$_.Name] = $_.Name
          }
        }
 
        $dc = $ds.Datacenter.Extensiondata
 
        $flags = New-Object VMware.Vim.FileQueryFlags
        $flags.FileSize = $true
        $flags.FileType = $true
 
        $disk = New-Object VMware.Vim.VmDiskFileQuery
        $disk.details = New-Object VMware.Vim.VmDiskFileQueryFlags
        $disk.details.capacityKb = $true
        $disk.details.diskExtents = $true
        $disk.details.diskType = $true
        $disk.details.thin = $true
 
        $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
        $searchSpec.details = $flags
        $searchSpec.Query += $disk
        $searchSpec.sortFoldersFirst = $true
 
        $dsBrowser = Get-View $ds.ExtensionData.browser
        $rootPath = "[" + $ds.Name + "]"
        $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)
        foreach($folder in $searchResult){
          if($fldList.ContainsKey($folder.FolderPath.TrimEnd('/'))){
            foreach ($file in $folder.File){
              if(!$hdList.ContainsKey($folder.FolderPath + $file.Path)){
                New-Object PSObject -Property @{
                  Folder = $folder.FolderPath
                  Name = $file.Path
                  Size = $file.FileSize
                  CapacityKB = $file.CapacityKb
                  Thin = $file.Thin
                  Extents = [string]::Join(',',($file.DiskExtents))
                }
                if($Delete){
                  If ($PSCmdlet.ShouldProcess(($folder.FolderPath + " " + $file.Path),"Remove VMDK")){
                    $dsBrowser.DeleteFile($folder.FolderPath + $file.Path)
                  }
                }
              }
            }
          }
          elseif($folder.File | where {"cos.vmdk","esxconsole.vmdk" -notcontains $_.Path}){
            $folder.File | %{
              New-Object PSObject -Property @{
                Folder = $folder.FolderPath
                Name = $_.Path
                Size = $_.FileSize
                CapacityKB = $_.CapacityKB
                Thin = $_.Thin
                Extents = [String]::Join(',',($_.DiskExtents))
              }
            }
            if($Delete){
              if($folder.FolderPath -eq $rootPath){
                $folder.File | %{
                  If ($PSCmdlet.ShouldProcess(($folder.FolderPath + " " + $_.Path),"Remove VMDK")){
                    $dsBrowser.DeleteFile($folder.FolderPath + $_.Path)
                  }
                }
              }
              else{
                If ($PSCmdlet.ShouldProcess($folder.FolderPath,"Remove Folder")){
                  $fileMgr.DeleteDatastoreFile($folder.FolderPath,$dc.MoRef)
                }
              }
            }
          }
        }
      }
    }
  }
}


Function Get-WMILoggedOnUser {
<#
.SYNOPSIS
    Function to get all logged on sessions (numbers) and coresponding users (domain name) on a local or remote system with WMI
  
.DESCRIPTION
    Function to get all logged on sessions (numbers) and coresponding users (domain name) on a local or remote system with WMI
  
  Gets the Win32_LogonSession and the associated Win32_LoggedOnUser information from WMI.
  Matches the user to the session by sessionid
  Creates a link between the LogType number to LogonTypeName name for the session logon type
  
  Returns an PSCustomObject:
    User properties: Domain,Name and SID
    UserSession properties: StartTime,LogonID,LogonType,LogonTypeName and the ComputerName
    
.PARAMETER ComputerName
  Specifies the computer against which you want to run the management operation.
  The value can be a fully qualified domain name, a NetBIOS name, or an IP address.
  Use the local computer name, use localhost, or use a dot (.) to specify the local computer.
  The local computer is the default. When the remote computer is in a different domain from the user,
  you must use a fully qualified domain name. This parameter can also be piped to the cmdlet.
  
.PARAMETER Logontype
  
  Parameter to select the returned logontype(s)
  
  See MSDN documentation for the WMI Win32_LogonSession class Property Logontype
  
  Win32_LogonSession.Logontype is Numeric value that indicates the type of logon session.

  0	Used only by the System account.

  2	Interactive
    Intended for users who are interactively using the machine, such as a user
    being logged on by a terminal server, remote shell, or similar process.

  3	Network
    Intended for high-performance servers to authenticate clear text passwords.
    LogonUser does not cache credentials for this logon type.

  4	Batch
    Intended for batch servers, where processes can be executed on behalf of a user
    without their direct intervention; or for higher performance servers that process many
    clear-text authentication attempts at a time, such as mail or web servers. LogonUser
    does not cache credentials for this logon type.

  5	Service
    Indicates a service-type logon. The account provided must have the service privilege enabled.

  6	Proxy
    Indicates a proxy-type logon.

  7	Unlock
    This logon type is intended for GINA DLLs logging on users who are interactively
    using the machine. This logon type allows a unique audit record to be generated
    that shows when the workstation was unlocked.

  8	NetworkCleartext
    Windows Server 2003 and Windows XP:  Preserves the name and password in the authentication packages,
    allowing the server to make connections to other network servers while impersonating the client.
    This allows a server to accept clear text credentials from a client, call LogonUser, verify that
    the user can access the system across the network, and still communicate with other servers.

  9	NewCredentials
    Windows Server 2003 and Windows XP:  Allows the caller to clone its current
    token and specify new credentials for outbound connections. The new logon session
    has the same local identify, but uses different credentials for other network connections.

  10	RemoteInteractive
    Terminal Services session that is both remote and interactive.

  11	CachedInteractive
    Attempt cached credentials without accessing the network.

  12	CachedRemoteInteractive
    Same as RemoteInteractive. This is used for internal auditing.

  13	CachedUnlock
    Workstation logon.

.PARAMETER Credential
    Allows alternate Credentials to be used in query
    
.EXAMPLE
    Get-WMILoggedOnUser
  
  Returns all types of logged on User sessions on the local machine (computer)
  
.EXAMPLE
    Get-WMILoggedOnUser -Computername 'localhost'  -LogonType 'All'
  
  Same as example 1: Returns all types of logged on User sessions on the local machine (computer)
  
.EXAMPLE
    Get-WMILoggedOnUser -Computername 'Server1','Server2' -LogonType 'Interactive'
  
  Returns only logged on Users with logon type of 'Interactive' (number 2)
  
.NOTES
    Author: Peter Kriegel
    Version 1.1.0 -- Boe Prox
        -Added pipeline support for computername
        -Expanded error handling
        -Allow alternate credentials
    Version 1.0.1 -- GiZmO 33
        -Added Error handling
    Version 1.0.0
        - Initial Creation
    12.July.2013
#>

    [Cmdletbinding()]
    param (
        [Parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [Alias('__Server','DNSHostname','IPAddress','Name')]
        [String[]]$Computername = $ENV:COMPUTERNAME,
    
    [Parameter(Position=1)]
    [ValidateSet('0','LocalSystem','2','Interactive','3','Network','4','Batch','5',
    'Service','6','Proxy','7','Unlock','8','NetworkCleartext','9','NewCredentials',
    '10','RemoteInteractive','11','CachedInteractive','12','CachedRemoteInteractive',
    '13','CachedUnlock','All')]
    [String[]]$LogonType = @('0','2','3','4','5','6','7','8','9','10','11','12','13'), # All
        [parameter()]
        [Alias('RunAs')]
        [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty     
    )

    Begin{
            #wmiparams
            $wmiParam = @{
                ErrorAction = 'Stop'
            }
            If ($PSBoundParameters['Credential']) {
                $wmiParam.Credential = $Credential
            }
            # define LogOnType hashtable for to convert Numbers into Text
            $HashLogonType = @{ 
                '0'='LocalSystem' 
                '2'='Interactive'
                '3'='Network'
                '4'='Batch'
                '5'='Service'
                '6'='Proxy'
                '7'='Unlock'
                '8'='NetworkCleartext'
                '9'='NewCredentials'
                '10'='RemoteInteractive'
                '11'='CachedInteractive'
                '12'='CachedRemoteInteractive'
                '13'='CachedUnlock'
            }
            
    } # end Begin block

    Process {
        Try {
            ForEach($CurComputerName in $ComputerName) {
                $wmiParam.Computername = $CurComputerName
                $wmiParam.Class = 'Win32_LogonSession'
                $LogonSessions = Get-WmiObject @wmiParam
                $wmiParam.Remove('Class')
                ForEach($LogonSession in $LogonSessions) {
                    Try {
                        $wmiParam.Query = "Associators of {Win32_LogonSession.LogonId=$($LogonSession.LogonId)} Where AssocClass=Win32_LoggedOnUser Role=Dependent"
                        $LoggedOnUser = Get-WmiObject @wmiParam | 
                            Select-Object Domain,Name,SID,StartTime,LogonID,LogonType,LogonTypeName,ComputerName
                        If ($LoggedOnUser.Name) {
                            $LoggedOnUser.StartTime = [Management.ManagementDateTimeConverter]::ToDateTime($LogonSession.starttime)
                            $LoggedOnUser.LogonID = $LogonSession.LogonID
                            $LoggedOnUser.LogonType = $LogonSession.logontype
                            $LoggedOnUser.LogonTypeName = $HashLogonType[[String]$LogonSession.logontype]
                            $LoggedOnUser.ComputerName = $CurComputerName
                
                    # Filter selected LogonTypes to report
                    If($LogonType -contains [String]$LoggedOnUser.LogonType -or $LogonType -contains $LoggedOnUser.LogonTypeName) {
                      # return result object
                      $LoggedOnUser
                    }
                        } Else {
                            Write-Warning ("{0}: Cannot find associated Logon Session!" -f $LogonSession.logonId)
                        }
                    } Catch {
                        Write-Warning ("{0}: {1}" -f $Logonsession.logonid,$_.exception.message)
                    }
                } # end  ForEach $LogonSession
                $wmiParam.Remove('Query')
            }  # end ForEach $Computer 
        } catch [exception] {
            Write-Warning ("{0}" -f $_.exception.message)
        }
    } # end process block
    End {}
}