├── Chapter 10 - Implementing Desired State Configuration
├── Page2.Htm
├── Index.Htm
├── Get-DSCEventLogEntry.ps1
├── Get-DSCReport.ps1
├── Recipe 10.3 - Finding and Installing DSC sources.ps1
├── Setup-DSCWebApp.ps1
├── Recipe 10.2 - Paramaterising DSC Configuration .ps1
├── Recipe 10.5 -Configuring DSC LCM.ps1
├── Recipe 10.4 - Using DSC with PSGallery Resources.ps1
└── Recipe 10.1 -Using DSC and built-in resources.ps1
├── Chapter 04 - Managing Storage
├── Recipe 4.x - Using Storage Spaces Direct.ps1
├── Recipe 4.9 Using Storage Spaces Direct LOG.txt
├── Recipe 4.1 - Using Disks.ps1
├── Recipe 4.2 - Managing NTFS permissions.ps1
├── Recipe 4.5 - Using File System Reporting.ps1
├── Add-DiskstoSRV1+2.ps1
└── Recipe 4.3 - Managing storage replica.ps1
├── Chapter 01 - Establishing a PowerShell Administrative Environment
├── doit.ps1
├── 1.4 - Creating an internal PS repository.ps1
├── 1.2 - Exploring Package Mangement.ps1
├── 1.5 - Establish a script signing environment.ps1
└── 1.3 - Exploring PowerShellGet+PSGallery.ps1
├── Chapter 08 - Leveraging containers
├── Recipe 8.1 - Setting up a container host.ps1
├── docker networking.ps1
├── Recipe 8.2 -Running the first container LOG.txt.txt
├── 8.x create a container using DOCKERFILE.ps1
├── Recipe 8.3 - Deploy IIS in a container.ps1
├── Recipe 8.2 - Deploying a hello world sample.ps1
└── 8.4 Create a container using DOCKERFILE.ps1
├── PowerShellCookBook2019
├── README.md
├── set-autologin.ps1
├── LICENSE
├── ReskitNetwork.md
└── README (PACKT).md
├── Chapter 03 - Deploying Active Directory
├── NewUsers.CSV
├── 3.6 - Finding expired computers and disabled users in AD.ps1
├── 3.3 - Adding users to AD using a CSV.ps1
├── 3.4 - Creating a group policy object.ps1
├── 3.1 - Installing Active Directory with DNS.ps1
└── 3.5 - Reporting on AD Users.ps1
├── Get-RecipeStructure.ps1
├── set-autologin.ps1
├── Chapter 12 - Exploring Azure
├── Ch 12 - Recipe Index.md
├── Recipe 12.2 - Azure Resources.ps1
├── Recipe 12.1 - Getting Started.ps1
├── Recipe 12.4 - Create Azure SMB share.ps1
├── Recipe 12.6 - Create Azure VM.ps1
├── Recipe 12.7 - Create and Use VPN.ps1
├── Recipe 12.3 - Explore Storage Account.ps1
└── Recipe 12.5 - Create Azure Web SIte.ps1
├── Chapter 07 - Managing Printers
├── Recipe 7-7 - Creating a Printer Pool.ps1
├── Recipe 7.7 - Creating a Printer Pool.ps1
├── Recipe 7.4 - Changing printer driver.ps1
├── Recipe 7.5 - Printing a test page on a printer.ps1
├── Recipe 7.2 - Publishing a printer.ps1
├── Recipe 7.6 - Modiying printer security.ps1
├── Recipe 7.x -Deploying Shared Printer.ps1
├── Create-SalesTeam.ps1
├── Recipe 7.3 - Changing spool folder.ps1
└── Recipe 7.1 - Installing and sharing printer.ps1
├── Chapter 11 - Managing Hyper-V
├── Create-HV2VMs.ps1
├── Recipe 11.2 - Creating a VM.ps1
├── Recipe 11.2 - Using PowerShell Direct.ps1
├── Recipe 11.3 - Using PowerShell Direct.ps1
├── Recipe 11.8 - Managing VM state.ps1
├── Recipe 11.5 - Configuring VM hardware.ps1
├── Recipe 11.7 - Implementing nested Hyper-V.ps1
├── Recipe 11.6 - Configuring Hyper-V networking.ps1
├── Recipe 11.1 - Installing and Configuring Hyper-V.ps1
├── Recipe 11.9 - Configuring VM and storage movement.ps1
├── Bonus Recipe 1 - Create a VM from existing VHD.ps1
├── Recipe 11.4 - Using VM Groups.ps1
├── Recipe 11.10 - Configuring VM replication.ps1
├── Recipe 11.11 - Managing VM Checkpoints.ps1
└── Recipe 11.12 - Creating a Hyper-V Status Report.ps1
├── Chapter 02 - Managing Windows Networking
├── 2.3 - Installing and authorizing a DHCP server.ps1
├── 2.5 - Convert IP address from static to DHCP.ps1
├── 2.4 - Configuring DHCP Scopes.ps1
├── 2.6 - Configuring DHCP Failover amd Load Balancing.ps1
├── 2.2 - Configuring IP Addressing.ps1
└── 2.1 - New ways to do old things.ps1
├── Chapter 13 - Monitoring Performance and Usage
├── Recipe 13.6 - Creating a Systems diagnostic report.ps1
├── Recipe 13.1a - Stress Network.ps1
├── Recipe 13.7 - Get Printer Usage report.ps1
├── Recipe 13.2 - Using WMI to retreive performance counters.ps1
├── Recipe 13.4 - Reporting on Performance Data.ps1
├── Recipe 13.5 - Generating a perf monitoring graph.ps1
├── Recipe 13.3b - Create performance collector set (CSV OUT).ps1
├── Recipe 13.3 - Create+Use PLA Data Collector set.ps1
├── Recipe 13.3a - Create performance collector set (TSV OUT).ps1
├── Recipe 13.1 - Explore perf counters with Get-Counter.ps1
└── Recipe 13.8 - Creating a Hyper-V Status Report.ps1
├── Chapter 09 - Managing Windows Internet Information Server
├── Recipe 9.3 - Manage TLS Cipher Suites.ps1
├── Recipe 9.5 - Configuring IIS Bindings.ps1
├── Recipe 9.2 - Install SSL.ps1
├── Recipe 9.1 - Install IIS Server.ps1
├── Recipe 9.2 - Configuring IIS for SSL.ps1
├── Recipe 9.7 - Manage Applications and Application Pools.ps1
├── Recipe 9.8 - Analyze IIS log files.ps1
├── Recipe 9.6 - Configure IIS Logging and Log Files.ps1
└── Recipe 9.9 - Managing and monitoring NLB.ps1
├── LICENSE
├── Chapter 06 - Deploying Windows Update
├── Recipe 6.4 - Creating computer target groups.ps1
├── Recipe 6.5 - Configuring WSUS auto-approvals.ps1
├── Recipe 6.6 - Managing Updates.ps1
├── Recipe 6.3 - Configuring WIndows Update Client.ps1
├── Recipe 6.1 - Installing WIndows Server Update Service.ps1
└── Recipe 6.2 - Configuring WSUS Update synchronization.ps1
├── Chapter 05 - Managing Shared Data
├── Recipe 5.4 - Creating an iSCSI Target.ps1
├── Recipe 5.3 - Accessing SMB Shares.ps1
├── Recipe 5.5 - Using an iSCSI target.ps1
├── Recipe 5.1 - Securing your SMB file server.ps1
├── Recipe x - Creating a scale out file server..ps1
├── Recipe 5.2 - Creating and securing SMB share.ps1
└── Recipe 5.6 - Configuring a DFS Namespace.ps1
├── Chapter 14 - Troubleshooting WIndows Server
├── Recipe 14.X - Use TroubleShooting packs.ps1
├── Recipe 14.2 - Using BPA.ps1
├── Recipe 14.3 - Managing Event Logs.ps1
└── Recipe 14.1 - Check Network Connectivity.ps1
├── ReskitNetwork.md
└── Errata.md
/Chapter 10 - Implementing Desired State Configuration/Page2.Htm:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 04 - Managing Storage/Recipe 4.x - Using Storage Spaces Direct.ps1:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Chapter 04 - Managing Storage/Recipe 4.9 Using Storage Spaces Direct LOG.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter 01 - Establishing a PowerShell Administrative Environment/doit.ps1:
--------------------------------------------------------------------------------
1 | cat '\\cookham24\d$\Dropbox\PACKT BOOK RECIPES 2019\logs\Server2019CookbookLogs\Ch 1 - Log Files\1.2 - Exploing package management LOG .txt'
2 |
3 |
--------------------------------------------------------------------------------
/Chapter 08 - Leveraging containers/Recipe 8.1 - Setting up a container host.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doctordns/PowerShellCookBook2019/HEAD/Chapter 08 - Leveraging containers/Recipe 8.1 - Setting up a container host.ps1
--------------------------------------------------------------------------------
/Chapter 08 - Leveraging containers/docker networking.ps1:
--------------------------------------------------------------------------------
1 | docker network create -d transparent --gateway 10.10.10.254 --subnet 10.10.10.0/24 transparent
2 |
3 | docker run --rm -it --network transparent microsoft/nanoserver cmd
--------------------------------------------------------------------------------
/PowerShellCookBook2019/README.md:
--------------------------------------------------------------------------------
1 | # PowerShellCookBook2019 Repository
2 |
3 | ## Contents
4 | This repository contains the recipes in Server 2019 Cookbook along with supporting material
5 |
6 | NB: This is a work in progress
--------------------------------------------------------------------------------
/Chapter 03 - Deploying Active Directory/NewUsers.CSV:
--------------------------------------------------------------------------------
1 | Firstname, Initials, Lastname, UserPrincipalName, Alias, Description, Password
2 | S,K,Masterly, skm, Sylvester, Data Team, Christmas42
3 | C,B Smith, CBS, Claire, Claire,Receptionist, Christmas42
4 | Billy-Bob, Joe-Bob, Bob, BBJB, BBJB, One of the Bob's, Christmas42
5 | Malcolm, DoWrite, Duelittle, Malcolm, Malcolm, Mr Danger, Christmas42
6 |
--------------------------------------------------------------------------------
/Get-RecipeStructure.ps1:
--------------------------------------------------------------------------------
1 | # Function to get the structure of a recipe
2 | function get-recipestructure
3 | {
4 | $Lines = Get-Content $psise.CurrentFile.FullPath
5 | $lineno = 0
6 | Foreach ($Line in $Lines) {
7 | $Lineno++
8 | if ($line -match '^#') {
9 | "[{0,4}] {1}" -F $lineno,$line
10 | }
11 | }
12 | }
13 |
14 | set-alias grs get-recipeStructure
15 | grs
--------------------------------------------------------------------------------
/set-autologin.ps1:
--------------------------------------------------------------------------------
1 | $RegPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
2 | $DefaultUsername = "reskit\administrator"
3 | $DefaultPassword = "Pa$$W0rd"
4 | Set-ItemProperty $RegPath "AutoAdminLogon" -Value "1" -type String
5 | Set-ItemProperty $RegPath "DefaultUsername" -Value "$DefaultUsername" -type String
6 | Set-ItemProperty $RegPath "DefaultPassword" -Value "$DefaultPassword" -type String
--------------------------------------------------------------------------------
/PowerShellCookBook2019/set-autologin.ps1:
--------------------------------------------------------------------------------
1 | $RegPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
2 | $DefaultUsername = "reskit\administrator"
3 | $DefaultPassword = "Pa$$W0rd"
4 | Set-ItemProperty $RegPath "AutoAdminLogon" -Value "1" -type String
5 | Set-ItemProperty $RegPath "DefaultUsername" -Value "$DefaultUsername" -type String
6 | Set-ItemProperty $RegPath "DefaultPassword" -Value "$DefaultPassword" -type String
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Index.Htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Main Page - ReskitApp Application
4 |
5 | HOME PAGE FOR RESKITAPP APPLICATION
6 | This is the root page of the RESKITAPP application
7 | Pushed via DSC
8 |
9 | Click to View Page 2
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Ch 12 - Recipe Index.md:
--------------------------------------------------------------------------------
1 | # Module 12 - Managing Azure
2 |
3 | This chapter looks using PowerShell to manage Azure
4 |
5 | Recipes in this chapter
6 |
7 |
8 | - 2.1 - Using PowerShell with Azure
9 | - 2.2 - Creating core Azure resources
10 | - 2.3 - Exploring your storage account
11 | - 2.4 - Creating and using an Azure SMB file share
12 | - 2.5 - Creating and using Azure websites
13 | - 2.6 - Creating and using Azure virtual machines
14 |
--------------------------------------------------------------------------------
/Chapter 08 - Leveraging containers/Recipe 8.2 -Running the first container LOG.txt.txt:
--------------------------------------------------------------------------------
1 | # Recipe 8.2 - Managing The Hello World Sample
2 | #
3 | # Run on CH1
4 |
5 | # 1. Start by pruning everything and ensuring you start fresh
6 | docker system prune -a
7 |
8 | # 2. Get Base Container Images
9 |
10 |
11 | # Download the container base images:
12 |
13 | docker pull microsoft/nanoserver:1809
14 | docker pull microsoft/windowsservercore:1809
15 |
16 | docker run microsoft/dotnet-samples:dotnetapp-nanoserver:1809
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7-7 - Creating a Printer Pool.ps1:
--------------------------------------------------------------------------------
1 | # Recipe7-7 - create Printer Pool
2 | # Run on PSRV printer server
3 |
4 | # 1. Add a port for the printer
$P = 'SalesPP2' # new port name
Add-PrinterPort -Name $P -PrinterHostAddress 10.10.10.62
# 2. Create the printer pool for SalesPrinter1:
$P1='SalesPP'
5 | $P2='SalesPP2'
6 | rundll32.exe printui.dll,PrintUIEntry /Xs /n $p Portname $P1,$P2
# 3. View resultant details, showing both ports:
$P = 'SalesPrinter1'
Get-Printer $P |
Format-Table -Property Name, Type, DriverName, PortName
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.7 - Creating a Printer Pool.ps1:
--------------------------------------------------------------------------------
1 | # Recipe7-7 - create Printer Pool
2 | # Run on PSRV printer server
3 |
4 | # 1. Add a port for the printer
5 | $P = 'SalesPP2' # printer name
6 | Add-PrinterPort -Name $P -PrinterHostAddress 10.10.10.62
7 |
8 | # 2. Create the printer pool for SalesPrinter1:
9 | $P1='SalesPP'
10 | $P2='SalesPP2'
11 | rundll32.exe printui.dll,PrintUIEntry /Xs /n $p Portname $P1,$P2
12 |
13 | # 3. View resultant details:
14 | Get-Printer $P |
15 | Format-Table -Property Name, Type, DriverName, PortName
16 |
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.4 - Changing printer driver.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 4-4 Change Printer Driver
2 |
3 | # 1. Add the print driver for the new printing device:
4 | $M2 = 'Xerox WorkCentre 6515 PCL6'
5 | Add-PrinterDriver -Name $M2
6 |
7 | # 2. Get the Sales group printer object and store it in $Printer:
8 | $Printern = 'SalesPrinter1'
9 | $Printer = Get-Printer -Name $Printern
10 |
11 | # 3. Update the driver using the Set-Printercmdlet:
12 | $Printer | Set-Printer -DriverName $M2
13 |
14 | # 4. Observe the result
15 | Get-Printer -Name $Printern |
16 | Format-Table -Property Name, DriverName, PortName,
17 | Published, Shared
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.5 - Printing a test page on a printer.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 7-5 - Printing a test page on a printer
2 |
3 | # 1. Get the printer objects from WMI:
4 | $Printers = Get-CimInstance -ClassName Win32_Printer
5 |
6 | # 2. Display the number of printers defined on PSRV:
7 | '{0} Printers defined on this system' -f $Printers.Count
8 |
9 | # 3. Get the Sales Group printer WMI object:
10 | $Printer = $Printers |
11 | Where-Object Name -eq 'SalesPrinter1'
12 |
13 | # 4. Display the printer's details:
14 | $Printer | Format-Table -AutoSize
15 |
16 | # 5. Print a test page:
17 | Invoke-CimMethod -InputObject $Printer -MethodName PrintTestPage
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.2 - Publishing a printer.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 7-2 Publishing a printer
2 | #
3 | # Run on Psrv
4 | # Uses Printer added in 7.1
5 |
6 | # 1. Get the printer to publish and store the returned object in $Printer:
7 | $Printer = Get-Printer -Name SalesPrinter1
8 |
9 | # 2. Observe the publication status:
10 | $Printer | Format-Table -Property Name, Published
11 |
12 | # 3. Publish and share the printer to AD:
13 | $Printer | Set-Printer -Location '10th floor 10E4'
14 | $Printer | Set-Printer -Shared $true -Published $true
15 |
16 | # 4. View the updated publication status:
17 | Get-Printer -Name SalesPrinter1 |
18 | Format-Table -Property Name, Location, Drivername,Published
19 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Create-HV2VMs.ps1:
--------------------------------------------------------------------------------
1 | # Create HV2 VMs for Chapter 11
2 | #
3 | # This snippet creates a set of VMs used in the Managing Hyper-V chapter.
4 | # Run this on HV2
5 |
6 |
7 | $VMLocation = 'C:\Vm\VMs'
8 | # Create VM1
9 | $VMN1 = 'SQLAcct1'
10 | New-VM -Name $VMN1 -Path "$VMLocation\$VMN1"
11 | # Create VM2
12 | $VMN2 = 'SQLAcct2'
13 | New-VM -Name $VMN2 -Path "$VMLocation\$VMN2"
14 | # Create VM3
15 | $VMN3 = 'SQLAcct3'
16 | New-VM -Name $VMN3 -Path "$VMLocation\$VMN3"
17 | # Create VM4
18 | $VMN4 = 'SQLMfg1'
19 | New-VM -Name $VMN4 -Path "$VMLocation\$VMN4"
20 | # Create VM5
21 | $VMN5 = 'SQLMfg2'
22 | New-VM -Name $VMN5 -Path "$VMLocation\$VMN5"
23 |
--------------------------------------------------------------------------------
/Chapter 02 - Managing Windows Networking/2.3 - Installing and authorizing a DHCP server.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 2.3 - Installing and authorizing a DHCP server
2 | #
3 | # Run on DC1
4 |
5 | # 1. Install the DHCP Feature
6 | Install-WindowsFeature -Name DHCP -IncludeManagementTools
7 |
8 | # 2. Add the DHCP server's security groups
9 | Add-DHCPServerSecurityGroup -Verbose
10 |
11 | # 3. Let DHCP know it's all configured
12 | $RegHT = @{
13 | Path = 'HKLM:\SOFTWARE\Microsoft\ServerManager\Roles\12'
14 | Name = 'ConfigurationState'
15 | Value = 2
16 | }
17 | Set-ItemProperty @RegHT
18 | d
19 |
20 | # 4. Authorise the DHCP server in AD
21 | Add-DhcpServerInDC -DnsName DC1.Reskit.Org
22 |
23 | # 5. Restart DHCP
24 | Restart-Service -Name DHCPServer –Force
25 |
--------------------------------------------------------------------------------
/Chapter 02 - Managing Windows Networking/2.5 - Convert IP address from static to DHCP.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 2.5 - Converting IP address from static to DHCP
2 | #
3 | # Run on SRV2
4 |
5 |
6 | # 1.Get the existing IP address information
7 | $IPType = 'IPv4'
8 | $Adapter = Get-NetAdapter |
9 | Where-Object Status -eq 'up'
10 | $Interface = $Adapter |
11 | Get-NetIPInterface -AddressFamily $IPType
12 | $IfIndex = $Interface.ifIndex
13 | $IfAlias = $Interface.Interfacealias
14 | Get-NetIPAddress -InterfaceIndex $IfIndex -AddressFamily $IPType
15 |
16 | # 2. Set the interface to get its address from DHCP:
17 | Set-NetIPInterface -InterfaceIndex $IfIndex -DHCP Enabled
18 |
19 | # 3. Test the results:
20 | Get-NetIPAddress -InterfaceIndex $IfIndex -AddressFamily $IPType
--------------------------------------------------------------------------------
/Chapter 02 - Managing Windows Networking/2.4 - Configuring DHCP Scopes.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 2.4 - Configuring DHCP Scopes
2 |
3 | # Run on DC1
4 |
5 | # 1. Create a Scope
6 | $SHT = @{
7 | Name = 'Reskit'
8 | StartRange = '10.10.10.150'
9 | EndRange = '10.10.10.199'
10 | SubnetMask = '255.255.255.0'
11 | ComputerName = 'DC1.Reskit.Org'
12 | }
13 | Add-DhcpServerV4Scope @SHT
14 |
15 | # 2. Get Scopes from the server
16 | Get-DhcpServerv4Scope -ComputerName DC1.Reskit.Org
17 |
18 | # 3. Set Option Values
19 | $OHT = @{
20 | ComputerName = 'DC1.Reskit.Org'
21 | DnsDomain = 'Reskit.Org'
22 | DnsServer = '10.10.10.10'
23 | }
24 | Set-DhcpServerV4OptionValue @OHT
25 |
26 | # 4. Get options set
27 | Get-DhcpServerv4OptionValue -ComputerName DC1.Reskit.Org
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.6 - Creating a Systems diagnostic report.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 13.6 - Creating a Systems Diagnostic report
2 | #
3 | # Run on SRV1
4 |
5 | # 1. Start the built-in data collector on the local system:
6 | $PerfReportName="System\System Diagnostics"
7 | $DataSet = New-Object -ComObject Pla.DataCollectorSet
8 | $DataSet.Query($PerfReportName,$null)
9 | $DataSet.Start($true)
10 |
11 | # 2. Wait for the data collector to finish:
12 | "Sleeping for [$($Dataset.Duration)] seconds"
13 | Start-Sleep -Seconds $Dataset.Duration
14 |
15 | # 3. Get the report and store it as HTML:
16 | $Dataset.Query($PerfReportName,$null)
17 | $PerfReport = $Dataset.LatestOutputLocation + "\Report.html"
18 |
19 | # 4. View the report:
20 | & $PerfReport
--------------------------------------------------------------------------------
/Chapter 08 - Leveraging containers/8.x create a container using DOCKERFILE.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 8.X- Creating a Image using a Dockerfile
2 | #
3 | # run on CH1
4 |
5 | # 1. Create folder and Set-location to here
6 | $NIHT = @{
7 | Path = 'C:\Foo\IISContainer'
8 | ItemType = 'Directory'
9 | ErrorAction = 'SilentlyContinue'
10 | }
11 | New-Item @NIHT
12 | Set-Location -Path $NIHT.Path
13 |
14 | # 2. Create DOCKERFILE
15 | $DF = @"
16 | FROM mcr.microsoft.com/windows/servercore:1809
17 | LABEL Description="IISDemo" Vendor="Microsoft" Version="Server2019"
18 | RUN powershell -Command Add-WindowsFeature Web-Server
19 | RUN powershell -Command GIP
20 | "@
21 | $DF | Out-File -FilePath .\DOCKERFILE -Encoding ascii
22 |
23 | # 3. Build the image
24 | docker build -t iis .
25 |
26 | # 4. Run the image
27 | docker run --name iisdemo -p 80:80 iis
28 |
29 | # 5. Navigate to it
30 | Start-Process "http://ch1/"
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.2 - Creating a VM.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.2 - Creating a VM
2 |
3 | # 1. Set up the VM name and paths for this recipe:
4 | $VMname = 'PSDirect'
5 | $VMLocation = 'C:\Vm\VMs'
6 | $VHDlocation = 'C:\Vm\Vhds'
7 | $VhdPath = "$VHDlocation\PSDirect.Vhdx"
8 | $ISOPath = 'C:\builds\en_windows_server_2019_x64_dvd_4cb967d8.iso'
9 |
10 | # 2. Create a new VM:
11 | New-VM -Name $VMname -Path $VMLocation -MemoryStartupBytes 1GB
12 |
13 | # 3. Create a virtual disk file for the VM:
14 | New-VHD -Path $VhdPath -SizeBytes 128GB -Dynamic | Out-Null
15 |
16 | # 4. Add the virtual hard drive to the VM:
17 | Add-VMHardDiskDrive -VMName $VMname -Path $VhdPath
18 |
19 | # 5. Set ISO image in the VM's DVD drive:
20 | $IHT = @{
21 | VMName = $VMName
22 | ControllerNumber = 1
23 | Path = $ISOPath
24 | }
25 | Set-VMDvdDrive @IHT
26 |
27 | # 6. Start the VM:
28 | Start-VM -VMname $VMname
29 |
30 | # 7. View the results:
31 | Get-VM -Name $VMname
32 |
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.3 - Manage TLS Cipher Suites.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 10-3 Manage TLS Cipher Suites
2 |
3 | # 1. Get the cipher suites on SRV1 and display
4 | Get-TlsCipherSuite |
5 | Format-Table Name, Exchange, Cipher, Hash, Certificate
6 |
7 | # 2. Find Cipher suites that support 3DES
8 | Get-TlsCipherSuite -Name 3DES |
9 | Format-Table Name, Exchange, Cipher, Hash, Certificate
10 |
11 | # 3 Disable 3DES based cipher suites
12 | Foreach ($CS in (Get-TlsCipherSuite -Name '3DES'))
13 | {Disable-TlsCipherSuite -Name $CS.Name}
14 |
15 | # 4. See if any cipher suites remain that support 3DES
16 | Get-TlsCipherSuite 3DES |
17 | Format-Table Name, Exchange, Cipher, Hash, Certificate
18 |
19 | # 5. Re-enable the 3DES cipher suite
20 | Enable-TlsCipherSuite -Name TLS_RSA_WITH_3DES_EDE_CBC_SHA
21 |
22 | # 6. Find Cipher suites that support 3DES
23 | Get-TlsCipherSuite 3DES |
24 | Format-Table -Property Name, Exchange, Cipher,
25 | ggeHash, Certificate
26 |
27 |
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.1a - Stress Network.ps1:
--------------------------------------------------------------------------------
1 | # Script 6-1b - Bonus script to stress network
2 | # This script allows you to variously stress systems to get perf counters to do nice things.
3 |
4 | # dc1
5 | Function Stress-DC1 {
6 | $sb =
7 | {
8 | invoke-command -computer DC1 -script {
9 | 1..1000000 | ForEach-Object {$u = get-aduser -filter *; $c = get-adcomputer -filter *}
10 | }
11 | }
12 |
13 | Start-job -Script $sb
14 | }
15 |
16 | Function Stress-CA {
17 | $sb =
18 | {
19 | invoke-command -computer CA -script {
20 | 1..10000000 | foreach {$i=0; $i++; $i=$i*$i*$i}
21 |
22 | }
23 | }
24 |
25 | Start-job -script $sb
26 | }
27 |
28 | Function Stress-FS1 {
29 | Start-Job -ScriptBlock {icm -ComputerName fs1 -ScriptBlock {dir . -rec}}
30 | Start-Job -ScriptBlock {icm -ComputerName fs1 -ScriptBlock {dir . -rec}}
31 | Start-Job -ScriptBlock {icm -ComputerName fs1 -ScriptBlock {dir . -rec}}
32 | Start-Job -ScriptBlock {icm -ComputerName fs1 -ScriptBlock {dir . -rec}}
33 | }
34 |
35 |
36 | # Here invoke them
37 | Stress-FS1
38 | stress-dc1
39 | stress-CA
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Get-DSCEventLogEntry.ps1:
--------------------------------------------------------------------------------
1 | # dsc debugging
2 |
3 | # 1. turn on DSC event logging
4 | wevtutil.exe set-log "Microsoft-Windows-Dsc/Analytic" /q:true /e:true
5 | wevtutil.exe set-log "Microsoft-Windows-Dsc/Debug" /q:True /e:true
6 | wevtutil.exe set-log "Microsoft-Windows-Dsc/Operational" /q:True /e:true
7 | # do stuff in dsc...
8 |
9 |
10 | # 2. Collect the logs:
11 | $DscEvents = [System.Array](Get-WinEvent "Microsoft-Windows-Dsc/Operational")
12 | $DscEvents += [System.Array](Get-WinEvent "Microsoft-Windows-Dsc/Analytic" -Oldest)
13 | $DscEvents += [System.Array](Get-WinEvent "Microsoft-Windows-Dsc/Debug" -Oldest)
14 |
15 | # Group based on Job ID
16 | $SeparateDscOperations = $DscEvents | Group {$_.Properties[0].Value}
17 |
18 |
19 | $SeparateDscOperations[0].Group
20 |
21 | # Look at errors
22 | $SeparateDscOperations | Where-Object {$_.Group.LevelDisplayName -contains "Error"}
23 |
24 | # last 30 minutes
25 | $DateLatest = (Get-Date).AddMinutes(-30)
26 | $SeparateDscOperations | Where-Object {$_.Group.TimeCreated -gt $DateLatest} |
27 |
28 | # finding errors
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.2 - Using PowerShell Direct.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11-2 - Using PS Direct with Hyper-V
2 | #
3 | # Run on HV1 after Tiger/PSDirect has been created on HV1
4 |
5 | # 1. Create a credential object for ReskitAdministrator:
6 | $RKAn = 'Reskit\Administrator'
7 | $PS = 'Pa$$w0rd'
8 | $RKP = ConvertTo-SecureString -String $PS -AsPlainText -Force
9 | $T = 'System.Management.Automation.PSCredential'
10 | $RKCred = New-Object -TypeName $T -ArgumentList $RKAn,$RKP
11 |
12 | # 2. Display the details of the psdirect VM:
13 | Get-VM -Name psdirect
14 |
15 | # 3. Invoke a command on the VM, specifying VM name:
16 | $SBHT = @{
17 | VMName = 'psdirect'
18 | Credential = $RKCred
19 | ScriptBlock = {hostname}
20 | }
21 | Invoke-Command @SBHT
22 |
23 | # 4. Invoke a command based on VMID:
24 | $VMID = (Get-VM -VMName psdirect).VMId.Guid
25 | Invoke-Command -VMid $VMID -Credential $RKCred -ScriptBlock {hostname}
26 |
27 | # 5. Enter a PS remoting session with the psdirect VM:
28 | Enter-PSSession -VMName psdirect -Credential $RKCred
29 | Get-CimInstance -Class Win32_ComputerSystem
30 | Exit-PSSession
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Thomas Lee
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Get-DSCReport.ps1:
--------------------------------------------------------------------------------
1 | function Get-DscReport
2 | {
3 | [CmdletBinding()]
4 | param
5 | (
6 | $AgentId = "$(throw 'Please enter an agaet ID')",
7 | $serviceURL = "httpS://SRV1.RESKIT.ORG:8080/PSDSCPullServer.svc"
8 | )
9 |
10 | $RequestUri = "$serviceURL/Nodes(AgentId= '$AgentId')/Reports"
11 | Write-Verbose "ServiceURI: [$RequestUri]"
12 | $request = Invoke-WebRequest -Uri $requestUri -ContentType "application/json;odata=minimalmetadata;streaming=true;charset=utf-8" `
13 | -UseBasicParsing -Headers @{Accept = "application/json";ProtocolVersion = "2.0"} `
14 | -ErrorAction SilentlyContinue -ErrorVariable ev
15 | Write-Verbose $Request
16 | $object = ConvertFrom-Json $request.content
17 | Write-Verbose $object
18 | return $object.value
19 | }
20 |
21 | $Session = New-CimSession srv2
22 | $AgentID = (Get-DscLocalConfigurationManager -CimSession $session).AgentId
23 | $Reports = Get-DscReport -verbose -AgentId $AgentID
24 |
25 | Foreach ($Reportin $Reports)
26 | | FT jobid, operationtype, refreshmode, status, EndTime
27 |
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Recipe 10.3 - Finding and Installing DSC sources.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 13-3 - Finding and installing DSC Resources
2 |
3 | # 1. Find available repositories
4 | Get-PSRepository
5 |
6 | # 2. See what DSC resources you can find
7 | Find-DscResource -Repository 'PSGallery' |
8 | Measure-Object
9 |
10 | # 3. See what IIS resources might exist
11 | Find-DscResource |
12 | Where-Object ModuleName -match 'web|iis' |
13 | Select-Object -Property ModuleName,Version -Unique |
14 | Sort-Object -Property ModuleName
15 |
16 | # 4. Examine the xWebAdministration module
17 | Find-DscResource -ModuleName 'xWebAdministration'
18 |
19 | # 5. Install the xWebAdministration module (on SRV1)
20 | Install-Module -Name 'xWebAdministration' -Force
21 |
22 | # 6. See local module details:
23 | Get-Module -Name xWebAdministration -ListAvailable
24 |
25 | # 7. See what is in the module
26 | Get-DscResource -Module xWebAdministration
27 |
28 | # 8 what is IN the module
29 | $Mod = Get-Module -Name xWebAdministration -ListAvailable
30 | $P = $Mod.Path
31 | $FP = Split-Path -Parent $P
32 | Get-ChildItem -Path $FP, $FP\DSCResources
--------------------------------------------------------------------------------
/PowerShellCookBook2019/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Thomas Lee
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Chapter 06 - Deploying Windows Update/Recipe 6.4 - Creating computer target groups.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 6.4 - Creating computer taget groups
2 | #
3 | # Run this on WSUS1
4 |
5 | # 1. Create a WSUS computer target group for the Domain Controllers
6 | $WSUSServer = Get-WsusServer -Name WSUS1 -port 8530
7 | $WSUSServer.CreateComputerTargetGroup('Domain Controllers')
8 |
9 | # 2. Examine existing target groups and viewing the new one
10 | $WSUSServer.GetComputerTargetGroups() |
11 | Format-Table -Property Name
12 |
13 | # 3. Find the DCs
14 | Get-WsusComputer -NameIncludes DC
15 |
16 | # 4. Add DC1 and DC2 to the Domain Controllers Target Group
17 | Get-WsusComputer -NameIncludes DC |
18 | Add-WsusComputer -TargetGroupName 'Domain Controllers'
19 |
20 | # 5. Get the DC group
21 | $DCGroup = $WSUSServer.GetComputerTargetGroups() |
22 | Where-Object Name -eq 'Domain Controllers'
23 |
24 | # 6. Find thecomputers in the group:
25 | Get-WsusComputer |
26 | Where-Object ComputerTargetGroupIDs -Contains $DCGroup.id |
27 | Sort-Object -Property FullDomainName |
28 | Format-Table -Property FullDomainName, ClientVersion,
29 | LastSyncTime
30 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.3 - Using PowerShell Direct.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.3 - Using PS Direct with Hyper-V
2 |
3 | # 1. Create a credential object for ReskitAdministrator:
4 | $RKAn = 'Administrator'
5 | $PS = 'Pa$$w0rd'
6 | $RKP = ConvertTo-SecureString -String $PS -AsPlainText -Force
7 | $T = 'System.Management.Automation.PSCredential'
8 | $RKCred = New-Object -TypeName $T -ArgumentList $RKAn,$RKP
9 |
10 | # 2. Display the details of the PSDirect VM:
11 | Get-VM -Name PSDirect
12 |
13 | # 3. Invoke a command on the VM, specifying VM name:
14 | $SBHT = @{
15 | VMName = 'PSDirect'
16 | Credential = $RKCred
17 | ScriptBlock = {hostname}
18 | }
19 | Invoke-Command @SBHT
20 |
21 | # 4. Invoke a command based on VMID:
22 | $VMID = (Get-VM -VMName PSDirect).VMId.Guid
23 | $ICMHT = @{
24 | VMid = $VMID
25 | Credential = $RKCred
26 | ScriptBlock = {hostname}
27 | }
28 | Invoke-Command @ICMHT
29 |
30 |
31 |
32 |
33 | $VMID = (Get-VM -VMName PSDirect).VMId.Guid
34 | Invoke-Command -VMid $VMID -Credential $RKCred -ScriptBlock {hostname}
35 |
36 | # 5. Enter a PS remoting session with the psdirect VM:
37 | Enter-PSSession -VMName psdirect -Credential $RKCred
38 | Get-CimInstance -Class Win32_ComputerSystem
39 | Exit-PSSession
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.8 - Managing VM state.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.8 - Managing VM state
2 |
3 | # 1. Get the VM's state to check if it is off
4 | Stop-VM -Name PSDirect -WarningAction SilentlyContinue
5 | Get-VM -Name PSDirect
6 |
7 | # 2. Start the VM, get its status, then wait until the VM has an
8 | # IP address assigned and the networking stack is working, then
9 | # examine the VM's state:
10 | Start-VM -VMName PSDirect
11 | Wait-VM -VMName PSDirect -For IPAddress
12 | Get-Vm -VMName PSDirect
13 |
14 | # 3. Suspend and view the PSDirect VM:
15 | Suspend-VM -VMName PSDirect
16 | Get-VM -VMName PSDirect
17 |
18 | # 4. Resumve the VM
19 | Resume-VM -VMName PSDirect
20 | Get-VM -VMName PSDirect
21 |
22 | # 5. Save the VM and check status:
23 | Save-VM -VMName PSDirect
24 | Get-VM -VMName PSDirect
25 |
26 | # 6. Resume the saved VM and view the status:
27 | Start-VM -VMName PSDirect
28 | Get-Vm -VMName PSDirect
29 |
30 | # 7. Restart a VM:
31 | Restart-VM -VMName PSDirect -Force
32 | Get-VM -VMName PSDirect
33 |
34 | # 8. Wait for VM to get an IP address:
35 | Wait-VM -VMName PSDirect -For IPaddress
36 | Get-VM -VMName PSDirect
37 |
38 | # 8. Perform a hard power off on the VM:
39 | Stop-VM -VMName PSDirect -TurnOff
40 | Get-VM -VMname PSDirect
--------------------------------------------------------------------------------
/Chapter 05 - Managing Shared Data/Recipe 5.4 - Creating an iSCSI Target.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 5.4 - Creating an iSCSI Target
2 | # Run from SRV1 as Administrator@reskit.org
3 |
4 | # 1. Install the iSCSI target feature on SRV1
5 | Install-WindowsFeature FS-iSCSITarget-Server
6 |
7 | # 2. Explore iSCSI target server settings:
8 | Get-IscsiTargetServerSetting
9 |
10 | # 3. Create a folder on SRV1 to hold the iscis virtual disk
11 | $NIHT = @{
12 | Path = 'C:\iSCSI'
13 | ItemType = 'Directory'
14 | ErrorAction = 'SilentlyContinue'
15 | }
16 | New-Item @NIHT | Out-Null
17 |
18 |
19 | # 4. Create an iSCSI disk (that is a LUN):
20 | $LP = 'C:\iSCSI\SalesData.Vhdx'
21 | $LN = 'SalesTarget'
22 | $VDHT = @{
23 | Path = $LP
24 | Description = 'LUN For Sales'
25 | SizeBytes = 500MB
26 | }
27 | New-IscsiVirtualDisk @VDHT
28 |
29 | # 5. Set the iSCSI target, specifiying who can initiate
30 | # an iSCSI connection.
31 | $THT = @{
32 | TargetName = $LN
33 | InitiatorIds = 'DNSNAME:FS1.Reskit.Org'
34 | }
35 | New-IscsiServerTarget @THT
36 |
37 | # 6. Create iSCSI disk target mapping:
38 | Add-IscsiVirtualDiskTargetMapping -TargetName $LN -Path $LP
39 |
40 |
41 |
42 | # Undo:
43 | Get-IscsiServerTarget | Remove-IscsiServerTarget
44 | Get-IscsiVirtualDisk | Remove-IscsiVirtualDisk
45 | Remove-item $LP
46 |
--------------------------------------------------------------------------------
/Chapter 05 - Managing Shared Data/Recipe 5.3 - Accessing SMB Shares.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 5.3 - Acessing SMB shares
2 | #
3 | # run from CL1
4 | # Uses the foo share on FS1 created earlier
5 |
6 | # 1. Examine the SMB client's configuration
7 | Get-SmbClientConfiguration
8 |
9 | # 2. You require SMB signing from the client. You must run this
10 | # command from an elevated console on the client computer
11 | $CHT = @{Confirm=$false}
12 | Set-SmbClientConfiguration -RequireSecuritySignature $True @CHT
13 |
14 | # 3. Examine SMB client's network interface
15 | Get-SmbClientNetworkInterface |
16 | Format-Table
17 |
18 | # 4. Examine the shares provided by FS1
19 | net view \\FS1
20 |
21 | # 5. Create a drive mapping, mapping the r: to the share on server FS1
22 | New-SmbMapping -LocalPath r: -RemotePath \\FS1.Reskit.Org\foo
23 |
24 | # 6. View the shared folder mapping
25 | Get-SmbMapping
26 |
27 | # 7. View the shared folder contents
28 | Get-ChildItem -Path r:
29 |
30 | # 8. Run a program from the shared file
31 | # assumes this application is already on that share
32 | R:\MarsInstaller.exe
33 |
34 | # 9. View existing connections
35 | # Note: you need to run this in an elevated console)
36 | Get-SmbConnection
37 |
38 | # 10. What files are open on FS1? If any files are open you view them
39 | # by doing this on FS1:
40 | Get-SmbOpenFile
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Setup-DSCWebApp.ps1:
--------------------------------------------------------------------------------
1 | # Setup-DSCWebApp.ps1
2 | #
3 |
4 | # Setup for DSC Recipe
5 | # Create folder/share on DC1
6 | $SB = {
7 | New-Item C:\ReskitApp -ItemType Directory
8 | New-SMBShare -Name ReskitApp -Path C:\ReskitApp
9 | }
10 | Invoke-Command -ComputerName DC1 -ScriptBlock $SB |
11 | Out-Null
12 | # Create Index.Htm on DC1
13 | $HP = '\\DC1.Reskit.Org\C$\ReskitApp\Index.htm'
14 | $P2 = '\\DC1.Reskit.Org\C$\ReskitApp\Page2.htm'
15 |
16 | $Index = @"
17 |
18 |
19 | Main Page - ReskitApp Application
20 |
21 | HOME PAGE FOR RESKITAPP APPLICATION
22 | This is the root page of the RESKITAPP application
23 |
24 | Pushed via DSC
25 |
26 | Click to View Page 2
27 |
28 |
29 | "@
30 | $Index |
31 | Out-File -FilePath $HP -Force
32 | # Create Page2.htm on DC1
33 | $Page2 = @"
34 |
35 |
36 | ReskitApp Application - Page 2
37 |
38 | Page 2 For the ReskitApp Web Application
39 |
40 | Click to Go Home
41 |
42 | "@
43 | $Page2 |
44 | Out-File -FilePath $P2 -Force
45 |
--------------------------------------------------------------------------------
/Chapter 08 - Leveraging containers/Recipe 8.3 - Deploy IIS in a container.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 8.3 - Deploy iis in a container
2 | #
3 | # Run from CH1
4 | # Run inside the console, NOT the ISE
5 |
6 | # 1. Create reskitapp folder:
7 | $EA = @{ErrorAction='SilentlyContinue'}
8 | New-Item -Path C:\ReskitApp -ItemType Directory @EA
9 |
10 | # 2. Create a web page:
11 | $Fn = 'C:\Reskitapp\Index.htm'
12 | $Index = @"
13 |
14 |
15 | ReskitApp Container Application
16 |
17 | HOME PAGE FOR RESKITAPP APPLICATION
18 | Running in a container in Windows Server 2019
19 |
20 | "@
21 | $Index | Out-File -FilePath $Fn
22 |
23 | # 3. Get a server core with IIS image from the Docker registry:
24 | docker pull mcr.microsoft.com/windows/servercore/iis
25 |
26 | # 4. Now run the image as a container named rkwebc:
27 | $image = 'mcr.microsoft.com/windows/servercore/iis'
28 | docker run -d -p80:80 --name rkwebc "$image"
29 |
30 | # 5.Copy our file into the container:
31 | Set-Location -Path C:\Reskitapp
32 | docker cp .\index.htm rkwebc:c:\inetpub\wwwroot\index.htm
33 |
34 | # 6. View the page:
35 | Start-Process "Http://CH1.Reskit.Org/Index.htm"
36 |
37 | # 7. Clean up:
38 | docker rm rkwebc -f | Out-Null
39 | docker image rm mcr.microsoft.com/windows/servercore/iis |
40 | Out-Null
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.5 - Configuring IIS Bindings.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 9.5 - Configure IIS bindings
2 | #
3 | # Run on SRV1 after running 9.1
4 |
5 | # 1. Import the web administration module
6 | Import-Module -Name WebAdministration
7 |
8 | # 2. Create and populate a new page
9 | $SitePath = 'C:\inetpub\WWW2'
10 | New-Item $SitePath -ItemType Directory | Out-Null
11 | $page = @'
12 |
13 |
14 | Main Page for WWW2.Reskit.Org
15 |
16 | HOME PAGE FOR WWW2.RESKIT.ORG
17 | This is the root page for this site
18 |
19 |
20 | '@
21 | $PAGE | OUT-FILE $sitepath\INDEX.HTML | Out-Null
22 |
23 | # 3.Create a new web site that uses Host headers
24 | $WSHT = @{
25 | PhysicalPath = $SitePath
26 | Name = 'WWW2'
27 | HostHeader = 'WWW2.reskit.org'
28 | }
29 | New-Website @WSHT
30 |
31 |
32 | # 4. Create DNS record on DC1
33 | Invoke-Command -Computer DC1.Reskit.Org -ScriptBlock {
34 | $DNSHT = @{
35 | ZoneName = 'Reskit.Org'
36 | Name = 'www2'
37 | IpAddress = '10.10.10.50'
38 | }
39 | Add-DnsServerResourceRecordA @DNSHT
40 | }
41 |
42 | # 5. And show the site
43 | $IE = New-Object -ComObject InterNetExplorer.Application
44 | $URL = 'http://www2.reskit.org'
45 | $IE.Navigate2($URL)
46 | $IE.Visible = $true
--------------------------------------------------------------------------------
/Chapter 02 - Managing Windows Networking/2.6 - Configuring DHCP Failover amd Load Balancing.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 2.6 - Configuring DHCP Load Balancing and Failover
2 |
3 | # Run on DC2
4 |
5 | # 1. Install the DHCP Server feature on DC2:
6 | $FHT = @{
7 | Name = 'DHCP','RSAT-DHCP'
8 | ComputerName = 'DC2.Reskit.Org'}
9 | Install-WindowsFeature @FHT
10 |
11 | # 2. Let DHCP know it's all configured:
12 | $IPHT = @{
13 | Path = 'HKLM:\SOFTWARE\Microsoft\ServerManager\Roles\12'
14 | Name = 'ConfigurationState'
15 | Value = 2
16 | }
17 | Set-ItemProperty @IPHT
18 |
19 | # 3. Authorize the DHCP server in AD and view the results
20 | Add-DhcpServerInDC -DnsName DC2.Reskit.Org
21 |
22 | # 4. View the DHCP Servers authorised in the domain
23 | Get-DhcpServerInDC
24 |
25 | # 5. Configure failover and load balancing:
26 | $FHT= @{
27 | ComputerName = 'DC1.Reskit.Org'
28 | PartnerServer = 'DC2.Reskit.Org'
29 | Name = 'DC1-DC2'
30 | ScopeID = '10.10.10.0'
31 | LoadBalancePercent = 60
32 | SharedSecret = 'j3RryIsG0d!'
33 | Force = $true
34 | }
35 | Add-DhcpServerv4Failover @FHT
36 | -
37 |
38 | # 5. Get acrive leases in the scope (from both servers!)
39 | 'DC1', 'DC2' |
40 | ForEach-Object {Get-DhcpServerv4Scope -ComputerName $_}
41 |
42 |
43 | # 6. Now get serve statistics from both servers
44 | 'DC1', 'DC2' |
45 | ForEach-Object {
46 | Get-DhcpServerv4ScopeStatistics -ComputerName $_}
47 |
--------------------------------------------------------------------------------
/Chapter 02 - Managing Windows Networking/2.2 - Configuring IP Addressing.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 2.2 - Configuring IP addressing
2 |
3 | # Run on SRV2
4 |
5 | # 1 Get existing IP address information for SRV2:
6 | $IPType = 'IPv4'
7 | $Adapter = Get-NetAdapter |
8 | Where-Object Status -eq 'Up' |Select -First 1
9 | $Interface = $Adapter |
10 | Get-NetIPInterface -AddressFamily $IPType
11 | $IfIndex = $Interface.ifIndex
12 | $IfAlias = $Interface.Interfacealias
13 | Get-NetIPAddress -InterfaceIndex $Ifindex -AddressFamily $IPType
14 |
15 | # 2. Set the IP address for SRV2
16 | $IPHT = @{
17 | InterfaceAlias = $IfAlias
18 | PrefixLength = 24
19 | IPAddress = '10.10.10.51'
20 | DefaultGateway = '10.10.10.254'
21 | AddressFamily = $IPType
22 | }
23 | New-NetIPAddress @IPHT | Out-Null
24 |
25 | # 3. Set DNS Server details
26 | $CAHT = @{
27 | InterfaceIndex = $IfIndex
28 | ServerAddresses = '10.10.10.10'
29 | }
30 | Set-DnsClientServerAddress @CAHT
31 |
32 | # 4. Test new configuration
33 | Get-NetIPAddress -InterfaceIndex $IfIndex -AddressFamily IPv4
34 | Test-NetConnection -ComputerName DC1.Reskit.Org
35 | Resolve-DnsName -Name SRV2.Reskit.Org -Server DC1.Reskit.Org |
36 | Where-Object Type -eq 'A'
37 |
38 |
39 | # Undo
40 | $IPHT = @{
41 | InterfaceAlias = $IfAlias
42 | PrefixLength = 24
43 | IPAddress = '10.10.10.51'
44 | DefaultGateway = '10.10.10.254'
45 | AddressFamily = $IPType
46 | }
47 | New-NetIPAddress @IPHT
--------------------------------------------------------------------------------
/Chapter 04 - Managing Storage/Recipe 4.1 - Using Disks.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 4.1 - Manaing physical Disks and Volumes
2 | #
3 | # Run on SRV1
4 | # SRV1 has 2 extra disks that are 'bare' and just added to the VM
5 |
6 |
7 | # 1. Get physical disks on this system:
8 | Get-Disk |
9 | Format-Table -AutoSize
10 |
11 | # 2. Initialize the disks
12 | Get-Disk |
13 | Where PartitionStyle -eq Raw |
14 | Initialize-Disk -PartitionStyle GPT
15 |
16 | # 3. Re-display disks
17 | Get-Disk |
18 | Format-Table -AutoSize
19 |
20 | # 4. Create a F: volume in disk 1
21 | $NVHT1 = @{
22 | DiskNumber = 1
23 | FriendlyName = 'Storage(F)'
24 | FileSystem = 'NTFS'
25 | DriveLetter = 'F'
26 | }
27 | New-Volume @NVHT1
28 |
29 | # 5. Create two volumes in Disk 2 - first create G:
30 | New-Partition -DiskNumber 2 -DriveLetter G -Size 4gb
31 |
32 | # 6. Create a second partition H:
33 | New-Partition -DiskNumber 2 -DriveLetter H -UseMaximumSize
34 |
35 | # 7. Format G: and H:
36 | $NVHT1 = @{
37 | DriveLetter = 'G'
38 | FileSystem = 'NTFS'
39 | NewFileSystemLabel = 'Log'}
40 | Format-Volume @NVHT1
41 | $NVHT2 = @{
42 | DriveLetter = 'H'
43 | FileSystem = 'NTFS'
44 | NewFileSystemLabel = 'GDShow'}
45 | Format-Volume @NVHT2
46 |
47 | # 8. Get partitions on this system
48 | Get-Partition |
49 | Sort-Object -Property DriveLetter |
50 | Format-Table -Property DriveLetter, Size, Type
51 |
52 | # 9. Get Volumes on SRV1
53 | Get-Volume |
54 | Sort-Object -Property DriveLetter
55 |
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.2 - Install SSL.ps1:
--------------------------------------------------------------------------------
1 | # Revipe 10-2 - Configure IIS for SSL
2 |
3 | # 1 - Import the WebAdministration module
4 | Import-Module -Name WebAdministration
5 |
6 | # 2 - Create a self signed certificate
7 | $CHT = @{
8 | CertStoreLocation = 'CERT:\LocalMachine\MY'
9 | DnsName = 'SRV1.Reskit.Org'
10 | }
11 | $SSLCert = New-SelfSignedCertificate @CHT
12 |
13 | # 3. Copy the certificate to the root store on SRV1:
14 | $C = 'System.Security.Cryptography.X509Certificates.X509Store'
15 | $Store = New-Object -TypeName $C ` -ArgumentList 'Root','LocalMachine'
16 | $Store.Open(‘ReadWrite’)
17 | $Store.Add($SSLcert)
18 | $Store.Close()
19 |
20 | # 4. Create a new SSL binding on the Default Web Site
21 | New-WebBinding -Name 'Default Web Site' -Protocol https -Port 443
22 |
23 | # 5 ASssign the cert created earlier to this new binding
24 | $sslcert | New-Item -Path IIS:\SslBindings\0.0.0.0!443
25 |
26 | # 6. View the site using https!
27 | $IE = New-Object -ComObject InterNetExplorer.Application
28 | $URL = 'https://srv1.reskit.org'
29 | $IE.Navigate2($URL)
30 | $IE.Visible = $true
31 |
32 |
33 |
34 |
35 | # cLEAN UP
36 | Get-ChildItem Cert:\LocalMachine\MY | Where-Object SUBJECT -MATCH 'SRV1.RESKIT.ORG' | Remove-ItemProperty
37 | Get-ChildItem Cert:\LocalMachine\ROOT | Where-Object SUBJECT -MATCH 'SRV1.RESKIT.ORG' | Remove-Item
38 | Get-ChildItem IIS:\SslBindings | Where-Object port -eq 443 | Remove-Item
39 | remove-webbinding -Protocol https
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.1 - Install IIS Server.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 9.1 Install/configure IIS
2 | #
3 | # Run from SRV1
4 |
5 |
6 | # 1. Add Web Server feature, sub-features, and tools to SRV1
7 | $FHT = @{
8 | Name = 'Web-Server'
9 | IncludeAllSubFeature = $true
10 | IncludeManagementTools = $true
11 | }
12 | Install-WindowsFeature @FHT
13 |
14 | # 2. See what actual features are installed
15 | Get-WindowsFeature -Name Web* | Where-Object Installed
16 |
17 | # 3. Check the WebAdministration module
18 | $Modules = @('WebAdministration', 'IISAdministration')
19 | Get-Module -Name $Modules -ListAvailable
20 |
21 | # 4 Get counts of commands in each module
22 | $C1 = (Get-Command -Module WebAdministration |
23 | Measure-Object |
24 | Select-Object -Property Count).Count
25 | $C2 = (Get-Command -Module IISAdministration |
26 | Measure-Object |
27 | Select-Object -Property Count).Count
28 | "$C1 commands in WebAdministration Module"
29 | "$C2 commands in IISAdministration Module"
30 |
31 | # 5. Look at the IIS provider
32 | Import-Module -Name WebAdministration
33 | Get-PSProvider -PSProvider WebAdministration
34 |
35 | # 6. What is in the IIS:
36 | Get-ChildItem -Path IIS:\
37 |
38 | # 7. What is in sites folder?
39 | Get-Childitem -Path IIS:\Sites
40 |
41 | # 8. Look at the default web site:
42 | $IE = New-Object -ComObject InterNetExplorer.Application
43 | $URL = 'HTTP://SRV1'
44 | $IE.Navigate2($URL)
45 | $IE.Visible = $true
46 |
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Recipe 12.2 - Azure Resources.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12.2 - Create Azure Assets
2 | #
3 | #
4 |
5 | # 1. Set Key variables:
6 | $Locname = 'uksouth' # location name
7 | $RgName = 'packt_rg' # resource group we are using
8 | $SAName = 'packt42sa' # Storage account name
9 |
10 | # 2. Login to your Azure Account
11 | $CredAZ = Get-Credential
12 | $Account = Login-AzAccount -Credential $CredAZ
13 |
14 | # 3. Create a resource group and tag it
15 | $RGTag = [Ordered] @{Publisher='Packt'}
16 | $RGTag += @{Author='Thomas Lee'}
17 | $RGHT = @{
18 | Name = $RgName
19 | Location = $Locname
20 | Tag = $RGTag
21 | }
22 | $RG = New-AzResourceGroup @RGHT
23 | $RG
24 |
25 | # 4 View RG with Tags
26 | Get-AzResourceGroup -Name $RGName |
27 | Format-List -Property *
28 |
29 | # 5. Test to see if an SA name is taken
30 | Get-AzStorageAccountNameAvailability $SAName
31 |
32 | # 6. Create a new Storage Account
33 | $SAHT = @{
34 | Name = $SAName
35 | SkuName = 'Standard_LRS'
36 | ResourceGroupName = $RgName
37 | Tag = $RGTag
38 | Location = $Locname
39 |
40 | }
41 | New-AzStorageAccount @SAHT
42 |
43 | # 7. Get overview of the SA in this Resource group
44 | $SA = Get-AzStorageAccount -ResourceGroupName $RgName
45 | $SA |
46 | Format-List -Property *
47 |
48 |
49 | # 8. Get Primary Endpoints for the SA
50 | $SA.PrimaryEndpoints
51 |
52 | # 9. Review SKU
53 | $SA.Sku
54 |
55 | # 10. View Context property
56 | $SA.Context
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.2 - Configuring IIS for SSL.ps1:
--------------------------------------------------------------------------------
1 | # Revipe 10-2 - Configure IIS for SSL/TLS
2 |
3 | # 1 - Import the WebAdministration module
4 | Import-Module -Name WebAdministration
5 |
6 | # 2 - Create a self signed certificate
7 | $CHT = @{
8 | CertStoreLocation = 'CERT:\LocalMachine\MY'
9 | DnsName = 'SRV1.Reskit.Org'
10 | }
11 | $SSLCert = New-SelfSignedCertificate @CHT
12 |
13 | # 3. Copy the certificate to the root store on SRV1:
14 | $C = 'System.Security.Cryptography.X509Certificates.X509Store'
15 | $AL = ‘Root’, ‘LocalMachine’
16 | $Store = New-Object -TypeName $C -ArgumentList $AL
17 | $Store.Open(‘ReadWrite’)
18 | $Store.Add($SSLcert)
19 | $Store.Close()
20 |
21 | # 4. Create a new SSL binding on the Default Web Site
22 | $NBHT = @{
23 | Name = 'Default Web Site'
24 | Protocol = 'https'
25 | Port = 443
26 | }
27 | New-WebBinding @NBHT
28 |
29 | # 5 ASssign the cert created earlier to this new binding
30 | $SSLCert | New-Item -Path IIS:\SslBindings\0.0.0.0!443
31 |
32 | # 6. View the site using https!
33 | $IE = New-Object -ComObject InterNetExplorer.Application
34 | $URL = 'https://srv1.reskit.org'
35 | $IE.Navigate2($URL)
36 | $IE.Visible = $true
37 |
38 |
39 |
40 |
41 | <# cLEAN UP for testing
42 | ls Cert:\LocalMachine\MY | WHERE SUBJECT -MATCH 'SRV1.RESKIT.ORG' | ri
43 | ls Cert:\LocalMachine\ROOT | WHERE SUBJECT -MATCH 'SRV1.RESKIT.ORG' | ri
44 | ls IIS:\SslBindings | where port -eq 443 | ri
45 | remove-webbinding -Protocol https
46 | #>
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Recipe 12.1 - Getting Started.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12-1 Getting started with Azure
2 | #
3 | # Run on CL
4 |
5 | # 1. Find core Azure Modules
6 | Find-Module -Name Az
7 |
8 | # 2. Install AZ modules
9 | Install-Module -Name Az -Force
10 |
11 | # 3. Discover Azure modules and how many cmdlets each contain
12 | $HT = @{ Label ='Cmdlets'
13 | Expression = {(Get-Command -module $_.name).count}}
14 | Get-Module Az* -ListAvailable |
15 | Sort {(Get-command -Module $_.Name).Count} -Descending |
16 | Format-Table -Property Name,Version,Author,$HT -AutoSize
17 |
18 | # 4. Find Azure AD cmdlets
19 | Find-Module AzureAD |
20 | Format-Table -Property Name,Version,Author -AutoSize -Wrap
21 |
22 | # 5. Download the AzureAD Module
23 | Install-Module -Name AzureAD -Force
24 |
25 | # 6. Discover Azure AD Module
26 | $FTHT = @{
27 | Property = 'Name', 'Version', 'Author', 'Description'
28 | AutoSize = $true
29 | Wrap = $true
30 | }
31 | Get-Module -Name AzureAD -ListAvailable |
32 | Format-Table @FTHT
33 |
34 | # 7. Login To Azure
35 | $Subscription = Login-AzAccount
36 |
37 | # 8. Get Azure Subscription details
38 | $SubID = $Subscription.Context.Subscription.SubscriptionId
39 | Get-AzSubscription -SubscriptionId $SubId |
40 | Format-List -Property *
41 |
42 | # 9. Get Azure Locations
43 | Get-AzLocation | Sort-Object Location |
44 | Format-Table Location, Displayname
45 |
46 | # 10 Get Azure Environments
47 | Get-AzEnvironment |
48 | Format-Table -Property name, ManagementPortalURL
49 |
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.7 - Get Printer Usage report.ps1:
--------------------------------------------------------------------------------
1 | # 1. Run WevtUtil to turn on printer monitoring.
2 | wevtutil.exe sl "Microsoft-Windows-PrintService/Operational" /enabled:true
3 |
4 | # 2. Define a function
5 |
6 | Function Get-PrinterUsage {
7 | # 2.1 Get events from the print server event log
8 | $LogName = 'Microsoft-Windows-PrintService/Operational'
9 | $Dps = Get-WinEvent -LogName $LogName |
10 | Where-Object ID -eq 307
11 | Foreach ($Dp in $Dps) {
12 | # 2.2 Ceate a hash table3 with an event log record
13 | $Document = [ordered] @{}
14 | # 2.3 Populate the hash table with properties from the
15 | # Event log entry
16 | $Document.Id = $Dp.Properties[0].value
17 | $Document.Type = $Dp.Properties[1].value
18 | $Document.User = $Dp.Properties[2].value
19 | $Document.Computer = $Dp.Properties[3].value
20 | $Document.Printer = $Dp.Properties[4].value
21 | $Document.Port = $Dp.Properties[5].value
22 | $Document.Bytes = $Dp.Properties[6].value
23 | $Document.Pages = $Dp.Properties[7].value
24 |
25 | # 2.4 Create an object for this printer usage entry
26 | $UEntry = New-Object -TypeName PSObject -Property $Document
27 |
28 | # 2.5 And give it a more relecant tyhpe name
29 | $UEntry.pstypenames.clear()
30 | $UEntry.pstypenames.add("Packt.PrintUsage")
31 |
32 | # 2.6 Output the entry
33 | $UEntry
34 | } # End of foreach
35 |
36 | } # End of function
37 |
38 | # 3.0 Set and use an alias to get printer usage
39 | Get-PrinterUsage | Format-Table
--------------------------------------------------------------------------------
/Chapter 03 - Deploying Active Directory/3.6 - Finding expired computers and disabled users in AD.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 3.5 - Finding expired computers and disabled users in AD
2 |
3 | # 1.Build the report header
4 | $RKReport = ''
5 | $RkReport += "*** Reskit.Org AD Daily AD report`n"
6 | $RKReport += "*** Generated [$(Get-Date)]`n"
7 | $RKReport += "***********************************`n`n"
8 |
9 | # 2. Report on computer accounts that have not logged in the past month
10 | $RkReport += "*** Machines not logged on in past month`n"
11 | $AMonthAgo = (Get-Date).AddMonths(-1)
12 | $ADCHT2 = @{
13 | Properties = 'lastLogonDate'
14 | Filter = 'lastLogonDate -lt $AMonthAgo'
15 | }
16 | $RkReport += Get-ADComputer @ADCHT2 |
17 | Sort-Object -Property lastLogonDate |
18 | Format-Table -Property Name, LastLogonDate |
19 | Out-String
20 |
21 | # 3. Get users who have not logged on in the past month
22 | $RKReport += "*** Users not logged on in past month`n"
23 | $RkReport += Get-AdUser @ADCHT2 |
24 | Sort-Object -Property lastLogonDate |
25 | Format-Table -Property Name, LastLogonDate |
26 | Out-String
27 |
28 | # 4. Find any user accounts that are disabled
29 |
30 | $ADCHT3 = @{
31 | Properties = 'Enabled'
32 | }
33 | $RKReport += "*** Disabled Users`n"
34 | $RkReport += Get-ADUser @Adcht3 -Filter {Enabled -ne $true}|
35 | Sort-Object -Property lastLogonDate |
36 | Format-Table -Property Name, LastLogonDate |
37 | Out-String
38 |
39 | # 5. Display the Report
40 | $RKReport
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.2 - Using WMI to retreive performance counters.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12.2 - Get Performance Counters using CIM Cmdlets
2 | #
3 | # Run on SRV1
4 |
5 | # 1. Find Perf related counters in Root\CIMV2 namespace:
6 | Get-CimClass -ClassName Win32*perf* | Measure-Object |
7 | Select-Object -Property Count
8 | Get-CimClass -ClassName Win32*perfFormatted* | Measure-Object |
9 | Select-Object -Property Count
10 | Get-CimClass -ClassName Win32*perfraw* | Measure-Object |
11 | Select-Object -Property Count
12 |
13 | # 2. Find key Performance classes for the OS
14 | Get-CimClass "Win32_PerfFormatted*PerfOs*" |
15 | Select-Object -Property CimClassName
16 |
17 | # 3. Find key performance classes for the disk
18 | Get-CimClass "win32_PerfFormatted*Disk*" |
19 | Select-Object -Property CimClassName
20 |
21 | # 4. Get Memory counter samples
22 | $Class = 'Win32_PerfFormattedData_PerfOS_Memory'
23 | Get-CimInstance -ClassName $Class |
24 | Select-Object -Property PagesPerSec, AvailableMBytes
25 |
26 | # 5. Get CPU counter samples
27 | $Class2 = 'Win32_PerfFormattedData_PerfOS_Processor'
28 | Get-CimInstance -ClassName $Class2 |
29 | Where-Object Name -eq '_Total' |
30 | Select-Object -Property Name, PercentProcessortime
31 |
32 | # 6. Get Memory counter samples from a remote system
33 | $CHT = @{
34 | ClassName = 'Win32_PerfFormattedData_PerfOS_Memory'
35 | ComputerName = 'DC1'
36 | }
37 | Get-CimInstance @CHT |
38 | Select-Object -Property PSComputerName, PagesPerSec,
39 | AvailableMBytes
40 |
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.4 - Reporting on Performance Data.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 13.4 - Create Performance Report
2 | #
3 | # Uses CSV output from Recipe 13.3
4 | # Run on SRV1
5 |
6 | # 1 - Import the CSV file of counters
7 | $Folder = 'C:\PerfLogs\Admin'
8 | $File = Get-ChildItem -Path $folder\*.csv -Recurse
9 |
10 | # 2. Import the performance counters.
11 | $Counters = Import-Csv $File.FullName
12 | "$($Counters.Count) counters in $($File.FullName)"
13 |
14 | # 3. Fix issue with 1st row in the counters
15 | $Counters[0] = $Counters[1]
16 |
17 | # 4. Obtain basic CPU stats
18 | $CN = '\\SRV1\Processor(_Total)\% Processor Time'
19 | $HT = @{
20 | Name = 'CPU'
21 | Expression = {[System.Double] $_.$cn}
22 | }
23 | $Stats = $counters |
24 | Select-Object -Property *,$ht |
25 | Measure-Object -Property CPU -Average -Minimum -Maximum
26 |
27 | # 5. Add 95th percent value of CPU
28 | $CN = '\\srv1\Processor(_Total)\% Processor Time'
29 | $Row = [int]($Counters.Count * .95 )
30 | $CPU = ($Counters.$CN | Sort-Object)
31 | $CPU95 = [double] $CPU[$Row]
32 | $AMHT = @{
33 | InputObject = $Stats
34 | Name = 'CPU95'
35 | MemberType = 'NoteProperty'
36 | Value = $CPU95
37 | }
38 | Add-Member @AMHT
39 |
40 | # 6. Combine the results into a single report:
41 | $Stats.CPU95 = $Stats.CPU95.ToString('n2')
42 | $Stats.Average = $Stats.Average.ToString('n2')
43 | $Stats.Maximum = $Stats.Maximum.ToString('n2')
44 | $Stats.Minimum = $Stats.Minimum.ToString('n2')
45 |
46 | # 7. Display statistics
47 | $Stats |
48 | Format-Table -Property Property,Count, Maximum, CPU95, Minimum
--------------------------------------------------------------------------------
/Chapter 14 - Troubleshooting WIndows Server/Recipe 14.X - Use TroubleShooting packs.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 14.3 - Use troubleshooting packs
2 | #
3 | # Run on SRV1
4 |
5 | #
6 | # NB: THis recipe was cut from the book, but here it is.
7 | # Using Get-TroubleshootingPack with -Answerfile does not work propertly.
8 |
9 | # 1. Get Trobleshooting packs
10 | $Path = 'C:\Windows\diagnostics\system'
11 | $TSPackfolders = Get-ChildItem -Path $Path -Directory
12 | $TSPacks =
13 | Foreach ($TSPack in $TSPackfolders) {
14 | Get-TroubleshootingPack -Path $TSPack.FullName}
15 |
16 | # 2. Display the packs
17 | $FTHT = @{
18 | Property = 'Name',
19 | 'Version',
20 | 'MinimumVersion',
21 | 'Description'
22 | Wrap = $true
23 | AutoSize = $true
24 | }
25 | $TSPacks | Format-Table @FTHT
26 |
27 | # 3. Get a troubleshooting pack
28 | $TsPack = $TSPacks | Where-Object id -eq 'NetworkDiagnostics'
29 |
30 | # 4. look at the problems this pack looks for
31 | $TSPack.RootCauses
32 |
33 | # 5. And look at the solutions to these issues
34 | $TSPack.RootCauses.Resolutions
35 |
36 | # 6. Run this troubleshooting pack
37 | # (answering questions from the command line)
38 | $TsPack | Invoke-TroubleshootingPack
39 |
40 | # 7. Use get-TroubleshootingPack to create an answer file:
41 | $TSHT = @{
42 | Path = $TSPack.Path
43 | AnswerFile = 'c:\Answers.xml'
44 | }
45 | Get-TroubleshootingPack @TSHT
46 |
47 | # 8. Display the XML:
48 | Get-Content -Path C:\Answers.xml
49 |
50 | # 9. Run WU pack using answer file
51 | $AFHT = @{
52 | AnswerFile = 'C:\Answers.xml'
53 | Unattend = $true
54 | }
55 | $TsPack |
56 | Invoke-TroubleshootingPack @AFHT
57 |
--------------------------------------------------------------------------------
/Chapter 06 - Deploying Windows Update/Recipe 6.5 - Configuring WSUS auto-approvals.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 6.5 - Configuring WSUS Auto Approvals
2 | #
3 | # Run on WSUS!
4 |
5 | # 1. Create the auto-approval rule:
6 | $WSUSServer = Get-WsusServer
7 | $ApprovalRule =
8 | $WSUSServer.CreateInstallApprovalRule('Critical Updates')
9 |
10 | # 2. Define a deadline for the rule:
11 | $Type = 'Microsoft.UpdateServices.Administration.' +
12 | 'AutomaticUpdateApprovalDeadline'
13 | $RuleDeadLine = New-Object -Typename $Type
14 | $RuleDeadLine.DayOffset = 3
15 | $RuleDeadLine.MinutesAfterMidnight = 180
16 | $ApprovalRule.Deadline = $RuleDeadLine
17 |
18 | # 3. Add update classifications to the rule:
19 | $UC = $ApprovalRule.GetUpdateClassifications()
20 | $C= $WSUSServer.GetUpdateClassifications() |
21 | Where-Object -Property Title -eq 'Critical Updates'
22 | $UC.Add($C)
23 | $D = $WSUSServer.GetUpdateClassifications() |
24 | Where-Object -Property Title -eq 'Definition Updates'
25 | $UC.Add($D)
26 | $ApprovalRule.SetUpdateClassifications($UpdateClassification)
27 |
28 |
29 | # 4. Assign the rule to a computer target group:
30 | $Type = 'Microsoft.UpdateServices.Administration.'+
31 | 'ComputerTargetGroupCollection'
32 | $TargetGroups = New-Object $Type
33 | $TargetGroups.Add(($WSUSServer.GetComputerTargetGroups() |
34 | Where-Object -Property Name -eq "Domain Controllers"))
35 | $ApprovalRule.SetComputerTargetGroups($TargetGroups)
36 |
37 | # 5. Enable and save the rule:
38 | $ApprovalRule.Enabled = $true
39 | $ApprovalRule.Save()
40 |
41 | # 6. Get a list of approval rules
42 | $WSUSServer.GetInstallApprovalRules() |
43 | Format-Table -Property Name, Enabled, Action
44 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.5 - Configuring VM hardware.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.5 - Configuring VM Hardware
2 | #
3 | # Run on HV1, using PSDirect VM
4 |
5 | # 1. Turn off the VM1 VM
6 | Stop-VM -VMName PSDirect
7 | Get-VM -VMName PSDirect
8 |
9 | # 2. Set the StartupOrder in the VM's BIOS:
10 | $Order = 'IDE','CD','LegacyNetworkAdapter','Floppy'
11 | Set-VMBios -VmName PSDirect -StartupOrder $Order
12 | Get-VMBios PSDirect
13 |
14 | # 3. Set CPU count for PSDirect
15 | Set-VMProcessor -VMName PSDirect -Count 2
16 | Get-VMProcessor -VmName PSDirect |
17 | Format-Table VMName, Count
18 |
19 | # 4. Set PSDirect memory
20 | $VMHT = [ordered] @{
21 | VMName = 'PSDirect'
22 | DynamicMemoryEnabled = $true
23 | MinimumBytes = 512MB
24 | StartupBytes = 1GB
25 | MaximumBytes = 2GB
26 | }
27 | Set-VMMemory @VMHT
28 | Get-VMMemory -VMName PSDirect
29 |
30 | # 5. Add a ScsiController to PSDirect
31 | Add-VMScsiController -VMName PSDirect
32 | Get-VMScsiController -VMName PSDirect
33 |
34 | # 6. Restart the VM
35 | Start-VM -VMName PSDirect
36 | Wait-VM -VMName PSDirect -For IPAddress
37 |
38 | # 7. Create a new VHDX file:
39 | $VHDPath = 'C:\Vm\Vhds\PSDirect-D.VHDX'
40 | New-VHD -Path $VHDPath -SizeBytes 8GB -Dynamic
41 |
42 | # 8. Add the VHD to the ScsiController:
43 | $VHDHT = @{
44 | VMName = 'PSDirect'
45 | ControllerType = 'SCSI'
46 | ControllerNumber = 0
47 | ControllerLocation = 0
48 | Path = $VHDPath
49 | }
50 | Add-VMHardDiskDrive @VHDHT
51 |
52 | # 9. Get Volumes from PSDirect
53 | Get-VMScsiController -VMName PSDirect |
54 | Select-Object -ExpandProperty Drives
55 |
56 |
57 |
58 |
59 |
60 | PS C:\foo>
--------------------------------------------------------------------------------
/Chapter 01 - Establishing a PowerShell Administrative Environment/1.4 - Creating an internal PS repository.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 1.4 - Creating an internal PowerShell repository
2 |
3 | # 1. Create repository folder
4 | $LPATH = 'C:\RKRepo'
5 | New-Item -Path $LPATH -ItemType Directory | Out-Null
6 |
7 | # 2. Share the folder for others
8 | $SMBHT = @{
9 | Name = 'RKRepo'
10 | Path = $LPATH
11 | Description = 'Reskit Repopository'
12 | FullAccess = 'Everyone'
13 | }
14 | New-SmbShare @SMBHT
15 |
16 | # 3. Create the repository as trusted
17 | $Path = '\\SRV1\RKRepo'
18 | $REPOHT = @{
19 | Name = 'RKRepo'
20 | SourceLocation = $Path
21 | PublishLocation = $Path
22 | InstallationPolicy = 'Trusted'
23 | }
24 | Register-PSRepository @REPOHT
25 |
26 | # 4. View configured repositories
27 | Get-PSRepository
28 |
29 | # 5. Create a Hello World module folder
30 | New-Item C:\HW -ItemType Directory
31 |
32 | # 6. And Create a very simple module
33 | $HS = @"
34 | Function Get-HelloWorld {'Hello World'}
35 | Set-Alias GHW Get-HelloWorld
36 | "@
37 | $HS | Out-File C:\HW\HW.psm1
38 |
39 | # 7. Load and test the Module
40 | Import-Module -Name c:\hw -verbose
41 | GHW
42 |
43 | # 8. Create a Manifest for the new modle
44 | $NMHT = @{
45 | Path = 'C:\HW\HW.psd1'
46 | RootModule = 'HW.psm1'
47 | Description = 'Hello World module'
48 | Author = 'DoctorDNS@Gmail.com'
49 | FunctionsToExport = 'Get-HelloWorld'
50 | }
51 |
52 | # 9. Publish the module:
53 | Publish-Module -Path C:\HW -Repository RKRepo
54 |
55 | # 10. See the results of publishing
56 | Find-Module -Repository RKRepo
57 |
58 | # 11. See repo folder
59 | Get-ChildItem -Path C:\RKRepo
60 |
61 |
--------------------------------------------------------------------------------
/Chapter 05 - Managing Shared Data/Recipe 5.5 - Using an iSCSI target.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 5.5 - Using an ISCSI Target
2 | #
3 | # Run from FS1
4 |
5 |
6 | # 1. Adjust the iSCSI service to auto start, then start the service
7 | Set-Service MSiSCSI -StartupType 'Automatic'
8 | Start-Service MSiSCSI
9 |
10 | # 2. Setup portal to SRV1
11 | $PHT = @{
12 | TargetPortalAddress = 'SRV1.Reskit.Org'
13 | TargetPortalPortNumber = 3260
14 | }
15 | New-IscsiTargetPortal @PHT
16 |
17 | # 3. Find and view the SalesTarget on portal
18 | $Target = Get-IscsiTarget |
19 | Where-Object NodeAddress -Match 'SalesTarget'
20 | $Target
21 |
22 | # 4. Connect to the target on SRV1
23 | $CHT = @{
24 | TargetPortalAddress = 'SRV1.Reskit.Org'
25 | NodeAddress = $Target.NodeAddress
26 | }
27 | Connect-IscsiTarget @CHT
28 |
29 |
30 | # 5. View ICI disk from FST on SRV1
31 | $ISD = Get-Disk |
32 | Where-Object BusType -eq 'iscsi'
33 | $ISD |
34 | Format-Table -AutoSize
35 |
36 | # 6. Turn disk online and make R/W
37 | $ISD |
38 | Set-Disk -IsOffline $False
39 | $ISD |
40 | Set-Disk -Isreadonly $False
41 |
42 | # 7. Format the volume on FS1
43 | $NVHT = @{
44 | FriendlyName = 'SalesData'
45 | FileSystem = 'NTFS'
46 | DriveLetter = 'I'
47 | }
48 | $ISD |
49 | New-Volume @NVHT
50 |
51 | # 8. Use the drive as a local drive:
52 | Set-Location -Path I:
53 | New-Item -Path I:\ -Name SalesData -ItemType Directory |
54 | Out-Null
55 | 'Testing 1-2-3' |
56 | Out-File -FilePath I:\SalesData\Test.Txt
57 | Get-ChildItem I:\SalesData
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | <# Undo it
66 |
67 | Disconnect-IscsiTarget -NodeAddress iqn.1991-05.com.microsoft:srv1-salestarget-target -Confirm:$false
68 |
69 | #>
--------------------------------------------------------------------------------
/ReskitNetwork.md:
--------------------------------------------------------------------------------
1 | # Reskit Network Topology
2 |
3 | This file contains the details of the Reskit Network
4 | Suitably updated - this is nearly a hosts file for the HV host.
5 |
6 | ## Core Servers
7 |
8 | ``` powershell
9 | # Domain controllers
10 | 10.10.10.10 DC1.Reskit.Org
11 | 10.10.10.11 DC2.Reskit.Org
12 |
13 | # Certificate servers
14 | 10.10.10.20 RootCA.Reskit.Org
15 | 10.10.10.21 CA.Reskit.Org
16 |
17 | # General purpose servers
18 | 10.10.10.50 SRV1.Reskit.Org
19 | 10.10.10.51 SRV2.Reskit.Org
20 | ```
21 |
22 | ## File and Storage Servers
23 |
24 | ```powershell
25 | # Scale-Out File server cluster address
26 | 10.10.10.100 FS.Reskit.Org # Cluster address
27 |
28 | # Individual nodes
29 | 10.10.10.101 FS1.Reskit.Org
30 | 10.10.10.102 FS2.Reskit.Org
31 |
32 | # Storage servers (iScsi targers. Storage Spaces Direct cluster)
33 | 10.10.10.111 SSRV1.Reskit.Org
34 | 10.10.10.112 SSRV2.Reskit.Org
35 | 10.10.10.113 SSRV3.Reskit.Org
36 |
37 | ```
38 |
39 | ## Hyper-V nodes
40 |
41 | ```powershell
42 | # Hyper-V Cluster address
43 | 10.10.10.200 HV.Reskit.Org
44 | # Individual Hyper-V nodes
45 | 10.10.10.201 HV1.Reskit.Org
46 | 10.10.10.202 HV2.Reskit.Org
47 | ```
48 | ## NLB IIS servers
49 |
50 | ```powershell
51 | 10.10.10.52 NLB1.Reskit.Org
52 | 10.10.10.52 NLB2.Reskit.Org
53 | ````
54 |
55 | ## Print server
56 |
57 | ```powershell
58 | 10.10.10.60 PSRV.Reskit.Org
59 | ```
60 |
61 | ## Windows Software Update Services (WSUS)
62 |
63 | ```powershell
64 | # WSUS server
65 | 10.10.10.240 WSUS1.Reskit.Org
66 | ```
67 |
68 | ## IP address for the host
69 |
70 | ```powershell
71 | # Assign nice name for host
72 | 10.10.10.252 Home.Reskit.Org
73 | ```
74 |
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Recipe 10.2 - Paramaterising DSC Configuration .ps1:
--------------------------------------------------------------------------------
1 | # Recipe 13-2 - Paramaterize DSC Configuratin
2 |
3 | # 1. Check status of DNS on SRV2
4 | Get-WindowsFeature DNS -ComputerName SRV2
5 |
6 | # 2. Create configuration
7 | Configuration ProvisionServices
8 | {
9 | param (
10 | [Parameter(Mandatory=$true)] $NodeName,
11 | [Parameter(Mandatory=$true)] $FeatureName)
12 | Import-DscResource –ModuleName 'PSDesiredStateConfiguration'
13 | Node $NodeName
14 | {
15 | WindowsFeature $FeatureName
16 | {
17 | Name = $FeatureName
18 | Ensure = 'Present'
19 | IncludeAllSubFeature = $true
20 | } # End Windows Feature
21 | } # End Node configuration
22 | } # End of Configuration document
23 |
24 | # 3. Ensure an empty DSC folder exists, then create MOF file
25 | $NIHT = @{
26 | Path = 'C:\DSC '
27 | ItemType = 'Directory'
28 | ErrorAction = 'SilentlyContinue'
29 | }
30 | New-Item @NIHT| Out-Null
31 | Get-ChildItem -Path C:\DSC | Remove-Item -Force | Out-Null
32 |
33 | # 4. Clear any existing Configuration documents on SRV2
34 | $RIHT =@{
35 | Path = '\\SRV2\c$\Windows\System32\configuration\*.mof'
36 | ErrorAction = 'SilentlyContinue'
37 | }
38 | Get-Childitem '\\SRV2\C$\Windows\System32\configuration\*.MOF' |
39 | Remove-Item @RIHT -Force
40 |
41 | # 5. Now run ProvisionServices to create the MOF to provision DNS on SRV2
42 | $PSHT = @{
43 | OutputPath = 'C:\DSC'
44 | NodeName = 'SRV2'
45 | FeatureName = 'DNS'
46 | }
47 | ProvisionServices @PSHT
48 |
49 | # 6. Do it...
50 | Start-DscConfiguration -Path C:\DSC -Wait -Verbose
51 |
52 | # 7. Check results
53 | Get-Service -Name DNS -ComputerName SRV2
54 |
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.7 - Manage Applications and Application Pools.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 9.7 - Manage Applications and Applications Pools
2 | #
3 | # Run on SRV1 after running 9.5, and 9.1
4 |
5 | # 1. Import the web administration module
6 | Import-Module -Name WebAdministration
7 |
8 | # 2. Create new application poor
9 | New-WebAppPool -Name WWW2Pool
10 |
11 | # 3. Create new application in the pool
12 | $WAHT = @{
13 | Name = 'WWW2'
14 | Site = 'WWW2'
15 | ApplicationPool = 'WWW2Pool'
16 | PhysicalPath = 'C:\inetpub\WWW2'
17 | }
18 | New-WebApplication @WAHT
19 |
20 | # 4. View the application pools
21 | Get-IISAppPool
22 |
23 | # 5. Set Application Pool Restart time
24 | $IPHT1 = @{
25 | Path = 'IIS:\AppPools\WWW2Pool'
26 | Name = 'Recycling.periodicRestart.schedule'
27 | }
28 | Clear-ItemProperty @IPHT1
29 | $RestartAt = @('07:55', '19:55')
30 | New-ItemProperty @IPHT1 -Value $RestartAt
31 |
32 | # 6. Set Application Pool Maximum Private memory
33 | $IPHT2 = @{
34 | Path = 'IIS:\AppPools\WWW2Pool'
35 | Name = 'Recycling.periodicRestart.privatememory'
36 | }
37 | Clear-ItemProperty @IPHT2
38 | [int32] $PrivMemMax = 150mb
39 | Set-ItemProperty -Path 'IIS:\AppPools\WWW2Pool' `
40 | -Name Recycling.periodicRestart.privateMemory `
41 | -Value $PrivMemMax
42 |
43 | # 7. Set max requests before a recycle and view
44 | $IPHT3 = @{
45 | Path = 'IIS:\AppPools\WWW2Pool'
46 | Name = 'Recycling.periodicRestart.requests'
47 | }
48 | Clear-ItemProperty @IPHT3
49 | [int32] $MaxRequests = 104242
50 | Set-ItemProperty @IPHT3 -Value $MaxRequests
51 | Get-ItemProperty @IPHT3
52 |
53 | # 8. Recyle the app pool
54 | $Pool = Get-IISAppPool -Name WWW2Pool
55 | $Pool.Recycle()
56 |
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.6 - Modiying printer security.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 4-7 - Modifying printer security
2 | #
3 | # Run on PSRV, after Create-Sales.ps1 has run
4 |
5 | # 1. Download the Set-PrinterPermissions script.
6 | $URL = 'https://gallery.technet.microsoft.com/scriptcenter/' +
7 | 'Modify-Printer-Permissions-149ae172/file/116651/1/' +
8 | 'Set-PrinterPermissions.ps1'
9 | $Target = 'C:\Foo\Set-PrinterPermissions.ps1'
10 | Start-BitsTransfer -Source $URL -Destination $Target
11 |
12 | # 2. Get help on the script
13 | Get-Help $Target
14 |
15 | # 3. Use PrintUI.DLL to bring up the printer properties GUI:
16 | rundll32.exe printui.dll,PrintUIEntry /p /nSalesprinter1
17 |
18 | # 4. From the GUI, click on Security to view the initial ACL.
19 |
20 | # 5. Remove the Everyone Group ACE from the printers ACL
21 | $SPHT1 = @{
22 | ServerName = 'PSRV'
23 | Remove = $True
24 | AccountName = 'EVERYONE'
25 | SinglePrinterName = 'SalesPrinter1'
26 | }
27 | C:\foo\Set-PrinterPermissions.ps1 @SPHT1
28 |
29 | # 6. Add Sales group to ACL with Print permissions
30 | $SPHT2 = @{
31 | ServerName = 'PSRV'
32 | AccountName = 'Reskit\Sales'
33 | AccessMask = 'Print'
34 | SinglePrinterName = 'SalesPrinter1'
35 | }
36 | C:\foo\Set-PrinterPermissions.ps1 @SPHT2
37 |
38 | # 7. Give SalesAdmins manage documents permission, and log
39 | $SPHT3 = @{
40 | ServerName = 'PSRV'
41 | AccountName = 'Reskit\SalesAdmins'
42 | AccessMask = 'ManageDocuments'
43 | SinglePrinterName = 'SalesPrinter1'
44 | }
45 | C:\foo\Set-PrinterPermissions.ps1 @SPHT3
46 |
47 | # 8. Bring up the Printer Gui
48 | rundll32.exe printui.dll,PrintUIEntry /p /nSalesprinter1
49 |
50 | # 9. Click the security tab and view the updated ACL
51 |
52 |
--------------------------------------------------------------------------------
/PowerShellCookBook2019/ReskitNetwork.md:
--------------------------------------------------------------------------------
1 | # Reskit Network Topology
2 |
3 | This file contains the details of the Reskit Network
4 | Suitably updated - this is nearly a hosts file for the HV host.
5 |
6 | ## Core Servers
7 |
8 | ``` powershell
9 | # Domain controllers
10 | 10.10.10.10 DC1.Reskit.Org
11 | 10.10.10.11 DC2.Reskit.Org
12 |
13 | # Certificate servers
14 | 10.10.10.20 RootCA.Reskit.Org
15 | 10.10.10.21 CA.Reskit.Org
16 |
17 | # General purpose servers
18 | 10.10.10.50 SRV1.Reskit.Org
19 | 10.10.10.51 SRV2.Reskit.Org
20 | ```
21 |
22 | ## File and Storage Servers
23 |
24 | ```powershell
25 | # Scale-Out File server cluster address
26 | 10.10.10.100 FS.Reskit.Org # Cluster address
27 |
28 | # Individual nodes
29 | 10.10.10.101 FS1.Reskit.Org
30 | 10.10.10.102 FS2.Reskit.Org
31 |
32 | # Storage servers (iScsi targers. Storage Spaces Direct cluster)
33 | 10.10.10.111 SSRV1.Reskit.Org
34 | 10.10.10.112 SSRV2.Reskit.Org
35 | 10.10.10.113 SSRV3.Reskit.Org
36 |
37 | ```
38 |
39 | ## Hyper-V nodes
40 |
41 | ```powershell
42 | # Hyper-V Cluster address
43 | 10.10.10.200 HV.Reskit.Org
44 | # Individual Hyper-V nodes
45 | 10.10.10.201 HV1.Reskit.Org
46 | 10.10.10.202 HV2.Reskit.Org
47 | ```
48 | ## NLB IIS servers
49 |
50 | ```powershell
51 | 10.10.10.52 NLB1.Reskit.Org
52 | 10.10.10.52 NLB2.Reskit.Org
53 | ````
54 |
55 | ## Print server
56 |
57 | ```powershell
58 | 10.10.10.60 PSRV.Reskit.Org
59 | ```
60 |
61 | ## Windows Software Update Services (WSUS)
62 |
63 | ```powershell
64 | # WSUS server
65 | 10.10.10.240 WSUS1.Reskit.Org
66 | ```
67 |
68 | ## IP address for the host
69 |
70 | ```powershell
71 | # Assign nice name for host
72 | 10.10.10.252 Home.Reskit.Org
73 | ```
74 |
--------------------------------------------------------------------------------
/Chapter 14 - Troubleshooting WIndows Server/Recipe 14.2 - Using BPA.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 14.2 - Using BPA
2 | #
3 | # Run on SRV1
4 | # uses DC1
5 |
6 | # 1. Get all BPA Models on SRV1
7 | Get-BpaModel |
8 | Format-Table -Property Name, Id, LastScanTime -Wrap
9 |
10 | # 2. Invoke BPA model for Web Server feature
11 | Invoke-BpaModel -ModelId Microsoft/Windows/WebServer
12 |
13 | # 3. Get the results of the BPA run
14 | $Results = Get-BpaResult -ModelId Microsoft/Windows/webServer
15 |
16 | # 4. Display how many tests/results in the BPA model
17 | $Results.Count
18 |
19 | # 5 How many errors and warnings were found?
20 | $Errors = $Results | Where-Object Severity -eq 'Error'
21 | $Warnings = $Results | Where-Object Severity -eq 'Warning'
22 | "Errors found : {0}" -f $Errors.Count
23 | "Warnings found : {0}" -f $Warnings.Count
24 |
25 | # 6. Look at other BPA Results:
26 | $Results | Format-Table -Property Title, Compliance -Wrap
27 |
28 | # 7. Use BPA Remotely - what models exist on DC1?
29 | Invoke-Command -ComputerName DC1 -ScriptBlock {Get-BpaModel} |
30 | Format-Table -Property Name, Id
31 |
32 | # 8. Run BPA Analyzer on DC1
33 | $ModelId = 'Microsoft/Windows/DirectoryServices'
34 | $SB = {Invoke-BpaModel -ModelId $using:ModelId}
35 | Invoke-Command -ComputerName DC1 -ScriptBlock $SB
36 |
37 | # 9. Get the results of DS BPA from DC1
38 | $SB = {Get-BpaResult -ModelId Microsoft/Windows/DirectoryServices}
39 | $RRESULTS = Invoke-Command -ComputerName DC1 -ScriptBlock $SB
40 |
41 | # 10 How many checks/results?
42 | "Total results returned: $($RResults.Count)"
43 | $RResults | Group-Object SEVERITY |
44 | Format-Table -Property Name, Count
45 |
46 | # 11. Use Set-BPAResult to just get errosr:
47 | $RResults |
48 | Where-Object Severity -EQ 'Error' |
49 | Format-List -Property Category,Problem,Impact,Resolution
50 |
51 |
--------------------------------------------------------------------------------
/Chapter 01 - Establishing a PowerShell Administrative Environment/1.2 - Exploring Package Mangement.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 1.2 - Exploring Package Management
2 | #
3 | # Run from SRV1
4 |
5 | # 1. Review the cmdlets in the PackageManagement module:
6 | Get-Command -Module PackageManagement
7 |
8 | # 2. Review the installed providers with Get-PackageProvider:
9 | Get-PackageProvider |
10 | Format-Table -Property Name,
11 | Version,
12 | SupportedFileExtensions,
13 | FromtrustedSource
14 |
15 | # 3. The provider list initially includes msi, msu, and Programs
16 | # package providers. These providers expose applications and
17 | # updates installed on your computer which you can explore.
18 | Get-Package -ProviderName 'msu' |
19 | Select-Object -ExpandProperty Name
20 |
21 | # 4. The NuGet source contains developer library packages. The
22 | # details of NuGet are outside the scope of this book.
23 | Get-PackageProvider -Name NuGet -ForceBootstrap
24 |
25 | # 5. There are also other package providers you can explore:
26 | Find-PackageProvider |
27 | Select-Object -Property Name,Summary |
28 | Format-Table -Wrap -AutoSize
29 |
30 | # 6. Notice Chocolatey, which is another popular repository for Windows
31 | # administrators as well as power users.
32 | # Note that you cannot use this provider until you install it and
33 | # confirm the installation:
34 | Install-PackageProvider -Name Chocolatey -Force
35 |
36 | # 7. Verify Chocolatey is now in the list of installed providers:
37 | Get-PackageProvider | Select-Object -Property Name,Version
38 |
39 | # 8. Look for available software packages from the Chocolatey package provider.
40 | $Packages = Find-Package -ProviderName Chocolatey
41 | "$($Packages.Count) packages available from Chocolatey"
42 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.7 - Implementing nested Hyper-V.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.7 - Implementing nested Hyper-V
2 | #
3 | # Run on PSDirect
4 |
5 | # 1. Stop VM1 VM:
6 | Stop-VM -VMName PSDirect
7 |
8 | # 2. Change and view the VM's processor to support virtualization:
9 | $VMHT = @{
10 | VMName = ‘PSDirect’
11 | ExposeVirtualizationExtensions = $true
12 | }
13 | Set-VMProcessor @VMHT
14 | Get-VMProcessor -VMName PSDirect |
15 | Format-Table -Property Name, Count,
16 | ExposeVirtualizationExtensions
17 |
18 | # 3. Start the VM1 VM:
19 | Start-VM -VMName PSDirect
20 | Wait-VM -VMName PSDirect -For Heartbeat
21 | Get-VM -VMName PSDirect
22 |
23 | # 4. Create credentials
24 | $User = 'Wolf\Administrator'
25 | $PHT = @{
26 | String = 'Pa$$w0rd'
27 | AsPlainText = $true
28 | Force = $true
29 | }
30 | $PSS = ConvertTo-SecureString @PHT
31 | $Type = 'System.Management.Automation.PSCredential'
32 | $CredRK = New-Object -TypeName $Type -ArgumentList $User,$PSS
33 |
34 | # 5. Create a script block for remote execution
35 | $SB = {
36 | Install-WindowsFeature -Name Hyper-V -IncludeManagementTools
37 | }
38 |
39 | # 6. Install Hyper-V inside the PSDirect VM
40 | $Session = New-PSSession -VMName PSDirect -Credential $CredRK
41 | $IHT = @{
42 | Session = $Session
43 | ScriptBlock = $SB
44 | }
45 | Invoke-Command @IHT
46 |
47 | # 7. Restart the VM to finish adding Hyper-V:
48 | Stop-VM -VMName PSDirect
49 | Start-VM -VMName PSDirect
50 | Wait-VM -VMName PSDirect -For IPAddress
51 | Get-VM -VMName PSDirect
52 |
53 | # 8. Create a nested VM:
54 | $SB2 = {
55 | $VMname = 'NestedVM'
56 | New-VM -Name $VMname -MemoryStartupBytes 1GB
57 | }
58 | $IHT2 = @{
59 | VMName = 'PSDirect'
60 | ScriptBlock = $SB2
61 | }
62 | Invoke-Command @IHT2 -Credential $CredRK
63 |
64 |
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.5 - Generating a perf monitoring graph.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 13.5
2 | # Create a performance monitoring Graph
3 |
4 | # 1. Load the Forms assembly
5 | Add-Type -AssemblyName System.Windows.Forms.DataVisualization
6 |
7 | # 2. Import the CSV data from earlier, and fix row 0
8 | $CSVFile = Get-ChildItem -path C:\PerfLogs\Admin\*.csv -rec
9 | $Counters = Import-Csv $CSVFile
10 | $Counters[0] = $Counters[1] # fix row 0 issues
11 |
12 | # 3. Create a chart object
13 | $CPUChart = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
14 |
15 | # 4. Defne the chart dimensions
16 | $CPUChart.Width = 1000
17 | $CPUChart.Height = 600
18 | $CPUChart.Titles.Add("SRV1 CPU Utilisation") | Out-Null
19 |
20 | # 5 Create and define the chart area
21 | $ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
22 | $ChartArea.Name = "SRV1 CPU Usage"
23 | $ChartArea.AxisY.Title = "% CPU Usage"
24 | $CPUChart.ChartAreas.Add($ChartArea)
25 |
26 | # 6. Identify the date/time column.
27 | $Name = ($counters[0] | Get-Member |
28 | Where-Object MemberType -EQ "NoteProperty")[0].Name
29 |
30 | # 7. Add the data points to the chart.
31 | $CPUChart.Series.Add("CPUPerc") | Out-Null
32 | $CPUChart.Series["CPUPerc"].ChartType = "Line"
33 | $CPUCounter = '\\SRV1\Processor(_Total)\% Processor Time'
34 | $counters | ForEach-Object{
35 | $CPUChart.Series["CPUPerc"].Points.AddXY($_.$name,$_.$CPUCounter) |
36 | Out-Null
37 | }
38 |
39 | # 8. Ensure folder exists, then save the chart image as a png file in the folder:
40 | $NIHT = @{
41 | Path = 'C:\Perflogs\Reports'
42 | ItemType = 'Directory'
43 | ErrorAction = 'SilentlyContinue'
44 | }
45 | New-Item @NIHT
46 | $CPUChart.SaveImage("C:\PerfLogs\Reports\Srv1CPU.Png", 'PNG')
47 |
48 | # 9. view the chart image
49 | MSPaint C:\PerfLogs\Reports\SRV1cpu.Png
50 |
--------------------------------------------------------------------------------
/Chapter 06 - Deploying Windows Update/Recipe 6.6 - Managing Updates.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 6.6 - Managing Updates
2 | #
3 | # Run on WSUS1 after earlier recipes are completed.
4 |
5 | # 1. Open a PowerShell session, and view the overall status of all Windows updates
6 | # on WSUS1:
7 | $WSUSServer = Get-WsusServer
8 | $WSUSServer.GetStatus()
9 |
10 | # 2. View the computer targets:
11 | $WSUSServer.GetComputerTargets() |
12 | Sort-Object -Property FullDomainName |
13 | Format-Table -Property FullDomainName, IPAddress, Last*
14 |
15 |
16 | # 3 Search the WSUS server for updates with titles containing Windows Server 2016.
17 | # Then pull out the security updates amd sort by creation date:
18 |
19 | $ST = 'Windows Server 2016'
20 | $SU = 'Security Updates'
21 | $SecurityUpdates = $WSUSServer.SearchUpdates($ST) |
22 | Where-Object UpdateClassificationTitle -eq $SU |
23 | Sort-Object -Property CreationDate -Descending
24 |
25 |
26 | # 4. View the matching updates (first 10).
27 | $SecurityUpdates |
28 | Sort-Object -Property Title |
29 | Select-Object -First 10 |
30 | Format-Table -Property Title, Description
31 |
32 |
33 | # 5. Select one of the updates to approve based on the KB article ID:
34 | $SelectedUpdate = $SecurityUpdates |
35 | Where-Object KnowledgebaseArticles -eq 3194798
36 |
37 | # 6. Define the computer target group where you will approve this update:
38 | $DCTargetGroup = $WSUSServer.GetComputerTargetGroups() |
39 | Where-Object -Property Name -eq 'Domain Controllers'
40 |
41 | # 7. Approve the update for installation in the target group:
42 | $SelectedUpdate.Approve('Install',$DCTargetGroup)
43 |
44 | # 8. Select one of the updates to decline based on a KB article ID:
45 | $DeclinedUpdate = $SecurityUpdates |
46 | Where-Object -Property KnowledgebaseArticles -eq 4020821
47 |
48 | # 9. Decline the update:
49 | $DeclinedUpdate.Decline($DCTargetGroup)
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.x -Deploying Shared Printer.ps1:
--------------------------------------------------------------------------------
1 | # Additional Recipe - not in final book
2 | #
3 | # Self provisioning methods for shared printers.
4 |
5 | # 1. Map a printer by using Printui.dll:
6 | $PrinterPath = "\\PSRV\SalesPrinter1"
7 | rundll32.exe printui.dll,PrintUIEntry /q /in /n$PrinterPath
8 |
9 | # 2. Set the default printer by using Printui.dll:
10 | rundll32 printui.dll,PrintUIEntry /y /n$PrinterPath
11 |
12 | # 3. Delete a printer by using Printui.dll:
13 | $PrinterPath = "\\Psrv\SalesPrinter1"
14 | rundll32.exe printui.dll,PrintUIEntry /q /dn /n$PrinterPath
15 |
16 | # 4. Map a printer by using WMI:
17 | $PrinterPath = "\\PrntSrv\Accounting HP"
18 | ([wmiclass]"Win32_Printer").AddPrinterConnection($PrinterPath)
19 |
20 | # 5. Set the default printer by using WMI:
21 | $PrinterPath = "\\Psrv\SalesPrinter1"
22 | $Filter = "DeviceID='$($PrinterPath.Replace('\','\\'))'"
23 | $Printer = Get-CimInstance -ClassName Win32_Printer | where name -eq 'SalesPrinter1'
24 | Invoke-CimMethod -InputObject $printer -MethodName SetDefaultPrinter
25 | (Get-WmiObject -Class Win32_Printer -Filter $filter).SetDefaultPrinter()
26 |
27 | #6. Remove a printer by using WMI:
28 | $PrinterPath = "\\PrntSrv\Accounting HP"
29 | $filter = "DeviceID='$($PrinterPath.Replace('\','\\'))'"
30 | (Get-WmiObject -Class Win32_Printer -Filter $filter).Delete()
31 |
32 | #7. Map a printer by using WScript
33 | $PrinterPath = "\\PrntSrv\Accounting HP"
34 | (New-Object -ComObject WScript.Network).AddWindowsPrinterConnection($PrinterPath)
35 |
36 | #8. Set the default printer by using WScript:
37 | $PrinterPath = "\\PrntSrv\Accounting HP"
38 | (New-Object -ComObject WScript.Network).
39 | SetDefaultPrinter($PrinterPath)
40 |
41 | #9. Remove a printer by using WScript:
42 | $PrinterPath = "\\PrntSrv\Accounting HP"
43 | (New-Object -ComObject WScript.Network).RemovePrinterConnection($PrinterPath
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.6 - Configuring Hyper-V networking.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.6 - Configuring Hyper-V Networking
2 | #
3 | # Run on HV1
4 |
5 | # 1. Get NIC details and any IP Address from the PSDirect VM
6 | Get-VMNetworkAdapter -VMName PSDirect
7 |
8 | # 2. Create a credential then get VM networking details
9 | $RKAn = 'localhost\Administrator'
10 | $PS = 'Pa$$w0rd'
11 | $RKP = ConvertTo-SecureString -String $PS -AsPlainText -Force
12 | $T = 'System.Management.Automation.PSCredential'
13 | $RKCred = New-Object -TypeName $T -ArgumentList $RKAn, $RKP
14 | $VMHT = @{
15 | VMName = 'PSDirect'
16 | ScriptBlock = {Get-NetIPConfiguration }
17 | Credential = $RKCred
18 | }
19 | Invoke-Command @VMHT | Format-List
20 |
21 | # 3. Create a virtual switch on HV1
22 | $VSHT = @{
23 | Name = 'External'
24 | NetAdapterName = 'Ethernet'
25 | Notes = 'Created on HV1'
26 | }
27 | New-VMSwitch @VSHT
28 |
29 | # 4. Connect VM1 to the switch
30 | Connect-VMNetworkAdapter -VMName PSDirect -SwitchName External
31 |
32 | # 5. See VM networking information:
33 | Get-VMNetworkAdapter -VMName PSDirect
34 |
35 | # 6. With VM1 now in the network, observe the IP address in the VM
36 | $NCHT = @{
37 | VMName = 'PSDirect'
38 | ScriptBlock = {Get-NetIPConfiguration}
39 | Credential = $RKCred
40 | }
41 | Invoke-Command @NCHT
42 |
43 | # 7. View the hostname on VM1
44 | # Reuse the hash table from step 6
45 | $NCHT.ScriptBlock = {hostname}
46 | Invoke-Command @NCHT
47 |
48 | # 8. Change the name of the host in VM1
49 | # Reuse the hash table from steps 6,7
50 | $NCHT.ScriptBlock = {Rename-Computer -NewName Wolf -Force}
51 | Invoke-Command @NCHT
52 |
53 | # 9. Reboot and wait for the restarted VM1
54 | Restart-VM -VMName PSDirect -Wait -For IPAddress -Force
55 |
56 | # 10. Get hostname of the VM1 VM
57 | $NCHT.ScriptBlock = {hostname}
58 | Invoke-Command @NCHT
--------------------------------------------------------------------------------
/Chapter 14 - Troubleshooting WIndows Server/Recipe 14.3 - Managing Event Logs.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 14.4 - Search Event Logs for specific events.
2 | #
3 | # Run on SRV1
4 |
5 | # 1. Get core event logs on SRV1
6 | Get-EventLog -LogName *
7 |
8 | # 2. Get remote classic event logs from DC1
9 | Get-EventLog -LogName * -ComputerName DC1
10 |
11 | # 3. Clear application log on DC1:
12 | Clear-EventLog -LogName Application -ComputerName DC1
13 |
14 | # 4. Look At the types of events on SRV1
15 | Get-EventLog -LogName Application |
16 | Group-Object -Property EntryType |
17 | Format-Table -Property Name, Count
18 |
19 | # 5. Examine which area created the events in the application log:
20 | Get-EventLog -LogName System |
21 | Group-Object -Property Source |
22 | Sort-Object -Property Count -Descending |
23 | Select-Object -First 10 |
24 | Format-Table -Property Name, Count
25 |
26 | # 6. Examine ALL event logs on SRV1
27 | $LocEventLogs = Get-WinEvent -ListLog *
28 | $LocEventLogs.Count
29 | $LocEventLogs |
30 | Sort-Object -Property RecordCount -Descending |
31 | Select-Object -First 10
32 |
33 | # 7. Examine ALL event logs on DC1
34 | $RemEventLogs = Get-WinEvent -ListLog * -ComputerName DC1
35 | $RemEventLogs.count
36 | $RemEventLogs |
37 | Sort-Object -Property RecordCount -Descending |
38 | Select-Object -First 10
39 |
40 | # 8. Look at New logs - Windows Update - what updates have been found
41 | $LN = 'Microsoft-Windows-WindowsUpdateClient/Operational'
42 | $Updates = Get-WinEvent -LogName $LN |
43 | Where-Object ID -EQ 41
44 | $Out = qoreach ($Update in $Updates) {
45 | $HT = @{}
46 | $HT.Time = [System.DateTime] $Update.TimeCreated
47 | $HT.Update = ($Update.Properties | Select-Object -First 1).Value
48 | New-Object -TypeName PSObject -Property $HT
49 | }
50 | $Out | Sort -Property Time
51 | Sort-Object -Property TimeCreated |
52 | Format-Table -Wrap
53 |
--------------------------------------------------------------------------------
/Chapter 03 - Deploying Active Directory/3.3 - Adding users to AD using a CSV.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 3.3 - Adding Users to Active Directory using a CSV File
2 |
3 | # 0. Create CSV
4 | $CSVDATA = @'
5 | Firstname, Initials, Lastname, UserPrincipalName, Alias, Description, Password
6 | S,K,Masterly, SKM, Sylvester, Data Team, Christmas42
7 | C,B, Smith, CBS, Claire, Receptionist, Christmas42
8 | Billy, Bob, JoeBob, BBJB, BillyBob, A Bob, Christmas42
9 | Malcolm, Dudley, Duelittle, Malcolm, Malcolm, Mr Danger, Christmas42
10 | '@
11 | $CSVDATA | Out-File -FilePath C:\Foo\Users.Csv
12 |
13 | # 1. Import a CSV file containing the details of the users you
14 | # want to add to AD:
15 | $Users = Import-CSV -Path C:\Foo\Users.Csv |
16 | Sort-Object -Property Alias
17 | $users | Sort-Object -Property Alias |Format-Table
18 |
19 | # 2. Add the users using the CSV
20 | ForEach ($User in $Users) {
21 | # Create a hash table of properties to set on created user
22 | $Prop = @{}
23 | # Fill in values
24 | $Prop.GivenName = $User.Firstname
25 | $Prop.Initials = $User.Initials
26 | $Prop.Surname = $User.Lastname
27 | $Prop.UserPrincipalName =
28 | $User.UserPrincipalName+"@reskit.org"
29 | $Prop.Displayname = $User.firstname.trim() + " " +
30 | $user.lastname.trim()
31 | $Prop.Description = $User.Description
32 | $Prop.Name = $User.Alias
33 | $PW = ConvertTo-SecureString -AsPlainText $user.password -Force
34 | $Prop.AccountPassword = $PW
35 | # To be safe!
36 | $Prop.ChangePasswordAtLogon = $true
37 | # Now create the user
38 | New-ADUser @Prop -Path 'OU=IT,DC=Reskit,DC=ORG' -Enabled:$true
39 | # Finally, display user created
40 | "Created $($Prop.Displayname)"
41 | }
42 |
43 |
44 |
45 | ### Remove the users created in the recipe
46 |
47 | $users = Import-Csv C:\foo\users.csv
48 | foreach ($User in $Users)
49 | {
50 | Get-ADUser -Identity $user.alias | remove-aduser
51 | }
52 |
--------------------------------------------------------------------------------
/Chapter 02 - Managing Windows Networking/2.1 - New ways to do old things.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 2.1 - New ways to do old things
2 | #
3 | # Run on SRV1
4 |
5 | # 1. Ipconfig vs new cmdlets
6 |
7 | # Two variations on the old way
8 | ipconfig.exe
9 | ipconfig.exe /all
10 |
11 | # The new Way
12 | Get-NetIPConfiguration
13 |
14 | # Related cmdlets - but not for the book...
15 | Get-NetIPInterface
16 | Get-NetAdapter
17 |
18 | # 2. Pinging a computer
19 |
20 | # The old way
21 | Ping DC1.Reskit.Org -4
22 |
23 | # The New way
24 | Test-NetConnection DC1.Reskit.Org
25 |
26 | # And some new things Ping does not do!
27 | Test-NetConnection DC1.Reskit.Org -CommonTCPPort SMB
28 | $ILHT = @{InformationLevel = 'Detailed'}
29 | Test-NetConnection DC1.Reskit.Org -port 389 @ILHT
30 |
31 | # 3. Using Sharing folder from DC1
32 |
33 | # The old way to use a shared folder
34 | net use X: \\DC1.Reskit.Org\c$
35 |
36 | # The new way using an SMB cmdlet
37 | New-SMBMapping -LocalPath 'Y:' -RemotePath \\DC1.Reskit.Org\c$
38 |
39 | # See what is shared the old way:
40 | net use
41 |
42 | # And the new way
43 | Get-SMBMapping
44 |
45 | # 4. - Sharing a folder from SRV1
46 |
47 | # Now share the old way
48 | net share Windows=C:\windows
49 | # and the new way
50 | New-SmbShare -Path C:\Windows -Name Windows2
51 | # And see what has been shared the old way
52 | net share
53 | # and the new way
54 | Get-SmbShare
55 |
56 | # 5. Getting DNS Cache
57 | # The Old way to see the DNS Client Cache
58 | ipconfig /displaydns
59 | # Vs
60 | Get-DnsClientCache
61 |
62 | # 6. Clear the dnsclient client cache the old way
63 | Ipconfig /flushdns
64 | # Vs the new way
65 | Clear-DnsClientCache
66 |
67 | # 7. DNS Lookups
68 | Nslookup DC1.Reskit.Org
69 | Resolve-DnsName -Name DC1.Reskit.Org -Type ALL
70 | #
71 |
72 |
73 | <# undo
74 | Get-SmbMapping x: | Remove-SmbMapping -force
75 | Get-SmbMapping y: | Remove-SmbMapping -confirm:$false
76 | Get-SMBSHARE Windows* | Remove-SMBShare
77 | #>
78 |
--------------------------------------------------------------------------------
/Chapter 05 - Managing Shared Data/Recipe 5.1 - Securing your SMB file server.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 5.1 - Securing your SMB file erver
2 | # Run on FS1
3 |
4 | # 1. - Add File Server features to FS1
5 | $Featuers = 'FileAndStorage-Services','File-Services',
6 | 'FS-FileServer','RSAT-File-Services'
7 | Add-WindowsFeature -Name $Featuers
8 |
9 |
10 | # 2. ` Retreive SMB Server settings
11 | Get-SmbServerConfiguration
12 |
13 | # 3. - Turn off SMB1
14 | $CHT = @{
15 | EnableSMB1Protocol = $false
16 | Confirm = $false
17 | }
18 | Set-SmbServerConfiguration @CHT
19 |
20 | # 4.Turn on SMB signing and encryption
21 | $SHT1 = @{
22 | RequireSecuritySignature = $true
23 | EnableSecuritySignature = $true
24 | EncryptData = $true
25 | Confirm = $false
26 | }
27 | Set-SmbServerConfiguration @SHT1
28 |
29 | # Step 5 - Turn off default server and workstations shares
30 | $SHT2 = @{
31 | AutoShareServer = $false
32 | AutoShareWorkstation = $false
33 | Confirm = $false
34 | }
35 | Set-SmbServerConfiguration @SHT2
36 |
37 | # Step 6 - turn off server announcements
38 | $SHT3 = @{
39 | ServerHidden = $true
40 | AnnounceServer = $false
41 | Confirm = $false
42 | }
43 | Set-SmbServerConfiguration @SHT3
44 |
45 | # Step 7 - restart the service with the new configuration
46 | Restart-Service lanmanserver
47 |
48 |
49 | <# undo and set back to defults
50 |
51 | Get-SMBShare foo* | remove-SMBShare -Confirm:$False
52 |
53 | Set-SmbServerConfiguration -EnableSMB1Protocol $true `
54 | -RequireSecuritySignature $false `
55 | -EnableSecuritySignature $false `
56 | -EncryptData $False `
57 | -AutoShareServer $true `
58 | -AutoShareWorkstation $false `
59 | -ServerHidden $False `
60 | -AnnounceServer $True
61 | Restart-Service lanmanserver
62 | #>
63 |
--------------------------------------------------------------------------------
/Chapter 01 - Establishing a PowerShell Administrative Environment/1.5 - Establish a script signing environment.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 1.6 - Establishing a script signing envionment
2 | # Performed on CL1
3 |
4 | # 1. Create a script-signing certificate
5 | $CHT = @{
6 | Subject = 'Reskit Code Signing'
7 | Type = 'CodeSigning'
8 | CertStoreLocation = 'Cert:\CurrentUser\My'
9 | }
10 | $Cert = New-SelfSignedCertificate @CHT
11 |
12 | # 2. Display newly created certificate
13 | Get-ChildItem -Path Cert:\CurrentUser\my -CodeSigningCert |
14 | Where-Object {$_.Subjectname.Name -match $CHT.Subject}
15 |
16 | # 3. Create a simple script
17 | $Script = @"
18 | # Sample Script
19 | 'Hello World!'
20 | Hostname
21 | "@
22 | $Script | Out-File -FilePath c:\foo\signed.ps1
23 | Get-ChildItem -Path C:\foo\signed.ps1
24 |
25 | # 4. Sign the script
26 | $SHT = @{
27 | Certificate = $cert
28 | FilePath = 'C:\foo\signed.ps1'
29 | }
30 | Set-AuthenticodeSignature @SHT
31 |
32 | # 5. Look at script after signing
33 | Get-ChildItem -Path C:\foo\signed.ps1
34 |
35 | # 6. Test the signature
36 | Get-AuthenticodeSignature -FilePath C:\foo\signed.ps1 |
37 | Format-List
38 |
39 | # 7. Ensure certificate is trusted
40 | # Note ugly construct in opening the store!
41 | $DestStoreName = 'Root'
42 | $DestStoreScope = 'CurrentUser'
43 | $Type = 'System.Security.Cryptography.X509Certificates.X509Store'
44 | $MHT = @{
45 | TypeName = $Type
46 | ArgumentList = ($DestStoreName, $DestStoreScope)
47 | }
48 | $DestStore = New-Object @MHT
49 | $DestStore.Open(
50 | [System.Security.Cryptography.X509Certificates.OpenFlags]::
51 | ReadWrite)
52 | $DestStore.Add($cert)
53 | $DestStore.Close()
54 |
55 | # 8. Resign With a trusted cert
56 | Set-AuthenticodeSignature @SHT | Out-Null
57 |
58 | # 9. Check the cert
59 | Get-AuthenticodeSignature -FilePath C:\foo\signed.ps1 |
60 | Format-List
61 |
62 |
63 |
64 |
65 |
66 |
67 | # UnDo
68 |
69 | Gci cert:\ -recurse | where subject -match 'Reskit Code Signing' | RI -Force
70 | ri C:\foo\signed.ps1
71 |
72 |
73 |
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Create-SalesTeam.ps1:
--------------------------------------------------------------------------------
1 | # Create-SaleTeam
2 |
3 | # Creates the OU, groups, users and group memberships used in Reskit.Org
4 |
5 | # Create Sales OU
6 | $OUPath = 'DC=Reskit,DC=Org'
7 | New-ADOrganizationalUnit -Name Sales -Path $OUPath
8 |
9 | # Setup for creating users for sales
10 | $OUPath = 'OU=Sales,DC=Reskit,DC=Org'
11 | $Password = 'Pa$$w0rd'
12 | $PasswordSS = ConvertTo-SecureString -String $Password -AsPlainText -Force
13 | $NewUserHT = @{
14 | AccountPassword = $PasswordSS;
15 | Enabled = $true;
16 | PasswordNeverExpires = $true;
17 | ChangePasswordAtLogon = $false
18 | Path = $OUPath
19 | }
20 | $Password = 'Pa$$w0rd'
21 | $PasswordSS = ConvertTo-SecureString -String $Password -AsPlainText -Force
22 |
23 | # Create Sales users Nigel, Samantha, Pippa, Jeremy
24 |
25 | New-ADUser @NewUserHT -SamAccountName Nigel -UserPrincipalName 'Nigel@reskit.org' `
26 | -Name "Nigel" -DisplayName 'Nigel Hawthorne-Smyth'
27 |
28 | New-ADUser @NewUserHT -SamAccountName Samantha -UserPrincipalName 'Samantha@reskit.org' `
29 | -Name "Samantha" -DisplayName 'Saamantha Rhees-Jenkins'
30 |
31 | New-ADUser @NewUserHT -SamAccountName Pippa -UserPrincipalName 'Pippa@reskit.org' `
32 | -Name "Pippa" -DisplayName 'Pippa van Spergel'
33 |
34 | New-ADUser @NewUserHT -SamAccountName Jeremy -UserPrincipalName 'Jeremy@reskit.org' `
35 | -Name "Jeremy" -DisplayName 'Jeremy Cadwalender'
36 |
37 | # Create Sales Groups
38 | $OUPath = 'OU=Sales,DC=Reskit,DC=Org'
39 | New-ADGroup -Name Sales -Path $OUPath -GroupScope Global
40 | New-ADGroup -Name SalesAdmins -Path $OUPath -GroupScope Global
41 | New-ADGroup -Name SalesPrinterUsers -Path $OUPath -GroupScope Global
42 |
43 |
44 | # Add users to the groups
45 | Add-ADGroupMember -Identity Sales -Members Nigel, Samantha, Pippa, Jeremy
46 | Add-ADGroupMember -Identity SalesAdmins -Members Nigel, Samantha
47 | Add-AdgroupMember -Identity SalesPrinterUsers -Members Sales, ThomasL
48 |
49 |
--------------------------------------------------------------------------------
/Chapter 04 - Managing Storage/Recipe 4.2 - Managing NTFS permissions.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 4.2 - Managing NTFS Permissions
2 | #
3 | # Run on SRV1
4 |
5 | # 1. Download NTFSSecurity module from PSGallery
6 | Install-Module NTFSSecurity -Force
7 |
8 | # 2. Get commands in the module
9 | Get-Command -Module NTFSSecurity
10 |
11 | # 3. Create a new folder, and a file in the folder
12 | New-Item -Path C:\Secure1 -ItemType Directory |
13 | Out-Null
14 | "Secure" | Out-File -FilePath C:\Secure1\Secure.Txt
15 | Get-ChildItem -Path c:\Secure1
16 |
17 | # 4. View ACL of the folder:
18 | Get-NTFSAccess -Path C:\Secure1 |
19 | Format-Table -AutoSize
20 |
21 | # 5. View ACL of file
22 | Get-NTFSAccess C:\Secure1\Secure.Txt |
23 | Format-Table -AutoSize
24 |
25 |
26 | # 6. Create Sales group if it does not exist
27 | try {
28 | Get-ADGroup -Identity 'Sales' -ErrorAction Stop
29 | }
30 | catch {
31 | New-ADGroup -Name Sales -GroupScope Global |
32 | Out-Null
33 | }
34 |
35 | # 7. Display
36 | Get-ADGroup -Identity Sales
37 |
38 |
39 | # 8. Add explicit full control for DomainAdmins
40 | $AHT1 = @{
41 | Path = 'C:\Secure1'
42 | Account = 'Reskit\Domain Admins'
43 | AccessRights = 'FullControl'
44 | }
45 | Add-NTFSAccess @AHT1
46 |
47 | # 9. Remove builtin\users access from secure.txt file
48 | $AHT2 = @{
49 | Path = 'C:\Secure1\Secure.Txt'
50 | Account = 'Builtin\Users'
51 | AccessRights = 'FullControl'
52 | }
53 |
54 | Remove-NTFSAccess @AHT2
55 |
56 | # 10. Remove inherited rights for the folder:
57 | $IRHT1 = @{
58 | Path = 'C:\Secure1'
59 | RemoveInheritedAccessRules = $True
60 | }
61 | Disable-NTFSAccessInheritance @IRHT1
62 |
63 | # 11. Add Sales group access to the folder
64 | $AHT3 = @{
65 | Path = 'C:\Secure1\'
66 | Account = 'Reskit\Sales'
67 | AccessRights = 'FullControl'
68 | }
69 | Add-NTFSAccess @AHT3
70 |
71 | # 12. get results on path
72 | Get-NTFSAccess -Path C:\Secure1 |
73 | Format-Table -AutoSize
74 |
75 | # 13. and on the file
76 | Get-NTFSAccess -Path C:\Secure1\Secure.Txt |
77 | Format-Table -AutoSize
78 |
79 |
80 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.1 - Installing and Configuring Hyper-V.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11-1 - Installing and configuring Hyper-V
2 | # Run on CL1
3 |
4 | # 1. From CL1, install the Hyper-V feature on HV1, HV2
5 | $Sb = {
6 | Install-WindowsFeature -Name Hyper-V -IncludeManagementTools
7 | }
8 | Invoke-Command -ComputerName HV1, HV2 -ScriptBlock $Sb
9 |
10 | # 2. Reboot the servers to complete the installation
11 | Restart-Computer -ComputerName HV1, HV2 -Force
12 |
13 | # 3. Create a PSSession with both HV Servers (after reboot)
14 | $S = New-PSSession HV1, HV2
15 |
16 | # 4. Create and set the location for VMs and VHDs on HV1 and HV2
17 | # then view results
18 | $Sb = {
19 | New-Item -Path C:\Vm -ItemType Directory -Force |
20 | Out-Null
21 | New-Item -Path C:\Vm\Vhds -ItemType Directory -Force |
22 | Out-Null
23 | New-Item -Path C:\Vm\VMs -ItemType Directory -force |
24 | Out-Null
25 | Get-ChildItem -Path C:\Vm }
26 | Invoke-Command -ScriptBlock $Sb -Session $S
27 |
28 | # 5. Set default paths for Hyper-V VM hard disks and
29 | # VM configuration information
30 | $SB = {
31 | $VMs = 'C:\Vm\Vhds'
32 | $VHDs = 'C:\Vm\VMs\Managing Hyper-V'
33 | Set-VMHost -ComputerName Localhost -VirtualHardDiskPath $VMs
34 | Set-VMHost -ComputerName Localhost -VirtualMachinePath $VHDs
35 | }
36 | Invoke-Command -ScriptBlock $SB -Session $S
37 |
38 | # 5. Setup NUMA spanning
39 | $SB = {
40 | Set-VMHost -NumaSpanningEnabled $true
41 | }
42 | Invoke-Command -ScriptBlock $SB -Session $S
43 |
44 | # 6. Set up EnhancedSessionMode
45 | $SB = {
46 | Set-VMHost -EnableEnhancedSessionMode $true
47 | }
48 | Invoke-Command -ScriptBlock $SB -Session $S
49 |
50 | # 7. Setup host resource metering on HV1, HV2
51 | $SB = {
52 | $RMInterval = New-TimeSpan -Hours 0 -Minutes 15
53 | Set-VMHost -ResourceMeteringSaveInterval $RMInterval
54 | }
55 | Invoke-Command -ScriptBlock $SB -Session $S
56 |
57 |
58 | # 8. Review key VMHost settings:
59 | $SB = {
60 | Get-VMHost
61 | }
62 | $P = 'Name', 'V*Path','Numasp*', 'Ena*','RES*'
63 | Invoke-Command -Scriptblock $SB -Session $S |
64 | Format-Table -Property $P
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.8 - Analyze IIS log files.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 9.8 - Analyze IIS Log Files
2 | #
3 | # Run from SRV1 after previous recipes have created log entries for SRV1
4 |
5 | # 1. Define the location of log files and a temporary file
6 | $LogFolder = 'C:\inetpub\logs\LogFiles\W3SVC1'
7 | $LogFiles = Get-ChildItem $LogFolder\*.log -Recurse
8 | $LogTemp = "C:\inetpub\logs\LogFiles\W3SVC1\AllLogs.tmp"
9 |
10 | # 2. $Logs holds each line of each log file
11 | $Logs = @() # Create empty array
12 | # Remove the comment lines
13 | $LogFiles |
14 | ForEach { Get-Content $_ |
15 | Where-Object {$_ -notLike "#[D,F,S,V]*" } |
16 | Foreach { $Logs += $_ } # add log entry to $Logs array
17 | }
18 |
19 | # 3. Build a better header
20 | $LogColumns = ( $LogFiles |
21 | Select-Object -First 1 |
22 | Foreach { Get-Content $_ |
23 | Where-Object {$_ -Like "#[F]*" } } )
24 | $LogColumns = $LogColumns -replace "#Fields: ", ""
25 | $LogColumns = $LogColumns -replace "-",""
26 | $LogColumns = $LogColumns -replace "\(",""
27 | $LogColumns = $LogColumns -replace "\)",""
28 |
29 | # 4. Save the updated log files
30 | $NL = [Environment]::NewLine
31 | $P = [System.String]::Join( [Environment]::NewLine, $Logs)
32 | $S = "{0}{1}{2}" -f $LogColumns, $NL,$P
33 | Set-Content -Path $LogTemp -Value $S
34 |
35 | # 5. Read the reformatted logs as a CSV file
36 | $Logs = Import-Csv -Path $LogTemp -Delimiter " "
37 |
38 | # 6. View Client IP addresses
39 | $Logs |
40 | Sort-Object -Property cip |
41 | Select-Object -Property CIP -Unique
42 |
43 | # 7. View User Agents used to communicate with SRV1
44 | $Logs |
45 | Sort-Object -property csUserAgent |
46 | Select-Object -Property csUserAgent -Unique
47 |
48 | # 8. View frequency of each user agent
49 | $Logs |
50 | Sort-Object -Property csUserAgent |
51 | Group-Object csuseragent |
52 | Sort-object -Property Count -Desc |
53 | Format-Table -Property Count, Name
54 |
55 | # 9. Who is using what:
56 | $Logs |
57 | Select-Object -Property CIP, CSUserAgent -Unique |
58 | Sort-Object -Property CIP
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Recipe 12.4 - Create Azure SMB share.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12-4 - Create an Azure SMB Share
2 |
3 | # Run from CL1
4 |
5 | # 1. Define Variables
6 | $Locname = 'uksouth' # location name
7 | $RgName = 'packt_rg' # resource group we are using
8 | $SAName = 'packt42sa' # storage account name
9 | $ShareName = 'packtshare' # must be lower case!
10 |
11 | # 2. Login to your Azure Account and ensure the RG and SA is created.
12 | $CredAZ = Get-Credential
13 | $Account = Login-AzAccount -Credential $CredAZ
14 |
15 | # 3. Get Storage account, accountkey and context:
16 | $SA = Get-AzStorageAccount -ResourceGroupName $Rgname
17 | $SAKHT = @{
18 | Name = $SAName
19 | ResourceGroupName = $RgName
20 | }
21 | $Sak = Get-AzStorageAccountKey @SAKHT
22 | $Key = ($Sak | Select-Object -First 1).Value
23 | $SCHT = @{
24 | StorageAccountName = $SAName
25 | StorageAccountKey = $Key
26 | }
27 | $SACon = New-AzStorageContext @SCHT
28 |
29 | # 4. Add credentials to local store:
30 | $T = "$SAName.file.core.windows.net"
31 | cmdkey /add:$T /user:"AZURE\$SAName" /pass:$Key
32 |
33 | # 5. Create a share:
34 | New-AzStorageShare -Name $ShareName -Context $SACon
35 |
36 | # 6. Test that Share is reachable
37 | $TNCHT = @{
38 | ComputerName = "$SAName.file.core.windows.net"
39 | Port = 445
40 | }
41 | Test-NetConnection @TNCHT
42 |
43 | # 7. Mount the share as Z:
44 | $Mount = 'Z:'
45 | $Rshare = "\\$SaName.file.core.windows.net\$ShareName"
46 | $SMHT = @{
47 | LocalPath = $Mount
48 | RemotePath = $Rshare
49 | UserName = $SAName
50 | Password = $Key
51 | }
52 | New-SmbMapping @SMHT
53 |
54 | # 8. View the share in Azure:
55 | Get-AzStorageShare -Context $SACon |
56 | Format-List -Property *
57 |
58 | # 9. View local SMB mappings:
59 | Get-SmbMapping
60 |
61 | # 10. Now use the new share - create a file in the share:
62 | New-Item -Path Z:\Foo -ItemType Directory | Out-Null
63 | 'Azure and PowerShell Rock!!!' |
64 | Out-File -FilePath Z:\Foo\recipe.txt
65 |
66 | # 11. Retrievie details about the share contents:
67 | Get-ChildItem -Path z:\ -Recurse |
68 | Format-Table -Property FullName, Mode, Length
69 |
70 | # 12. Get the content from the file:
71 | Get-Content -Path Z:\Foo\recipe.txt
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.6 - Configure IIS Logging and Log Files.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 10-6 - Configure IIS Logging and log files
2 |
3 | # 1. Import the web administration module to ensure IIS provider is loaded
4 | Import-Module WebAdministration
5 |
6 | # 2. Look at where you are currently storing log files:
7 | $IPHT1 = @{
8 | Path = 'IIS:\Sites\Default Web Site'
9 | Name = 'logfile.directory'
10 | }
11 | $LogfileLocation = (Get-ItemProperty @IPHT1).value
12 | $LF = [System.Environment]::ExpandEnvironmentVariables("$LF")
13 | Get-ChildItem $LogFileFolder -Recurse
14 |
15 | # 3. Change the folder to C:\IISLogs
16 | New-Item -Path C:\IISLogs -ItemType Directory
17 | $IPHT2 = @{
18 | Path = 'IIS:\Sites\Default Web Site'
19 | Name = 'logfile.directory'
20 | }
21 | Set-ItemProperty @IPHT2 -Value 'C:\IISLogs'
22 |
23 | # 4. Change the Logging type:
24 | $IPHT3 = @{
25 | Path = 'IIS:\Sites\Default Web Site'
26 | Name = 'logFile.logFormat'
27 | }
28 | Set-ItemProperty @IPHT3 -Value 'W3C'
29 |
30 | # 5. Change logging frequency:
31 | $IPHT3 = @{
32 | Path = 'IIS:\Sites\Default Web Site'
33 | Name = 'logFile.period'
34 | }
35 | Set-ItemProperty @IPHT3 -Value Weekly
36 |
37 | # 6. Change logging to use a maximum size:
38 | $IPHT4 = @{
39 | Path = 'IIS:\Sites\Default Web Site'
40 | Name = 'logFile.period'
41 | }
42 | Set-ItemProperty @IPHT4 -Value 'MaxSize'
43 | $Size = 1GB
44 | $IPHT5 = @{
45 | Path = 'IIS:\Sites\Default Web Site'
46 | Name = 'logFile.truncateSize'
47 | }
48 | Set-ItemProperty @IPHT5 -Value $size
49 |
50 | # 7. Disable logging:
51 | $IPHT5 = @{
52 | Path = 'IIS:\Sites\Default Web Site'
53 | Name = 'logFile.enabled'
54 | }
55 | Set-ItemProperty @IPHT5 -Value $false
56 |
57 | # 8. Delete old log files
58 | $LogDirs = Get-ChildItem -Path IIS:\Sites |
59 | Get-ItemProperty -Name logFile.directory.value |
60 | Select -Unique
61 | $Age = 30 # h0ow long to keep log files for
62 | $DaysOld = (Get-Date).AddDays(-$Age)
63 | foreach ($LogDir in $LogDirs){
64 | $Dir = [Environment]::ExpandEnvironmentVariables($LogDir)
65 | $DIR
66 | Get-ChildItem -Path $Dir -Recurse -ErrorAction SilentlyContinue |
67 | Where-Object LastWriteTime -lt $DaysOld
68 | Remove-Item
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/Chapter 14 - Troubleshooting WIndows Server/Recipe 14.1 - Check Network Connectivity.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 14.1 - Check connectivity
2 | #
3 | # Run on SRV1
4 | # Uses SRV1, DC1, DC2
5 |
6 | # 1. Use Test-NetConnnection to test connection to DC1
7 | Test-Connection -ComputerName DC1
8 |
9 | # 2. Test with simple true/false return
10 | Test-Connection -ComputerName DC1 -Quiet
11 |
12 | # 3. Test multiple systems at once
13 | Test-Connection -ComputerName 'DC1','DC2','SRV2' -Count 1
14 |
15 | # 4. Test connectivity for SMB traffic with DC1
16 | Test-NetConnection -ComputerName DC1 -CommonTCPPort SMB
17 |
18 | # 5. Get detailed connectivity check, using DC1 with HTTP
19 | $TNCHT = @{
20 | ComputerName = 'DC1'
21 | CommonTCPPort = 'HTTP'
22 | InformationLevel = 'Detailed'
23 | }
24 | Test-NetConnection @TNCHT
25 |
26 | # 6. Look for a particular port (i.e SMV# Recipe 14.1 - Check connectivity
27 | #
28 | # Run on SRV1
29 | # Uses SRV1, DC1, DC2
30 |
31 | # 1. Use Test-NetConnnection to test connection to DC1
32 | Test-Connection -ComputerName DC1
33 |
34 | # 2. Test with simple true/false return
35 | Test-Connection -ComputerName DC1 -Quiet
36 |
37 | # 3. Test multiple systems at once
38 | Test-Connection -ComputerName 'DC1','DC2','SRV2' -Count 1
39 |
40 | # 4. Test connectivity for SMB traffic with DC1
41 | Test-NetConnection -ComputerName DC1 -CommonTCPPort SMB
42 |
43 | # 5. Get detailed connectivity check, using DC1 with HTTP
44 | $TNCHT = @{
45 | ComputerName = 'DC1'
46 | CommonTCPPort = 'HTTP'
47 | InformationLevel = 'Detailed'
48 | }
49 | Test-NetConnection @TNCHT
50 |
51 | # 6. Look for a particular port (i.e LDAP on DC1)
52 | Test-NetConnection -ComputerName DC1 -Port 389
53 |
54 | # 7. Look for a host that does not exist
55 | Test-NetConnection -ComputerName 10.10.10.123
56 |
57 | # 8. Look for a host that exists but a port/application
58 | # that does not exist:
59 | Test-NetConnection -ComputerName DC1 -PORT 9999
60 |
61 |
62 | on DC1)
63 | Test-NetConnection -ComputerName DC1 -Port 445
64 |
65 | # 7. Look for a host that does not exist
66 | Test-NetConnection -ComputerName 10.10.10.123
67 |
68 | # 8. Look for a host that exists but a port/application
69 | # that does not exist:
70 | Test-NetConnection -ComputerName DC1 -PORT 9999
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Chapter 04 - Managing Storage/Recipe 4.5 - Using File System Reporting.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 4.5 - Using Storage Reporting
2 | #
3 | # Run on SRV1 after you run Recipe 4.4 to install FSRM
4 |
5 | # 1. Create a new Storage report for large files on C:\ on SRV1
6 | $NRHT = @{
7 | Name = 'Large Files on SRV1'
8 | NameSpace = 'C:\'
9 | ReportType = 'LargeFiles'
10 | LargeFileMinimum = 10MB
11 | Interactive = $true
12 | }
13 | New-FsrmStorageReport @NRHT
14 |
15 | # 2. Get reports
16 | Get-FsrmStorageReport *
17 |
18 | # 3. After Storage Report is run, view in filestore
19 | $Path = 'C:\StorageReports\Interactive'
20 | Get-ChildItem -Path $Path
21 |
22 | # 4. View the report
23 | $Rep = Get-ChildItem -Path $Path\*.html
24 | Invoke-item -Path $Rep
25 |
26 | # 5. Extract key information from the XML
27 | $XF = Get-ChildItem -Path $Path\*.xml
28 | $XML = [XML] (Get-Content -Path $XF)
29 | $Files = $XML.StorageReport.ReportData.Item
30 | $Files | Where-Object Path -NotMatch '^Windows|^Program|^Users'|
31 | Format-Table -Property name, path,
32 | @{ name ='Sizemb'
33 | expression = {(([int]$_.size)/1mb).tostring('N2')}},
34 | DaysSinceLastAccessed -AutoSize
35 |
36 | # 6. Create a monthly task in task scheduler
37 | $Date = Get-Date '04:00'
38 | $NTHT = @{
39 | Time = $Date
40 | Monthly = 1
41 | }
42 | $Task = New-FsrmScheduledTask @NTHT
43 | $NRHT = @{
44 | Name = 'Monthly Files by files group report'
45 | Namespace = 'C:\'
46 | Schedule = $Task
47 | ReportType = 'FilesbyFileGroup'
48 | FileGroupINclude = 'text files'
49 | LargeFileMinimum = 25MB
50 | }
51 | New-FsrmStorageReport @NRHT | Out-Null
52 |
53 | # 7. Get details of the task
54 | Get-ScheduledTask |
55 | Where-Object taskname -Match 'Monthly' |
56 | Format-Table -AutoSize
57 |
58 | # 8. Run the task now
59 | Get-ScheduledTask -TaskName '*Monthly*' |
60 | Start-ScheduledTask
61 | Get-ScheduledTask -TaskName '*Monthly*'
62 |
63 | # 9. view the report
64 | $Path = 'C:\StorageReports\Scheduled'
65 | $Rep = Get-ChildItem -Path $path\*.html
66 | Invoke-item -Path $Rep
67 |
68 |
69 |
70 |
71 | # cleanup
72 | Unregister-ScheduledTask -TaskName "StorageReport-Monthly report on Big Files" -Confirm:$False
73 | Get-FsrmStorageReport | Remove-FsrmStorageReport
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.3 - Changing spool folder.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 7.3 - Changing the spool directory.
2 |
3 | # 1. Load the System.Printing namespace and classes:
4 | Add-Type -AssemblyName System.Printing
5 |
6 | # 2. Define the required permissions—that is, the ability to administrate the server:
7 | $Permissions =
8 | [System.Printing.PrintSystemDesiredAccess]::
9 | AdministrateServer
10 |
11 | # 3. Create a PrintServer object with the required permissions:
12 | $NOHT = @{
13 | TypeName = 'System.Printing.PrintServer'
14 | ArgumentList = $Permissions
15 | }
16 | $PS = New-Object @NOHT
17 |
18 |
19 | # 4. Create a new spool path:
20 | $NIHT = @{
21 | Path = 'C:\SpoolPath'
22 | ItemType = 'Directory'
23 | Force = $true
24 | ErrorAction = 'SilentlyContinue'
25 | }
26 | New-Item @NIHT | Out-Null
27 |
28 | # 5 Update the default spool folder path:
29 | $Newpath = 'C:\SpoolPath'
30 | $PS.DefaultSpoolDirectory = $Newpath
31 |
32 | # 6. Commit the change:
33 | $Ps.Commit()
34 |
35 | # 7. Restart the Spooler to accept the new folder:
36 | Restart-Service -Name Spooler
37 |
38 | # 8. Once the Spooler has restarted, view the results:
39 | New-Object -TypeName System.Printing.PrintServer |
40 | Format-Table -Property Name,
41 | DefaultSpoolDirectory
42 |
43 |
44 |
45 | # Another way to set the Spooler directory is by directly editing the registry as follows:
46 |
47 |
48 | # 9. First stop the Spooler service:
49 | Stop-Service -Name Spooler
50 |
51 | # 10. Create a new spool directory:
52 | $SPL = 'C:\SpoolViaRegistry'
53 | $NIHT2 = @{
54 | Path = $SPL
55 | Itemtype = 'Directory'
56 | ErrorAction = 'SilentlyContinue'
57 | }
58 | New-Item @NIHT2 | Out-Null
59 |
60 | # 11. Create the spooler folder and configure in the registry
61 | $RPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\' +
62 | 'Print\Printers'
63 | $Spooldir = 'C:\SpoolViaRegistry' # Folder should exist
64 | $IP = @{
65 | Path = $RPath
66 | Name = 'DefaultSpoolDirectory'
67 | Value = $SPL
68 | }
69 | Set-ItemProperty @IP
70 |
71 | # 12. Restart the Spooler:
72 | Start-Service -Name Spooler
73 |
74 | # 13. View the results:
75 | New-Object -TypeName System.Printing.PrintServer |
76 | Format-Table -Property Name, DefaultSpoolDirectory
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.3b - Create performance collector set (CSV OUT).ps1:
--------------------------------------------------------------------------------
1 | # 7.3 Create and add a data collector set
2 | # This script creates a CSV
3 |
4 | #region Create the counter
5 | # 1. Create and populate a new collector
6 | $Name = 'SRV1 Collector Set - CSV'
7 | $SRV1CS = New-Object -COM Pla.DataCollectorSet
8 | $SRV1CS.DisplayName = $Name
9 | $SRV1CS.Duration = 12*3600 # 12 hours - 19:00
10 | $SRV1CS.SubdirectoryFormat = 1
11 | $SRV1CS.SubdirectoryFormatPattern = 'yyyy\-MM'
12 | $JPHT = @{
13 | Path = "$Env:SystemDrive"
14 | Childpath = "\PerfLogs\Admin\$Name"
15 | }
16 | $SRV1CS.RootPath = Join-Path "$Env:SystemDrive" "\PerfLogs\Admin\$Name"
17 |
18 | $SRV1Collector = $SRV1CS.DataCollectors.CreateDataCollector(0)
19 | $SRV1Collector.FileName = '$Name_'
20 | $SRV1Collector.FileNameFormat = 1
21 | $SRV1Collector.FileNameFormatPattern = "\-MM\-dd"
22 | $SRV1Collector.SampleInterval = 15
23 | $SRV1Collector.LogFileFormat = 0 # comma separated
24 | $SRV1Collector.LogAppend = $True
25 |
26 | # 2. Define counters of interest
27 | $Counters = @(
28 | '\Memory\Pages/sec',
29 | '\Memory\Available MBytes',
30 | '\Processor(_Total)\% Processor Time',
31 | '\PhysicalDisk(_Total)\% Disk Time',
32 | '\PhysicalDisk(_Total)\Disk Transfers/sec' ,
33 | '\PhysicalDisk(_Total)\Avg. Disk Sec/Read',
34 | '\PhysicalDisk(_Total)\Avg. Disk Sec/Write',
35 | '\PhysicalDisk(_Total)\Avg. Disk Queue Length'
36 | )
37 |
38 | # 3. Add the counters to the collector
39 | $SRV1Collector.PerformanceCounters = $Counters
40 |
41 | # 4. Create a schedule - start tomorrow morning at 07:00
42 | $StartDate = Get-Date -Day $((Get-Date).Day+1) -Hour 7 -Minute 0 -Second 0
43 | $Schedule = $SRV1CS.Schedules.CreateSchedule()
44 | $Schedule.Days = 127
45 | $Schedule.StartDate = $StartDate
46 | $Schedule.StartTime = $StartDate
47 |
48 | # 5. Create, add and start the collector set
49 | try
50 | {
51 | $SRV1CS.Schedules.Add($Schedule)
52 | $SRV1CS.DataCollectors.Add($SRV1Collector)
53 | $SRV1CS.Commit("$Name" , $null , 0x0003) | Out-Null
54 | $SRV1CS.Start($false);
55 | }
56 | catch [Exception]
57 | {
58 | Write-Host "Exception Caught: " $_.Exception -ForegroundColor Red
59 | return
60 | }
61 |
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Recipe 10.5 -Configuring DSC LCM.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 10.5 - Configuring LCM
2 | #
3 |
4 | # 1. Nuke any Local MOF files and configurations on SRV2, and ensure c:\DSC exists
5 | $RIHT =@{
6 | Path = 'C:\Windows\System32\configuration\*.mof'
7 | ErrorAction = 'SilentlyContinue'
8 | }
9 | Get-Childitem @RIHT |
10 | Remove-Item @RIHT -Force
11 | $EASC = @{
12 | ErrorAction = 'SilentlyContinue'}
13 | New-Item -Path c:\DSC -ItemType Directory @EASC |
14 | Out-Null
15 |
16 | # 2. Get Default settings for LCM:
17 | Get-DscLocalConfigurationManager |
18 | Format-List -Property ActionafterReboot,
19 | AllowModuleOverwrite,
20 | Configuration*,
21 | LCMState,
22 | PartialConfigurations,
23 | Reboot*,
24 | Refresh*,
25 | Report*,
26 | Resource*
27 |
28 | # 3. Create meta configuration for this host
29 | Configuration SRV2LcmConfig {
30 | Node Localhost{
31 | LocalConfigurationManager {
32 | ConfigurationMode = 'ApplyOnly'
33 | RebootNodeIfNeeded = $true
34 | }
35 | }
36 | }
37 |
38 | # 4. Run the config and create the mof
39 | SRV2LcmConfig -OutputPath C:\DSC
40 |
41 | # 5. Set LCM
42 | Set-DscLocalConfigurationManager -Path c:\DSC -Verbose
43 |
44 | # 6. and check updated values:
45 |
46 | Get-DscLocalConfigurationManager |
47 | Format-List -Property ActionafterReboot,
48 | AllowModuleOverwrite,
49 | Configuration*,
50 | LCMState,
51 | PartialConfigurations,
52 | Reboot*,
53 | Refresh*,
54 | Report*,
55 | Resource*
56 |
57 |
58 |
59 |
60 | # Reset should u need to
61 |
62 | Configuration SRV2LcmConfig {
63 | Node Localhost{
64 | LocalConfigurationManager {
65 | AllowModuleOverwrite = $false
66 | ConfigurationModeFrequencyMins = 15
67 | ConfigurationMode = 'ApplyAndMOnitor'
68 | RebootNodeIfNeeded = $false
69 | }
70 | }
71 | }
72 | SRV2LcmConfig -OutputPath c:\dsc
73 | Set-DscLocalConfigurationManager -Path c:\DSC -Verbose
74 |
75 |
--------------------------------------------------------------------------------
/Chapter 05 - Managing Shared Data/Recipe x - Creating a scale out file server..ps1:
--------------------------------------------------------------------------------
1 | # Recipe 9.6 - Make file server fault tolerant
2 | # This recipe is run on FS1, but involves FS2
3 | # ISCSI initiator is setup on FS1, FS2
4 |
5 | # Step 1 - add clustering features
6 | Install-WindowsFeature –Name Failover-Clustering, `
7 | -ComputerName FS1 `
8 | –IncludeManagementTools
9 |
10 | Install-WindowsFeature –Name Failover-Clustering `
11 | -ComputerName FS2 `
12 | –IncludeManagementTools
13 |
14 |
15 | # Step 2 - Test the nodes
16 | $CheckOutput = 'c:\foo\clustercheck.htm'
17 | Test-Cluster -Node FS1, FS2 -ReportName $CheckOutput
18 |
19 |
20 | # Step 3 - View Validation test results
21 | Invoke-Item -Path $CheckOutput
22 |
23 |
24 | # Step 4 - Create The Cluster
25 | New-Cluster -Name FS `
26 | -Node 'fs1.reskit.org', 'fs2.reskit.org' `
27 | -StaticAddress 10.10.10.100
28 |
29 | # 5. Add the Cluster Scale Out File Server role:
30 | Add-ClusterScaleOutFileServerRole -Name SalesFS
31 |
32 | # 6. Add the Target to the CSV
33 | Get-ClusterResource |
34 | Where-Object OwnerGroup -Match 'Available' |
35 | Add-ClusterSharedVolume -Name VM
36 |
37 | # 7 add a normal FailOver share
38 | $SdFolder = 'S:\SalesData'
39 | New-SMBShare -Name SalesData `
40 | -Path $SdFolder `
41 | -Description 'SalesData'
42 |
43 | # 8. Add a Continously Avaliable share
44 | $HvFolder = 'C:\ClusterStorage\Volume1\HVData'
45 | New-Item -Path $HvFolder -ItemType Directory |
46 | Out-Null
47 | New-SMBShare -Name SalesHV -Path $HvFolder `
48 | -Description 'Sales HV (CA)' `
49 | -FullAccess 'Reskit\IT Team' `
50 | -ContinuouslyAvailable:$true
51 |
52 | # 9. View Shares
53 | Get-SmbShare
54 |
55 |
56 | <# Remove it
57 | Get-SMBShare -name SalesData | Remove-SMBShare -Confirm:$False
58 | Get-SMBShare -name HVShare | Remove-SMBShare -Confirm:$False
59 |
60 | get-clusterresource | Stop-ClusterResource
61 | Stop-Cluster
62 |
63 | Get-ClusterSharedVolume | Remove-ClusterSharedVolume
64 | Get-Clusterresource | stop-clusterresource
65 | Get-ClusterGroup -Name salesfs | remove-clusterresource
66 | Get-ClusterResource | remove-clusterresource -Force
67 | Remove-Cluster -force -cleanupad
68 | #>
69 |
70 | # later
71 | Add-ClusterSharedVolume -Name HVCSV
72 |
--------------------------------------------------------------------------------
/Chapter 07 - Managing Printers/Recipe 7.1 - Installing and sharing printer.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 7-1 Installing and sharing printers
2 | #
3 | # Run on Psrv.Reskit.Org
4 |
5 | # 1. Install the Print-Server feature on PSRV, along with the print management
6 | # tools:
7 | Install-WindowsFeature -Name Print-Server, RSAT-Print-Services
8 |
9 |
10 | # 2. Create a folder for the Xerox printer drivers:
11 | $NIHT = @{
12 | Path = 'C:\Foo\Xerox'
13 | ItemType = 'Directory'
14 | Force = $true
15 | ErrorAction = "Silentlycontinue"
16 | }
17 | New-Item @NIHT | Out-Null
18 |
19 | #3. Download printer drivers for Xerox printers:
20 | $URL='http://download.support.xerox.com/pub/drivers/6510/'+
21 | 'drivers/win10x64/ar/6510_5.617.7.0_PCL6_x64.zip'
22 | $Target='C:\Foo\Xerox\Xdrivers.zip'
23 | Start-BitsTransfer -Source $URL -Destination $Target
24 |
25 | # 4. Expand the zip file
26 | $Drivers = 'C:\Foo\Xerox\Drivers'
27 | Expand-Archive -Path $Target -DestinationPath $Drivers
28 |
29 | # 5. Install the drivers
30 | $M1 = 'Xerox Phaser 6510 PCL6'
31 | $P = 'C:\Foo\Xerox\Drivers\6510_5.617.7.0_PCL6_x64_Driver.inf\'+
32 | 'x3NSURX.inf'
33 | rundll32.exe printui.dll,PrintUIEntry /ia /m "$M1" /f "$P"
34 | $M2 = 'Xerox WorkCentre 6515 PCL6'
35 | rundll32.exe printui.dll,PrintUIEntry /ia /m "$M2" /f "$P"
36 |
37 |
38 | # 6. Add a PrinterPort for a new printer:
39 | $PPHT = @{
40 | Name = 'SalesPP'
41 | PrinterHostAddress = '10.10.10.61'
42 | }
43 | Add-PrinterPort @PPHT
44 |
45 |
46 | # 7. Add the printer
47 | $PRHT = @{
48 | Name = 'SalesPrinter1'
49 | DriverName = $m1
50 | PortName = 'SalesPP'
51 | }
52 | Add-Printer @PRHT
53 |
54 | # 8. Share the printer:
55 | Set-Printer -Name SalesPrinter1 -Shared $True
56 |
57 | # 9. Review what you have done:
58 | Get-PrinterPort -Name SalesPP |
59 | Format-Table -Autosize -Property Name, Description,
60 | PrinterHostAddress, PortNumber
61 | Get-PrinterDriver -Name xerox* |
62 | Format-Table -Property Name, Manufacturer,
63 | DriverVersion, PrinterEnvironment
64 | Get-Printer -ComputerName PSRV -Name SalesPrinter1 |
65 | Format-Table -Property Name, ComputerName,
66 | Type, PortName, Location, Shared
67 |
68 |
69 |
70 |
71 | # undo things
72 |
73 | Remove-printer SalesPrinter1
74 | net stop spooler;net start spooler
75 | Remove-PrinterPort 'SalesPP'
76 |
77 |
--------------------------------------------------------------------------------
/Chapter 06 - Deploying Windows Update/Recipe 6.3 - Configuring WIndows Update Client.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 6.3 - Configuring the Windows Update client Via GPO
2 | #
3 | # Run on CL1
4 |
5 | # 0. Get WIndows Upate module and install it
6 | Get-PackageProvider -Name NuGet -ForceBootstrap | Out-Null
7 | Install-Module PSWindowsUpdate -force
8 |
9 | # 1. Examine
10 |
11 | # 1. Define the WSUS server URL using the properties returned from GetWsusServer:
12 | $WSUSServer = Get-WsusServer -Name WSUS1.Reskit.Org -Port 8530
13 | $FS = "http{2}://{0}:{1}"
14 | $N = $WSUSServer.Name
15 | $P = 8530 # default port
16 | $WSUSServerURL = $FS -f $n, $p, ('','s')[$WSUSServer.UseSecureConnection]
17 | $WSUSServerURL
18 |
19 | # 2. Create a Group Policy Object (GPO) and link it to the domain:
20 | $PolicyName = 'Reskit WSUS Policy'
21 | New-GPO -Name $PolicyName
22 | New-GPLink -Name $PolicyName -Target 'DC=RESKIT,DC=Org'
23 |
24 | # 3. Add registry key settings to the group policy to assign the WSUS server:
25 | # Set to use WSUS not WU
26 | $KEY1 = 'HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU'
27 | $RVHT1 = @{
28 | Name = $PolicyName
29 | Key = $KEY1
30 | ValueName = 'UseWUServer'
31 | Type = 'DWORD'
32 | Value = 1
33 | }
34 | Set-GPRegistryValue @RVHT1 | Out-Null
35 | # Set AU options
36 | $KEY2 = 'HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU'
37 | $RVHT2 = @{
38 | Name = $PolicyName
39 | Key = $KEY2
40 | ValueName = 'AUOptions'
41 | Type = 'DWORD'
42 | Value = 2
43 | }
44 | Set-GPRegistryValue @RVHT2 | Out-Null
45 | # Set WSUS Server URL
46 | $KEY3 = 'HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate'
47 | $RVHT3 = @{
48 | Name = $PolicyName
49 | Key = $KEY3
50 | ValueName = 'WUServer'
51 | Type = 'String'
52 | Value = $WSUSServerURL
53 | }
54 | Set-GPRegistryValue @RVHT3 | Out-Null
55 | # Set WU Status server URL
56 | $KEY4 = 'HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate'
57 | $RVHT4 = @{
58 | Name = $PolicyName
59 | Key = $KEY4
60 | ValueName = 'WUStatusServer'
61 | Type = 'String'
62 | Value = $WSUSServerURL
63 | }
64 | Set-GPRegistryValue @RVHT4 | Out-Null
65 |
66 |
67 | # 4. Get a report on the GPO
68 | $RHT = @{
69 | Name = $PolicyName
70 | ReportType = 'Html'
71 | Path = 'C:\foo\out.html'
72 | }
73 | Get-GPOReport @RHT
74 | Invoke-Item -Path $RHT.Path
75 |
--------------------------------------------------------------------------------
/Chapter 03 - Deploying Active Directory/3.4 - Creating a group policy object.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 3.4 - Creating a group policy object
2 |
3 | # 1. Create Group Policy object
4 | $Pol =
5 | New-GPO -Name ITPolicy -Comment "IT GPO" -Domain Reskit.Org
6 |
7 | # 2. Ensure just computer settings are enabled
8 | $Pol.GpoStatus = 'UserSettingsDisabled'
9 |
10 | # 3. Configure the policy with two settings
11 | $EPHT1= @{
12 | Name = 'ITPolicy'
13 | Key = 'HKLM\Software\Policies\Microsoft\Windows\PowerShell'
14 | ValueName = 'ExecutionPolicy'
15 | Value = 'Unrestricted'
16 | Type = 'String'
17 | }
18 | Set-GPRegistryValue @EPHT1 | Out-Null
19 | $EPHT2= @{
20 | Name = 'ITPolicy'
21 | Key = 'HKLM\Software\Policies\Microsoft\Windows\PowerShell'
22 | ValueName = 'EnableScripts'
23 | Type = 'DWord'
24 | Value = 1
25 | }
26 | Set-GPRegistryValue @EPHT2 | Out-Null
27 |
28 | # 4. Create a screen saver GPO And set status and a comment
29 | $Pol2 = New-GPO -Name 'Screen Saver Time Out'
30 | $Pol2.GpoStatus = 'ComputerSettingsDisabled'
31 | $Pol2.Description = '15 minute timeout'
32 |
33 | # 5. Set a registry value
34 | $EPHT3= @{
35 | Name = 'Screen Saver Time Out'
36 | Key = 'HKCU\Software\Policies\Microsoft\Windows\'+
37 | 'Control Panel\Desktop'
38 | ValueName = 'ScreenSaveTimeOut'
39 | Value = 900
40 | Type = 'DWord'
41 | }
42 | Set-GPRegistryValue @EPHT3 | Out-Null
43 |
44 | # 6. Assign the GPOs to the IT OU
45 | $GPLHT1 = @{
46 | Name = 'ITPolicy'
47 | Target = 'OU=IT,DC=Reskit,DC=org'
48 | }
49 | New-GPLink @GPLHT1 | Out-Null
50 | $GPLHT2 = @{
51 | Name = 'Screen Saver Time Out'
52 | Target = 'OU=IT,DC=Reskit,DC=org'
53 | }
54 | New-GPLink @GPLHT2 | Out-Null
55 |
56 | # 7. Display the GPOs in the domain
57 | Get-GPO -All -Domain Reskit.Org |
58 | Sort -Property DisplayName |
59 | Format-Table -Property Displayname, Description, GpoStatus
60 |
61 | # 8. Create and view a GPO Report
62 | $RPath = 'C:\Foo\GPOReport1.HTML'
63 | Get-GPOReport -Name 'ITPolicy' -ReportType Html -Path $RPath
64 | Invoke-Item -Path $RPath
65 |
66 |
67 |
68 | # to undo for testing
69 |
70 | Remove-GPLink -Name 'Screen Saver Time Out' -Target 'OU=IT,DC=Reskit,DC=Org'
71 | Remove-GPLink -Name 'ITPolicy' -Target 'OU=IT,DC=Reskit,DC=Org'
72 | Get-GPO 'ITPolicy' | Remove-GPO
73 | Get-GPO 'Screen Saver Time Out' | remove-GPO
74 | Get-GPO -Domain 'Reskit.Org' -All |
75 | Format-Table -Property DisplayName, GPOStatus, Description
--------------------------------------------------------------------------------
/Errata.md:
--------------------------------------------------------------------------------
1 | # Book Errata
2 |
3 | A considerable amount of time was expended proofreading the book details.
4 | Besides the author there were several other people who also looked for errors.
5 | Sadly, not all errors were caught during production but not all.
6 |
7 | This document describes the errors found.
8 |
9 | ## Errors
10 |
11 | ### Preface
12 |
13 | Page IX, 4th paragraph, second line, should read:
14 | "spelled out in full. Thus, no abbreviated parameter names or positional parameters. This"
15 |
16 | ### Chapter 1 - Establishing a PowerShell Administrative Environment
17 |
18 | Page 11 - small error in screen shots. they should not be different.
19 | Page 12, 2nd Paragraph, penultimate line - the sentence should read: "And for versions later than 1803, the
20 | mechanism may change again."
21 | And with the passage of time since the book was written, the mechanism has indeed changed again.
22 |
23 | Page 15 - Step 15 should read SRV1, not SRV2
24 |
25 | ### Chapter 2 -Managing Windows Networking
26 |
27 | Page 65/66 - Step 6 is not actually shown. The output (on page 66) is form step 7 not step 6.
28 |
29 | ### Chapter 4 - Managing Windows Storage
30 |
31 | Page 134 - The code is fine in the book, but the GITHUB copy had an error in step 5 which is fixed.
32 |
33 | ### Chapter 12 - Managing Azure
34 |
35 | Page 446, last paragraph in intro = this recipe does not check whether the RG and the SA are already created.
36 | Page 447, step 2 - the text is wrong, only login to the Azure account
37 | Page 447. step 5 - the name of the share should be $ShareName.
38 |
39 |
40 |
41 |
42 |
43 | ### Chapter 14 - Managing Performance and Usage
44 |
45 | page 467 - step 9, second line - the Counter should be $Counter2
46 |
47 | Page 471 - photo for step 9 is likewise incorrect in terms of counter name even though the output values are correct.
48 |
49 | Page 471 - the lead in to the graphic for step 9, the server name cited should be HV1.
50 |
51 | Page 479 - the values for LogFileFormat mentioned in the text are wrong and should be like this:
52 | '''powershell
53 | public enum LogFileFormat
54 | {
55 | CommaSeparated = 0,
56 | TabSeparated = 1,
57 | Sql = 2,
58 | Binary = 3,
59 | }
60 | '''
61 |
62 | Page 482 - graphic for step 2 is incorrect.
63 |
64 | Page 493 - step 13. Error in getting CPU numbers
65 | # (Script updated too)
66 | '''powershell
67 | #this
68 | $VMReport.VMCPU = $VM.CPUUsage
69 | #should be
70 | $VMReport.VMCPU = $VM.ProcessorCount
71 |
72 |
73 |
--------------------------------------------------------------------------------
/Chapter 04 - Managing Storage/Add-DiskstoSRV1+2.ps1:
--------------------------------------------------------------------------------
1 | # Add-DiskstoSrv1+2
2 | #
3 | #
4 | # Add two disks to SRV1/2 for Storage Chapter
5 |
6 | # Create volumes for Srv1, 2
7 | New-VHD -Path D:\v6\SRV1\SRV1-F.vhdx -SizeBytes 10gb -Dynamic
8 | New-VHD -Path D:\v6\SRV1\SRV1-G.vhdx -SizeBytes 10gb -Dynamic
9 | New-VHD -Path D:\v6\SRV2\SRV2-F.vhdx -SizeBytes 10gb -Dynamic
10 | New-VHD -Path D:\v6\SRV2\SRV2-G.vhdx -SizeBytes 10gb -Dynamic
11 |
12 | # Add disks
13 | Add-VMHardDiskDrive -VMName SRV1 -Path D:\v6\srv1\SRV1-F.vhdx -ControllerType SCSI -ControllerNumber 0
14 | Add-VMHardDiskDrive -VMName SRV1 -Path D:\v6\srv1\SRV1-G.vhdx -ControllerType SCSI -ControllerNumber 0
15 | Add-VMHardDiskDrive -VMName SRV2 -Path D:\v6\srv2\SRV2-F.vhdx -ControllerType SCSI -ControllerNumber 0
16 | Add-VMHardDiskDrive -VMName SRV2 -Path D:\v6\srv2\SRV2-G.vhdx -ControllerType SCSI -ControllerNumber 0
17 |
18 | # what have we here then?
19 | Get-VMHardDiskDrive -vmname srv1
20 | Get-VMHardDiskDrive -vmname srv2
21 |
22 |
23 | # Format the srv2 drives so that recipe 4.3 works
24 | $SB = {
25 |
26 | # Initialize the disks
27 | Get-Disk |
28 | Where PartitionStyle -eq Raw |
29 | Initialize-Disk -PartitionStyle GPT
30 |
31 | $NVHT1 = @{
32 | DiskNumber = 1
33 | FriendlyName = 'Storage'
34 | FileSystem = 'NTFS'
35 | DriveLetter = 'F'
36 | }
37 | New-Volume @NVHT1
38 | # Create two volumes in Disk 2 - first create G:
39 | New-Partition -DiskNumber 2 -DriveLetter G -Size 4gb
40 | # Create a second partition H:
41 | New-Partition -DiskNumber 2 -DriveLetter H -UseMaximumSize
42 | # Format G: and H:
43 | $NVHT1 = @{
44 | DriveLetter = 'G'
45 | FileSystem = 'NTFS'
46 | NewFileSystemLabel = 'Log'}
47 | Format-Volume @NVHT1
48 | $NVHT2 = @{
49 | DriveLetter = 'H'
50 | FileSystem = 'NTFS'
51 | NewFileSystemLabel = 'GDShow'}
52 | Format-Volume @NVHT2
53 | }
54 | Invoke-Command -ComputerName SRV2 -ScriptBlock $SB -Credential $Credrk
55 |
56 |
57 | ### For testing - remove the disksfrom the VMs, delete them, and recreate them if necessary!
58 |
59 | # Remove disks from the VMs
60 | Get-VMHardDiskDrive -vmname srv1 | where ControllerType -eq scsi | remove-vmharddiskdrive
61 | Get-VMHardDiskDrive -vmname srv2 | where ControllerType -eq scsi | remove-vmharddiskdrive
62 |
63 | # remove disks
64 | Remove-Item -Path D:\v6\SRV1\SRV1-F.vhdx
65 | Remove-Item -Path D:\v6\SRV1\SRV1-G.vhdx
66 | Remove-Item -Path D:\v6\SRV2\SRV2-F.vhdx
67 | Remove-Item -Path D:\v6\SRV2\SRV2-G.vhdx
68 |
--------------------------------------------------------------------------------
/Chapter 04 - Managing Storage/Recipe 4.3 - Managing storage replica.ps1:
--------------------------------------------------------------------------------
1 | # 4.3 - Manage Storage replica
2 | #
3 | # Run on SRV1, with SRV2, DC1 online
4 |
5 |
6 | # 1. Create Content on F:
7 | 1..100 | ForEach {
8 | $NF = "F:\CoolFolder$_"
9 | New-Item -Path $NF -ItemType Directory | Out-Null
10 | 1..100 | ForEach {
11 | $NF2 = "$NF\CoolFile$_"
12 | "Cool File" | Out-File -PSPath $NF2
13 | }
14 | }
15 |
16 | # 2. Show what is on F: locally
17 | Get-ChildItem -Path F:\ -Recurse | Measure-Object
18 |
19 | # 3. And examine the same drives remotely on SRV2
20 | $SB = {
21 | Get-ChildItem -Path F:\ -Recurse |
22 | Measure-Object
23 | }
24 | Invoke-Command -ComputerName SRV2 -ScriptBlock $SB
25 |
26 | # 4. Add storage replica feature to SRV1
27 | Add-WindowsFeature -Name Storage-Replica
28 |
29 | # 5. Restart SRV1 to finish the installation process
30 | Restart-Computer
31 |
32 | # 6. Add SR Feature to SRV2
33 | $SB= {
34 | Add-WindowsFeature -Name Storage-Replica | Out-Null
35 | }
36 | Invoke-Command -ComputerName SRV2 -ScriptBlock $SB
37 |
38 | # 7. And restart SRV2 Waiting for the restart
39 | $RSHT = @{
40 | ComputerName = 'SRV2'
41 | Force = $true
42 | }
43 | Restart-Computer @RSHT -Wait -For PowerShell
44 |
45 | # 8. Create an SR Replica
46 | $SRHT = @{
47 | SourceComputerName = 'SRV1'
48 | SourceRGName = 'SRV1RG'
49 | SourceVolumeName = 'F:'
50 | SourceLogVolumeName = 'G:'
51 | DestinationComputerName = 'SRV2'
52 | DestinationRGName = 'SRV2RG'
53 | DestinationVolumeName = 'F:'
54 | DestinationLogVolumeName = 'G:'
55 | LogSizeInBytes = 2gb
56 | }
57 | New-SRPartnership @SRHT -Verbose
58 |
59 | # 9. View it
60 | Get-SRPartnership
61 |
62 | # 10. And examine the same drives remotely on SRV2
63 | $SB = {
64 | Get-Volume |
65 | Sort-Object -Property DriveLetter |
66 | Format-Table
67 | }
68 | Invoke-Command -ComputerName SRV2 -ScriptBlock $SB
69 |
70 |
71 | # 11. Reverse the replication
72 | $SRHT2 = @{
73 | NewSourceComputerName = 'SRV2'
74 | SourceRGName = 'SRV2RG'
75 | DestinationComputerName = 'SRV1'
76 | DestinationRGName = 'SRV1RG'
77 | Confirm = $false
78 | }
79 | Set-SRPartnership @SRHT2
80 |
81 |
82 | # 12 View RG
83 | Get-SRPartnership
84 |
85 | # 13. Examine the same drives remotely on SRV2
86 | $SB = {
87 | Get-ChildItem -Path F:\ -Recurse |
88 | Measure-Object
89 | }
90 | Invoke-Command -ComputerName SRV2 -ScriptBlock $SB
91 |
92 |
--------------------------------------------------------------------------------
/Chapter 08 - Leveraging containers/Recipe 8.2 - Deploying a hello world sample.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 8.2 - Deploying a Hello World Application
2 | #
3 | # Run on CH1
4 |
5 |
6 | # 1. Find Hello-work containers at the Docker Hub
7 | docker search hello-world
8 |
9 | # 2. Pull the Docker official hello-world image
10 | docker pull hello-world
11 |
12 | # 3. Check the Image just downloaded
13 | docker image ls
14 |
15 | # 4. Run the hello-world container image
16 | docker run hello-world
17 |
18 | # 5. Look for Microsoft images on the Docker Hub:
19 | docker search microsoft
20 |
21 | # 6. Get nano server base image
22 | docker image pull mcr.microsoft.com/windows/nanoserver:1809
23 |
24 | # 7. Run the nanoserver base image:
25 | docker run mcr.microsoft.com/windows/nanoserver:1809
26 |
27 | # 8. Check the images available now on CH1:
28 | docker image ls
29 |
30 | # 9. Inspect the first image:
31 | $Images = docker image ls
32 | $Rxs = '(\w+) +(\w+) +(\w+) '
33 | $OK = $Images[1] -Match $Rxs
34 | $Image = $Matches[1] # grab the image name
35 | docker inspect $image | ConvertFrom-Json
36 |
37 | # 10. Get another (older) image and try to run it:
38 | docker image pull microsoft/nanoserver | Out-Null
39 | docker run microsoft/nanoserver
40 |
41 | # 11. run it with isolation
42 | docker run --isolation=hyperv microsoft/nanoserver
43 |
44 | # 12. look at differences in run times with hyper-V
45 | # run with no isolation
46 | $S1 = Get-Date
47 | docker run hello-world |
48 | Out-Null
49 | $E1 = Get-Date
50 | $T1 = ($E1-$S1).TotalMilliseconds
51 | # run with isolation
52 | $S2 = Get-Date
53 | docker run --isolation=hyperv hello-world | Out-Null
54 | $E2 = get-date
55 | $T2 = ($E2-$S2).TotalMilliseconds
56 | "Without isolation, took : $T1 milliseconds"
57 | "With isolation, took : $T2 milliseconds"
58 |
59 | # 13. run a detached container!
60 | docker image pull microsoft/iis | out-null
61 | docker run -d -p 80:80 microsoft/iis ping -t localhost |
62 | Out-Null
63 |
64 | # 14. Use IIS:
65 | Start-Process http://CH1.Reskit.Org
66 |
67 | # 15. Is IIS loaded?IIS?
68 | Get-Windowsfeature -Name Web-Server
69 |
70 | # 16. check the container
71 | docker container ls
72 |
73 | # 17. And stop kill the contaienr
74 | $CS = (docker container ls)[1] |
75 | Where-Object {$_ -match '( \w+$)'}
76 | $CN = $Matches[0].trim()
77 | docker container stop ($CN) | Out-Null
78 |
79 | # 18. And remove all images
80 | docker rmi $(docker images -q) -f | out-Null
81 |
82 | # 19. and what's left?
83 | docker image ls
84 | docker container ls
85 |
86 |
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Recipe 10.4 - Using DSC with PSGallery Resources.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 10.4 - Using DSC with PS Gallery resources
2 | #
3 | # Run on SRV1 After 10.3 (Getting resources)
4 |
5 | # Step 1 - Copy xWebAdministration module to SRV2
6 |
7 | $CIHT = @{
8 | Path = 'C:\Program Files\WindowsPowerShell\' +
9 | 'Modules\xWebAdministration'
10 | Destination = '\\SRV2\C$\Program Files\WindowsPowerShell\'+
11 | 'Modules'
12 | Recurse = $True
13 | }
14 | Copy-Item @CIHT
15 |
16 | # 2. Clear any existing Configuration documents on SRV, and local mof files
17 | $RIHT =@{
18 | Path = '\\SRV2\c$\Windows\System32\configuration\*.mof'
19 | ErrorAction = 'SilentlyContinue'
20 | }
21 | Get-Childitem @RIHT |
22 | Remove-Item @RIHT -Force
23 | Remove-Item C:\DSC\* -Recurse -Force
24 |
25 | # 3. Create Configuration:
26 | Configuration RKAppSRV2 {
27 | Import-DscResource -ModuleName xWebAdministration
28 | Import-DscResource -ModuleName PSDesiredStateConfiguration
29 | Node SRV2 {
30 | Windowsfeature IISSrv2 {
31 | Ensure = 'Present'
32 | Name = 'Web-Server'
33 | }
34 | Windowsfeature IISSrvTools {
35 | Ensure = 'Present'
36 | Name = 'Web-Mgmt-Tools'
37 | DependsOn = '[WindowsFeature]IISSrv2'
38 | }
39 | File RKAppFiles {
40 | Ensure = 'Present'
41 | Checksum = 'ModifiedDate'
42 | Sourcepath = '\\DC1\ReskitApp\'
43 | Type = 'Directory'
44 | Recurse = $true
45 | DestinationPath = 'C:\ReskitApp\'
46 | DependsOn = '[Windowsfeature]IISSrv2'
47 | MatchSource = $true
48 | }
49 | xWebAppPool ReskitAppPool {
50 | Name = 'RKAppPool'
51 | Ensure = 'Present'
52 | State = 'Started'
53 | DependsOn = '[File]RKAppFiles'
54 | }
55 | xWebApplication ReskitAppPool {
56 | Website = 'Default Web Site'
57 | WebAppPool = 'RKAppPool'
58 | Name = 'ReskitApp'
59 | PhysicalPath = 'C:\ReskitApp\'
60 | Ensure = 'Present'
61 | DependsOn = '[xWebAppPool]ReskitAppPool'
62 | }
63 | Log Completed {
64 | Message = 'Finished Configuring ReskitAp via DSC against SRV2'
65 | }
66 | } # End of SRV2 Configuration
67 | } # End of Configuration
68 |
69 | # 4. Run the configuration block to compile it
70 | RKAppSRV2 -OutputPath C:\DSC
71 |
72 | # 5. Deploy the configuration to SRV2
73 | Start-DscConfiguration -Path C:\DSC -Verbose -Wait
74 |
75 | # 6. Test Result
76 | Start-Process 'http://SRV2/ReskitApp/'
77 |
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.3 - Create+Use PLA Data Collector set.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 6.3 - Create and add a data collector set
2 |
3 | # 1. Create and populate a new collector
4 | $Name = 'SRV1 Collector Set'
5 | $SRV1CS = New-Object -COM Pla.DataCollectorSet
6 | $SRV1CS.DisplayName = $Name
7 | $SRV1CS.Duration = 12*3600 # 12 hours - 19:00
8 | $SRV1CS.SubdirectoryFormat = 1
9 | $SRV1CS.SubdirectoryFormatPattern = 'yyyy\-MM'
10 | $JPHT = @{
11 | Path = "$Env:SystemDrive"
12 | ChildPath = "\PerfLogs\Admin\$Name"
13 | }
14 | $SRV1CS.RootPath = Join-Path @JPHT
15 | $SRV1Collector = $SRV1CS.DataCollectors.CreateDataCollector(0)
16 | $SRV1Collector.FileName = "$Name_"
17 | $SRV1Collector.FileNameFormat = 1
18 | $SRV1Collector.FileNameFormatPattern = "\-MM\-dd"
19 | $SRV1Collector.SampleInterval = 15
20 | $SRV1Collector.LogFileFormat = 3 # BLG separated
21 | $SRV1Collector.LogAppend = $True
22 |
23 | # 2. Define counters of interest
24 | $Counters = @(
25 | '\Memory\Pages/sec',
26 | '\Memory\Available MBytes',
27 | '\Processor(_Total)\% Processor Time',
28 | '\PhysicalDisk(_Total)\% Disk Time',
29 | '\PhysicalDisk(_Total)\Disk Transfers/sec' ,
30 | '\PhysicalDisk(_Total)\Avg. Disk Sec/Read',
31 | '\PhysicalDisk(_Total)\Avg. Disk Sec/Write',
32 | '\PhysicalDisk(_Total)\Avg. Disk Queue Length'
33 | )
34 |
35 | # 3. Add the counters to the collector
36 | $SRV1Collector.PerformanceCounters = $Counters
37 |
38 | # 4. Create a schedule - start tomorrow morning at 07:00
39 | $StartDate = Get-Date -Day $((Get-Date).Day+1) -Hour 7 -Minute 0 -Second 0
40 | $Schedule = $SRV1CS.Schedules.CreateSchedule()
41 | $Schedule.Days = 127
42 | $Schedule.StartDate = $StartDate
43 | $Schedule.StartTime = $StartDate
44 |
45 | # 5. Create, add and start the collector set
46 | try
47 | {
48 | $SRV1CS.Schedules.Add($Schedule)
49 | $SRV1CS.DataCollectors.Add($SRV1Collector)
50 | $SRV1CS.Commit("$Name" , $null , 0x0003) | Out-Null
51 | $SRV1CS.Start($false);
52 | }
53 | catch
54 | {
55 | Write-Host "Exception Caught: " $_.Exception -ForegroundColor Red
56 | return
57 | }
58 |
59 | ### at this point the collector set is live inside Windows
60 |
61 | # Not for the book...
62 | pause
63 |
64 | # 6. Remove the counter
65 | $DCStRemote = New-Object -COM Pla.DataCollectorSet
66 | $Name = 'SRV1 Collector Set'
67 | $DCstRemote.Query($Name,'LocalHost')
68 | $DCstRemote.Stop($true)
69 | $DCstRemote.Delete()
70 |
71 | # 7. Restart the counter
72 | $DCStRemote = New-Object -COM Pla.DataCollectorSet
73 | $Name = 'SRV1 Collector Set'
74 | $DCstRemote.Query($Name,'LocalHost')
75 | $DCstRemote.Start($true)
--------------------------------------------------------------------------------
/Chapter 08 - Leveraging containers/8.4 Create a container using DOCKERFILE.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 8.4- Creating a Image using a Dockerfile
2 | #
3 | # run on CH1
4 |
5 | # 1. Create folder and Set-location to the folder on CH1
6 | $SitePath = 'C:\RKWebContainer'
7 | $NIHT = @{
8 | Path = $SitePath
9 | ItemType = 'Directory'
10 | ErrorAction = 'SilentlyContinue'
11 | }
12 | New-Item @NIHT | Out-Null
13 | Set-Location -Path $NIHT.Path
14 |
15 | # 2. Create a script to run in the container to create a new site in the Containe
16 | $SB = {
17 | # 2.1 create folder in the container
18 | $SitePath = 'C:\RKWebContainer'
19 | $NIHT = @{
20 | Path = $SitePath
21 | ItemType = 'Directory'
22 | ErrorAction = 'SilentlyContinue'
23 | }
24 | New-Item @NIHT | Out-Null
25 | Set-Location -Path $NIHT.Path
26 | # 2.1 Create a page for the site
27 | $PAGE = @'
28 |
29 |
30 | Main Page for RKWeb.Reskit.Org
31 |
32 | HOME PAGE FOR RKWEBr.RESKIT.ORG
33 | Containers and PowerShell Rock!
34 |
35 | '@
36 | $PAGE | OUT-FILE $SitePath\Index.html | Out-Null
37 | #2.2 Create a new web site in the container that uses Host headers
38 | $WSHT = @{
39 | PhysicalPath = $SitePath
40 | Name = 'RKWeb'
41 | HostHeader = 'RKWeb.Reskit.Org'
42 | }
43 | New-Website @WSHT
44 | } # End of script block
45 | # 2.5 Save script block to file
46 | $SB | Out-File $SitePath\Config.ps1
47 |
48 | # 3. Create a new A record for our soon to be containerized site:
49 | Invoke-Command -Computer DC1.Reskit.Org -ScriptBlock {
50 | $DNSHT = @{
51 | ZoneName = 'Reskit.Org'
52 | Name = 'RKWeb'
53 | IpAddress = '10.10.10.221'
54 | }
55 | Add-DnsServerResourceRecordA @DNSHT
56 | }
57 |
58 | # 4. Create Dockerfile
59 | $DF = @"
60 | FROM mcr.microsoft.com/windows/servercore:1809
61 | LABEL Description="RKWEB Container" Vendor="PS Partnership" Version="1.0.0.42"
62 | RUN powershell -Command Add-WindowsFeature Web-Server
63 | RUN powershell -Command GIP
64 | WORKDIR C:\\RKWebContainer
65 | COPY Config.ps1 \Config.ps1
66 | RUN powershell -command ".\Config.ps1"
67 | "@
68 | # to add in maybe
69 | # Run powershell -Command c:/config.ps1
70 | $DF | Out-File -FilePath .\Dockerfile -Encoding ascii
71 |
72 | # 5. Build the image:
73 | docker build -t rkwebc .
74 |
75 | # 6. Run the image:
76 | docker run -d --name rkwebc -p 80:80 rkwebc
77 |
78 | # 7. Now navigate to the container:
79 | Invoke-WebRequest -UseBasicParsing HTTP://RKweb.Reskit.Org
80 | Start-Process "http://RKWeb.Reskit.Org"
81 |
82 | # 8. test net connection
83 | Test-NetConnection -ComputerName localhost -Port 80
84 |
85 | # 7. clean up forcibly
86 | docker container rm rkwebc -f
87 |
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.3a - Create performance collector set (TSV OUT).ps1:
--------------------------------------------------------------------------------
1 | # 11.3 - Create and add a data collector set
2 | # This variant creates a TSV Output file
3 | #
4 | # Run on SRV1
5 |
6 | # 1. Create and populate a new collector
7 | $Name = 'SRV1 Collector Set - tsv'
8 | $SRV1CS = New-Object -COM Pla.DataCollectorSet
9 | $SRV1CS.DisplayName = $Name
10 | $SRV1CS.Duration = 12*3600 # 12 hours - 19:00
11 | $SRV1CS.SubdirectoryFormat = 1
12 | $SRV1CS.SubdirectoryFormatPattern = 'yyyy\-MM'
13 | $JPHT = @{
14 | Path = "$Env:SystemDrive"
15 | ChildPath = "\PerfLogs\Admin\$Name"
16 | }
17 | $SRV1CS.RootPath = Join-Path @JPHT
18 | $SRV1Collector = $SRV1CS.DataCollectors.CreateDataCollector(0)
19 | $SRV1Collector.FileName = "$Name_"
20 | $SRV1Collector.FileNameFormat = 1
21 | $SRV1Collector.FileNameFormatPattern = "\-MM\-dd"
22 | $SRV1Collector.SampleInterval = 15
23 | $SRV1Collector.LogFileFormat = 1 # Tab separated
24 | $SRV1Collector.LogAppend = $True
25 |
26 | # 2. Define counters of interest
27 | $Counters = @(
28 | '\Memory\Pages/sec',
29 | '\Memory\Available MBytes',
30 | '\Processor(_Total)\% Processor Time',
31 | '\PhysicalDisk(_Total)\% Disk Time',
32 | '\PhysicalDisk(_Total)\Disk Transfers/sec' ,
33 | '\PhysicalDisk(_Total)\Avg. Disk Sec/Read',
34 | '\PhysicalDisk(_Total)\Avg. Disk Sec/Write',
35 | '\PhysicalDisk(_Total)\Avg. Disk Queue Length'
36 | )
37 |
38 | # 3. Add the counters to the collector
39 | $SRV1Collector.PerformanceCounters = $Counters
40 |
41 | # 4. Create a schedule - start tomorrow morning at 07:00
42 | $StartDate = Get-Date -Day $((Get-Date).Day+1) -Hour 7 -Minute 0 -Second 0
43 | $Schedule = $SRV1CS.Schedules.CreateSchedule()
44 | $Schedule.Days = 127
45 | $Schedule.StartDate = $StartDate
46 | $Schedule.StartTime = $StartDate
47 |
48 | # 5. Create, add and start the collector set
49 | try
50 | {
51 | $SRV1CS.Schedules.Add($Schedule)
52 | $SRV1CS.DataCollectors.Add($SRV1Collector)
53 | $SRV1CS.Commit("$Name" , $null , 0x0003) | Out-Null
54 | $SRV1CS.Start($false);
55 | }
56 | catch [Exception]
57 | {
58 | Write-Host "Exception Caught: " $_.Exception -ForegroundColor Red
59 | return
60 | }
61 |
62 |
63 | pause
64 |
65 | # 6. Remove the counter
66 | $DCStRemote = New-Object -COM Pla.DataCollectorSet
67 | $Name = 'SRV1 Collector Set - tsv'
68 | $DCstRemote.Query($Name,'LocalHost')
69 | $DCstRemote.Stop($true)
70 | $DCstRemote.Delete()
71 |
72 | # 7 and start the counter too
73 | $DCStRemote = New-Object -COM Pla.DataCollectorSet
74 | $Name = 'SRV1 Collector Set'
75 | $DCstRemote.Query($Name,'LocalHost')
76 | $DCstRemote.Start($true)
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Recipe 12.6 - Create Azure VM.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12.6 - Create an Azure VM
2 | #
3 | # Run on CL1
4 |
5 | # 1. Define key variables
6 | $Locname = 'uksouth' # location name
7 | $RgName = 'packt_rg' # resource group name
8 | $SAName = 'packt42sa' # Storage account name
9 | $VNName = 'packtvnet' # Virtual Network Name
10 | $CloudSN = 'packtcloudsn' # Cloud subnet name
11 | $NSGName = 'packt_nsg' # NSG name
12 | $Ports = @(80, 3389) # ports to open in VBM
13 | $IPName = 'Packt_IP1' # Private IP Address name
14 | $User = 'AzureAdmin' # User Name
15 | $UserPS = 'JerryRocks42!' # User Password
16 | $VMName = 'Packt42VM' # VM Name
17 |
18 | # 2. Login to azure account
19 | $CredAZ = Get-Credential
20 | Login-AzAccount -Credential $CredAZ
21 |
22 | # 3. Ensure the resource group is created:
23 | $RG = Get-AzResourceGroup -Name $RgName -ErrorAction SilentlyContinue
24 | if (-not $rg) {
25 | $RGTag = @{Publisher = 'Packt'}
26 | $RGTag += @{Author = 'Thomas Lee'}
27 | $RGHT1 = @{
28 | Name = $RgName
29 | Location = $Locname
30 | Tag = $RGTag
31 | }
32 | $RG = New-AzResourceGroup @RGHT1
33 | Write-Host "RG $RgName created"
34 | }
35 |
36 | # 4. Ensure the Storage Account is created
37 | $SA = Get-AzStorageAccount -Name $SAName -ResourceGroupName $RgName -ErrorAction SilentlyContinue
38 | if (-not $SA) {
39 | $SATag = [Ordered] @{Publisher = 'Packt'}
40 | $SATag += @{Author = 'Thomas Lee'}
41 | $SAHT - @{
42 | Name = $SAName
43 | ResourceGroupName = $RgName
44 | Location = $Locname
45 | Tag = $SATag
46 | $SkuName = 'Standard_LRS'
47 | }
48 | $SA = New-AzStorageAccount @SAHT
49 | Write-Host "SA $SAName created"
50 | }
51 |
52 |
53 | # 5. Create VM credentials
54 | $T = 'System.Management.Automation.PSCredential'
55 | $P = ConvertTo-SecureString -String $UserPS -AsPlainText -Force
56 | $VMCred = New-Object -TypeName $T -ArgumentList $User, $P
57 |
58 | # 6. Create a simple VM using defaults
59 | $VMHT = @{
60 | ResourceGroupName = $RgName
61 | Location = $Locname
62 | Name = $VMName
63 | VirtualNetworkName = $VNName
64 | SubnetName = $CloudSN
65 | SecurityGroupName = $NSGName
66 | PublicIpAddressName = $IPName
67 | OpenPorts = $Ports
68 | Credential = $VMCred
69 | }
70 | New-AzVm @VMHT
71 |
72 |
73 |
74 | # 7. Get the VM's External IP address
75 | $VMIP = Get-AzPublicIpAddress -ResourceGroupName $RGname
76 | $VMIP = $VMIP.IpAddress
77 | "VM Public IP Address: [$VMIP]"
78 |
79 | # 8. Connect to the VM
80 | mstsc /v:"$VMIP"
81 |
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.1 - Explore perf counters with Get-Counter.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 13.1 - Using Get-Counter to get performance counters
2 | #
3 | # Run on SRV1
4 | # Uses DC1,DC2,HV1,HV2,SRV1,SRV2
5 |
6 | # 1. Discover performance counter sets on SRV1:
7 | $CounterSets = Get-Counter -ListSet *
8 | $CS1 = 'There are {0} counter sets on [{1}]'
9 | $CS1 -f $CounterSets.count,(hostname)
10 |
11 | # 2. Discover performance counter sets on remote systems
12 | $Machines = 'DC1','DC2','HV1','HV2','SRV1','SRV2'
13 | Foreach ($Machine in $Machines)
14 | {
15 | $RCounters = Get-Counter -ListSet * -ComputerName $Machine
16 | $CS2 = "There are {0} counters on [{1}]"
17 | $CS2 -f $RCounters.Count, $Machine
18 | }
19 |
20 | # 3 List key performance counter sets
21 | Get-Counter -ListSet Processor, Memory, Network*,*Disk |
22 | Sort-Object -Property CounterSetName |
23 | Format-Table -Property CounterSetName
24 |
25 | # 4. Get description of the memory counter set
26 | Get-Counter -ListSet Memory |
27 | Format-Table -Property Name, Description -Wrap
28 |
29 | # 5. Get and display counters in the memory counter set
30 | $CountersMem = (Get-Counter -ListSet Memory).Counter
31 | 'Memory counter set has [{0}] counters:' -f $countersMem.Count
32 | $CountersMem
33 |
34 | # 6. Get and display a sample from each counter in the memory counter set
35 | $Counters = (Get-Counter -ListSet Memory).counter
36 | $FS = '{0,-19} {1,-60} {2,-10}'
37 | $FS -f 'At', 'Counter', 'Value' # Display header row
38 | foreach ($Counter in $Counters)
39 | {
40 | $C = Get-Counter -Counter $Counter
41 | $T = $C.Timestamp # Time
42 | $N = $C.CounterSamples.Path.Trim() # Counter Name
43 | $V = $C.CounterSamples.CookedValue # Value
44 | '{0,-15} {1,-59} {2,-14}' -f $T, $N, $V
45 | }
46 |
47 | # 7. Explore Counter Set types for key perf counters
48 | Get-Counter -ListSet Processor, Memory, Network*, *Disk* |
49 | Select-Object -Property CounterSetName, CounterSetType
50 |
51 | # 8. Explore a local performance counter sample set
52 | $Counter1 = '\Memory\Page Faults/sec'
53 | $PFS = Get-Counter -Counter $Counter1
54 | $PFS
55 |
56 | # 9. Look at remote performance counter sample set on HV1:
57 | $Counter2 = '\\HV1\Memory\Page Faults/sec'
58 | $RPFS = Get-Counter -Counter $Counter1
59 | $RPFS
60 |
61 |
62 | # 10. Look inside a counter sample set
63 | $PFS | Get-Member -MemberType *Property |
64 | Format-Table -Wrap
65 |
66 | # 11. What is inside a local multi-value counter sample
67 | $Counter3 = '\Processor(*)\% Processor Time'
68 | $CPU = Get-Counter -Counter $Counter3
69 | $CPU
70 |
71 | # 12. Vew a multi-value counter sample on HV2
72 | $Counter4 = '\\hv2\Processor(*)\% Processor Time'
73 | $CPU = Get-Counter -Counter $Counter4
74 | $CPU
75 |
--------------------------------------------------------------------------------
/Chapter 03 - Deploying Active Directory/3.1 - Installing Active Directory with DNS.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 3.1 - Installing Active Directory with DNS
2 |
3 | # This recipe uses DC1 and DC2
4 | # The recipe starts on DC1, then uses DC2.
5 | # DC1 is initially a stand-alone work group server you convert
6 | # into a DC with DNS.
7 | # Then you convert DC2 (a domain joined server) to a DC and setup DNS there too.
8 |
9 |
10 | ### Part 1 - run on DC1
11 |
12 | # 1. Install the AD Domain Services feature and management tools
13 | Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
14 |
15 | # 2. Install DC1 as forest root server (DC1.Reskit.Org)
16 | $PSSHT = @{
17 | String = 'Pa$$w0rd'
18 | AsPlainText = $true
19 | Force = $true
20 | }
21 | $PSS = ConvertTo-SecureString @PSSHT
22 | $ADHT = @{
23 | DomainName = 'Reskit.Org'
24 | SafeModeAdministratorPassword = $PSS
25 | InstallDNS = $true
26 | DomainMode = 'WinThreshold'
27 | ForestMode = 'WinThreshold'
28 | Force = $true
29 | NoRebootOnCompletion = $true
30 | }
31 | Install-ADDSForest @ADHT
32 |
33 | # 3. Restart computer
34 | Restart-Computer -Force
35 |
36 | # 4. After reboot, log back into DC1 as Reskit\Administrator, then
37 | Get-ADRootDSE |
38 | Format-Table -Property dns*, *functionality
39 |
40 |
41 |
42 | ### Part 2 - run on DC2
43 | # Assumes DC1 is now a DC, DC2 is another workgroup server
44 |
45 | # 5. Check DC1 can be resolved, and
46 | # can be reached over 445 and 389 from DC2
47 | Resolve-DnsName -Name DC1.Reskit.Org -Type A
48 | Test-NetConnection -ComputerName DC1.Reskit.Org -Port 445
49 | Test-NetConnection -ComputerName DC1.Reskit.Org -Port 389
50 |
51 | # 6. Add the AD DS features on DC2
52 | $Features = 'AD-Domain-Services', 'DNS','RSAT-DHCP', 'Web-Mgmt-Tools'
53 | Install-WindowsFeature -Name $Features
54 |
55 | # 7. Promote DC2 to be a DC in the Reskit.Org domain
56 | $URK = "administrator@reskit.org"
57 | $PSS = ConvertTo-SecureString -String 'Pa$$w0rd' -AsPlainText -Force
58 | $CredRK = New-Object system.management.automation.PSCredential $URK,$PSS
59 | $IHT =@{
60 | DomainName = 'Reskit.org'
61 | SafeModeAdministratorPassword = $PSS
62 | SiteName = 'Default-First-Site-Name'
63 | NoRebootOnCompletion = $true
64 | Force = $true
65 | }
66 | Install-ADDSDomainController @IHT -Credential $CredRK
67 |
68 | # 8 Reboot DC2
69 | Restart-Computer -Force
70 |
71 | # 9. After reboot, logon to DC1 and view the forest
72 | Get-AdForest |
73 | Format-Table -Property *master*,globaL*,Domains
74 |
75 | # 10. View details of the domain
76 | Get-ADDomain |
77 | Format-Table -Property DNS*,PDC*,*master,Replica*
78 |
79 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.9 - Configuring VM and storage movement.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.9 - Configuring VM and storage movement
2 |
3 | # 1. View the PSDirect VM on HV1 and verify that it is turned off and not saved
4 | Get-VM -Name PSDirect -Computer HV1
5 |
6 | # 2. Get the VM configuration location
7 | (Get-VM -Name PSDirect).ConfigurationLocation
8 |
9 | # 3. Get Hard Drive locations
10 | Get-VMHardDiskDrive -VMName PSDirect |
11 | Format-Table -Property VMName, ControllerType, Path
12 |
13 | # 4. Move the VM's to the C\PSDirectNew folder:
14 | $MHT = @{
15 | Name = 'PSDirect'
16 | DestinationStoragePath = 'C:\PSDirectNew'
17 | }
18 | Move-VMStorage @MHT
19 |
20 | # 5. View the configuration details after moving the VM's storage:
21 | (Get-VM -Name PSDirect).ConfigurationLocation
22 | Get-VMHardDiskDrive -VMName PSDirect |
23 | Format-Table -Property VMName, ControllerType, Path
24 |
25 | # 6. Get the VM details for VMs from HV2:
26 | Get-VM -ComputerName HV2
27 |
28 | # 7. Enable VM migration from both HV1 and HV2:
29 | Enable-VMMigration -ComputerName HV1, HV2
30 |
31 | # 8. Configure VM Migration on both hosts:
32 | $SVHT = @{
33 | UseAnyNetworkForMigration = $true
34 | ComputerName = 'HV1', 'HV2'
35 | VirtualMachineMigrationAuthenticationType = 'Kerberos'
36 | VirtualMachineMigrationPerformanceOption = 'Compression'
37 | }
38 | Set-VMHost @SVHT
39 |
40 | # 9. Move the VM to HV2
41 | $Start = Get-Date
42 | $VMHT = @{
43 | Name = 'PSDirect'
44 | ComputerName = 'HV1'
45 | DestinationHost = 'HV2'
46 | IncludeStorage = $true
47 | DestinationStoragePath = 'C:\PSDirect' # on HV2
48 | }
49 | Move-VM @VMHT
50 | $Finish = Get-Date
51 | ($Finish - $Start)
52 |
53 | # 10. Display the time taken to migrate
54 | $OS = "Migration took: [{0:n2}] minutes"
55 | ($os -f ($($finish-$start).TotalMinutes))
56 |
57 | # 11. Check the VMs on HV1
58 | Get-VM -ComputerName HV2
59 |
60 | # 12. Check the VMs on HV2
61 | Get-VM -ComputerName HV2
62 |
63 | # 13. Look at the details of the moved VM
64 | ((Get-VM -Name PSDirect -Computer HV2).ConfigurationLocation)
65 | Get-VMHardDiskDrive -VMName PSDirect -Computer HV2 |
66 | Format-Table -Property VMName, Path
67 |
68 | ### Move it back (not for publication)
69 |
70 | # 14. Move the VM to HV1
71 | $Start = Get-Date
72 | $VMHT2 = @{
73 | Name = 'PSDirect'
74 | ComputerName = 'HV2'
75 | DestinationHost = 'HV1'
76 | IncludeStorage = $true
77 | DestinationStoragePath = 'C:\vm\vhds\PSDirect' # on HV1
78 | }
79 | Move-VM @VMHT2
80 | $Finish = Get-Date
81 | ($Finish - $Start)
82 |
83 | # 10. Display the time taken to migrate
84 | $OS = "Migration took: [{0:n2}] minutes"
85 | ($os -f ($($finish-$start).TotalMinutes))
86 |
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Recipe 12.7 - Create and Use VPN.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12-7 - Create and use Azure VPN
2 |
3 | # 1. Define Variables
4 | $Locname = 'uksouth' # location name
5 | $RgName = 'packt_rg' # resource group name
6 | $GWSubnetName = 'GatewaySubnet'
7 | $GWName = 'pactvpngw'
8 | $GWIPName = 'gwip'
9 | $NetworkName = 'PacktVnet'
10 | $GWIPName = 'gwip'
11 | $VPNClientAddressPool = "172.16.201.0/24"
12 |
13 | # 2. If necessary
14 | Login-AzureRmAccount
15 |
16 | # 3. Create a self signed root ca cert and a user cert
17 | $P2SRootCertFileName = 'C:\PacktCARootCert.cer'
18 | $P2SRootCertName = 'PacktRootCert'
19 | $Mc = 'C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\x64\makecert.exe'
20 | & $Mc -sky exchange -r -n "CN=PACKTCA" -pe -a sha1 -len 2048 -ss Root $P2SRootCertFileName
21 | & $Mc -n "CN=VPNUserCert" -pe -sky exchange -m 12 -ss My -in "PACKTCA" -is root -a sha1
22 | $Cert = New-Object -Typename System.Security.Cryptography.X509Certificates.X509Certificate2 `
23 | -ArgumentList $P2sRootCertName
24 | $CertBase64 = [system.convert]::ToBase64String($Cert.RawData)
25 | $P2SRootCert = New-AzureRmVpnClientRootCertificate -Name $P2SRootCertName -PublicCertData $CertBase64
26 |
27 | # 4. Create the RMGateway objects
28 | $Vnet = Get-AzureRmVirtualNetwork -Name $NetworkName -ResourceGroupName $RgName
29 | $Subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name $GWSubnetName -VirtualNetwork $Vnet
30 | $PIPHT = @{
31 | Name = $GWIPName
32 | ResourceGroupName = $RgName
33 | Location = $Locname
34 | AllocationMethod = 'Dynamic'
35 | Tag = "@{Owner = 'PACKT'; Type = 'IP'}"
36 | }
37 | $Pip2 = New-AzureRmPublicIpAddress -@$PIPHT
38 | $IPCHT = @{
39 | Name = $GWIPName
40 | Subnet = $subnet
41 | PublicIpAddress = $Pip2
42 | }
43 | $IpConf = New-AzureRmVirtualNetworkGatewayIpConfig @IPCHT
44 |
45 | # 5. Create the Gateway
46 | $Start = Get-Date
47 | New-AzureRmVirtualNetworkGateway -Name $GWName -ResourceGroupName $RgName `
48 | -Location $Locname -IpConfigurations $ipconf `
49 | -GatewayType Vpn -VpnType RouteBased `
50 | -EnableBgp $false -GatewaySku Standard `
51 | -VpnClientAddressPool $VPNClientAddressPool `
52 | -VpnClientRootCertificates $p2srootcert `
53 | -Tag @{Owner = 'PACKT'; Type = 'Gateway'}
54 | $Finish = Get-Date
55 | "Creating the gateway took $(($Finish-$Start).totalminutes) minutes"
56 |
57 |
58 | # 6. Get the VPN client package URL
59 | $URHT = @{
60 | ResourceGroupName = $RGName
61 | VirtualNetworkGatewayName = $GWName
62 | ProcessorArchitecture = 'Amd64'
63 | $Url = $Urls.Split('"')[1]
64 | }
65 | $Urls = Get-AzureRmVpnClientPackage @URHT
66 |
67 | # 7. Get the VPN Package
68 | $wc = New-Object System.Net.WebClient
69 | $wc.DownloadFile($URL, 'C:\PacktVPNClient.EXE')
70 | Get-ChildItem -path C:\PacktVPNClient.EXE
71 |
72 | # 8. Install VPN Package
73 | C:\PacktVPNClient.EXE
--------------------------------------------------------------------------------
/Chapter 06 - Deploying Windows Update/Recipe 6.1 - Installing WIndows Server Update Service.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 6.1 - Installing WIndows Server Update Services
2 | #
3 | # Run as administrator on WSUS1
4 |
5 |
6 | # 1. Install the Windows Update feature and tools
7 | $IFHT = @{
8 | Name = 'UpdateServices'
9 | IncludeManagementTools = $true
10 | }
11 | Install-WindowsFeature @IFHT
12 |
13 | # 2. Determine the features installed on WSUS1 server after installation of WSUW
14 | Get-WindowsFeature | Where-Object Installed
15 |
16 | # 3. Create a folder for WSUS update content
17 | $WSUSDir = 'C:\WSUS'
18 | If (-Not (Test-Path -Path $WSUSDir -ErrorAction SilentlyContinue))
19 | {New-Item -Path $WSUSDir -ItemType Directory | Out-Null}
20 |
21 | # 4. Perform post-installation configuration using WsusUtil.exe
22 | $CMD ="$env:ProgramFiles\" + "Update Services\Tools\WsusUtil.exe "
23 | & $CMD Postinstall CONTENT_DIR=$WSUSDir
24 |
25 | # 5. View the post installation log file
26 | $LOG = "$env:localappdata\temp\WSUS_Post*.log"
27 | Get-ChildItem -Path $LOG
28 |
29 | # 6. View some websites on this machine, noting the WSUS website
30 | Get-Website -Name ws* | Format-Table -AutoSize
31 |
32 | # 7. View the cmdlets in the UpdateServices module
33 | Get-Command -Module UpdateServices
34 |
35 | # 8. Inspect the TypeName and properties of the object
36 | # created with GetWsusServer
37 | $WSUSServer = Get-WsusServer
38 | $WSUSServer.GetType().Fullname
39 | $WSUSServer | Select-Object -Property *
40 |
41 | # 9. The object is of type UpdateServer in the
42 | # Microsoft.UpdateServices.Internal.BaseApi namespace, and
43 | # is the main object you use to manage WSUS from PowerShell.
44 | ($WSUSServer | Get-Member -MemberType Method).count
45 | $WSUSServer | Get-Member -MemberType Method
46 |
47 |
48 | # 10. View WSUS Configuration
49 | $WSUSServer.GetConfiguration() |
50 | Select-Object -Property SyncFromMicrosoftUpdate,LogFilePath
51 |
52 | # 11. Get product categories after initial install:
53 | $WSUSProducts = Get-WsusProduct -UpdateServer $WSUSServer
54 | $WSUSProducts.Count
55 | $WSUSProducts
56 |
57 | # 12. Display subscription information
58 | $WSUSSubscription = $WSUSServer.GetSubscription()
59 | $WSUSSubscription | Select-Object -Property * | Format-List
60 |
61 |
62 | # 13. Get the latest categories of products available from Microsoft Update
63 | # servers.
64 | $WSUSSubscription.StartSynchronization()
65 | Do {
66 | Write-Output $WSUSSubscription.GetSynchronizationProgress()
67 | Start-Sleep -Seconds 5
68 | }
69 | While ($WSUSSubscription.GetSynchronizationStatus() -ne
70 | 'NotProcessing')
71 |
72 | # 14. Once synchronization is complete, check the results of the synchronization:
73 | $WSUSSubscription.GetLastSynchronizationInfo()
74 |
75 | # 15.Review the categories of the products available after synchronzation:
76 | $WSUSProducts = Get-WsusProduct -UpdateServer $WSUSServer
77 | $WSUSProducts.Count
78 | $WSUSProducts
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Bonus Recipe 1 - Create a VM from existing VHD.ps1:
--------------------------------------------------------------------------------
1 | # create vm from vhdx
2 |
3 | # 1. Create variables
4 | $Locname = 'uksouth' # location name
5 | $RgName = 'packt_rg' # resource group we are using
6 | $SAName = 'packt42sa' # storage account name
7 | $CName = 'vhd' # a blob container
8 | $VHDName = 'server42.vhd' # vhd name
9 | $OP = 'd:\test\windows server 2016.vhdx'
10 | $LP = 'd:\test\ws2016.vhd' # local path to vhdx
11 |
12 | $Cred = Get-Credential thomas_lee@msn.com
13 | $Acct = Login-AzAccount -Credential $cred
14 |
15 | # 2. Convert vhdx to vhd
16 | $s = Get-Date
17 | Convert-VHD –Path $OP -DestinationPath $LP
18 | $e = Get-Date
19 | $e - $s
20 |
21 | # 3. upload
22 | $URL = "https://$SAName.blob.core.windows.net/$Cname/$vhdName"
23 | $s2 = get-date
24 | Add-AzVhd -ResourceGroupName $RgName -Destination $URL -LocalFilePath $LP
25 | $e2 = get-date
26 | $e2-$s2
27 |
28 |
29 | # 4. Create a managed image
30 | $IC = New-AzImageConfig -Location $Locname
31 | $IC = Set-AzImageOsDisk -Image $IC -OsType Windows -OsState Generalized -BlobUri $URL
32 | $Image = New-AzImage -ImageName $imageName -ResourceGroupName $RGName -Image $IC
33 |
34 | # 5, Create the networking resources
35 | $singleSubnet = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix 10.0.0.0/24
36 | $vnet = New-AzVirtualNetwork -Name $vnetName -ResourceGroupName $resourceGroup -Location $location `
37 | -AddressPrefix 10.0.0.0/16 -Subnet $singleSubnet
38 | $pip = New-AzPublicIpAddress -Name $ipName -ResourceGroupName $resourceGroup -Location $location `
39 | -AllocationMethod Dynamic
40 | $rdpRule = New-AzNetworkSecurityRuleConfig -Name $ruleName -Description 'Allow RDP' -Access Allow `
41 | -Protocol Tcp -Direction Inbound -Priority 110 -SourceAddressPrefix Internet -SourcePortRange * `
42 | -DestinationAddressPrefix * -DestinationPortRange 3389
43 | $nsg = New-AzNetworkSecurityGroup -ResourceGroupName $resourceGroup -Location $location `
44 | -Name $nsgName -SecurityRules $rdpRule
45 | $nic = New-AzNetworkInterface -Name $nicName -ResourceGroupName $resourceGroup -Location $location `
46 | -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id
47 | $vnet = Get-AzVirtualNetwork -ResourceGroupName $resourceGroup -Name $vnetName
48 |
49 | # Start building the VM configuration
50 | $vm = New-AzVMConfig -VMName $vmName -VMSize $vmSize
51 |
52 | # Set the VM image as source image for the new VM
53 | $vm = Set-AzVMSourceImage -VM $vm -Id $image.Id
54 |
55 | # Finish the VM configuration and add the NIC.
56 | $vm = Set-AzVMOSDisk -VM $vm -DiskSizeInGB $diskSizeGB -CreateOption FromImage -Caching ReadWrite
57 | $vm = Set-AzVMOperatingSystem -VM $vm -Windows -ComputerName $computerName -Credential $cred `
58 | -ProvisionVMAgent -EnableAutoUpdate
59 | $vm = Add-AzVMNetworkInterface -VM $vm -Id $nic.Id
60 |
61 | # Create the VM
62 | New-AzVM -VM $vm -ResourceGroupName $resourceGroup -Location $location
--------------------------------------------------------------------------------
/Chapter 05 - Managing Shared Data/Recipe 5.2 - Creating and securing SMB share.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 5.2 - Creating and securing SMB shares
2 | #
3 | # Run from FS1
4 |
5 | # 0 Just in case
6 | $EAHT = @{Erroraction='SilentlyContinue'}
7 | New-Item -Path c:\Foo -ItemType Directory @EAHT
8 |
9 | # 1. Discover existing shares and access rights
10 | Get-SmbShare -Name * |
11 | Get-SmbShareAccess |
12 | Format-Table -GroupBy Name
13 |
14 | # 2. Share a folder
15 | New-SmbShare -Name Foo -Path C:\Foo
16 |
17 | # 3. Update the share to have a description
18 | $CHT = @{Confirm=$False}
19 | Set-SmbShare -Name Foo -Description 'Foo share for IT' @CHT
20 |
21 | # 4. Set folder enumeration mode
22 | $CHT = @{Confirm = $false}
23 | Set-SMBShare -Name Foo -FolderEnumerationMode AccessBased @CHT
24 |
25 | # 5. Set encryption on for Foo share
26 | Set-SmbShare –Name Foo -EncryptData $true @CHT
27 |
28 | # 6. Remove all access to foo share
29 | $AHT1 = @{
30 | Name = 'foo'
31 | AccountName = 'Everyone'
32 | Confirm = $false
33 | }
34 | Revoke-SmbShareAccess @AHT1 | Out-Null
35 |
36 | # 7. Add reskit\administrators R/O
37 | $AHT2 = @{
38 | Name = 'foo'
39 | AccessRight = 'Read'
40 | AccountName = 'Reskit\ADMINISTRATOR'
41 | ConFirm = $false
42 | }
43 | Grant-SmbShareAccess @AHT2 | Out-Null
44 |
45 | # 8. Add system full access
46 | $AHT3 = @{
47 | Name = 'foo'
48 | AccessRight = 'Full'
49 | AccountName = 'NT Authority\SYSTEM'
50 | Confirm = $False
51 | }
52 | Grant-SmbShareAccess @AHT3 | Out-Null
53 |
54 | # 9. Set Creator/Owner to Full Access
55 | $AHT4 = @{
56 | Name = 'foo'
57 | AccessRight = 'Full'
58 | AccountName = 'CREATOR OWNER'
59 | Confirm = $False
60 | }
61 | Grant-SmbShareAccess @AHT4 | Out-Null
62 |
63 | # 10. Grant Saves Team read access, SalesAdmins has Full access
64 | $AHT5 = @{
65 | Name = 'Foo'
66 | AccessRight = 'Read'
67 | AccountName = 'Sales'
68 | Confirm = $false
69 | }
70 | Grant-SmbShareAccess @AHT5 | Out-Null
71 | $AHT6 = @{
72 | Name = 'Foo'
73 | AccessRight = 'Full'
74 | AccountName = 'SalesAdmins'
75 | Confirm = $false
76 | }
77 | Grant-SmbShareAccess @AHT6 | Out-Null
78 |
79 | # 11. Review share access
80 | Get-SmbShareAccess -Name Foo |
81 | Sort-Object AccessRight
82 |
83 | # 12. Set file ACL to be same as share acl
84 | Set-SmbPathAcl -ShareName 'Foo'
85 |
86 |
87 | # 13. Create a file in c:\foo
88 | 'foo' | Out-File -FilePath C:\Foo\Foo.Txt
89 |
90 |
91 | # 14. Set file ACL to be same as share acl
92 | Set-SmbPathAcl -ShareName 'Foo'
93 |
94 | # 15. View folder ACL using Get-NTFSAccess
95 | Get-NTFSAccess -Path C:\Foo |
96 | Format-Table -AutoSize
97 |
98 | # 16. View file ACL
99 | Get-NTFSAccess -Path C:\Foo\Foo.Txt |
100 | Format-Table -AutoSize
101 |
102 |
103 |
104 |
105 | # reset for testing
106 |
107 | <# reset the shares
108 | Get-smbshare foo | remove-smbshare -Confirm:$false
109 |
110 | #>
111 |
--------------------------------------------------------------------------------
/PowerShellCookBook2019/README (PACKT).md:
--------------------------------------------------------------------------------
1 | # Learn Windows Server 2019
2 |
3 | TO DO: Insert a photo of the book cover.
4 |
5 | ## Introduction
6 |
7 | This is the code repository for Administering Windows Server 2019 with PowerShell Cookbook, published by Packt.
8 | This repository is based on the [author's personal GitHub repository](https://github.com/doctordns/PowerShellCookBook2019).
9 |
10 | ** Write, deploy, and maintain your Server 2019 **
11 |
12 | ## What This Book is About
13 |
14 | ... intro
15 |
16 | This book covers the following:
17 |
18 | TODO: Add list of chapters
19 |
20 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1789134323) today!
21 |
22 | ## Instructions and Navigation
23 |
24 | All of the code is organized into folders.
25 | Each folder contains the recipes in a chapter of the book.
26 |
27 | The PowerShell code in each recipe looks like the following:
28 |
29 | ```powerShell
30 | $JG420 = Get-ADUser -Identity 'JerryGarcia'
31 | If ($JG420.enabled) {
32 | "User [$($JG402.SAMACCOUNTNAME)] is enabled
33 | }
34 | ```
35 |
36 | ## What do you need to follow this book
37 |
38 | As the practical examples involve the use of Windows Server 2019, Windows 10 and Azure, you need access to all of these.
39 | You can obtain the ISO images for WIndow 10 and Windows Server 2019 from the Internet.
40 | aYou can also get a free Azure subscription to test the Azure related recipes.
41 | The book also uses some third party software - details of where to find such tools is contained in the relevant chapter.
42 |
43 | With the following software and hardware list you can run all code files present in the book (Chapter 1-7).
44 |
45 | ### Software and Hardware List
46 |
47 | | Chapter | Software required | OS required |
48 | | -------- | ------------------------------------ | ----------------------------------- |
49 | | 1-7 | Any text editor, Visual Studio Code | Computer with Windows, Linux or macOS |
50 |
51 | We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it](https://www.packtpub.com/sites/default/files/downloads/LearnCloudFormation_ColorImages.pdf).
52 |
53 | ## Related Books
54 |
55 | This is a list of books you may find helpful in your PowerShell journey.
56 |
57 | 1. Month of lunches by Don Jones
58 |
59 | 2. PowerShell Cook Book by Lee Holmes
60 |
61 | ## Get to Know the Author
62 |
63 | **Thomas Lee** is a consultant, trainer and author.
64 | He has more than 50 years of experience in various software and hardware development projects for various companies across the globe.
65 |
66 | I'll say more about him in due course!
67 |
68 | He's a wonderful guy. Really!!
69 |
70 | ## Other book by the author
71 |
72 | * [title](https:/)
73 |
74 | ### Suggestions and Feedback
75 |
76 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSdy7dATC6QmEL81FIUuymZ0Wy9vH1jHkvpY57OiMeKGqib_Ow/viewform) if you have any feedback or suggestions.
77 |
78 | If you have issues with the specific recipes, file an issue at:
79 | [The recipe Git Hub Repository](https://github.com/doctordns/PowerShellCookBook2019/issues)
80 |
--------------------------------------------------------------------------------
/Chapter 06 - Deploying Windows Update/Recipe 6.2 - Configuring WSUS Update synchronization.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 3-2 - Configuring WUS update synchronization
2 |
3 | # 1. Locate the versions of WIndows Server supported by Windows Update
4 | Get-WsusProduct |
5 | Where-Object -FilterScript {$_.product.title -match
6 | '^Windows Server'}
7 |
8 | # 2. And get updat titles for Windows 10
9 | Get-WsusProduct -TitleIncludes 'Windows 10'
10 |
11 | # 3. Create and view a list of software product titles to include
12 | $CHP =
13 | (Get-WsusProduct |
14 | Where-Object -FilterScript {$_.product.title -match
15 | '^Windows Server'}).Product.Title
16 | $CHP += @('Microsoft SQL Server 2016','Windows 10')
17 | $CHP
18 |
19 |
20 | # 4. Assign the desired products to include in Windows Update:
21 | Get-WsusProduct |
22 | Where-Object {$PSItem.Product.Title -in $CHP} |
23 | Set-WsusProduct
24 |
25 | # 5. Updates are classified into distinct categories; a view which classifications of
26 | # updates are available:
27 | Get-WsusClassification
28 |
29 | # 6. Build a list of desired update classifications to make available on your WSUS
30 | # server and view the list:
31 | $CCL = @('Critical Updates',
32 | 'Definition Updates',
33 | 'Security Updates',
34 | 'Service Packs',
35 | 'Update Rollups',
36 | 'Updates')
37 |
38 | # 7. Set the list of desired update classifications in WSUS:
39 | Get-WsusClassification |
40 | Where-Object {$_.Classification.Title -in
41 | $CCL} |
42 | Set-WsusClassification
43 |
44 | # 8. Get Synchronization details
45 | $WSUSServer = Get-WsusServer
46 | $WSUSSubscription = $WSUSServer.GetSubscription()
47 |
48 |
49 |
50 | # 9. Start synchronizing available updates
51 | $WSUSSubscription.StartSynchronization()
52 |
53 | # 10 loop and wait for syncronization to complete
54 | $IntervalSeconds = 5
55 | $NP = 'NotProcessing'
56 | Do {
57 | $WSUSSubscription.GetSynchronizationProgress()
58 | Start-Sleep -Seconds $IntervalSeconds
59 | } While ($WSUSSubscription.GetSynchronizationStatus() -eq $NP)
60 |
61 |
62 | # 11. Synchronize the updates which can take a long while to compelete.
63 | $IntervalSeconds = 1
64 | $NP = 'NotProessing'
65 | # Wait for synchronizing to start
66 | Do {
67 | Write-Output $WSUSSubscription.GetSynchronizationProgress()
68 | Start-Sleep -Seconds $IntervalSeconds
69 | }
70 | While ($WSUSSubscription.GetSynchronizationStatus() -eq $NP)
71 | # Wait for all phases of process to end
72 | Do {
73 | Write-Output $WSUSSubscription.GetSynchronizationProgress()
74 | Start-Sleep -Seconds $IntervalSeconds
75 | }
76 | Until ($WSUSSubscription.GetSynchronizationStatus() -eq $NP)
77 |
78 | # 12. When the final loop is complete, check the results of the
79 | # synchronization:
80 | $WSUSSubscription.GetLastSynchronizationInfo()
81 |
82 | # 13. Configure automatic synchronization to run once per day:
83 | $WSUSSubscription = $WSUSServer.GetSubscription()
84 | $WSUSSubscription.SynchronizeAutomatically = $true
85 | $WSUSSubscription.NumberOfSynchronizationsPerDay = 1
86 | $WSUSSubscription.Save()
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.4 - Using VM Groups.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.4 - Using VM Groups
2 | #
3 | # Run on HV2
4 |
5 |
6 | # 0. Create VMs on HV2
7 | # Use the script: Create-HV2VMs.ps1
8 |
9 | # 1. Setup Hyper-V VM groups and display group
10 | $VHGHT1 = @{
11 | Name = 'SQLAccVMG'
12 | GroupType = 'VMCollectionType'
13 | }
14 | $VMGroupACC = New-VMGroup @VHGHT1
15 | $VHGHT2 = @{
16 | Name = 'SQLMfgVMG'
17 | GroupType = 'VMCollectionType'
18 | }
19 | $VMGroupMFG = New-VMGroup @VHGHT2
20 |
21 | # 2. Create arrays of group member VM Names
22 | $ACCVMs = 'SQLAcct1', 'SQLAcct2','SQLAcct3'
23 | $MFGVms = 'SQLMfg1', 'SQLMfg2'
24 |
25 | # 3. Add members to the Accounting SQL VMgroup
26 | Foreach ($Server in $ACCVMs) {
27 | $VM = Get-VM -Name $Server
28 | Add-VMGroupMember -Name SQLAccVMG -VM $VM
29 | }
30 |
31 | # 4. Add memvers to the Manufacturing SQL VM Group
32 | Foreach ($Server in $MfgVMs) {
33 | $VM = Get-VM -Name $Server
34 | Add-VMGroupMember -Name SQLMfgVMG -VM $VM
35 | }
36 |
37 | # 5 Create a management collection VMGroup
38 | $VMGHT = @{
39 | Name = 'VMMGSQL'
40 | GroupType = 'ManagementCollectionType'
41 | }
42 | $VMMGSQL = New-VMGroup @VMGHT
43 |
44 | # 6. Add the two VMCollectionType groups to the VMManagement group
45 | Add-VMGroupMember -Name VMMGSQL -VMGroupMember $VMGroupACC,
46 | $VMGroupMFG
47 |
48 | # 7. Set FormatEnumerationLimit to a higher value, then view the VMGroups
49 | $FormatEnumerationLimit = 99
50 | Get-VMGroup |
51 | Format-Table -Property Name, GroupType, VMGroupMembers,
52 | VMMembers
53 |
54 | # 8. Stop all the SQL VMs
55 | Foreach ($VM in ((Get-VMGroup VMMGSQL).VMGroupMembers.vmmembers)) {
56 | Stop-VM -Name $vm.name -WarningAction SilentlyContinue
57 | }
58 |
59 | # 9. Set CPU count in ALL SQL VMs to 4
60 | Foreach ($VM in ((Get-VMGroup VMMGSQL).VMGroupMembers.VMMembers)) {
61 | Set-VMProcessor -VMName $VM.name -Count 4
62 | }
63 |
64 | # 10. Set Accounting SQL VMs to have 6 processors
65 | Foreach ($VM in ((Get-VMGroup SQLAccVMG).VMMembers)) {
66 | Set-VMProcessor -VMName $VM.name -Count 6
67 | }
68 |
69 | # 11. Check Processor counts for all VMs sorted by CPU Count:
70 | $VMS = (Get-VMGroup -Name VMMGSQL).VMGroupMembers.VMMembers
71 | Get-VMProcessor -VMName $VMS.name |
72 | Sort-Object -Property Count -Descending |
73 | Format-Table -Property VMName, Count
74 |
75 | # 12. Remove VMs from VM Groups
76 | $VMs = (Get-VMGroup -Name SQLAccVMG).VMMEMBERS
77 | Foreach ($VM in $VMS) {
78 | $X = Get-VM -vmname $VM.name
79 | Remove-VMGroupMember -Name SQLAccVMG -VM $x
80 | }
81 | $VMs = (Get-VMGroup -Name SQLMFGVMG).VMMEMBERS
82 | Foreach ($VM in $VMS) {
83 | $X = Get-VM -vmname $VM.name
84 | Remove-VMGroupMember -Name SQLmfgvMG -VM $x
85 | }
86 |
87 | # 13. Remove VMGrouwps from VMManagementGroups
88 | $VMGS = (Get-VMGroup -Name VMMGSQL).VMMembers
89 | Foreach ($VMG in $VMGS) {
90 | $X = Get-VMGroup -vmname $VMG.name
91 | Remove-VMGroupMember -Name VMMGSQL -VMGroupName $x
92 | }
93 | # 14. Remove all the VMGroups
94 | Remove-VMGroup SQLACCVMG -force
95 | Remove-VMGroup SQLMFGVMG -force
96 | Remove-VMGroup VMMGSQL -Force
--------------------------------------------------------------------------------
/Chapter 13 - Monitoring Performance and Usage/Recipe 13.8 - Creating a Hyper-V Status Report.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11-12 Creating a Hyper-V Status Report
2 |
3 | # 1. Create a basic report object hash table
4 | $ReportHT = [Ordered] @{}
5 |
6 | # 2. Get the host details and add them to the Report object
7 | $HostDetails = Get-CimInstance -ClassName Win32_ComputerSystem
8 | $ReportHT.HostName = $HostDetails.Name
9 | $ReportHT.Maker = $HostDetails.Manufacturer
10 | $ReportHT.Model = $HostDetails.Model
11 |
12 | # 3. Add the PowerShell version information
13 | $ReportHT.PSVersion = $PSVersionTable.PSVersion.tostring()
14 | # Add OS information:
15 | $OS = Get-CimInstance -Class Win32_OperatingSystem
16 | $ReportHT.OSEdition = $OS.Caption
17 | $ReportHT.OSArch = $OS.OSArchitecture
18 | $ReportHT.OSLang = $OS.OSLanguage
19 | $ReportHT.LastBootTime = $os.LastBootUpTime
20 | $Now = Get-Date
21 | $UTD = [float] ("{0:n3}" -f (($Now -$OS.LastBootUpTime).Totaldays))
22 | $ReportHT.UpTimeDays = $UTD
23 |
24 | # 4. Add a count of processors in the host
25 | $PHT = @{
26 | ClassName = 'MSvm_Processor'
27 | Namespace = 'root/virtualization/v2'
28 | }
29 | $Proc = Get-CimInstance @PHT
30 | $ReportHT.CPUCount = ($Proc |
31 | Where-Object elementname -Match 'Logical Processor').COUNT
32 |
33 | # 5. Add the current host CPU usage
34 | $Cname = '\\.\processor(_total)\% processor time'
35 | $CPU = Get-Counter -Counter $Cname
36 | $ReportHT.HostCPUUsage = $CPU.CounterSamples.CookedValue
37 |
38 | # 6. Add the total host physical memory:
39 | $Memory = Get-Ciminstance -Class Win32_ComputerSystem
40 | $HostMemory = [float] ( "{0:n2}" -f ($Memory.TotalPhysicalMemory/1GB))
41 | $ReportHT.HostMemoryGB = $HostMemory
42 |
43 | # 7. Add the memory allocated to VMs:
44 | $Sum = 0
45 | Get-VM | Foreach-Object {$sum += $_.MemoryAssigned + $Total}
46 | $Sum = [float] ( "{0:N2}" -f ($Sum/1gb) )
47 | $ReportHT.AllocatedMemoryGB = $Sum
48 |
49 | # 8. Create the host report object:
50 | $Reportobj = New-Object -TypeName PSObject -Property $ReportHT
51 |
52 | # 9. Create report Header
53 | $Report = "Hyper-V Report for: $(hostname)`n"
54 | $Report += "At: [$(Get-Date)]"
55 |
56 |
57 | # 10 Add report object to report:
58 | $Report += $Reportobj | Out-String
59 |
60 | # 11. Get VM details on the local VM host and create a container array for individual
61 | # VM related objects:
62 | $VMs = Get-VM -Name *
63 | $VMHT = @()
64 |
65 | # 12. Get VM details for each VM into an object added to the hash table container:
66 | Foreach ($VM in $VMs) {
67 | # Create VM Report hash table
68 | $VMReport = [ordered] @{}
69 | # Add VM's Name
70 | $VMReport.VMName = $VM.VMName
71 | # Add Status
72 | $VMReport.Status = $VM.Status
73 | # Add Uptime
74 | $VMReport.Uptime = $VM.Uptime
75 | # Add VM CPU
76 | $VMReport.VMCPU = $VM.CPUProcessorCount
77 | # Replication Mode/Status
78 | $VMReport.ReplMode = $VM.ReplicationMode
79 | $VMReport.ReplState = $Vm.ReplicationState
80 |
81 | # Create object from Hash table, add to array
82 | $VMR = New-Object -TypeName PSObject -Property $VMReport
83 | $VMHT += $VMR
84 | }
85 |
86 | # 123 Finish creating the report
87 | $Report += $VMHT | Format-Table | Out-String
88 |
89 | # 13. Display the report:
90 | $Report
91 |
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Recipe 12.3 - Explore Storage Account.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12-3 Explore Azure Storage Account
2 |
3 | # Run from CL1
4 |
5 | # 1. Define key variables
6 | $Locname = 'uksouth' # location name
7 | $RgName = 'packt_rg' # resource group we are using
8 | $SAName = 'packt42sa' # storage account name
9 | $CName = 'packtcontainer' # a blob container name
10 | $CName2 = 'packtcontainer2' # a second blob container name
11 |
12 | # 2. Login to your Azure Account and ensure the RG and SA is created.
13 | $CredAz = Get-Credential
14 | $Account = Login-AzAccount -Credential $CredAz
15 |
16 | # 3. Ensure the RG and SA is created.
17 | $RGHT = @{
18 | Name = $RgName
19 | ErrorAction = 'SilentlyContinue'
20 | }
21 | $RG = Get-AzResourceGroup @RGHT
22 | if (-not $RG) {
23 | $RGTag = [Ordered] @{Publisher='Packt'}
24 | $RGTag += @{Author='Thomas Lee'}
25 | $RGHT2 = @{
26 | Name = $RgName
27 | Location = $Locname
28 | Tag = $RGTag
29 | }
30 | $RG = New-AzResourceGroup @RGHT2
31 | "RG $RgName created"
32 | }
33 | $SAHT = @{
34 | Name = $SAName
35 | ResourceGroupName = $RgName
36 | ErrorAction = 'SilentlyContinue'
37 | }
38 | $SA = Get-AzStorageAccount @SAHT
39 | if (-not $SA) {
40 | $SATag = [Ordered] @{Publisher = 'Packt'}
41 | $SATag += @{Author = 'Thomas Lee'}
42 | $SAHT = @{
43 | Name = $SAName
44 | ResourceGroupName = $RgName
45 | Location = $Locname
46 | Tag = $SATag
47 | SkuName = 'Standard_LRS'
48 | }
49 | $SA = New-AzStorageAccount @SAHT
50 | "SA $SAName created"
51 | }
52 |
53 | # 4. Get and display the storage account key
54 | $SAKHT = @{
55 | Name = $SAName
56 | ResourceGroupName = $RgName
57 | }
58 | $Sak = Get-AzStorageAccountKey @SAKHT
59 | $Sak
60 |
61 | # 5. Extract the first key's 'password'
62 | $Key = ($Sak | Select-Object -First 1).Value
63 |
64 | # 6. Get the Storage Account context which encapsulates credentials
65 | # for the storage account)
66 | $SCHT = @{
67 | StorageAccountName = $SAName
68 | StorageAccountKey = $Key
69 | }
70 | $SACon = New-AzStorageContext @SCHT
71 | $SACon
72 |
73 | # 7. Create 2 blob containers
74 | $CHT = @{
75 | Context = $SACon
76 | Permission = ‘Blob’
77 | }
78 | New-AzStorageContainer -Name $CName @CHT
79 | New-AzStorageContainer -Name $CName2 @CHT
80 |
81 | # 8. View blob containers
82 | Get-AzStorageContainer -Context $SACon |
83 | Select-Object -ExpandProperty CloudBlobContainer
84 |
85 |
86 | # 9. Create a blob
87 | 'This is a small Azure blob!!' | Out-File .\azurefile.txt
88 | $BHT = @{
89 | Context = $SACon
90 | File = '.\azurefile.txt'
91 | Container = $CName
92 | }
93 | $Blob = Set-AzStorageBlobContent @BHT
94 | $Blob
95 |
96 | # 10. Construct and display the blob name
97 | $BlobUrl = "$($Blob.Context.BlobEndPoint)$CName/$($Blob.name)"
98 | $BlobUrl
99 |
100 | # 11. view the URL via IE
101 | $IE = New-Object -ComObject InterNetExplorer.Application
102 | $IE.Navigate2($BlobUrl)
103 | $IE.Visible = $true
--------------------------------------------------------------------------------
/Chapter 01 - Establishing a PowerShell Administrative Environment/1.3 - Exploring PowerShellGet+PSGallery.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 1.3 - Exploring PowerShellGet
2 | # This recipe looks at what you can get with the tools in the PowerShellGet module
3 | # Run on CL1 and uses DC1, SRV1
4 | # Run as administrator
5 |
6 | # 0. Before you use this recipe, ensure the NuGet provider has been installed:
7 | Install-PackageProvider -Name NuGet -ForceBootstrap
8 |
9 |
10 | # 1. Review the commands available in the PowerShellGet module:
11 | Get-Command -Module PowerShellGet
12 |
13 |
14 | # 2. View the NuGet PackageProvider version:
15 | Get-PackageProvider -Name NuGet |
16 | Select-Object -Property Version
17 |
18 | # 3. View the current version of PowerShellGet
19 | Get-Module -Name PowerShellGet -ListAvailable
20 |
21 | # 4. Install PowerShellGet:
22 | Install-Module -Name PowerShellGet -Force
23 |
24 | # 5. Check the version of PowerShellGet:
25 | Get-Module -Name PowerShellGet -ListAvailable
26 |
27 | # 6. View the default PSGallery repository for PowerShellGet:
28 | Get-PSRepository
29 |
30 | # 7. Review the package providers in the PSGallery repository:
31 | Find-PackageProvider -Source PSGallery |
32 | Select-Object -Property Name, Summary |
33 | Format-Table -Wrap -autosize
34 |
35 | # 8. Use the Get-Command cmdlet to find Find-* cmdlets in PowerShellGet:
36 | Get-Command -Module PowerShellGet -Verb Find
37 |
38 | # 9. Request all the commands in the PowerShellGet module
39 | # and display the count:
40 | $Commands = Find-Command -Module PowerShellGet
41 | $CommandCount = $Commands.Count
42 |
43 | # 10. Request all the available modules in the PowerShell Gallery
44 | $Modules = Find-Module -Name *
45 | $ModuleCount=$Modules.Count
46 |
47 | # 11. Get DSC resources available in PSGallery
48 | $DSCResources = Find-DSCResource
49 | $DSCResourcesCount = $DSCResources.Count
50 |
51 | # 12. Get DSC resources available in PSGallery
52 | "$CommandCount commands available in PowerShellGet"
53 | "$ModuleCount Modules available in the PowerShell Gallery"
54 | "$DSCResourcesCount DSCResources available in PowerShell Gallery"
55 |
56 |
57 | # 13. Install the TreeSize module, as an example, or choose your own. As this is a
58 | # public repository, Windows does not trust it by default, so you must approve the
59 | # installation:
60 | Install-Module -Name TreeSize -Force
61 |
62 | # 14. Review and test the commands in the module:
63 | Get-Command -Module TreeSize
64 | Get-TreeSize -Path C:\Windows\System32\Drivers -Depth 1
65 |
66 | # 15. Remove the module:
67 | Uninstall-Module -Name TreeSize
68 |
69 | # 16. Create a download folder:
70 | $NIHT = @{
71 | ItemType = 'Directory'
72 | Path = "$env:HOMEDRIVE\DownloadedModules"
73 | }
74 | New-Item @NIHT | Out-Null
75 |
76 | # 17. Download the module and save it to the folder
77 | $Path = "$env:HOMEDRIVE\DownloadedModules"
78 | Save-Module -Name TreeSize -Path $Path
79 | Get-ChildItem -Path $Path -Recurse | format-Table Fullname
80 |
81 | # 18. Import the treesize module:
82 | $ModuleFolder = "$env:HOMEDRIVE\downloadedModules\TreeSize"
83 | Get-ChildItem -Path $ModuleFolder -Filter *.psm1 -Recurse |
84 | Select-Object -ExpandProperty FullName -First 1 |
85 | Import-Module -Verbose
86 |
--------------------------------------------------------------------------------
/Chapter 10 - Implementing Desired State Configuration/Recipe 10.1 -Using DSC and built-in resources.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 10.1 - Using DSC and built-in resources
2 | #
3 | # Run on SRV1
4 |
5 | # 0. Create initial documents for Reskit application
6 | # Also share the application on DC1
7 | # create folders/share
8 | $SB = {
9 | New-Item C:\ReskitApp -ItemType Directory
10 | New-SMBShare -Name ReskitApp -Path C:\ReskitApp
11 | }
12 | Invoke-Command -ComputerName DC1 -ScriptBlock $SB |
13 | Out-Null
14 | # create index.htm
15 | $HP = '\\dc1.reskit.org\c$\reskitapp\Index.htm'
16 | $Index = @"
17 |
18 |
19 | Main Page - ReskitApp Application
20 |
21 | HOME PAGE FOR RESKITAPP APPLICATION
22 | This is the root page of the RESKITAPP application
23 |
24 | Pushed via DSC
25 |
26 | Click to View Page 2
27 |
28 |
29 | "@
30 | $Index |
31 | Out-File -FilePath $HP -Force
32 | # create page2.htm
33 | $P2 = '\\DC1.Reskit.Org\C$\Reskitapp\Page2.htm'
34 | $Page2 = @"
35 |
36 |
37 | ReskitApp Application - Page 2
38 |
39 | Page 2 For the ReskitApp Web Application
40 |
41 | Click to Go Home
42 |
43 | "@
44 | $Page2 |
45 | Out-File -FilePath $P2 -Force
46 |
47 | #### Recipe begins here
48 |
49 | # 1. Discover DSC resources on SRV1
50 | Get-DscResource |
51 | Format-Table -Property Name, ModuleName, Version
52 |
53 | # 2. Look at File Resource
54 | Get-DscResource -Name File |
55 | Format-List -Property *
56 |
57 | # 3 Get DSC Resource Syntax
58 | Get-DscResource -Name File -Syntax
59 |
60 | # 4. Create/compile a configuration block
61 | Configuration PrepareSRV2 {
62 | Import-DscResource –ModuleName 'PSDesiredStateConfiguration'
63 | Node SRV2
64 | {
65 | File BaseFiles
66 | {
67 | DestinationPath = 'C:\ReskitApp\'
68 | SourcePath = '\\DC1\ReskitApp\'
69 | MatchSource = $true
70 | Ensure = 'Present'
71 | Recurse = $True
72 | }
73 | }
74 | }
75 |
76 | # 5. View configuration function
77 | Get-Item -Path Function:\PrepareSRV2
78 |
79 | # 6. Create output folder for DSC
80 | $Conf = {
81 | $EASC = @{ErrorAction = 'SilentlyContinue'}
82 | New-Item -Path C:\ReskitApp -ItemType Directory @EASC
83 | }
84 | Invoke-command -ComputerName SRV2 -ScriptBlock $Conf |
85 | Out-Null
86 |
87 | # 7. Run function to produce MOF file
88 | PrepareSRV2 -OutputPath C:\DSC
89 |
90 | # 8. View MOF File
91 | Get-Content -Path C:\DSC\SRV2.mof
92 |
93 | # 9. Make it so Mr Riker
94 | Start-DscConfiguration -Path C:\DSC -Wait -Verbose
95 |
96 | # 10. Observe results
97 | Get-ChildItem -Path '\\SRV2\C$\ReskitApp'
98 |
99 | # 11. Induce configuration drift:
100 | Remove-Item -Path \\SRV2\C$\ReskitApp\Index.htm
101 |
102 | # 12. Fix configuration drift
103 | Start-DscConfiguration -Path C:\DSC\ -Wait -Verbose
104 |
105 | # 13. What happens if NO config drift?
106 | Start-DscConfiguration -Path C:\DSC\ -Wait -Verbose
--------------------------------------------------------------------------------
/Chapter 09 - Managing Windows Internet Information Server/Recipe 9.9 - Managing and monitoring NLB.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 9.9 - Managing and monitoring network load balancing
2 | #
3 | # Uses NLB1, 2 - run on NLB1
4 | # end of recipe uses DC1
5 |
6 |
7 | # 1. Install web-server (and .NET 3.5) feature NLB1, NLB2:
8 | $IHT1 = @{
9 | Name = 'Web-Server'
10 | IncludeManagementTools = $True
11 | IncludeAllSubFeature = $True
12 | Source = 'D:\sources\sxs'
13 | }
14 | Install-WindowsFeature @IHT1 -ComputerName NLB1
15 | Install-WindowsFeature @IHT1 -ComputerName NLB2
16 |
17 |
18 | # 2. And add NLB to NLB1, NLB2
19 | $IHT2 = @{
20 | Name = 'NLB'
21 | IncludeManagementTools = $True
22 | IncludeAllSubFeature = $True
23 | }
24 | Install-WindowsFeature @IHT -ComputerName NLB1 | Out-Null
25 | Install-WindowsFeature @IHT -ComputerName NLB2 | Out-Null
26 |
27 |
28 | # 3. Confirm NLB and Web-Server feats are loaded on both systems:
29 | $SB = {
30 | Get-WindowsFeature Web-Server, NLB
31 | }
32 | Invoke-Command -ScriptBlock $SB -ComputerName NLB1, NLB2 |
33 | Format-table -Property DisplayName,PSComputername,Installstate
34 |
35 | # 4. Create the NLB cluster, initially on NLB1:
36 | $NLBHT1 = @{
37 | InterFaceName = 'Ethernet'
38 | ClusterName = 'ReskitNLB'
39 | ClusterPrimaryIP = '10.10.10.55'
40 | SubnetMask = '255.255.255.0'
41 | OperationMode = 'Multicast'
42 | }
43 | New-NlbCluster @NLBHT1
44 |
45 | # 5. Add NLB2 to the ReskitNLB cluster:
46 | $NLBHT2 = @{
47 | NewNodeName = 'NLB2.Reskit.Org'
48 | NewNodeInterface = 'Ethernet'
49 | InterfaceName = 'Ethernet'
50 | }
51 | Add-NlbClusterNode @NLBHT2
52 |
53 | # 6. Create a network firewall rule:
54 | $SB = {
55 | $NFTHT =@{
56 | DisplayGroup = 'File and Printer Sharing'
57 | Enabled = 'True'
58 | }
59 | Set-NetFirewallRule @NFTHT
60 | }
61 | Invoke-Command -ScriptBlock $SB -ComputerName NLB1
62 | Invoke-Command -ScriptBlock $SB -ComputerName NLB2
63 |
64 |
65 | # 7. Create a default document—differently on each machine:
66 | 'NLB Cluster: Hosted on NLB1' |
67 | Out-File -FilePath C:\inetpub\wwwroot\index.html
68 | 'NLB Cluster: Greetings from NLB2' |
69 | Out-File -FilePath \\nlb2\c$\inetpub\wwwroot\index.html
70 |
71 | # 8. check VIP
72 | Get-NlbClusterVip
73 |
74 | # 9. Add a DNS A record for the cluster:
75 | $SB = {
76 | $NAHT = @{
77 | Name = 'ReskitNLB'
78 | IPv4Address = '10.10.10.55'
79 | ZoneName = 'Reskit.Org'
80 | }
81 | Add-DnsServerResourceRecordA @NAHT
82 | }
83 | Invoke-Command -ComputerName DC1 -ScriptBlock $SB
84 |
85 | # DO REMAINDER OF THIS RECIPE FROM DC1
86 |
87 | # 10. view the cluster node details From DC1
88 | Get-NlbClusterNode -HostName NLB1.Reskit.Org
89 |
90 | # 11. View the NLB site from DC1
91 | Start-Process 'HTTP://ReskitNLB.Reskit.Org'
92 |
93 | # 12. Stop one node (the one that responded in step 10):
94 | Stop-NlbClusterNode -HostName NLB1
95 | Clear-DnsClientCache
96 |
97 | # 13. view the cluster node details from NLB1
98 | Get-NlbClusterNode -HostName NLB1
99 |
100 | # 14. Then view the site again (from DC1):
101 | Start-Process 'HTTP://ReskitNLB.Reskit.Org'
102 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.10 - Configuring VM replication.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.10 - Configuring VM replication
2 |
3 | # 1. Configure HV1 and HV2 to be trusted for delegation in AD on DC1
4 | $Sb1 = {
5 | Set-ADComputer -Identity HV1 -TrustedForDelegation $True
6 | }
7 | Invoke-Command -ComputerName DC1 -ScriptBlock $Sb1
8 | $Sb2 = {
9 | Set-ADComputer -Identity HV2 -TrustedForDelegation $True}
10 | Invoke-Command -ComputerName DC1 -ScriptBlock $Sb2
11 |
12 |
13 | # 2. Reboot the HV1 and HV2:
14 | Restart-Computer -ComputerName HV1 -Force
15 | Restart-Computer -ComputerName HV2 -Force
16 |
17 | # 3. Once both systems are restarted, logon back to HV2,
18 | # set up both servers as a replication server
19 | $VMRHT = @{
20 | ReplicationEnabled = $true
21 | AllowedAuthenticationType = 'Kerberos'
22 | KerberosAuthenticationPort = 42000
23 | DefaultStorageLocation = 'C:\Replicas'
24 | ReplicationAllowedFromAnyServer = $true
25 | ComputerName = 'HV1', 'HV2'
26 | }
27 | Set-VMReplicationServer @VMRHT
28 |
29 | # 4. Enable PSDirect on HV2 to be a replica source
30 | $VMRHT = @{
31 | VMName = 'PSDirect'
32 | Computer = 'HV2'
33 | ReplicaServerName = 'HV1'
34 | ReplicaServerPort = 42000
35 | AuthenticationType = 'Kerberos'
36 | CompressionEnabled = $true
37 | RecoveryHistory = 5
38 | }
39 | Enable-VMReplication @VMRHT
40 |
41 | # 5. View the replication status of HV2
42 | Get-VMReplicationServer -ComputerName HV2
43 |
44 | # 6. Check PSDIrect on HV2:
45 | Get-VM -ComputerName HV2 -VMName PSDirect
46 |
47 | # 7. Start the initial replication
48 | Start-VMInitialReplication -VMName PSDirect -ComputerName HV2
49 |
50 | # 8. Examine the initial replication state on HV1 just after
51 | # you start the initial replication
52 | Measure-VMReplication -ComputerName HV2
53 |
54 | # 9. Wait for replication to finish, then examine the
55 | # replication status on HV1
56 | Measure-VMReplication -ComputerName HV2
57 |
58 | # 10. Test PSDirect failover to HV1
59 | $SB = {
60 | $VM = Start-VMFailover -AsTest -VMName PSDirect -Confirm:$false
61 | Start-VM $VM
62 | }
63 | Invoke-Command -ComputerName HV1 -ScriptBlock $SB
64 |
65 | # 11. View the status of VMs on HV2:
66 | Get-VM -ComputerName HV1
67 |
68 | # 12. Stop the failover test
69 | $SB = {
70 | Stop-VMFailover -VMName PSDirect
71 | }
72 | Invoke-Command -ComputerName HV1 -ScriptBlock $SB
73 |
74 | # 13. View the status of VMs on HV1 and HV2 after failover stopped
75 | Get-VM -ComputerName HV1
76 |
77 | Get-VM -ComputerName HV2
78 |
79 | # 14. Stop VM1 on HV2 prior to performing a planned failover
80 | Stop-VM PSDirect -ComputerName HV2
81 |
82 | # 15. Start VM failover from H1
83 | Start-VMFailover -VMName PSDirect -ComputerName HV1 -Confirm:$false
84 |
85 | #16. Complete the failover
86 | $CHT = @{
87 | VMName = 'PSDIrect'
88 | ComputerName = 'HV1'
89 | Confirm = $false
90 | }
91 | Complete-VMFailover @CHT
92 |
93 | # 17. Start the replicated VM on HV1
94 | Start-VM -VMname PSDirect -ComputerName HV1
95 |
96 | # 18. See VMs on HV1 and HV2 after the planned failover
97 | Get-VM -ComputerName HV1
98 | Get-VM -ComputerName HV2
99 |
100 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.11 - Managing VM Checkpoints.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11-10 - Managing VM Checkpoints
2 |
3 | # 1. Create credentials for PSDirect
4 | $RKAn = 'Wolf\Administrator'
5 | $PS = 'Pa$$w0rd'
6 | $RKP = ConvertTo-SecureString -String $PS -AsPlainText -Force
7 | $T = 'System.Management.Automation.PSCredential'
8 | $RKCred = New-Object -TypeName $T -ArgumentList $RKAn,$RKP
9 |
10 | # 2. Look at C: in PSDirect before we start
11 | $SB = { Get-ChildItem -Path C:\ }
12 | $ICHT = @{
13 | VMName = 'PSDirect'
14 | ScriptBlock = $SB
15 | Credential = $RKCred
16 | }
17 | Invoke-Command @ICHT
18 |
19 | # 3. Create a snapshot of PSDirect1 on HV1:
20 | $CPHT = @{
21 | VMName = 'PSDirect'
22 | ComputerName = 'HV1'
23 | SnapshotName = 'Snapshot1'
24 | }
25 | Checkpoint-VM @CPHT
26 |
27 | # 4. Look at the files created to support the checkpoints
28 | $Parent = Split-Path -Parent (Get-VM -Name PSdirect |
29 | Select-Object -ExpandProperty HardDrives).Path |
30 | Select -First 1
31 | Get-ChildItem -Path $Parent
32 |
33 | # 5. Create some content in a file on PSDIrect and display it
34 | $SB = {
35 | $FileName1 = 'C:\File_After_Checkpoint_1'
36 | Get-Date | Out-File -FilePath $FileName1
37 | Get-Content -Path $FileName1
38 | }
39 | $ICHT = @{
40 | VMName = 'PSDirect'
41 | ScriptBlock = $SB
42 | Credential = $RKCred
43 | }
44 | Invoke-Command @ICHT
45 |
46 | # 6. Take a second checkpoint
47 | $SNHT = @{
48 | VMName = 'PSDirect'
49 | ComputerName = 'HV1'
50 | SnapshotName = 'Snapshot2'
51 | }
52 | Checkpoint-VM @SNHT
53 |
54 | # 7. Get the VM checkpoint details for PSDirect
55 | Get-VMSnapshot -VMName PSDirect
56 |
57 | # 8. Look at the files supporting the two checkpoints
58 | Get-ChildItem -Path $Parent
59 |
60 | # 9. Create and display another file in PSdirect (ie after you have taken Snapshot2)
61 | $SB = {
62 | $FileName2 = 'C:\File_After_Checkpoint_2'
63 | Get-Date | Out-File -FilePath $FileName2
64 | Get-ChildItem -Path C:\ -File
65 | }
66 | $ICHT = @{
67 | VMName = 'PSDirect'
68 | ScriptBlock = $SB
69 | Credential = $RKCred
70 |
71 | }
72 | Invoke-Command @ICHT
73 |
74 | # 10. Restore VM1 back to the checkpoint named Snapshot1
75 | $Snap1 = Get-VMSnapshot -VMName PSDirect -Name Snapshot1
76 | Restore-VMSnapshot -VMSnapshot $Snap1 -Confirm:$false
77 | Start-VM -Name PSDirect
78 | Wait-VM -For IPAddress -Name PSDirect
79 |
80 | # 11. See what files we have now on PSDirect
81 | $SB = {
82 | Get-ChildItem -Path C:\
83 | }
84 | $ICHT = @{
85 | VMName = 'PSDirect'
86 | ScriptBlock = $SB
87 | Credential = $RKCred
88 | }
89 | Invoke-Command @ICHT
90 |
91 | # 12. Roll forward to Snapshot2
92 | $Snap2 = Get-VMSnapshot -VMName PSdirect -Name Snapshot2
93 | Restore-VMSnapshot -VMSnapshot $Snap2 -Confirm:$false
94 | Start-VM -Name PSDirect
95 | Wait-VM -For IPAddress -Name PSDirect
96 |
97 | # 13. Observe the files you now have on VM2
98 | $SB = {
99 | Get-ChildItem -Path C:\
100 | }
101 | $ICHT = @{
102 | VMName = 'PSDirect'
103 | ScriptBlock = $SB
104 | Credential = $RKCred
105 | }
106 | Invoke-Command @ICHT
107 |
108 | # 14. Restore to Snapshot1 again:
109 | $Snap1 = Get-VMSnapshot -VMName PSDirect -Name Snapshot1
110 | Restore-VMSnapshot -VMSnapshot $Snap1 -Confirm:$false
111 | Start-VM -Name PSDirect
112 | Wait-VM -For IPAddress -Name PSDirect
113 |
114 | # 15. Check snapshots and VM data files again:
115 | Get-VMSnapshot -VMName PSDirect
116 | Get-ChildItem -Path $Parent
117 |
118 | # 16. Remove all the snapshots from HV1:
119 | Get-VMSnapshot -VMName PSDirect |
120 | Remove-VMSnapshot
121 |
122 | # 17. Check VM data files again:
123 | Get-ChildItem -Path $Parent
--------------------------------------------------------------------------------
/Chapter 05 - Managing Shared Data/Recipe 5.6 - Configuring a DFS Namespace.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 5.6 - Configuring a DFS Namespace
2 | #
3 | # Run on CL1
4 |
5 |
6 | # 1. Add DFSN Rsat Tools to CL1
7 | Get-WindowsCapability -Online -Name *FileServices.Tools* |
8 | Add-WindowsCapability -Online |
9 | Out-Null
10 |
11 | # 2. Install DFS Namespace, DFS Replication, and the related management tools:
12 | $IHT = @{
13 | Name = 'FS-DFS-Namespace'
14 | IncludeManagementTools = $True
15 | }
16 | Install-WindowsFeature @IHT -ComputerName SRV1
17 | Install-WindowsFeature @IHT -ComputerName SRV2
18 |
19 | # 3. View the DFSN module and the DFSN cmdlets:
20 | Get-Module -Name DFSN -ListAvailable
21 |
22 | # 4. Create folders and shares for DFS Root:
23 | $SB = {
24 | New-Item -Path C:\ShareData -ItemType Directory -Force |
25 | Out-Null
26 | New-SmbShare -Name ShareData -Path C:\ShareData -FullAccess Everyone
27 | }
28 | Invoke-Command -ComputerName SRV1, SRV2 -ScriptBlock $SB |
29 | Out-Null
30 |
31 | # 5. Create DFS Namespace Root pointing to ShareData:
32 | $NSHT = @{
33 | Path = '\\Reskit.Org\ShareData'
34 | TargetPath = '\\SRV1\ShareData'
35 | Type = 'DomainV2'
36 | Description = 'Reskit Shared Data DFS Root'
37 | }
38 | New-DfsnRoot @NSHT
39 |
40 | # 6. Add a second target and view results:
41 | $NSHT2 = @{
42 | Path = '\\Reskit.Org\ShareData'
43 | TargetPath = '\\Srv2\ShareData'
44 | }
45 | New-DfsnRootTarget @NSHT2 | Out-Null
46 | Get-DfsnRootTarget -Path \\Reskit.Org\ShareData
47 |
48 | # 7. Create IT Data shares and populate:
49 | # FS1 folders/shares
50 | $SB = {
51 | New-Item -Path C:\IT2 -ItemType Directory | Out-Null
52 | New-SmbShare -Name 'ITData' -Path C:\IT2 -FullAccess Everyone
53 | # Add content to files in root
54 | 'Root' | Out-File -FilePath C:\IT2\Root.Txt
55 | }
56 | Invoke-Command -ScriptBlock $SB -Computer FS1 | Out-Null
57 | # FS2 folders/shares
58 | $SB = {
59 | New-Item -Path C:\IT2 -ItemType Directory | Out-Null
60 | New-SmbShare -Name 'ITData' -Path C:\IT2 -FullAccess Everyone
61 | 'Root' | Out-File -FilePath c:\IT2\Root.Txt
62 | }
63 | Invoke-Command -ScriptBlock $SB -Computer FS2 | Out-Null
64 | # DC1 folders/shares
65 | $SB = {
66 | #New-Item -Path C:\ITM -ItemType Directory | Out-Null
67 | New-SmbShare -Name 'ITM' -Path C:\ITM -FullAccess Everyone
68 | 'Root' | Out-File -Filepath C:\ITM\Root.Txt
69 | }
70 | Invoke-Command -ScriptBlock $SB -Computer DC1 | Out-Null
71 | # DC2 folders/shares
72 | $SB = {
73 | New-Item C:\ITM -ItemType Directory | Out-Null
74 | New-SmbShare -Name 'ITM' -Path C:\ITM -FullAccess Everyone
75 | 'Root' | Out-File -FilePath c:\ITM\Root.Txt
76 | }
77 | Invoke-Command -ScriptBlock $SB -Computer DC2
78 |
79 | # 8. Create DFS Namespace and set DFS targets
80 | $NSHT1 = @{
81 | Path = '\\Reskit\ShareData\IT\ITData'
82 | TargetPath = '\\FS1\ITData'
83 | EnableTargetFailback = $true
84 | Description = 'IT Data'
85 | }
86 | New-DfsnFolder @NSHT1 | Out-Null
87 |
88 | $NSHT2 = @{
89 | Path = '\\Reskit\ShareData\IT\ITData'
90 | TargetPath = '\\FS2\ITData'
91 | }
92 | New-DfsnFolderTarget @NSHT2 | Out-Null
93 |
94 | $NSHT3 = @{
95 | Path = '\\Reskit\ShareData\IT\ITManagement'
96 | TargetPath = '\\DC1\ITM'
97 | EnableTargetFailback = $true
98 | Description = 'IT Management Data'
99 | }
100 | New-DfsnFolder @NSHT3 | Out-Null
101 |
102 | $NSHT4 = @{
103 | Path = '\\Reskit\ShareData\IT\ITManagement'
104 | TargetPath = '\\DC2\ITM'
105 | }
106 | New-DfsnFolderTarget @NSHT4 | Out-Null
107 |
108 | # 9. View the hierarchy
109 | Get-ChildItem -Path \\Reskit.Org\ShareData\IT -Recurse
110 |
111 |
--------------------------------------------------------------------------------
/Chapter 11 - Managing Hyper-V/Recipe 11.12 - Creating a Hyper-V Status Report.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 11.2 Creating a Hyper-V Status Report
2 |
3 | # 1. Create a basic report object hash table
4 | $ReportHT = [Ordered] @{}
5 |
6 | # 2. Get the host details and add them to the Report object
7 | $HostDetails = Get-CimInstance -ClassName Win32_ComputerSystem
8 | $ReportHT.HostName = $HostDetails.Name
9 | $ReportHT.Maker = $HostDetails.Manufacturer
10 | $ReportHT.Model = $HostDetails.Model
11 |
12 | # 3. Add the PowerShell version information
13 | $ReportHT.PSVersion = $PSVersionTable.PSVersion.tostring()
14 | # Add OS information:
15 | $OS = Get-CimInstance -Class Win32_OperatingSystem
16 | $ReportHT.OSEdition = $OS.Caption
17 | $ReportHT.OSArch = $OS.OSArchitecture
18 | $ReportHT.OSLang = $OS.OSLanguage
19 | $ReportHT.LastBootTime = $os.LastBootUpTime
20 | $Now = Get-Date
21 | $UTD = [float] ("{0:n3}" -f (($Now -$OS.LastBootUpTime).Totaldays))
22 | $ReportHT.UpTimeDays = $UTD
23 |
24 | # 4. Add a count of processors in the host
25 | $PHT = @{
26 | ClassName = 'MSvm_Processor'
27 | Namespace = 'root/virtualization/v2'
28 | }
29 | $Proc = Get-CimInstance @PHT
30 | $ReportHT.CPUCount = ($Proc |
31 | Where-Object elementname -match 'Logical Processor').COUNT
32 |
33 | # 5. Add the current host CPU usage
34 | $Cname = '\\.\processor(_total)\% processor time'
35 | $CPU = Get-Counter -Counter $Cname
36 | $ReportHT.HostCPUUsage = $CPU.CounterSamples.CookedValue
37 |
38 | # 6. Add the total host physical memory:
39 | $Memory = Get-Ciminstance -Class Win32_ComputerSystem
40 | $HostMemory = [float] ( "{0:n2}" -f ($Memory.TotalPhysicalMemory/1GB))
41 | $ReportHT.HostMemoryGB = $HostMemory
42 |
43 | # 7. Add the memory allocated to VMs:
44 | $Sum = 0
45 | Get-VM | Foreach-Object {$sum += $_.MemoryAssigned + $Total}
46 | $Sum = [float] ( "{0:N2}" -f ($Sum/1gb) )
47 | $ReportHT.AllocatedMemoryGB = $Sum
48 |
49 | # 8. Create and view the host report object:
50 | $Reportobj = New-Object -TypeName PSObject -Property $ReportHT
51 | $ReportBase = $Reportobj | Out-String
52 |
53 | # 9. Create some New VMs:
54 | New-VM -VMName SQL1 | Out-Null
55 | New-VM -VMName SQL2 | Out-Null
56 | New-VM -VMName OM1 | Out-Null
57 |
58 | # 10. Get VM details on the local VM host and create a container array for individual
59 | # VM related objects:
60 | $VMs = Get-VM -Name *
61 | $VMHT = @()
62 |
63 | # 11. Get VM details for each VM into an object added to the hash table container:
64 | Foreach ($VM in $VMs) {
65 | # Create VM Report hash table
66 | $VMReport = [ordered] @{}
67 | # Add VM's Name
68 | $VMReport.VMName = $VM.VMName
69 | # Add Status
70 | $VMReport.Status = $VM.Status
71 | # Add Uptime
72 | $VMReport.Uptime = $VM.Uptime
73 | # Add VM CPU
74 | $VMReport.VMCPU = $VM.CPUUsage
75 | # Replication Mode/Status
76 | $VMReport.ReplMode = $VM.ReplicationMode
77 | $VMReport.ReplState = $Vm.ReplicationState
78 | # Create object from Hash table, add to array
79 | $VMR = New-Object -TypeName PSObject -Property $VMReport
80 | $VMHT += $VMR
81 | }
82 |
83 | # 12. Display the array of objects as a table:
84 | $VMDetails = $VMHT |
85 | Sort-Object -Property Uptime -Descending |
86 | Format-Table |
87 | Out-String
88 |
89 | # 13. Now create the report
90 | $ReportBody = "Hyper-V Status Report`n"
91 | $ReportBody += "---------------------`n`n"
92 | $ReportBody += "Created on:"
93 | $ReportBody += (Get-Date | Out-String)
94 | $ReportBody += "Hyper-V Server Details:"
95 | $ReportBody += $ReportBase
96 | $ReportBody += 'VM Details on this host:'
97 | $ReportBody += $VMDetails
98 |
99 |
100 | # 14. Display the Report
101 | $ReportBody
102 |
103 |
104 |
105 |
106 |
107 | # remove fake VMs
108 | # get-vm -vmname SQL1, SQL1, OM1? | Remove-VM
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/Chapter 03 - Deploying Active Directory/3.5 - Reporting on AD Users.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 3.5 - Reporting on AD Users
2 |
3 | # 1. Define a function Get-ReskitUser
4 | # The function returns objects related to users in reskit.org
5 | Function Get-ReskitUser {
6 | # Get PDC Emulator DC
7 | $PrimaryDC = Get-ADDomainController -Discover -Service PrimaryDC
8 | # Get Users
9 | $ADUsers = Get-ADUser -Filter * -Properties * -Server $PrimaryDC
10 | # Iterate through them and create $Userinfo hash table:
11 | Foreach ($ADUser in $ADUsers) {
12 | # Create a userinfo HT
13 | $UserInfo = [Ordered] @{}
14 | $UserInfo.SamAccountname = $ADUser.SamAccountName
15 | $Userinfo.DisplayName = $ADUser.DisplayName
16 | $UserInfo.Office = $ADUser.Office
17 | $Userinfo.Enabled = $ADUser.Enabled
18 | $userinfo.LastLogonDate = $ADUser.LastLogonDate
19 | $UserInfo.ProfilePath = $ADUser.ProfilePath
20 | $Userinfo.ScriptPath = $ADUser.ScriptPath
21 | $UserInfo.BadPWDCount = $ADUser.badPwdCount
22 | New-Object -TypeName PSObject -Property $UserInfo
23 | }
24 | } # end of function
25 |
26 | # 2. Get the users
27 | $RKUsers = Get-ReskitUser
28 |
29 | # 3. Build the report header
30 | $RKReport = ''
31 | $RkReport += "*** Reskit.Org AD Report`n"
32 | $RKReport += "*** Generated [$(Get-Date)]`n"
33 | $RKReport += "*******************************`n`n"
34 |
35 | # 4. Report on Disabled users
36 | $RkReport += "*** Disabled Users`n"
37 | $RKReport += $RKUsers |
38 | Where-Object {$_.Enabled -NE $true} |
39 | Format-Table -Property SamAccountName, Displayname |
40 | Out-String
41 |
42 | # 5. Report users who have not recently logged on
43 | $OneWeekAgo = (Get-Date).AddDays(-7)
44 | $RKReport += "`n*** Users Not logged in since $OneWeekAgo`n"
45 | $RkReport += $RKUsers |
46 | Where-Object {$_.Enabled -and $_.LastLogonDate -le $OneWeekAgo} |
47 | Sort-Object -Property LastlogonDate |
48 | Format-Table -Property SamAccountName,lastlogondate |
49 | Out-String
50 |
51 | # 6. Users with high invalid password attempts
52 | #
53 | $RKReport += "`n*** High Number of Bad Password Attempts`n"
54 | $RKReport += $RKUsers | Where-Object BadPwdCount -ge 5 |
55 | Format-Table -Property SamAccountName, BadPwdCount |
56 | Out-String
57 |
58 | # 7. Add Another report header line for this part of the
59 | # report and create an empty array of priviledged users
60 | $RKReport += "`n*** Privileged User Report`n"
61 | $PUsers = @()
62 |
63 | # 8. Query the Enterprise Admins/Domain Admins/Scheme Admins
64 | # groups for members and add to the $Pusers array
65 | # Get Enterprise Admins group members
66 | $Members = Get-ADGroupMember -Identity 'Enterprise Admins' -Recursive |
67 | Sort-Object -Property Name
68 | $PUsers += foreach ($Member in $Members) {
69 | Get-ADUser -Identity $Member.SID -Properties * |
70 | Select-Object -Property Name,
71 | @{Name='Group';expression={'Enterprise Admins'}},
72 | whenCreated,LastlogonDate
73 | }
74 | # Get Domain Admins group members
75 | $Members =
76 | Get-ADGroupMember -Identity 'Domain Admins' -Recursive |
77 | Sort-Object -Property Name
78 | $PUsers += Foreach ($Member in $Members)
79 | {Get-ADUser -Identity $member.SID -Properties * |
80 | Select-Object -Property Name,
81 | @{Name='Group';expression={'Domain Admins'}},
82 | WhenCreated, Lastlogondate,SamAccountName
83 | }
84 | # Get Schema Admins members
85 | $Members =
86 | Get-ADGroupMember -Identity 'Schema Admins' -Recursive |
87 | Sort-Object Name
88 | $PUsers += Foreach ($Member in $Members) {
89 | Get-ADUser -Identity $member.SID -Properties * |
90 | Select-Object -Property Name,
91 | @{Name='Group';expression={'Schema Admins'}}, `
92 | WhenCreated, Lastlogondate,SamAccountName
93 | }
94 |
95 | # 9 Add the special users to the report
96 | $RKReport += $PUsers | Out-String
97 |
98 | # 10. Display the report
99 | $RKReport
--------------------------------------------------------------------------------
/Chapter 12 - Exploring Azure/Recipe 12.5 - Create Azure Web SIte.ps1:
--------------------------------------------------------------------------------
1 | # Recipe 12.5 - Create an Azure Web App
2 |
3 | # 1. Define Variables
4 | $Locname = 'uksouth' # location name
5 | $RgName = 'packt_rg' # resource group we are using
6 | $SAName = 'packt42sa' # storage account name
7 | $AppSrvName = 'packt42'
8 | $AppName = 'packt42website'
9 |
10 | # 2. Login to your Azure Account and ensure RG exists
11 | $CredAZ = Get-Credential
12 | Login-AzAccount -Credential $CredAz
13 |
14 | # 3. Ensure Resource Group is created
15 | $RGHT1 = @{
16 | Name = $RgName
17 | ErrorAction = 'Silentlycontinue'
18 | }
19 | $RG = Get-AzResourceGroup @RGHT1
20 | if (-not $RG) {
21 | $RGTag = [Ordered] @{Publisher='Packt'}
22 | $RGTag += @{Author='Thomas Lee'}
23 | $RGHT2 = @{
24 | Name = $RgName
25 | Location = $Locname
26 | Tag = $RGTag
27 | }
28 | $RG = New-AzResourceGroup @RGHT2
29 | Write-Host "RG $RgName created"
30 | }
31 |
32 | # 4. Ensure the Stoage Account is created.
33 | $SAHT = @{
34 | Name = $SAName
35 | ResourceGroupName = $RgName
36 | ErrorAction = 'SilentlyContinue'
37 | }
38 | $SA = Get-AzStorageAccount @SAHT
39 | if (-not $SA) {
40 | $SATag = [Ordered] @{Publisher='Packt'}
41 | $SATag += @{Author='Thomas Lee'}
42 | $SAHT = @{
43 | Name = $SAName
44 | ResourceGroupName = $RgName
45 | Location = $Locname
46 | Tag = $SATag
47 | SkuName = 'Standard_LRS'
48 | }
49 | $SA = New-AStorageAccount @SAHT
50 | "SA $SAName created"
51 | }
52 |
53 | # 5. Create app service plan
54 | $SPHT = @{
55 | ResourceGroupName = $RgName
56 | Name = $AppSrvName
57 | Location = $Locname
58 | Tier = 'Free'
59 | }
60 | New-AzAppServicePlan @SPHT | Out-Null
61 |
62 | # 6. View the service plan
63 | $PHT = @{
64 | ResourceGroupName = $RGname
65 | Name = $AppSrvName
66 | }
67 | Get-AzAppServicePlan @PHT
68 |
69 | # 7. Create the new azure webapp
70 | $WAHT = @{
71 | ResourceGroupName = $RgName
72 | Name = $AppName
73 | AppServicePlan = $AppSrvName
74 | Location = $Locname
75 | }
76 | New-AzWebApp @WAHT | Out-Null
77 |
78 | # 8. View application details
79 | $WebApp = Get-AzWebApp -ResourceGroupName $RgName -Name $AppName
80 | $WebApp |
81 | Format-Table -Property Name, State, Hostnames, Location
82 |
83 | # 9 Now see the web site
84 | $SiteUrl = "https://$($WebApp.DefaultHostName)"
85 | $IE = New-Object -ComObject InterNetExplorer.Application
86 | $IE.Navigate2($SiteUrl)
87 | $IE.Visible = $true
88 |
89 | # 10. Install the PSFTP module
90 | Install-module PSFTP -Force | Out-Null
91 | Import-Module PSFTP
92 |
93 | # 11. Get publishing profile XML and extract FTP upload details
94 | $APHT = @{
95 | ResourceGroupName = $RgName
96 | Name = $AppName
97 | OutputFile = 'C:\Foo\pdata.txt'
98 | }
99 | $x = [xml] (Get-AzWebAppPublishingProfile @APHT)
100 | $x.publishData.publishProfile[1]
101 |
102 | # 12. Extract crededentials and site details
103 | $UserName = $x.publishData.publishProfile[1].userName
104 | $UserPwd = $x.publishData.publishProfile[1].userPWD
105 | $Site = $x.publishData.publishProfile[1].publishUrl
106 |
107 | # 13. Connect to the FTP site
108 | $FTPSN = 'FTPtoAzure'
109 | $PS = ConvertTo-SecureString $UserPWD -AsPlainText -Force
110 | $T = 'System.Management.automation.PSCredentiaL'
111 | $Cred = New-Object -TypeName $T -ArgumentList $UserName,$PS
112 | $FTPHT = @{
113 | Credentials = $Cred
114 | Server = $Site
115 | Session = $FTPSN
116 | UsePassive = $true
117 | }
118 | Set-FTPConnection @FTPHT
119 | $Session = Get-FTPConnection -Session $FTPSN
120 |
121 | # 15. Create a Web Page and upload it
122 | 'My First Azure Web Site' | Out-File -FilePath C:\Foo\Index.Html
123 | $Filename = 'C:\foo\index.html'
124 | $IHT = @{
125 | Path = '/'
126 | LocalPath = 'C:\foo\index.html'
127 | Session = $FTPSN
128 | }
129 | Add-FTPItem @IHT
130 |
131 |
132 | # 16. NoW look at the site using default browser (Chrome):
133 | $SiteUrl = "https://$($WebApp.DefaultHostName)"
134 | Start-Process -FilePath $SiteUrl
--------------------------------------------------------------------------------