Add users or groups to local admin group

Sometimes you need to add users or groups in local Administrators group on a windows server. This function helps to accomplish that on one or more servers. Load a text- or csv-file and pipe it to Add-AdminGroup. All servers not responding will be shown at the end for later follow-up.

function Add-AdminGroup
{
	Param (
		[parameter(Mandatory = $true,
				   ValueFromPipeline = $true,
				   position = 0)]
		[Alias('IPAddress', '__Server', 'CN', 'server')]
		[string[]]$Computername,
		[parameter(ValueFromPipelineByPropertyName)]
		[Alias('groupname', 'adgroup')]
		[string[]]$group
	)
	
	Process
	{
		if (Test-Connection -quiet -Computername $computername)
		{
			Write-Output "Adding $group to local administrators on" $Computername
			Invoke-Command -ComputerName $Computername -ScriptBlock {
			Add-LocalGroupMember -Group Administrators -Member $args[0]
			} -ArgumentList $group
			
		}
		else
		{
			write-output "No response from" $Computername
			$failed += $computername
		}
		
	}
	end
		{
			foreach ($obj in $failed)
			{
				Write-Output $obj
			}
		}
	
}

List VMs according to memory and CPU usage

For internal billing purpose I needed a way list all Windows VMs for a given subsidiary and their CPU and memory configuration.

Connect-VIServer -Server vcenter.corp.lan

$var = get-vm -location Subsidiary1 | Where{ $_.Guest.OSFullName -like '*windows*' }  | select numcpu, memorygb | Group-Object numcpu,memorygb

function get-numOfVms
{
	param
	(
		[parameter(Mandatory = $true)]
		[pscustomobject]$VMs
	)

	$results = foreach ($row in $var)
	{
		$cpu, $mem = $row.Name -split ',', 2
		[pscustomobject]@{
			NumOfVMs = $row.Count
			NumOfCPUs   = $cpu
			MemoryGB = $mem.Trim()
		}
	}
	
	return $results
}
$total = get-numOfVms -VMs $var
$total | Export-Csv -Path totalvms.csv -NoTypeInformation

 

Example of totalvms.csv. It gives you a number of each specific CPU and memory configuration.

"NumOfVMs","NumOfCPUs","MemoryGB"
"1","2","8"
"12","1","4"
"4","4","8"
"2","4","4"
"9","1","8"
"5","4","12"
"22","4","32"
"6","4","16"
"2","1","12"
"1","4","24"
"1","1","16"
"1","4","6"
"1","1","6"
"1","24","32"
"1","4","25"
"3","2","16"
"1","8","6"
"1","1","3"

Create DHCP scopes from a CSV file

A fast way to import multiple DHCP scopes to a DHCP server. Some settings needs to be added on top level. For example DNS servers.

Required header in CSV:
name;description;startrange;endrange;subnetmask;scopeid;router

$dhcpserver = "1.1.1.1"
$scopes = Import-Csv -Path dhcp.csv -Delimiter ";"
foreach ($scope in $scopes)
{
	$name = $scope.name
	$description = $scope.description
Write-Output "Creating scope  $name"
Add-DhcpServerv4Scope -ComputerName $dhcpserver -Name "$name" -Description "$description" -StartRange $scope.startrange -EndRange $scope.endrange -SubnetMask $scope.subnetmask -State Active -LeaseDuration 1.00:00:00
Set-DhcpServerv4OptionValue -Router $scope.router -ScopeId $scope.scopeid -ComputerName $dhcpserver
}

Invoke webrequest example

This example uses invoke-webrequest to retrieve computer information from a company reporting webpage. Only text inside TD elements are stored in a array for future use and added to a PSObject.

function Get-ComputerInfo
{
	[CmdletBinding()]
	param
(
		[parameter(
			 ValueFromPipeline = $true,
			 position = 0,
			 Mandatory = $true)]
	[string]$computername
)

	process
	{
		$Request = @{
			'domain'	  = 'domain1.company.net'
			'name'    = $computername
		}
		$lab = Invoke-WebRequest -Uri https://reporting.company.net/searchcomputer.php -Body $Request -Method Post

		$output = $lab.ParsedHtml.body.getElementsBytagname('TD') | select -expand innerhtml

		if ($output[7] -match '\D\d\d\d\d\d\d\d')
		{
			$user = Get-ADUser -Identity $output[7] | select -ExpandProperty name
		}
		else
		{
			$user = "Unknown"
			$output[7]= "Unknown"
		}

		$result = New-Object PSObject -Property @{
			Computername	    = $output[0];
			OU				    = $output[2];
			IP				    = $output[6];
			OS				    = $output[3];
			LastUser		    = $output[7];
			LastUSerFullName    = $user;
			LastSeen		    = $output[5];
			Master			    = $output[4];
		}
		Write-Output $result | select computername, ou, ip, os, master, lastuser, lastuserfullname, lastseen
	}#End Process
}

Migrate VMs between clusters with powecli

A short script to migrate VMs to a new cluster or host. Migrates one vm at a time to save network bandwith. After migration it upgrades Vmware tools to match current host version.

Takes a CSV file as input with VMs to migrate.

Param (
	[Parameter (Mandatory = $True)]
	$file
)
$vms = Import-Csv $file

foreach ($vm in $vms)
{
	Write-Host "Migrating VM" $vm.name
	Move-VM -VM $vm.name -Destination Cluster01
	Write-Host "Updating Vm-tools on " $vm.name
	Update-Tools -VM $vm.name -NoReboot
}

Fix VMware tools not running on Windows servers

I had some trouble with VMwaretools stopping on some machines and decided to automate restart och vmware tools. I wrote this script which takes a view parameter to view current status. If you start the script whitout the view parameter it will try to restart vmware tools.

fix-toolsnorunning.ps1

param
(
[parameter(Mandatory = $false)]
[switch]
$view
)

#Connect to Vcenter
$cred = Get-Credential
Connect-VIServer vcenter -Credential $cred | Out-Null

Write-Host -ForegroundColor Green "Collecting VMs"
$toolsvm=get-vm | where { $_.GuestId -like "*Windows*" -and $_.Extensiondata.Summary.Guest.ToolsStatus -like "toolsnotrunning" -and $_.Powerstate -eq "PoweredOn"}

#Stop script if no VMs reports tools not running
if ($toolsvm -eq $null)
{
Write-Host "Nothing to fix"
Disconnect-VIServer vcenter -Confirm:$false
exit
}

if ($view)
{
Write-Host "VMs whitout tools running"
foreach ($vm in $toolsvm)
{
Write-Host $vm
}
}
Else
{

foreach ($vm in $toolsvm)
{

if ($vm -match "^(?<Name>\S*)\s.*$") { $vm_name = $Matches.Name }
else { $vm_name = $vm }

$vm_hostname = $vm_name.name +".domain.local"

if (Test-Connection -Computername $vm_hostname -BufferSize 16 -Count 1 -Quiet)
{
Invoke-Command -Computername $vm_hostname -ScriptBlock { stop-Service -name vmvss; start-service vmvss } -Credential $cred
Write-Host "Service restarted on $vm_name"
}
Else
{
Write-Host -ForegroundColor Red "Unable to contact $vm_name"
}

}
}
#Disconnect from Vcenter.
Disconnect-VIServer vcenter -Confirm:$false

Create a new host via OP5 API with powershell

If you need to create a new host with OP5 api you can use something like this.
Template, hostgroups and contactgroups are not mandatory and can be removed from hash table.

 

function new-op5host
(
	[parameter(Mandatory = $true)]
	[string]$hostname,
	[parameter(Mandatory = $true)]
	[string]$alias
)
{
	$username = 'api_user$Default'
	$password = "password"
	
	$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
	
	$hash = @{
		file_id = "etc/hosts.cfg";
		host_name = "$hostname";
		address = "$hostname.domain.com";
		alias = "$alias";
		max_check_attempts = "3";
		notification_interval = "5";
		notification_options = "d", "r";
		notification_period = "24x7";
		template = "Win_hosts";
		hostgroups = "Windows servers";
		contact_groups = "Windowsservrar"
	}
	$jsonData = $hash | convertto-json
	
	$result = Invoke-RestMethod -Method POST -ContentType "application/json" -Uri "https://op5.domain.com/api/config/host" -Body $jsonData -Headers @{ Authorization = ("Basic {0}" -f $base64AuthInfo) }
	
	#Save
	$result = Invoke-RestMethod -Method POST -ContentType "application/json" -Uri "https://op5.domain.com/api/config/change" -Headers @{ Authorization = ("Basic {0}" -f $base64AuthInfo) }
		
}

Change wallpaper on windows 7

I needed a script to change desktop wallpaper for all users using the default one with an outdated company logo on. I came up with this startup script as a solution. Set $filesize to the size of the old wallpaper to only change wallpapers with same filesize. Use as logon script.

$filesize = 100593
$bg = Get-Item ("$env:USERPROFILE\appdata\Roaming\Microsoft\Windows\Themes\TranscodedWallpaper.jpg)
if ($bg.length -eq $filesize)
{
Copy-item "\\fileserver\UsrLogon\wallpaper\img0.jpg" "$env:USERPROFILE\appdata\Roaming\Microsoft\Windows\Themes\img0.jpg" -Force
Set-ItemProperty -path 'HKCU:\Control Panel\Desktop\' -name wallpaper -value "$env:USERPROFILE\appdata\Roaming\Microsoft\Windows\Themes\img0.jpg"
rundll32.exe user32.dll, UpdatePerUserSystemParameters
}