Remotely or locally recycle IIS application pool via PowerShell with AppPool Menu

2016-05-12 / PowerShell / 3 Comments

Save the PowerShell as Recycle-AppPool.ps1 and you can call with or without options.

Recycle-AppPool.ps1 -ServerName REMOTESERVER —– (Will run on a server remotely with current logged in creds)
Recycle-AppPool.ps1 -ServerName REMOTESERVER -WithCredentials —– (Will run on a server remotely with different credentials specified)
Recycle-AppPool.ps1 —– (Will run on locally, defaults to localhost with current logged in user)

<#
.SYNOPSIS
Recycles a selected IIS application pool 

.DESCRIPTION
Recycle-AppPools.ps1 uses a PS session to connect to a local or remote computer. It pulls down the currently configured application pools and builds a menu. 
The end user gets to select from the menu which application pool to restart. The Recycle-AppPools.ps1 then connects back to the PS Session and recycles the selected
application pool.

.PARAMETER ServerNAme 
a single computer name or leave off for localhost

.PARAMETER WithCredentials
Use this switch to specifiy credentials other than the current logged in user.

.EXAMPLE
Recycle-AppPool.ps1 -ServerName REMOTESERVER
Will run on a remote server with current logged in creds

.EXAMPLE 
Recycle-AppPool.ps1 -ServerName REMOTESERVER -WithCredentials
Will run on a server remotely with different credentials specified during launch

.EXAMPLE
Recycle-AppPool.ps1
Will run on locally. Defaults to localhost with current logged in user

.NOTES
WithCredentials is a switch, it does not accept any credentials. A prompt will appear later.
#>

Param(
   [string]$ServerName = 'localhost',
   [switch]$WithCredentials
 
) #end param
 
if (!(Test-Connection -ComputerName $ServerName -Quiet -Count 1))
{
    Write-Output "Unable to connect to $serverName"
    break
}
 
$scriptBlock = {
    Clear-Host
    Write-Output "Connected to: $env:computerName"
    if (Get-Module -ListAvailable -Name WebAdministration)
    {
        Write-Host "Loading PowerShell Web Administration..."
        Import-Module WebAdministration -ErrorAction SilentlyContinue
    }
    else
    {
        Write-Host "WebAdministration module does not exist..."
        break
    }
 
    $poolTable = @{}
    $allAppPools = Get-ChildItem IIS:\apppools
    $poolNumber = 0 
    Write-Output "Select Application Pool to Restart on server: $env:computerName"
    Write-Output ""
    foreach ($appPool in $allAppPools )
    {
        $pool = $appPool.Name
        $poolNumber += 1
        $poolTable.Add($poolNumber, $pool)
        Write-Output "$poolNumber > To restart app pool : $pool "
    }
    Write-Output ""
    $selectedPool = Read-Host "Enter # of Application Pool to Restart "
    if ($selectedPool)
    {    
        foreach ($hashValue in $poolTable.GetEnumerator())
        {  
            $key = $hashValue.Name
            $val = $hashValue.Value 
            if ($key -eq $selectedPool)
            {
                Write-Output "Restarting : $val"          
                Restart-WebAppPool $val       
            } 
        }
    }
    Write-Output "Completed reset on: $env:computerName"
    Write-Output ""
}
 
try {
     
    if ($WithCredentials)
    {
        $credentials = Get-Credential -Message "Enter credentials with administrative privilege on server"
        $session = New-PSSession -ComputerName $serverName -Credential $credentials -ErrorAction SilentlyContinue
    }
    else
    {
        $session = New-PSSession -ComputerName $serverName -ErrorAction SilentlyContinue
    }
 
    if ($session)
    {
        Invoke-Command -Session $session -ScriptBlock $scriptBlock -ErrorAction Continue
        Remove-PSSession -Session $session | Out-Null
    }
    else
    {
        Write-Output "An error has occured setting up PowerShell session (check username and password)"
    }
}
catch
{
    if ($session)
    {
        Remove-PSSession -Session $session | Out-Null
    }
    Write-Output "An error has occured setting up PowerShell session on $serverName "
}
Read More

PowerShell script to logoff user remotely on a list of servers

2015-11-25 / PowerShell, Server, Windows / 0 Comments

Problem:

I needed a PowerShell script to remotely logoff a domain user on multiple servers.

 

Solution:

Using my script with the PowerShell module PSTerminalServices from https://psterminalservices.codeplex.com/
I was able to create a method to disconnect the users remotely

$username = 'jbaldanza'
$filepath = 'c:\temp\servers.txt'

If (!(Get-module PSTerminalServices )) 
{
    try 
    {
        Import-Module PSTerminalServices
        Write-Host "PSTerminalServices Module Loaded" -ForegroundColor Green
    } 
    catch 
    {
        Write-Host "PSTerminalServices module does not exist, please install" -ForegroundColor Red
    }
}

foreach ($server in (Get-Content -Path $filepath)) 
{
    Write-Host "Checking for $username on $server" -ForegroundColor Cyan   
    try 
    {
        $loggedInUsers = get-tssession -ComputerName $server
        if ($loggedInUsers.UserName -contains $username) 
        {

            Write-Host "Found $username connected to $server" -ForegroundColor Green
            $userNameSessionID = $loggedInUsers | Where-Object -Property UserName -eq $username | Select-Object -Property SessionID
            foreach ($sessionID in $userNameSessionID) 
            {
                $currentSessionID = $sessionID.SessionId       
                Write-Host "$username's SessionID is $currentSessionID" -ForegroundColor Cyan
                try 
                {
                    Start-Sleep 2
                    Stop-TSSession -ComputerName $server -Id $currentSessionID -Confirm:$false -Force
                    Write-Host "Disconnected $username's session $currentSessionID from $server" -ForegroundColor Green
                }
                catch 
                {
                    Write-Host "Unable to disconnect $username's session $currentSesionID from $server" -ForegroundColor Red
                }
            }
        }
        else 
        {
            Write-Host "User $username not connected to $server" -ForegroundColor Yellow
        }
    }
    catch 
    {
        Write-Host "Unable to connect to $server" -ForegroundColor Red
    }
}
Read More

PowerShell script to change permission of a certificate’s private key

2015-11-01 / PowerShell, Server / 2 Comments

Problem:
I needed to change the permissions of a certificate’s private key in the windows local computer store on multiple servers. I use the certificate’s thumbprint to find the certificate and then apply the permissions to the user listed.

Solution:

$serviceAccount = 'NETWORK SERVICE'
$certThumbprint = 'x xx xx x xx xx xx dd dd ee ee ff ff gg hh 5e 20 3f 53 52'
$permissionType = 'Read'
    try
    {
        #Clear Existing Variables
        $cert = ''
        $keyFullPath = ''
        Write-Host "--------------------------"
        Write-Host "Server: $env:ComputerName" -ForegroundColor Cyan
        Write-Host "Finding Certificate..." -ForegroundColor Green
        #Get Certificate
        $cert = Get-ChildItem -Path cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq ($certThumbprint -replace '\s','')}
        If ($cert -ne $null -and $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName -ne $null) 
        {
            # Get Location of the machine related keys
            $keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys"; 
            $keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName;
            $keyFullPath = $keyPath + $keyName;
            Write-Host "Found Certificate..." -ForegroundColor Green
            Write-Host "Granting access to $serviceAccount..." -ForegroundColor Green
            #Grant Full Control to account listed in $serviceAccount
            $acl = (Get-Item $keyFullPath).GetAccessControl('Access') #Get Current Access
            $buildAcl = New-Object  System.Security.AccessControl.FileSystemAccessRule($serviceAccount,$permissionType,"Allow") #Build Access Rule
            $acl.SetAccessRule($buildAcl) #Add Access Rule
            Set-Acl $keyFullPath $acl #Save Access Rules
            Write-Host "Access granted to $serviceAccount..." -ForegroundColor Green
            Write-Host "--------------------------"
        }
        Else {
            Write-Host "Unable to find Certificate that matches thumbprint $certThumbprint or the private key is missing..." -ForegroundColor Red
            Write-Host "--------------------------"
        }
    }
    catch
    {
        Write-Host "Unable to grant access to $serviceAccount..." -ForegroundColor Yellow
        Write-Host "--------------------------"
        throw $_;
    }
Read More

PowerShell script to modify local account password on multiple remote computers

2015-07-02 / Microsoft, PowerShell, Server / 0 Comments

I had a need to do this for a client.

Problem: Need to change a single user’s account password and flags across multiple systems

Solution:
You can use this script to modify a local user’s password across multiple machines. It will check that the machine is reachable (by ping) and it will set the account to never expire and enabled (userflag 66048)

Modify the $user and $password fields with their desired strings and update the $computers path to the computers.txt file with a list of computers
Run the PowerShell script as someone who is administrator on the machines in the computers.txt file

$computers = Get-Content -path C:\temp\computers.txt
$user = "USER"
$password = "PASSWORD"
Foreach ($computer in $computers)
{
    #Start-Sleep 1
    $ErrorMessage = ""
    $FailedItem = ""
    $localuser = ""
     
    if (Test-Connection $computer -ErrorAction stop -count 3 -Quiet)
    {
        try
        {
            $localuser = [adsi]"WinNT://$computer/$user,user"
             
            if ($localuser.Path -ne $null)
            {
                $localuser.SetPassword($Password)
                $localuser.userflags = 66048
                $localuser.SetInfo()
                Write-Host "Password changed on: $computer" -ForegroundColor Green
            }
            else
            {
                Write-Host "$user not found on: $computer" -ForegroundColor Red
            }
        }
        catch
        {
            Write-Host "Error changing password on: $computer" -ForegroundColor Red
            #$ErrorMessage = $_.Exception.Message
            #$FailedItem = $_.Exception.ItemName
            #Write-Host $ErrorMessage -ForegroundColor Gray
            #Write-Host $FailedItem -ForegroundColor Gray
        }
    }
    else
    {
        Write-Host "Unable to connect, not changing password on: $computer" -ForegroundColor Red
    }
}
Read More