Search This Blog

Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Friday, January 03, 2025

Deploy port forward script on multiple computers

# deploy-cond_portforward.ps1
# a stand-alone script that deploys the port-forward to a list of target computers
# v1.0 - 2024-10-08 s.t. - initial release


# EDIT THIS - create a temporary list of all computer on which we want to deploy
$complstfileToAdd = @'
AH00001
RA00003
BM0001-W10
'@
Set-Content "$env:TEMP\comps.txt" $complstfileToAdd

# create the .ps1 file that will execute the portforward - this file must be tailored to each host after deployment
$psfileToAdd = @'
# condprtforward.ps1
# a powershell script to check the portforwading on iBox and re-add if not present
# To be run by powershell from Task Scheduler */10min with SYSTEM rights and arguments "-noprofile -executionpolicy bypass -file C:\WINDOWS\cond_portfwd.ps1"
# Version 1.0 - 2024 s.t.

# EDIT THIS - define IP and ports
$lclip = "127.0.0.1"
$lclport = "65535"
$2ndlclprt = ""
$rmtip = "127.0.0.2"
$rmtport = "65535"
$2ndrmtprt = ""

# check if run with admin rights
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))  
{  
  $arguments = "& '" +$myinvocation.mycommand.definition + "'"
  Start-Process powershell -Verb runAs -ArgumentList $arguments
  Break
}

#test if the portforward is already active
if (Test-NetConnection $lclip -Port $lclport -WarningAction SilentlyContinue -InformationLevel Quiet) {
 Write-Host "got_response, $lclport is open"
} else {
#add rules
 Write-Host "add_rules $lclip : $lclport $rmtip : $rmtport"
 netsh interface portproxy reset
 netsh advfirewall firewall add rule name="PortProxy Custom 1" dir=in action=allow protocol=TCP localport=$lclport
 netsh interface portproxy add v4tov4 listenport=$lclport listenaddress=$lclip connectport=$rmtport connectaddress=$rmtip
 
 if($2ndrmtprt) {
  Write-Host "2nd port is defined, adding 2nd rule"
  netsh advfirewall firewall add rule name="PortProxy Custom 2" dir=in action=allow protocol=TCP localport=$2ndlclprt
  netsh interface portproxy add v4tov4 listenport=$2ndlclprt listenaddress=$lclip connectport=$2ndrmtport connectaddress=$rmtip
  }
}
##Write-Host "end"
##Start-Sleep 5
'@
Set-Content "$env:TEMP\cond_portfwd.ps1" $psfileToAdd

# create the scheduled task .xml file that will be "imported" in order to create the task
$xmlfileToAdd = @'
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2024-10-08T00:00:00.0000000</Date>
    <Author>Administrator</Author>
    <Description>Launch and maintain Port Forward</Description>
    <URI>\PortForward</URI>
  </RegistrationInfo>
  <Triggers>
    <BootTrigger>
      <Repetition>
        <Interval>PT10M</Interval>
        <StopAtDurationEnd>false</StopAtDurationEnd>
      </Repetition>
      <Enabled>true</Enabled>
    </BootTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>S-1-5-18</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
      <Arguments>-noprofile -executionpolicy bypass -file C:\WINDOWS\cond_portfwd.ps1</Arguments>
    </Exec>
  </Actions>
</Task>
'@
Set-Content "$env:TEMP\PortForward.xml" $xmlfileToAdd

# start the deployment. first ask for some admin credentials valid on targets
$cred = Get-Credential -Message "Please enter admin credentials valid on target computers";
if($cred -isnot [PSCredential]) {Write-Host -ForegroundColor Red -BackgroundColor DarkBlue "No valid credentials provided. Exiting!" ; exit 1}
# copy the files to each target computer. no need to see the errors, we have our own errorreporting
$ErrorActionPreference= 'silentlycontinue'
foreach($line in Get-Content $env:TEMP\comps.txt) {
Write-Host -ForegroundColor Gray "`nStart running on $line"
$comp = New-PSSession -Credential $cred $line
if ($?) { Write-Host -ForegroundColor Green "Session to $comp established" }else{ Write-Host -ForegroundColor Red "Unable to connect to $line" }
Copy-Item -ToSession $comp $env:TEMP\cond_portfwd.ps1 -Destination C:\WINDOWS\cond_portfwd.ps1 -Force
if ($?) {  Write-Host -ForegroundColor Green ".ps1 file copied" }else{ Write-Host -ForegroundColor Red ".ps1 file NOT copied on $line" }
Copy-Item -ToSession $comp "$env:TEMP\PortForward.xml" -Destination "C:\WINDOWS\TEMP\PortForward.xml" -Force
if ($?) {  Write-Host -ForegroundColor Green ".xml file copied" }else{ Write-Host -ForegroundColor Red ".xml file NOT copied on $line" }
# create the scheduled task from the .xml file
Invoke-Command -ComputerName $line -Credential $cred { $Task = Get-Content "C:\WINDOWS\TEMP\PortForward.xml" -raw ; Register-ScheduledTask -Xml $Task -TaskName 'PortForward' -User SYSTEM -Force }
if ($?) {  Write-Host -ForegroundColor Green "Scheduledtask created"}else{ Write-Host -ForegroundColor Red "Scheduledtask NOT created on $line" }
}

# local cleanup
Remove-Item "$env:TEMP\comps.txt"
Remove-Item "$env:TEMP\PortForward.xml"
Remove-Item "$env:TEMP\cond_portfwd.ps1"

# reminder
Write-Host -ForegroundColor Yellow -BackgroundColor DarkBlue "`nOn each of the target computers please edit C:\WINDOWS\cond_portfwd.ps1"

exit

Saturday, January 06, 2024

Powershell backup

 #Backup folder
$dateStr = (Get-Date -Format "yyy-MM-dd-HH-mm")
$Source = "C:\source"
$Staging = "U:\BKPTemp"
$Destination = "U:\Backup\destination_$dateStr.zip"
Get-ChildItem "U:\Backup\" -Recurse -File | Where CreationTime -lt  (Get-Date).AddDays(-90)  | Remove-Item -Force
Add-Type -AssemblyName System.IO.Compression.Filesystem
Copy-Item -Path $Source -Destination $Staging -Recurse
[System.IO.Compression.ZipFile]::CreateFromDirectory($Staging, $Destination)
Remove-Item -Path $Staging -Force -Recurse
exit

Tuesday, January 28, 2020

Copy standard switch port groups from one esx host to another

The below code asks for lmvap-vcs60 credentials, connects to Vcenter, and copied aesx11 vSwitch2 portgroups over to a new host called aesx05 using vSwitch1. (or so said my buddy Josh O. who wrote it) 

$vccred = get-credential
connect-viserver -server lmvap-vcs60.domain.tld -credential $vccred
$dest = get-virtualswitch -name vSwitch1 -vmhost aesx05.domain.tld
$source = get-virtualportgroup -vmhost aesx11.domain.tld -virtualswitch vSwitch2 -standard
$countvar = $source.count
for ($a=0 ; $a -le $countvar-1 ; $a++)
{
$pgname = $source[$a].name
$vlan = $source[$a].VLANID
new-virtualportgroup -virtualswitch $dest -name $pgname -VLANID $vlan
}
disconnect-viserver -server lmvap-vcs60.domain.tld -confirm:$false



Monday, April 01, 2019

VM Management

# powershell script for VM mass management. Requires a .csv file containing the list of VMs and a name for the snapshot/ If no snapshot name is given, "Snapshot_1" is used.

 #load powercli if needed
if (!(Get-Module -Name VMware.VimAutomation.Core) -and (Get-Module -ListAvailable -Name VMware.VimAutomation.Core)) {
    Write-Output "loading the VMware Core Module..."
    if (!(Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
        # Error out if loading fails
        Write-Error "`nERROR: Cannot load the VMware Module. Is the PowerCLI installed?"
     }
    $Loaded = $True
    }
 #   elseif (!(Get-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -and !(Get-Module -Name VMware.VimAutomation.Core) -and ($Loaded -ne $True)) {
 #       Write-Output "loading the VMware Core Snapin..."
 #    if (!(Add-PSSnapin -PassThru VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
 #    # Error out if loading fails
 #    Write-Error "`nERROR: Cannot load the VMware Snapin or Module. Is the PowerCLI installed?"
 #    }
 #   }

# Define vmConfigSpec params
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
$vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
$vmConfigSpec.Tools.ToolsUpgradePolicy = "UpgradeAtPowerCycle"

# Get the command-line params
 $command = $args[0]
 $list = $args[1]
 $server = $args[2]

# define default params
if (!$list) { $list = "vm_mgmt.csv"}
if (!$server) { $server = "default.vCenter.domain.tld"}

# Start processing the command
  switch ($command) {
    default { $myname = $MyInvocation.MyCommand.Definition
    echo "`nERROR! Usage:"
    echo "$myname command [list] [server] "
    echo "`ncommand is one of the following: viewsnap, takesnap, delsnap, revertsnap, hwupd, vmtoolsupd, vmoff, vmon."
    echo " list is a .csv file containing 'VM_Name,Snapshot_name'. If no list provided, 'vm_mgmt.csv' will be used."
    echo " server is the name of the server connecting to. If no server is provided, 'default.vCenter.domain.tld' will be used.`n"
    }
 
  "viewsnap" {
    ### View Snapshot
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nView Snaphots:`n"
      get-vm -Name $_.VM_Name | get-snapshot
  } }

  "takesnap" {   
    ### Take Snapshot
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nTaking Snapshots`n"
      get-vm -Name $_.VM_Name | New-Snapshot -Name $_.Snapshot_1 -Quiesce -Memory
  } }

  "delsnap" {   
    ### Delete Snapshot
    Connect-VIServer -Server $server -Protocol https
    import-csv $list | ForEach-Object {
    $_.VM_Name
    $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
   echo "`nDelete Snapshots`n"
    get-snapshot -name $_.Snapshot_1 -vm $_.VM_Name | remove-snapshot -confirm:$false
  } }

  "revertsnap" {
    ### Revert To Snapshot
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
    echo "`nReverting Snapshots. Confirmation is required for each restore.`n"
      set-vm -VM $_.VM_Name -Snapshot $_.Snapshot_1 -whatif
    # set-vm -VM $_.VM_Name -Snapshot $_.Snapshot_1 -confirm:$false
  } }

  "hwupd" { 
    # VM Hardware upgrade
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nVM Hardware upgrade to vmx-13`n"
      $do = New-Object -TypeName VMware.Vim.VirtualMachineConfigSpec
      $do.ScheduledHardwareUpgradeInfo = New-Object -TypeName VMware.Vim.ScheduledHardwareUpgradeInfo
      $do.ScheduledHardwareUpgradeInfo.UpgradePolicy = “always”
      $do.ScheduledHardwareUpgradeInfo.VersionKey = “vmx-13”
      $vm.ExtensionData.ReconfigVM_Task($do)
  } }

  "vmtoolsupd" {
    # VM Tools update
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nUpdating VM Tools`n"
      get-vm -Name $_.VM_Name | %{$_.Extensiondata.ReconfigVM($vmConfigSpec)}
  } }

  "vmoff" {
    # VM power off
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nTurning VMs OFF`n"
      $vm = Get-VM -Name $_.VM_Name | Shutdown-VMGuest -Confirm:$false
  } }

  "vmon" {
    # VM power on
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nTurning VMs ON`n"
      $vm = Get-VM -Name $_.VM_Name | Start-VM -Confirm:$false
  } }

}



-----------------------------------------------
type vm_mgmt.csv

VM_NAME,Snapshot_name
some-vm-name,Snapshot_342
another-vm-name,Snapshot_temp4

Saturday, January 02, 2016

"FullyQualifiedErrorId : -2144108477,PSSessionOpenFailed"

The PowerShell window displayed this error.
VERBOSE: Connecting to E15MB2.exchange2013demo.com.
New-PSSession : [e15mb2.exchange2013demo.com] Processing data from remote server e15mb2.exchange2013demo.com failed
with the following error message: The WinRM Shell client cannot process the request. The shell handle passed to the WSMan Shell function is not valid. The shell handle is valid only when WSManCreateShell function completes successfully. Change the request including a valid shell handle and try again. For more information, see the about_Remote_Troubleshooting Help topic.
At line:1 char:1
+ New-PSSession -ConnectionURI “$connectionUri” -ConfigurationName Microsoft.Excha …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme….RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : -2144108212,PSSessionOpenFailed
The cause of this error in my specific case was that the SSL certificate was no longer bound to the Exchange Back End website on that Exchange 2013 server.
To fix this, in IIS Manager right-click the Exchange Back End website and click Bindings.

Highlight https and click Edit.
If you see “Not selected” like I did, click on Select.
Choose the certificate you want to bind to the site.
Apply the changes and retry the Exchange management shell. If it connects successfully to the server then you have most likely resolved this issue.