Tag Archives: Powershell

Ping computers via Powershell

We have all used ping.exe from a command line at some point for quickly resolving computer host names to an IP address. I created a Powershell script whilst onsite with a client last week to provide the same functionality. Using Active Directory as a data source to obtain all computer accounts which were enabled. Then utilizing the test-computer cmdlet via Powershell to check if the computers were online.

The output is then saved into a nice csv file which can be easily read in Excel.

There are a few freeware tools such as Angry IP scanner or Advanced IP scanner that can do something similar.

Initial code is below and available via GITHUB [davidmcisaac/Powershellpub].

Active Directory powershell module is required to be installed for script to execute.

<#Created by DM 050517 Resolve_ComputerName_2_IP.ps1 #>
$comp =@();$rep =@();$cp =@()
$IPNull = "N/A"
$PingSuccess ="Online"
$PingnonSuccess ="Offline"
$comp = Get-ADComputer -Filter * |Where-Object {$_.enabled -eq $true}|select DNSHostName
foreach ($cp in $comp)
    {#Loop through each computer found
        $t=@()
        $catcherror=@()
        $t= Test-Connection -ComputerName $cp.DNSHostName -Count 1 -ErrorAction SilentlyContinue -ErrorVariable CatchError
        if ([string]::IsNullOrEmpty($catcherror))
            {#Test Connection received reply. Write IP to csv
            $rep += $t|select @{Name="Computer";exp={[string]$_.Address}},IPv4Address,ipv6address,@{Name="Status";exp={[string]$PingSuccess}}
            }
        else
            {#Write error to csv
            $rep += $cp|select @{Name="Computer";exp={$cp.DNSHostName}},@{Name="IPv4Address";exp={[string]$IPNull}},@{Name="IPv6Address";exp={[string]$IPNull}},@{Name="Status";exp={[string]$PingnonSuccess}}
            }   
    }
$rep|export-csv -NoTypeInformation C:\computer_2_ip_report.csv

Plan to make a few changes in the future, to account for larger environment where filtering by Organisation Unit would be useful

Clear Exchange 2013 IIS Logs

Something I’ve been working on for a while is a script to clear up all those Exchange IIS logs which are generated through time.

Why are these logs not recycled after a period of time, well for good reason in most cases is to assist with troubleshooting when something goes wrong.

Anyhow, unlike logs such as the Exchange transport log these; which are recycled after they reach a certain size. The IIS logs don’t clear down automatically.

To help clear down disk space the following script can be used. Any IIS logs older than 30 days located in the “Exchange Back end” WWW will be purged.

Download this file save as ps1 and run as administrator on your Exchange servers. I have tested this on Exchange 2013 SP1 CU6 servers.

As always please test on non-production/test servers first to check that this will work with your own environment and have a solid backup of Exchange.

<# Created by DM 151216 
Clear_Exchange_IISLogs.ps1 
got date info from here https://technet.microsoft.com/en-us/library/ff730960.aspx #>
##Variables

Write-host "Starting script"
$Retain_Logs =30
$TodaysDate = Get-Date
$ExchangeWWW = Get-Website -Name "Exchange Back End"
$ExchangeIISLog = $ExchangeWWW.logFile.directory
$LogFilesDeleted = "C:\temp\IISlogsDeleted_$(get-date -f dd-MM-yy).txt"
$DeleteOlderThan = $TodaysDate.AddDays(-$Retain_Logs)

if ($ExchangeIISLog -cge "%SystemDrive%")
        {
            $newpath = $ExchangeIISLog -replace "%SystemDrive%","C:"
            $direction = "1"
        Write-host "IIS Log folder for Exchange located here $newpath"
        }
else
        {
            $direction = "2"
            Write-host "IIS Log folder for Exchange located here $ExchangeIISLog"
        } 

##Select the right path
switch ($direction)
    {
    1
        {
        ##get list of files to delete from new path
            $LogsToDelete = Get-ChildItem $newpath -Include *.log -Recurse | Where {$_.LastWriteTime -le "$DeleteOlderThan"}
            add-content $LogFilesDeleted "Starting to delete IIS Logs files located in $IISLogsPath @ $TodaysDate" 
            add-content $LogFilesDeleted "------------------------------------------------------------------------"
        }
    2
        {
        ##get list of files to delete from orignal    
            $LogsToDelete = Get-ChildItem $ExchangeIISLog -Include *.log -Recurse | Where {$_.LastWriteTime -le "$DeleteOlderThan"}
            add-content $LogFilesDeleted "Starting to delete IIS Logs files located in $IISLogsPath @ $TodaysDate" 
            add-content $LogFilesDeleted "------------------------------------------------------------------------"
        }
    }
#Loop through each file older than value set in $Retain_Logs and record success
Write-Host "Starting to clear Logs"
foreach ($File in $LogsToDelete)
    {
        Remove-Item $File -ea SilentlyContinue
        $filestatus = Test-path $File    
            
        if ($filestatus -eq $True)
        {
            add-content $LogFilesDeleted "Failed to delete $file"
        }
        
        elseif ($filestatus -eq $False)
        {   
            add-content $LogFilesDeleted "Successfully deleted $file"
        }
    }
add-content $LogFilesDeleted "------------------------------------------------------------------------"
add-content $LogFilesDeleted "Finished deleting IIS Logs files located in $IISLogsPath @ $TodaysDate" 
add-content $LogFilesDeleted "------------------------------------------------------------------------"
Write-Host "Check $LogFilesDeleted for list of files deleted successfully and any errors"  

Script output
script execution

 

 

Sample output

Log file output

Log file output

Remove Windows 10 built in apps

A bunch of Windows 10 updates ran on my laptop yesterday and decided to re-install windows built in apps that I previously uninstalled.

The offending update seemed to be KB 3124263 Cumulative Update for Windows 10 Version 1511: January 12, 2016 

Wrote a wee powershell script to remove the apps I didn’t want, which will no doubt reappear sometime in the future.

The list of apps to uninstall should be saved in a file called applist.txt in C:\temp\ and the below powershell script can be saved as PS1 script and run as administrator.

<#Created by DM 180915
copy applist.txt file to C:\temp\ 
Additional apps can be uninstalled if required and add name to applist.txt. 
To find list of apps run the following command Get-AppxPackage|ft Name|out-file C:\temp\all_applist.txt 
Execution policy will have to be set to unrestricted before running script Open Powershell and run as Administrator Execute following command Set-ExecutionPolicy -ExecutionPolicy Unrestricted#>
$applist = get-content -path C:\temp\applist.txt
Foreach ($i in $applist)
{
Get-AppxPackage $i | Remove-AppxPackage
}
The following list can be copied into notepad and saved as applist.txt
Please note you don't need to uninstall these all apps, in this instance these are the ones I didn't required.

Microsoft.3DBuilder
Microsoft.WindowsAlarms
Microsoft.Getstarted
Microsoft.MicrosoftOfficeHub
Microsoft.SkypeApp
Microsoft.Office.OneNote
Microsoft.People
Microsoft.BingFinance
Microsoft.BingNews
Microsoft.BingSports
Microsoft.BingWeather
Microsoft.XboxApp
Microsoft.ZuneMusic
Microsoft.ZuneVideo

Start/Stop SSH access to VMWare ESXi using PowerCli

On occasion many VMware vSphere admins have to carry out a task on a ESXi host directly. Whether this is restarting the management agents, installing vibs or general administration. To do so remotely you need SSH and the ESXi shell services running.

For enhanced security the default action in ESXi 6 is for SSH and ESXi shell services to be disabled on startup.

Previously I went through the task of opening the vSphere client and enabling these manually each time. The following script provides a scripted method to stop and start these services for you. The script could be adapted to change other services and initiate secondary actions if required.

Prerequisite:

Install VMware vSphere PowerCLI, script has been tested with version 6 R1 available here vSphere PowerCLI 6.0 Release 1

All the variables are declared at the start of the script and prefixed with the dollar $ symbol.

##Created by DM 311015
##Host Services
##VM variables
$vcenter_server ="vcenter.vsphere.local"
$vcenter_user ="administrator@vsphere.local"
$vcenter_pwd ="Password123"
##Load VMware PS plugin
Add-PSSnapin VMware.VimAutomation.Core >$null
Clear-Host
###########################Start- Custom Task #########################
##Create do loop if value does eq 1,2,3,4. Exit added if option 5 selected
do
{
write-host "
------Main Menu --------
Select one of the following options
Manage Host via vCenter
option 1: Start SSH and ESXi host services via vCenter
option 2: Stop SSH and ESXi host services via vCenter
Manage Host directly
option 3: Start SSH and ESXi host services via Host
option 4: Stop SSH and ESXi host services via Host
option 5: Exit
------------------------
"
$option = Read-Host "Enter option"
if ($option -eq "1" -OR $option -eq "2" -OR $option -eq "3" -OR $option -eq "4")
 {
 write-host 
"------Host Selection --"
 $esxihost = Read-Host "Enter FQDN of ESXi host to process"
 write-host 
"-----------------------"
 switch ($option)
 {
 1
 {
 connect-viserver -server $vcenter_server -User $vcenter_user -Password $vcenter_pwd >$null
 Clear-Host
 "Start SSH and ESXi Shell service"
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "SSH"}|Start-VMHostService |ft -AutoSize Label, Running
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "ESXi Shell"}|Start-VMHostService |ft -AutoSize Label, Running
 }
 2
 { 
 connect-viserver -server $vcenter_server -User $vcenter_user -Password $vcenter_pwd >$null
 Clear-Host
 "Stop SSH and ESXi Shell service"
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "SSH"}|Stop-VMHostService -confirm:$false |ft -AutoSize Label, Running
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "ESXi Shell"}|Stop-VMHostService -confirm:$false |ft -AutoSize Label, Running
 }
 3
 { 
 $esxihost_root = Read-Host "Enter ESXi host root user"
 $esxihost_pwd = Read-Host "Enter ESXi host root password"
 connect-viserver -server $esxihost -User $esxihost_root -Password $esxihost_pwd >$null
 Clear-Host
 "Start SSH and ESXi Shell service"
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "SSH"}|Start-VMHostService |ft -AutoSize Label, Running
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "ESXi Shell"}|Start-VMHostService |ft -AutoSize Label, Running
 }
 4
 { 
 $esxihost_root = Read-Host "Enter ESXi host root user"
 $esxihost_pwd = Read-Host "Enter ESXi host root password"
 connect-viserver -server $esxihost -User $esxihost_root -Password $esxihost_pwd >$null
 Clear-Host
 "Stop SSH and ESXi Shell service"
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "SSH"}|Stop-VMHostService -confirm:$false |ft -AutoSize Label, Running
 Get-VMHostService -VMHost $esxihost|?{$_.Label -eq "ESXi Shell"}|Stop-VMHostService -confirm:$false |ft -AutoSize Label, Running
 }
 }
 }
elseif ($option -eq "5" -or $option -Contains "exit" -or $option -Contains "quit")
 {write-host "Ok then good bye :)"
 exit
 }
elseif ($option -ne "1" -OR $option -ne "2" -OR $option -ne "3" -OR $option -ne "4" -OR $option -ne "5")
 {write-host 
 "Invalid Input. Please re-enter selection"
 }
}
while ($option -ne "1" -OR $option -ne "2" -OR $option -ne "3" -OR $option -ne "4")

Change Virtual Machine memory with VMware PowerCLI

Changing memory assigned to a virtual machine, you may think will be a quick 2 minute job. By default this task can only be performed whilst the virtual machine is powered off. If the guest vm supports hot add then this can be done when the machine is online.

To enable Hot add on a virtual machine you can follow this guide from VMware Change Memory Hot Add Settings in the vSphere Web Client

Turning a VM off during the business day might not go down to well with your customers/users. That leaves us with carrying out the change out of hrs, I’m your like me and prefer to keep your evening as your own rather than working.

The following can be saved as a ps1 script and scheduled to run out of hrs in a maintenance window. If you specify the email setting in the script an email will be generated once completed to notify that the change has been completed.

Prerequisite:

Install VMware vSphere PowerCLI, script has been tested with version 6 R1 available here vSphere PowerCLI 6.0 Release 1

All the variables are declared at the start of the script and prefixed with the dollar $ symbol.

##Created by DM 180915
##Task Change VM memory
##VM name
$VM2change = "test-server"
##Email Settings
$emailServer = "192.168.1.1"
$sender = "powercli@vsphere.local"
$recipients = "admin@vsphere.local"
##Load VMware PS plugin
Add-PSSnapin VMware.VimAutomation.Core
##Connect to vCenter
connect-viserver -server vcenter.vsphere.local -User administrator@vsphere.local -Password Password123
###########################Start- Custom Task #########################
$beforechange = (GET-VM -Name $VM2change|FT -auto MemoryGB|out-string)
##Stop VM
GET-VM -Name $VM2change| Stop-VMGuest -Confirm:$False
start-sleep -s 180
##Change Memory
GET-VM -Name $VM2change| set-vm -MemoryGB 28 -Confirm:$False
##Start VM
GET-VM -Name $VM2change| Start-VM -Confirm:$False
$afterchange = (GET-VM -Name $VM2change|FT -auto MemoryGB|Out-String)
##ping VM
start-sleep -s 120
$isalive= (Test-Connection -ComputerName $VM2change -count 1|Out-String)
###########################End- Custom task #########################
##Compose eMail and send
$body = @" 
Memory Before,$beforechange.
Memory After, $afterchange.
Is VM up??, $isalive
"@
send-mailmessage -from $sender -to $recipients -subject "VM Memory Change $VM2change" -Bodyashtml "$body" -smtpserver $EmailServer

Clone Virtual Machine in VMware with PowerCLI

Cloning a virtual machine can either be performed when powered on or off. I personally prefer to create a clone whilst the VM is offline to ensure that all data is in a consistent state.

Turning a VM off during the business day might not go down to well with your customers/users.

The following can be saved as a ps1 script and scheduled to run out of hrs in a maintenance window. If you specify the email setting in the script an email will be generated once completed to notify that the change has been completed.

Prerequisite:

Install VMware vSphere PowerCLI, script has been tested with version 6 R1 available here vSphere PowerCLI 6.0 Release 1

All the variables are declared at the start of the script and prefixed with the dollar $ symbol.

##Task Clone VM
##Declare variables
$VM2change = "test-server"
$VMclone = "$VM2change_clone"
$Hostesxi = "esxihost1.vsphere.local"
$vcenter_server ="vcenter.vsphere.local"
$vcenter_user ="administrator@vsphere.local"
$vcenter_pwd ="Password123"
##Email Settings
$emailServer = "192.168.1.1"
$sender = "powercli@vsphere.local"
$recipients = "admin@vsphere.local"
$dateofclone = $(get-date -f dd-MM-yyyy)
##Load VMware PS plugin
Add-PSSnapin VMware.VimAutomation.Core
##Connect to vCenter
connect-viserver -server $vcenter_server -User $vcenter_user -Password $vcenter_pwd
###########################Start- Custom Task #########################
##Stop VM
GET-VM -Name $VM2change| Stop-VMGuest -Confirm:$False
start-sleep -s 180
##Clone VM, set disk type to thin and create in template folder
New-VM -VM $VM2change -Name $VMclone -VMHost $Hostesxi -DiskStorageFormat Thin -Location "VM Template" -Notes "Clone created $dateofclone by David McIsaac"
##Convert to template
Set-VM -VM $VMclone -ToTemplate -Confirm:$False
##Start orignal VM
GET-VM -Name $VM2change| Start-VM -Confirm:$False
##Get Clone info
$VMcloneinfo = (Get-Template -Name $VMclone| fl *|Out-String)
##ping original VM
start-sleep -s 120
$isalive= (Test-Connection -ComputerName $VM2change -count 1|Out-String)
###########################End- Custom task #########################
##Compose email and send
$body = @" 
VM Clone Created,$VMcloneinfo.
Is original VM up??, $isalive
"@
send-mailmessage -from $sender -to $recipients -subject "VM Cloned $VM2change" -Bodyashtml "$body" -smtpserver $EmailServer

How to reduce Veeam ONE Database size

Veeam ONE is the monitoring and reporting component of the popular Veeam Availability Suite.

The default installation stores the monitoring data within a Microsoft SQL Express database. Depending on version this will either be a SQL 2008 or SQL 2012 Express which has a maximum size of 10 GB.

I’ve seen an issue in a couple of our customer environments that DB size can grow to the maximum size. Reason being due to a high number of events being generated from a Hyper-V node windows security log. If you are currently running version 8 it is recommended to install the following patch which should resolve the underlying issue from occurring again.

Link to Veeam ONE v8 Update 2 https://www.veeam.com/kb2025

To reduce the size of the database follow the below steps:

Procedure has been tested on a Veeam ONE v8, running Microsoft SQL 2008 R2 Express on Windows Server 2012 R2.

PLEASE NOTE: It is critical to perform a backup of the database before carrying out this procedure. The official line from Veeam is to log a call with support if you come across this issue. So you may want to log a support call as this method may be unsupported.

Due to the high quantity of transaction logs generated during this process I would recommend to delete at maximum 2 weeks data at a time. Then backup the database and then shrink the logs.

1. Stop Veeam ONE Services
Log onto the Veeam One Server
Open powershell as administrator

stop-service VeeamDCS
stop-service VeeamRSS

2. Backup your Veeam ONE SQL database
If you unsure how to do so do this, the following Veeam Knowledge Base article provides instructions
http://www.veeam.com/kb1471
Or alternatively execute the following SQL query

BACKUP DATABASE [VeeamOne] TO  DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL10_50.VEEAMSQL2008R2\MSSQL\Backup\veeamone.bak' WITH NOFORMAT, NOINIT,  NAME = N'VeeamOne-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10
GO

3. Identify a range of records to delete
Run the following SQL query to identify a suitable date range. To query to see how many rows are affected

USE [VeeamOne]
GO
SELECT * from monitor.Event
where time &lt;'2015-06-06';
GO

4. Execute deletion of required records
If you are happy with the returned values that will be delete.
Run the following SQL query to delete records earlier than the date range specified

USE [VeeamOne]
GO
DELETE from monitor.Event
where time &lt;'2015-06-06';
GO

5. Backup SQL DB again

6. Shrink Transaction Log

USE [VeeamOne]
GO
DBCC SHRINKFILE (N'VeeamOne_log' , 0, TRUNCATEONLY)
GO

8. This step should be carried out only once the database has been trimmed down to a suitable size

USE [VeeamOne]
GO
DBCC SHRINKFILE (N'VeeamOne' , 0, TRUNCATEONLY)
GO

9. Now it should be ok to restart Veeam ONE services to restore service

start-service VeeamDCS
start-service VeeamRSS