├── .gitattributes ├── FTP └── UploadContents-FTPServer.ps1 ├── File System ├── Copy-FilesOnDomainUsingDifferentCredentials.ps1 ├── Extract-ZipArchives.ps1 └── Run-SQLServerManagementAsOtherUser.ps1 ├── IIS ├── IIS-Batch-WebApplication-Configuration.ps1 ├── IIS-ServerSettings-AddCommonMimeTypes.ps1 ├── IIS-ServerSettings-EnableOnlyKnownMimeTypes.ps1 ├── IIS-ServerSettings-SetAppPoolIdentityAnonymous.ps1 ├── IIS-ServerSettings-SetRequireSSLForFormsAuth.ps1 ├── IIS-ServerSettings-SetRequireSSLOnAllWebsites.ps1 ├── IIS-ServerSettings-SetRetailMode.ps1 ├── IIS-ServerSettings-TurnAutomaticBackupsOn.ps1 ├── IIS-WebsiteSettings-EncryptWebConfigConnectionStrings.ps1 ├── Install-WebDeploy.ps1 └── Manager module │ ├── IIS-Manager.psd1 │ └── IIS-Manager.psm1 ├── LICENSE.txt ├── Misc ├── Automate Windows Security prompt input │ ├── Run-Explorer.ps1 │ ├── Run-RemoteDesktop.ps1 │ └── Run-SqlTool.ps1 ├── Create schedule task to execute ps1 script │ ├── Kill-Process.ps1 │ ├── Kill-Process.vbs │ └── Setup │ │ ├── Create-ScheduleTask-To-Kill-Process.ps1 │ │ └── ScheduleTask-To-Kill-Process.xml ├── PowerShell 5 Presentation Scripts (April 2015) │ ├── Demo-Class_Enum-Script.ps1 │ ├── Demo-CodeAnalysis-Commands.ps1 │ ├── Demo-OneGet-Commands.ps1 │ ├── Demo-OurOwnOneGet-Commands.ps1 │ ├── Demo-OurPowerShellGet-Commands.ps1 │ ├── Demo-ParseContacts-Commands.ps1 │ └── contacts.adr └── Wiremock │ └── Download-Start-Wiremock.ps1 ├── NuGet └── CreateAndPublishNuGetPackage.ps1 ├── Octopus-Deploy ├── API │ └── Add-Machine.ps1 ├── Create-ScheduledTask.ps1 ├── DACPAC-Deploy-Helpers.ps1 ├── Replace-WebConfig-ConnectionStringsKeys-With-OctopusVars.ps1 └── WebDeploy-Helpers.ps1 ├── Performance └── RunPerfMonitor-AppServers.ps1 ├── README.md ├── SQL Server Install ├── ConfigFile │ └── SQLServerConfigurationFile.ini └── SQLServerInstall.ps1 ├── SQL ├── Insert-SeedData.ps1 └── SetupScripts │ ├── 001.Pre-Deploy.sql │ ├── 800.Grant_DOMAIN-Username_Access.sql │ └── 900.Post-Deploy.sql ├── Security ├── Set-AcceptedCryptographicProtocols.ps1 └── Set-StrongCryptographyDotNet.ps1 ├── TeamCity └── Version-DatabaseProject.ps1 ├── Visual Studio ├── Locate-and-Load-DLL.ps1 ├── Manage-Intellitrace.ps1 ├── Run-NUnitIntegrationTests.ps1 ├── RunIntegrationTests.ps1 ├── RunTestsWithCoverageData.ps1 └── SQL Server Projects │ ├── BatchDeploy-DACPACs.ps1 │ └── BuildPostDeploymentScript.ps1 ├── Web └── Get-ImagesFromWebsite.ps1 └── WebDeploy ├── Fetch-SetParameters.ps1 ├── Install-WebPackage.ps1 └── Modify-SetParameters.ps1 /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /FTP/UploadContents-FTPServer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Transfers files to the defined FTP server location 4 | 5 | .NOTES 6 | authors: 7 | https://github.com/jlouros 8 | version: 9 | 0.2 10 | missing features: 11 | add capability to pass Username and Password (instead of NetworkCredentials) 12 | Check if target FTP destination is a valid folder 13 | Accept FTP destination as a string (instead of Url) 14 | Use SecureString for password 15 | #> 16 | 17 | Param( 18 | [parameter(Mandatory=$true)] 19 | [System.String]$directory, 20 | [parameter(Mandatory=$true)] 21 | [ValidateNotNullOrEmpty()] 22 | [System.String]$ftpAddressUrl, 23 | [parameter(Mandatory=$true)] 24 | [System.String]$ftpUsername, 25 | [parameter(Mandatory=$true)] 26 | [System.String]$ftpPassword 27 | ) 28 | 29 | Function Check-IfFtpDirectoryExists { 30 | [OutputType('System.Boolean')] 31 | Param( 32 | [parameter(Mandatory=$true)] 33 | [ValidateNotNullOrEmpty()] 34 | [System.Uri]$ftpAddress, 35 | [parameter(Mandatory=$true)] 36 | [System.Net.NetworkCredential]$ftpCredentials 37 | ) 38 | 39 | $ftpDirectoryExisits = $true; 40 | Try 41 | { 42 | [System.Net.FtpWebRequest]$checkdirRequest = [System.Net.WebRequest]::Create($ftpAddress) 43 | $checkdirRequest.Credentials = $ftpCredentials 44 | $checkdirRequest.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory 45 | #$checkdirRequest.UsePassive = $true 46 | #$checkdirRequest.KeepAlive = $false 47 | 48 | $resp = $checkdirRequest.GetResponse() 49 | $resp.Close() 50 | } 51 | Catch 52 | { 53 | # process error 54 | if($_.Exception.Message -match 'File unavailable') { 55 | # expected expection, proceed with return False 56 | $ftpDirectoryExisits = $false 57 | } else { 58 | # unexpected error, cancel script execution 59 | Write-Output 'Unexcepected error found. Terminating script execution' 60 | Write-Error $_.Exception.Message -ErrorAction Stop 61 | } 62 | } 63 | 64 | return $ftpDirectoryExisits 65 | } 66 | 67 | Function Create-FTPDirectoryRecursively { 68 | Param( 69 | [parameter(Mandatory=$true)] 70 | [ValidateNotNullOrEmpty()] 71 | [System.Uri]$ftpTargetPath, 72 | [parameter(Mandatory=$true)] 73 | [System.Net.NetworkCredential]$ftpCredentials 74 | ) 75 | 76 | [System.String[]]$ftpSegments = $ftpTargetPath.Segments; 77 | $ftpUrl = [string]::Format('{0}://{1}', $ftpTargetPath.Scheme, $ftpTargetPath.Host); 78 | 79 | # create necessary FTP folders 80 | for($i = 0; $i -lt $ftpSegments.Length; $i++) 81 | { 82 | $ftpUrl += $ftpSegments[$i]; 83 | 84 | Write-Output "Checking is '$ftpUrl' exists" 85 | 86 | if((Check-IfFtpDirectoryExists $ftpUrl $ftpCredentials) -eq $false) 87 | { 88 | Write-Output "Couldn't find specified location. Creating '$ftpUrl' folder" -ForegroundColor Gray 89 | 90 | [System.Net.FtpWebRequest]$mkdRequest = [System.Net.WebRequest]::Create($ftpUrl) 91 | $mkdRequest.Credentials = $ftpCredentials 92 | $mkdRequest.Method = [System.Net.WebRequestMethods+FTP]::MakeDirectory 93 | 94 | $mkdResponse = $mkdRequest.GetResponse(); 95 | $mkdResponse.Close(); 96 | } 97 | } 98 | } 99 | 100 | Function Transfer-ContentsToFTP { 101 | Param( 102 | [parameter(Mandatory=$true)] 103 | [ValidateNotNullOrEmpty()] 104 | [System.Array]$filesToTransfer, 105 | [parameter(Mandatory=$true)] 106 | [ValidateNotNullOrEmpty()] 107 | [System.Uri]$ftpTargetPath, 108 | [parameter(Mandatory=$true)] 109 | [System.Net.NetworkCredential]$ftpCredentials 110 | ) 111 | 112 | # transfer files 113 | foreach($srcFile in $filesToTransfer) 114 | { 115 | $fileDesitnation = New-Object System.Uri($ftpTargetPath, $srcFile.Name) 116 | 117 | Write-Output "Uploading file '$fileDesitnation'" 118 | 119 | # Upload file to FTP server 120 | [System.Net.FtpWebRequest]$ufRequest = [System.Net.WebRequest]::Create($fileDesitnation) 121 | $ufRequest.Credentials = $ftpCredentials 122 | $ufRequest.Method = [System.Net.WebRequestMethods+FTP]::UploadFile 123 | 124 | # Read file contents 125 | $content = [System.IO.File]::ReadAllBytes($srcFile.FullName) 126 | $ufRequest.ContentLength = $content.Length 127 | 128 | $requestStream = $ufRequest.GetRequestStream(); 129 | $requestStream.Write($content, 0, $content.Length); 130 | $requestStream.Close(); 131 | 132 | $ufResponse = $ufRequest.GetResponse(); 133 | $ufResponse.Close(); 134 | } 135 | 136 | } 137 | 138 | Function Transfer-DirectoryContents { 139 | Param( 140 | [parameter(Mandatory=$true)] 141 | [ValidateNotNullOrEmpty()] 142 | [System.String]$sourceDirectory, 143 | [parameter(Mandatory=$true)] 144 | [ValidateNotNullOrEmpty()] 145 | [System.Uri]$ftpTargetPath, 146 | [parameter(Mandatory=$true)] 147 | [System.Net.NetworkCredential]$ftpCredentials 148 | ) 149 | 150 | $directories = (Get-Item $sourceDirectory).GetDirectories() 151 | 152 | foreach($currDir in $directories) 153 | { 154 | $newFtpDir = New-Object System.Uri($ftpTargetPath, "$($currDir.Name)/".Replace('//', '/')) 155 | $files = (Get-Item $currDir.FullName).GetFiles() 156 | 157 | Create-FTPDirectoryRecursively $newFtpDir $ftpCredentials 158 | 159 | if($files.Count -gt 0) { 160 | Transfer-ContentsToFTP $files $newFtpDir $ftpCredentials 161 | } 162 | 163 | Transfer-DirectoryContents $currDir.FullName $newFtpDir $ftpCredentials 164 | } 165 | } 166 | 167 | 168 | Function Process-UploadContents { 169 | Param( 170 | [parameter(Mandatory=$true)] 171 | [ValidateNotNullOrEmpty()] 172 | [System.String]$sourceDirectory, 173 | [parameter(Mandatory=$true)] 174 | [ValidateNotNullOrEmpty()] 175 | [System.Uri]$ftpTargetPath, 176 | [parameter(Mandatory=$true)] 177 | [System.Net.NetworkCredential]$ftpCredentials 178 | ) 179 | 180 | if($ftpTargetPath.AbsolutePath.EndsWith('/') -eq $false) { Write-Error "Passed FTP target directory is not valid: '$ftpTargetPath'." -ErrorAction Stop } 181 | 182 | if((Test-Path $sourceDirectory) -eq $false) { Write-Error "Invalid or unexisting source directory: '$sourceDirectory'." -ErrorAction Stop } 183 | 184 | 185 | $sourceDirItems = (Get-Item $sourceDirectory).GetFiles() 186 | 187 | if(($sourceDirItems -eq $null)-or ($sourceDirItems.Count -lt 1)) { Write-Error "Source directory is empty: '$sourceDirectory'. Terminating script, since no files will be copied" -ErrorAction Stop } 188 | 189 | Create-FTPDirectoryRecursively $ftpTargetPath $ftpCredentials 190 | 191 | Transfer-ContentsToFTP $sourceDirItems $ftpTargetPath $ftpCredentials 192 | 193 | Transfer-DirectoryContents $sourceDirectory $ftpTargetPath $ftpCredentials 194 | } 195 | 196 | 197 | # script execution 198 | 199 | 200 | #set ftp Url 201 | $ftpUrl = New-Object System.Uri($ftpAddressUrl) 202 | #set ftp Credentials 203 | $ftpCredentials = New-Object System.Net.NetworkCredential($ftpUsername,$ftpPassword) 204 | 205 | #upload all files from '$directory' 206 | Process-UploadContents $directory $ftpUrl $ftpCredentials -------------------------------------------------------------------------------- /File System/Copy-FilesOnDomainUsingDifferentCredentials.ps1: -------------------------------------------------------------------------------- 1 | $srcDir = "$env:HOMEDRIVE\code\myWebApp\src\bin\" 2 | $desDir = 'P:\inetpub\myWebApp\' 3 | 4 | $remoteMachineRootFolder = '\\web-app-001.local.domain\C$' 5 | 6 | # network credentials, use this only for generic unsecure accounts. 7 | $networkDomainUser = 'local\administrator' 8 | $networkDomainPass = 'Password123' 9 | 10 | # user credentials for the remote machine 11 | $pass = $networkDomainPass | ConvertTo-SecureString -AsPlainText -Force 12 | $Cred = New-Object -TypeName System.Management.Automation.PsCredential -ArgumentList ($networkDomainUser, $pass) 13 | 14 | # create new network drive and assign it to 'P' 15 | New-PSDrive -Name P -Credential $Cred -PSProvider FileSystem -Root $remoteMachineRootFolder 16 | 17 | # copy folder to remove destination 18 | Write-Output -InputObject 'Starting file copy to remote directory...' 19 | Copy-Item -Path $srcDir -Destination $desDir -Force -Recurse 20 | 21 | 22 | # remove network drive 'P' 23 | Remove-PSDrive -Name P -------------------------------------------------------------------------------- /File System/Extract-ZipArchives.ps1: -------------------------------------------------------------------------------- 1 | # finds all '.zip' files located in the current directory (where this script is located) 2 | # extracts each archive to '\unzipped\' 3 | 4 | # requires .Net Framework 4.5 5 | if(-not ($PSVersionTable.CLRVersion.Major -eq 4 -and $PSVersionTable.CLRVersion.Revision -gt 17000)) 6 | { 7 | Write-Error -Message 'This script requires .Net Framework 4.5. Unable to proceed.' -ErrorAction Stop 8 | } 9 | 10 | $zipFiles = Get-ChildItem -Path . | Where-Object { $_.Name.EndsWith('.zip') } 11 | 12 | foreach($zipFile in $zipFiles) 13 | { 14 | Add-Type -AssemblyName System.IO.Compression.FileSystem | Out-Null 15 | 16 | $extractLocation = Join-Path -Path $zipFile.Directory -ChildPath 'unzipped' 17 | 18 | Write-Output -InputObject "Extracting '$($zipFile.Name)' to '$extractLocation'" 19 | 20 | [IO.Compression.ZipFile]::ExtractToDirectory($zipFile.FullName, $extractLocation) 21 | } 22 | 23 | 24 | 25 | #################### 26 | # PowerShell 5.0 27 | #################### 28 | 29 | Import-Module -Name Microsoft.PowerShell.Archive 30 | 31 | $srcFile = '.\myZipFile.zip' 32 | $destFolder = '.\ExtractedContents\' 33 | Expand-Archive -Path $srcFile -DestinationPath $destFolder -------------------------------------------------------------------------------- /File System/Run-SQLServerManagementAsOtherUser.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Opens a local instance of the selected SQL tools, using a 'local\administrator' credentials 4 | .NOTES 5 | Useful when you need to use 'Windows Authention' to reach out a machine hosted on a different Active Directory 6 | #> 7 | 8 | Param( 9 | [String] $DomainUser = 'local\administrator', 10 | [Switch] $SqlProfiler 11 | ) 12 | 13 | # path to Sql Server 2012 Management Studio 14 | $Ssms2012Path = 'C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\Ssms.exe' 15 | 16 | # path to Sql Server 2012 Profiler 17 | $SqlProfiler2012Path = 'C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\PROFILER.EXE' 18 | 19 | 20 | # pick Ssms or Profile depending on what the user picked 21 | $selectedApp = $Ssms2012Path 22 | if($SqlProfiler) { 23 | $selectedApp = $SqlProfiler2012Path 24 | } 25 | 26 | 27 | if(-not(Test-Path $selectedApp)) { 28 | 29 | Write-Error "Invalid path provided: '$selectedApp'" -ErrorAction Stop 30 | } 31 | 32 | 33 | runas.exe /netonly /user:$DomainUser $selectedApp -------------------------------------------------------------------------------- /IIS/IIS-Batch-WebApplication-Configuration.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | #Requires -RunAsAdministrator 3 | #Requires -Modules WebAdministration 4 | 5 | # this script creates IIS WebSite and Virtual Applications in batch 6 | # just change the '$settings' variable with the desired configurations 7 | 8 | 9 | # WARNING: current setting does not accept null values 10 | $settings = @{ 11 | 'WebSite1' = @{ 12 | 'AppPoolName' = 'WebSite1' 13 | 'ManagedRuntimeVersion' = 'v2.0' 14 | 'PipelineMode' = 'Classic' 15 | 'IdentityType' = 'LocalSystem' 16 | 'CpuMode' = 'x86' 17 | 'WebSiteName' = 'WebSite1' 18 | 'WebBinding' = 'WebSite1.localhost' 19 | 'PhysicalPath' = "$env:HOMEDRIVE\_CompanyName\Websites\WebSite1" 20 | 'VirtualApplications' = @( 21 | @{ 22 | 'Name' = 'ContainerTagTest' 23 | 'PhysicalPath' = "$env:HOMEDRIVE\_CompanyName\Websites\ContainerTagTest" 24 | 'AppPoolName' = 'WebSite1' 25 | }, 26 | @{ 27 | 'Name' = 'CompanyName' 28 | 'PhysicalPath' = "$env:HOMEDRIVE\_CompanyName\Websites\CompanyName" 29 | 'AppPoolName' = 'WebSite1' 30 | } 31 | ) 32 | } 33 | 'WebSite2' = @{ 34 | 'AppPoolName' = 'WebSite2' 35 | 'ManagedRuntimeVersion' = 'v4.0' 36 | 'PipelineMode' = 'Integrated' 37 | 'IdentityType' = 'LocalSystem' 38 | 'CpuMode' = 'x64' 39 | 'WebSiteName' = 'WebSite2' 40 | 'WebBinding' = 'WebSite2.localhost' 41 | 'PhysicalPath' = "$env:HOMEDRIVE\_CompanyName\Websites\WebSite2-UI" 42 | 'VirtualApplications' = @( 43 | @{ 44 | 'Name' = 'API' 45 | 'PhysicalPath' = "$env:HOMEDRIVE\_CompanyName\Websites\WebSite2-API" 46 | 'AppPoolName' = 'WebSite2' 47 | } 48 | ) 49 | } 50 | } 51 | 52 | 53 | 54 | function Check-Windows() { 55 | 56 | $windows = [Environment]::OSVersion.Version -ge (New-Object -TypeName 'Version' -ArgumentList 6,1) 57 | 58 | if($windows -eq $false) { 59 | Write-Error -Message "'Windows 7' required, unable to continue!" -ErrorAction Stop 60 | } else { 61 | Write-Host '[Pass] Windows' -ForegroundColor Green 62 | } 63 | } 64 | 65 | function Check-DotNetFramework() { 66 | 67 | $dotNetInstalled = $(Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | 68 | Get-ItemProperty -Name Version -ErrorAction SilentlyContinue | 69 | Where-Object { $_.PSChildName -match '^(?!S)\p{L}'} | 70 | Select-Object -Property PSChildName, Version | 71 | Where-Object {$_.PSChildName -eq 'Full' -and $_.Version -ge (New-Object -TypeName 'Version' -ArgumentList 4,5)}) -ne 72 | $null 73 | 74 | if($dotNetInstalled -eq $false) { 75 | Write-Error -Message "'.Net Framework 4.5' is not installed on your machine, unable to continue!" -ErrorAction Stop 76 | } else { 77 | Write-Host '[Pass] .Net Framework' -ForegroundColor Green 78 | } 79 | } 80 | 81 | function Check-IIS() { 82 | 83 | $iisInstalled = $(Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\InetStp\ | 84 | Select-Object -Property setupstring, @{N='Version'; E={(New-Object -TypeName 'Version' -ArgumentList $_.MajorVersion,$_.MinorVersion)}} | 85 | Where-Object { $_.Version -ge (New-Object -TypeName 'Version' -ArgumentList 7,5)}) -ne 86 | $null 87 | 88 | if($iisInstalled -eq $false) { 89 | Write-Error -Message "'IIS 7.5' is not installed on your machine, unable to continue!" -ErrorAction Stop 90 | } else { 91 | Write-Host '[Pass] IIS' -ForegroundColor Green 92 | } 93 | } 94 | 95 | function Check-SqlServer() { 96 | 97 | [reflection.assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null 98 | $s = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server' 99 | 100 | $sqlServerInstalled = $($s | Select-Object -Property Version, EngineEdition | 101 | Where-Object { $_.Version -ge (New-Object -TypeName 'Version' -ArgumentList 10,50) -and $_.EngineEdition -eq [Microsoft.SqlServer.Management.Smo.Edition]::EnterpriseOrDeveloper }) -ne 102 | $null 103 | 104 | if($sqlServerInstalled -eq $false) { 105 | Write-Error -Message "'Sql Sever 2008 R2 (Developer edition)' is not installed on your machine, unable to continue!" -ErrorAction Stop 106 | } else { 107 | Write-Host '[Pass] Sql Server' -ForegroundColor Green 108 | } 109 | } 110 | 111 | function Check-WebServicesExtensions() { 112 | 113 | #http://www.microsoft.com/en-us/download/details.aspx?id=23689 114 | $webServerExt = $(Get-WmiObject -Class win32_product | 115 | Where-Object {$_.Vendor -ieq 'Microsoft Corporation'} | 116 | Where-Object {$_.Name -match 'Microsoft WSE 2.0 SP3' -and $_.Version -ge (New-Object -TypeName 'Version' -ArgumentList 2,0)}) -ne 117 | $null 118 | 119 | if($webServerExt -eq $false) { 120 | Write-Error -Message "'Web Services Extensions 2.0 SP3' is not installed on your machine, unable to continue!" -ErrorAction Stop 121 | } else { 122 | Write-Host '[Pass] Web Services Extensions' -ForegroundColor Green 123 | } 124 | } 125 | 126 | function Check-VisualJSharp() { 127 | #http://www.microsoft.com/en-us/download/details.aspx?id=15468 128 | $jSharp = $(Get-WmiObject -Class win32_product | 129 | Where-Object {$_.Vendor -ieq 'Microsoft Corporation'} | 130 | Where-Object {$_.Name -match 'Microsoft Visual J# 2.0' -and $_.Version -ge (New-Object -TypeName 'Version' -ArgumentList 2,0)}) -ne 131 | $null 132 | 133 | if($jSharp -eq $false) { 134 | Write-Error -Message "'Visual J# 2.0' is not installed on your machine, unable to continue!" -ErrorAction Stop 135 | } else { 136 | Write-Host '[Pass] Visual J#' -ForegroundColor Green 137 | } 138 | } 139 | 140 | function Check-WebDeploy() { 141 | #http://www.microsoft.com/web/downloads/platform.aspx 142 | $webDeploy = $(Get-WmiObject -Class win32_product | 143 | Where-Object {$_.Vendor -ieq 'Microsoft Corporation'} | 144 | Where-Object {$_.Name -match 'Microsoft Web Deploy' -and $_.Version -ge (New-Object -TypeName 'Version' -ArgumentList 3,1237)}) -ne 145 | $null 146 | 147 | if($webDeploy -eq $false) { 148 | Write-Error -Message "'WebDeploy 3.5' is not installed on your machine, unable to continue!" -ErrorAction Stop 149 | } else { 150 | Write-Host '[Pass] WebDeploy' -ForegroundColor Green 151 | } 152 | } 153 | 154 | function Check-ReportViewer() { 155 | #http://www.microsoft.com/en-us/download/details.aspx?id=35747 156 | $reportViewer = $(Get-WmiObject -Class win32_product | 157 | Where-Object {$_.Vendor -ieq 'Microsoft Corporation'} | 158 | Where-Object {$_.Name -match 'Microsoft Report Viewer 2012 Runtime' -and $_.Version -ge (New-Object -TypeName 'Version' -ArgumentList 11,1)}) -ne 159 | $null 160 | 161 | if($reportViewer -eq $false) { 162 | Write-Error -Message "'Report Viewer 2012 Runtime' is not installed on your machine, unable to continue!" -ErrorAction Stop 163 | } else { 164 | Write-Host '[Pass] Report Viewer 2012' -ForegroundColor Green 165 | } 166 | } 167 | 168 | function New-IISAppPool() { 169 | [CmdletBinding(DefaultParameterSetName='Username')] 170 | Param 171 | ( 172 | [Parameter(Mandatory=$true, Position = 0, ValueFromPipeline=$true)] 173 | [ValidateScript({ 174 | if (Test-Path -Path "IIS:\AppPools\$_") { Throw New-Object -TypeName System.ArgumentException -ArgumentList "The IIS Application Pool '$_' already exists.", 'Name' } 175 | else { $true; } 176 | })] 177 | [string] $Name, 178 | 179 | [Parameter(Position=1)] 180 | [Alias('MRV', 'V', 'Runtime')] 181 | [ValidateSet('v2.0', 'v4.0')] 182 | [string] $ManagedRuntimeVersion = 'v2.0', 183 | 184 | [Parameter(Position=2)] 185 | [Alias('Pipeline')] 186 | [ValidateSet('Integrated', 'Classic')] 187 | [string] $PipelineMode = 'Integrated', 188 | 189 | [Parameter(Position=3)] 190 | [Alias('CPU')] 191 | [ValidateSet('x86', 'x64')] 192 | [string] $CpuMode = 'x64', 193 | 194 | [Parameter(Position=4, ParameterSetName='Username')] 195 | [Parameter(Position=4, ParameterSetName='Credential')] 196 | [ValidateSet('LocalSystem', 'LocalService', 'NetworkService', 'SpecificUser', 'ApplicationPoolIdentity')] 197 | [string] $IdentityType = 'ApplicationPoolIdentity', 198 | 199 | [Parameter(ParameterSetName='Username')] 200 | [string] $Username = [string]::Empty, 201 | 202 | [Parameter(ParameterSetName='Credential')] 203 | [System.Management.Automation.PSCredential]$Credential, 204 | 205 | [switch] $Interactive 206 | ) 207 | 208 | [System.Management.Automation.PSCredential] $AppPoolCredential 209 | 210 | if ($IdentityType.ToLowerInvariant() -eq 'SpecificUser'.ToLowerInvariant()) 211 | { 212 | if ($PSCmdlet.ParameterSetName -imatch 'Credential') 213 | { 214 | $AppPoolCredential = $Credential 215 | } 216 | else 217 | { 218 | if ([string]::IsNullOrWhiteSpace($Username)) 219 | { 220 | if ($Interactive) 221 | { 222 | $AppPoolCredential = $Host.UI.PromptForCredential('Application Pool Identity Credentials', 'Please specify the username and password to be used for the Application Pool Identity.', $Username, '', [System.Management.Automation.PSCredentialTypes]::Domain, [System.Management.Automation.PSCredentialUIOptions]::ValidateUserNameSyntax) 223 | } 224 | else 225 | { 226 | $AppPoolCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $(Read-Host -Prompt 'Application Pool Identity Username'), $(Read-Host -Prompt 'Application Pool Identity Password' -AsSecureString) 227 | } 228 | } 229 | 230 | if ($Interactive) 231 | { 232 | $AppPoolCredential = $Host.UI.PromptForCredential('Application Pool Identity Password', 'Please enter the password for the specified user to be used for the Application Pool Identity.', $Username, '', [System.Management.Automation.PSCredentialTypes]::Domain, [System.Management.Automation.PSCredentialUIOptions]::ValidateUserNameSyntax) 233 | } 234 | else 235 | { 236 | $AppPoolCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $(Read-Host -Prompt "Application Pool Identity Password for '$Username'" -AsSecureString) 237 | } 238 | } 239 | } 240 | 241 | Write-Verbose -Message 'The following IIS Application Pool will be created:' 242 | Write-Verbose -Message " Application Pool Name: $Name" 243 | Write-Verbose -Message " Application Pool Managed Runtime Version: $ManagedRuntimeVersion" 244 | Write-Verbose -Message " Application Pool CPU Mode: $CpuMode" 245 | Write-Verbose -Message " Application Pool Pipeline Mode: $PipelineMode" 246 | Write-Verbose -Message " Application Pool Identity Type: $IdentityType" 247 | if ($IdentityType -imatch 'SpecificUser') 248 | { 249 | Write-Verbose -Message " Application Pool Identity Username: $Username" 250 | } 251 | 252 | New-WebAppPool -Name $Name 253 | 254 | Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name managedRuntimeVersion -Value $ManagedRuntimeVersion 255 | 256 | if ($PipelineMode -imatch 'Classic') 257 | { 258 | Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name managedPipelineMode -Value 1 259 | } 260 | 261 | if ($CpuMode -imatch 'x86') 262 | { 263 | Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name enable32BitAppOnWin64 -Value $true 264 | } 265 | 266 | switch ($IdentityType.ToLowerInvariant()) 267 | { 268 | 'localsystem' { Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name processModel.identityType -Value 0 } 269 | 'localservice' { Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name processModel.identityType -Value 1 } 270 | 'networkservice' { Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name processModel.identityType -Value 2 } 271 | 'specificuser' 272 | { 273 | Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name processModel.identityType -Value 3 274 | Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name processModel.userName -Value $AppPoolCredential.UserName 275 | Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name processModel.password -Value $(Get-Password -Password $AppPoolCredential.Password) 276 | } 277 | default { Set-ItemProperty -Path "IIS:\AppPools\$Name" -Name processModel.identityType -Value 4 } 278 | } 279 | 280 | Write-Verbose -Message "Application Pool '$Name' was successfully created." 281 | } 282 | 283 | function Setup-Websites() { 284 | 285 | foreach($key in $settings.Keys) { 286 | $node = $settings[$key] 287 | 288 | Write-Host "running '$key' setup..." 289 | 290 | # check AppPool settings 291 | $appPool = Get-Item -Path "IIS:\AppPools\$($node.AppPoolName)" -ErrorAction SilentlyContinue 292 | $createAppPool = $true; 293 | 294 | if($appPool -ne $null) { 295 | $validAppPoolSettings = ($appPool.managedPipelineMode -match $node.PipelineMode) -and 296 | ($appPool.managedRuntimeVersion -match $node.ManagedRuntimeVersion) -and 297 | ($appPool.enable32BitAppOnWin64 -eq ($node.CpuMode -eq 'x86')) 298 | 299 | if($validAppPoolSettings -eq $false) { 300 | Remove-WebAppPool -Name $node.AppPoolName 301 | } else { 302 | $createAppPool = $false; 303 | } 304 | } 305 | 306 | if($createAppPool) { 307 | New-IISAppPool -Name $node.AppPoolName -PipelineMode $node.PipelineMode -IdentityType $node.IdentityType -CpuMode $node.CpuMode -ManagedRuntimeVersion $node.ManagedRuntimeVersion | Out-Null 308 | } 309 | 310 | # check website settings 311 | $website = Get-Website | Where-Object {$_.Name -cmatch $($node.WebSiteName)} 312 | 313 | if($website -ne $null) { 314 | $correctBinding = Get-WebBinding -Name $node.WebSiteName | Where-Object { $_.protocol -eq 'http' -and $_.bindingInformation -eq "*:80:$($node.WebBinding)"} 315 | 316 | if($correctBinding -eq $null) { 317 | New-WebBinding -Name $node.WebSiteName -Protocol 'http' -Port 80 -HostHeader $node.WebBinding -IPAddress '*' 318 | } 319 | } else { 320 | if(-not(Test-Path -Path $node.PhysicalPath)) { 321 | New-Item -ItemType Directory -Path $node.PhysicalPath | Out-Null 322 | } 323 | New-Website -Name $node.WebSiteName -ApplicationPool $node.AppPoolName -Port 80 -PhysicalPath $node.PhysicalPath -HostHeader $node.WebBinding -IPAddress '*' | Out-Null 324 | } 325 | 326 | # check 'Api' settings (virutal application) 327 | foreach($virtualAppConf in $node.VirtualApplications) { 328 | Write-Host " checking '$($virtualAppConf.Name)' virtual application..." 329 | 330 | $api = Get-WebApplication -Site $node.WebSiteName -Name $virtualAppConf.Name 331 | 332 | if($api -eq $null) { 333 | if(-not(Test-Path -Path $virtualAppConf.PhysicalPath)) { 334 | New-Item -ItemType Directory -Path $virtualAppConf.PhysicalPath | Out-Null 335 | } 336 | New-WebApplication -Site $node.WebSiteName -Name $virtualAppConf.Name -PhysicalPath $virtualAppConf.PhysicalPath -ApplicationPool $virtualAppConf.Name | Out-Null 337 | } 338 | } 339 | } 340 | } 341 | 342 | 343 | #------------------------------------- 344 | # Script begins here 345 | #------------------------------------- 346 | 347 | 348 | Write-Host 'About to check required software for CompanyName main applications!' 349 | $userAggrement = Read-Host -Prompt 'Operation may change your current settings, do you want to proceed [Y]es/[N]o?' 350 | Write-Host "`r`n" 351 | 352 | if(-not($userAggrement -match 'y')) { 353 | return; 354 | } 355 | 356 | 357 | # Check Windows version (7/2008 or above) 358 | Check-Windows 359 | 360 | # Check SQL Server version (2008 R2 or above) (Developer or Enterprise edition) 361 | Check-SqlServer 362 | 363 | # Check IIS version installed (7.5 or above) 364 | Check-IIS 365 | 366 | # Check .Net Framework version (4.5 or above) 367 | Check-DotNetFramework 368 | 369 | # Check Microsoft Web Services Extensions (2.0 SP3) 370 | Check-WebServicesExtensions 371 | 372 | # Check Visual J# 2.0 is installed 373 | Check-VisualJSharp 374 | 375 | # Check if WebDeploy 3.5 is installed 376 | Check-WebDeploy 377 | 378 | # Check if Report Viewer 2012 is installed 379 | Check-ReportViewer 380 | 381 | 382 | # Setup all the websites defined in the settings variable 383 | Setup-Websites 384 | 385 | 386 | Write-Host "WARNING: Please check your IIS for inconsistencies!`r`n" -ForegroundColor Yellow -------------------------------------------------------------------------------- /IIS/IIS-ServerSettings-AddCommonMimeTypes.ps1: -------------------------------------------------------------------------------- 1 | Function Set-MimeTypeIfNotPresent 2 | { 3 | <# 4 | .SYNOPSIS 5 | Associates file extension with MIME type in IIS 6 | #> 7 | 8 | 9 | param( 10 | [Parameter(Mandatory=$true)] 11 | [string]$fileExtension, 12 | [Parameter(Mandatory=$true)] 13 | [string]$mimeType 14 | ) 15 | 16 | $config = Get-WebConfiguration -Filter system.webServer/staticContent/mimeMap | Where-Object { $_.fileExtension -eq $fileExtension } 17 | 18 | if($config -eq $null) 19 | { 20 | Write-Output -InputObject "'$fileExtension' file extension configuration not found. Adding with MIME type '$mimeType'" 21 | Add-WebConfiguration -Filter system.webServer/staticContent -AtIndex 0 -Value @{fileExtension=$fileExtension; mimeType=$mimeType} 22 | } 23 | else 24 | { 25 | Write-Output -InputObject "Configuration for '$fileExtension' found. No changes will be performed" 26 | } 27 | } 28 | 29 | 30 | Import-Module -Name WebAdministration -ErrorAction Stop 31 | 32 | 33 | Set-MimeTypeIfNotPresent -fileExtension '.webm' -mimeType 'video/webm' 34 | Set-MimeTypeIfNotPresent -fileExtension '.ogg' -mimeType 'video/ogg' 35 | Set-MimeTypeIfNotPresent -fileExtension '.mov' -mimeType 'video/quicktime' 36 | Set-MimeTypeIfNotPresent -fileExtension '.mp4' -mimeType 'video/mp4' 37 | Set-MimeTypeIfNotPresent -fileExtension '.svg' -mimeType 'image/svg+xml' 38 | Set-MimeTypeIfNotPresent -fileExtension '.woff' -mimeType 'font/x-woff' 39 | Set-MimeTypeIfNotPresent -fileExtension '.otf' -mimeType 'font/otf' 40 | Set-MimeTypeIfNotPresent -fileExtension '.eot' -mimeType 'application/vnd.ms-fontobject' 41 | Set-MimeTypeIfNotPresent -fileExtension '.ttf' -mimeType 'application/octet-stream' -------------------------------------------------------------------------------- /IIS/IIS-ServerSettings-EnableOnlyKnownMimeTypes.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Filters requests to only allow MIME types defined by us. 4 | .NOTES 5 | Whitelist only known MIME types. 6 | Recommended for PCI compliance. 7 | #> 8 | 9 | #Requires -Version 4.0 10 | #Requires -RunAsAdministrator 11 | #Requires -Modules WebAdministration 12 | 13 | 14 | Import-Module -Name WebAdministration -ErrorAction Stop 15 | 16 | 17 | $requestFilterPath = 'system.webServer/security/requestFiltering/fileExtensions' 18 | 19 | 20 | #clear all previously set configurations for file extensions request filtering 21 | Clear-WebConfiguration -Filter $requestFilterPath 22 | 23 | 24 | # disallow unknown file extensions 25 | $fileExt = Get-WebConfiguration -Filter $requestFilterPath 26 | 27 | Write-Output -InputObject 'Setting to disallow unlisted file extensions on IIS' 28 | 29 | $fileExt.allowUnlisted = $false 30 | $fileExt.applyToWebDAV = $true 31 | $fileExt | Set-WebConfiguration -Filter $requestFilterPath 32 | 33 | 34 | 35 | # allowing known file extensions 36 | Add-WebConfigurationProperty -Filter $requestFilterPath -Name Collection -Value @( 37 | @{fileExtension='.'; allowed='true'}, 38 | @{fileExtension='.aspx'; allowed='true'}, 39 | @{fileExtension='.asmx'; allowed='true'} 40 | @{fileExtension='.axd'; allowed='true'}, 41 | @{fileExtension='.htm'; allowed='true'}, 42 | @{fileExtension='.html'; allowed='true'}, 43 | @{fileExtension='.js'; allowed='true'}, 44 | @{fileExtension='.json'; allowed='true'}, 45 | @{fileExtension='.css'; allowed='true'}, 46 | @{fileExtension='.png'; allowed='true'}, 47 | @{fileExtension='.gif'; allowed='true'}, 48 | @{fileExtension='.jpg'; allowed='true'}, 49 | @{fileExtension='.jpeg'; allowed='true'}, 50 | @{fileExtension='.txt'; allowed='true'}, 51 | @{fileExtension='.xml'; allowed='true'}, 52 | @{fileExtension='.wsdl'; allowed='true'}, 53 | @{fileExtension='.svc'; allowed='true'}, 54 | @{fileExtension='.ashx'; allowed='true'}, 55 | @{fileExtension='.asp'; allowed='true'}, 56 | @{fileExtension='.bmp'; allowed='true'}, 57 | @{fileExtension='.ico'; allowed='true'}, 58 | @{fileExtension='.sitemap'; allowed='true'}, 59 | @{fileExtension='.xls'; allowed='true'}, 60 | @{fileExtension='.zip'; allowed='true'}, 61 | @{fileExtension='.xslx'; allowed='true'}, 62 | @{fileExtension='.csv'; allowed='true'}, 63 | @{fileExtension='.pdf'; allowed='true'}) -------------------------------------------------------------------------------- /IIS/IIS-ServerSettings-SetAppPoolIdentityAnonymous.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Set anonymous authention to 'Application pool identity' 4 | .NOTES 5 | Ensures that 'Application pool identity' is used for anonymous users. 6 | This is a server configuration, keep in mind that, if set, website configurations can override this server settings. 7 | Recommended for PCI compliance. 8 | #> 9 | 10 | #Requires -RunAsAdministrator 11 | 12 | 13 | & "$Env:SystemRoot\system32\inetsrv\appcmd.exe" set config /section:anonymousAuthentication /username:'' --password -------------------------------------------------------------------------------- /IIS/IIS-ServerSettings-SetRequireSSLForFormsAuth.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Enable require SSL globally on IIS for 'Forms Authentication' 4 | .NOTES 5 | This setting is applied even if 'Forms Authentication' is disabled. 6 | This is a server configuration, keep in mind that, if set, website configurations can override this server settings. 7 | Recommended for PCI compliance. 8 | #> 9 | 10 | #Requires -RunAsAdministrator 11 | 12 | 13 | & "$Env:SystemRoot\system32\inetsrv\appcmd.exe" set config /commit:WEBROOT /section:authentication /forms.requireSSL:true -------------------------------------------------------------------------------- /IIS/IIS-ServerSettings-SetRequireSSLOnAllWebsites.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Enables 'Require SSL' (SSL Settings) on all websites 4 | .NOTES 5 | Use this script mainly for verification. 6 | This script does NOT take care of 'Site Bindings". 7 | Recommended for PCI compliance. 8 | #> 9 | 10 | #Requires -Version 4.0 11 | #Requires -RunAsAdministrator 12 | #Requires -Modules WebAdministration 13 | 14 | 15 | Import-Module -Name WebAdministration -ErrorAction Stop 16 | 17 | 18 | # get a list of all websites and web applications 19 | $listWebsite = @() 20 | $siteApp = & "$Env:SystemRoot\system32\inetsrv\appcmd.exe" list app 21 | $siteApp | ForEach-Object { 22 | $webApp = [regex]::Match($_, 'APP\s\"([\w\.\/]+)\"').Groups[1].Value 23 | 24 | $listWebsite += ,@($webApp) 25 | } 26 | 27 | 28 | # apply necessary changes 29 | $securityAccessPath = 'system.webserver/security/access' 30 | $sslSetting = 'Ssl' 31 | 32 | $listWebsite | ForEach-Object { 33 | 34 | $accessSettings = Get-WebConfiguration -Filter $securityAccessPath -PSPath "IIS:\Sites\$_" 35 | 36 | if($accessSettings.sslFlags -ne $sslSetting) 37 | { 38 | Write-Output -InputObject "Setting to require SSL on website '$_'" 39 | 40 | $accessSettings.sslFlags = $sslSetting 41 | $accessSettings | Set-WebConfiguration -Filter $securityAccessPath 42 | } 43 | } 44 | 45 | 46 | # verify all the settings are correct 47 | $errorsFound = 0 48 | $listWebsite | ForEach-Object { 49 | 50 | $accessSettings = Get-WebConfiguration -Filter $securityAccessPath -PSPath "IIS:\Sites\$_" 51 | 52 | if($accessSettings.sslFlags -ne $sslSetting) 53 | { 54 | $errorsFound += 1 55 | Write-Output -InputObject "Error! Require SSL is not set on website '$_'" 56 | } 57 | } 58 | 59 | if($errorsFound -eq 0) 60 | { 61 | Write-Output -InputObject 'Success! Require SSL is enable on all websites.' 62 | } 63 | else 64 | { 65 | Write-Error -Message 'Error! Require SSL is not properly set on all websites' -ErrorAction Stop 66 | } -------------------------------------------------------------------------------- /IIS/IIS-ServerSettings-SetRetailMode.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Sets IIS to run in retail mode 4 | .NOTES 5 | Retail mode disables development settings. 6 | Recommended for PCI compliance. 7 | #> 8 | 9 | #Requires -RunAsAdministrator 10 | 11 | 12 | & "$Env:SystemRoot\system32\inetsrv\appcmd.exe" set config /section:deployment /retail:true /commit:MACHINE -------------------------------------------------------------------------------- /IIS/IIS-ServerSettings-TurnAutomaticBackupsOn.ps1: -------------------------------------------------------------------------------- 1 | Write-Output -InputObject 'Enabling IIS automatic backups!' 2 | 3 | Import-Module -Name WebAdministration -ErrorAction Stop 4 | 5 | $isTurnedOn = Get-WebConfigurationProperty -Filter system.webServer/wdeploy/backup -Name turnedOn | Select-Object -ExpandProperty Value 6 | $isEnabled = Get-WebConfigurationProperty -Filter system.webServer/wdeploy/backup -Name enabled | Select-Object -ExpandProperty Value 7 | 8 | Set-WebConfigurationProperty -Filter system.webServer/wdeploy/backup -Name turnedOn –Value $true 9 | Set-WebConfigurationProperty -Filter system.webServer/wdeploy/backup -Name enabled –Value $true -------------------------------------------------------------------------------- /IIS/IIS-WebsiteSettings-EncryptWebConfigConnectionStrings.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Encrypts web config connection strings 4 | .NOTES 5 | Checks each web config and encrypts every found connection string section. 6 | Recommended for PCI compliance. 7 | #> 8 | 9 | #Requires -Version 4.0 10 | #Requires -RunAsAdministrator 11 | 12 | 13 | Get-ChildItem -Path "$env:HOMEDRIVE\inetpub\" -Filter 'web.config' -Recurse | ForEach-Object { 14 | 15 | $directory = $_.Directory.FullName 16 | $filePath = $_.FullName 17 | $webConfig = [xml](Get-Content -Path $filePath) 18 | 19 | if($webConfig.SelectSingleNode('//connectionStrings').HasChildNodes) { 20 | Write-Output -InputObject "`r`nencrypting '$filePath' connection strings..." 21 | 22 | & $env:windir\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef 'connectionStrings' $directory -prov 'DataProtectionConfigurationProvider' 23 | } 24 | 25 | if(-not ([string]::IsNullOrWhiteSpace($webConfig.SelectSingleNode('//system.web/sessionState[@sqlConnectionString]')))) { 26 | Write-Output -InputObject "`r`nencrypting '$filePath' session state..." 27 | 28 | & $env:windir\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef 'system.web/sessionState' $directory -prov 'DataProtectionConfigurationProvider' 29 | } 30 | } -------------------------------------------------------------------------------- /IIS/Install-WebDeploy.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | 3 | ########### 4 | # Reference: http://stackoverflow.com/questions/19238520/how-to-configure-web-deploy-publishing-feature-on-iis-so-developer-can-publish#23140489 5 | ############ 6 | 7 | 8 | # 1st step: Manuall install webdeploy 9 | 10 | # 2nd step: Run the following 11 | Install-WindowsFeature Web-Server 12 | Install-WindowsFeature Web-Mgmt-Service 13 | Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WebManagement\Server -Name EnableRemoteManagement -Value 1 14 | Net Stop WMSVC 15 | Net Start WMSVC 16 | 17 | netsh advfirewall firewall add rule name="Allow Web Management" dir=in action=allow service="WMSVC" -------------------------------------------------------------------------------- /IIS/Manager module/IIS-Manager.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlouros/PowerShell-toolbox/e95df6b9bea19620be2dfad8fd13ab39b2e8d123/IIS/Manager module/IIS-Manager.psd1 -------------------------------------------------------------------------------- /IIS/Manager module/IIS-Manager.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | #Requires -RunAsAdministrator 3 | #Requires -Modules WebAdministration 4 | 5 | function Get-Password() 6 | { 7 | Param 8 | ( 9 | [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)] 10 | [System.Security.SecureString] $Password 11 | ) 12 | 13 | process 14 | { 15 | $passwordPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password) 16 | $ptPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto($passwordPointer) 17 | 18 | [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($passwordPointer); 19 | 20 | $ptPassword 21 | } 22 | } 23 | 24 | filter Invoke-Ternary 25 | { 26 | param 27 | ( 28 | [Parameter(Mandatory=$True, Position=1)] 29 | [scriptblock]$Predicate, 30 | [Parameter(Mandatory=$True, Position=2)] 31 | [scriptblock]$TrueExpr, 32 | [Parameter(Mandatory=$True, Position=3)] 33 | [scriptblock]$FalseExpr 34 | ) 35 | 36 | if (&$Predicate) 37 | { 38 | &$TrueExpr 39 | } 40 | else 41 | { 42 | &$FalseExpr 43 | } 44 | } 45 | Set-Alias ?: Invoke-Ternary 46 | 47 | <# 48 | .SYNOPSIS 49 | Adds a custom HTTP Header to the IIS Server or specified web site on every response. 50 | 51 | .DESCRIPTION 52 | This function adds a custom HTTP response header to each outgoing response for 53 | the specified website or for any response eminating from the server. 54 | 55 | .PARAMETER WebSiteName 56 | The name of the website that should return the specified HTTP response header. 57 | 58 | If this parameter is not specified, the HTTP response header will be output on each 59 | outgoing response from the server for all websites. 60 | 61 | .PARAMETER HttpHeader 62 | The HTTP response header to be output with each response; e.g. X-Custom-Http-Header 63 | 64 | .PARAMETER HttpHeaderValue 65 | The optional value to be sent with the HTTP response header. 66 | 67 | .EXAMPLE 68 | PS C:> Add-CustomHttpResponseHeader -WebSiteName "Default Web Site" -HttpHeader "X-Custom-Http-Header" -HttpHeaderValue "The value" 69 | 70 | On each response for the 'Default Web Site' the 'X-Custom-Http-Header' will be output with a value of 'The value'. 71 | 72 | .EXAMPLE 73 | PS C:> Add-CustomHttpResponseHeader -HttpHeader "X-Custom-Server-Header" -HttpHeaderValue "My server header" 74 | 75 | On each response from the web server for all hosted web sites, the 'X-Custom-Server-Header' will be output with the value 76 | 'My server header'. 77 | 78 | 79 | #> 80 | function Add-CustomHttpResponseHeader() 81 | { 82 | Param 83 | ( 84 | [Alias('WEBSITE', 'WEB', 'W')] 85 | [string] $WebSiteName, 86 | 87 | [Parameter(Mandatory=$True)] 88 | [ValidateNotNullOrEmpty()] 89 | [Alias('HEADER', 'H')] 90 | [string] $HttpHeader, 91 | 92 | [Alias('VALUE', 'V')] 93 | [string] $HttpHeaderValue 94 | ) 95 | 96 | [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.Web.Administration') | Out-Null 97 | $serverManager = New-Object Microsoft.Web.Administration.ServerManager 98 | 99 | if ([string]::IsNullOrWhiteSpace($WebSiteName)) 100 | { 101 | $config = $serverManager.GetApplicationHostConfiguration() 102 | } 103 | else 104 | { 105 | $config= $serverManager.GetWebConfiguration($WebSiteName) 106 | } 107 | 108 | $httpProtocolSection = $config.GetSection('system.webServer/httpProtocol') 109 | $customHeadersCollection = $httpProtocolSection.GetCollection('customHeaders') 110 | 111 | $newHeader = $customHeadersCollection.CreateElement('add') 112 | $newHeader['name'] = $HttpHeader 113 | $newHeader['value'] = ?: { [string]::IsNullOrEmpty($HttpHeaderValue) } { [string]::Empty } { $HttpHeaderValue } 114 | 115 | $customHeadersCollection.Add($newHeader) 116 | 117 | $serverManager.CommitChanges() 118 | } 119 | 120 | <# 121 | .SYNOPSIS 122 | Sets up an Internet Information Services (IIS) Application Pool 123 | 124 | .DESCRIPTION 125 | This command allows you to setup an IIS Application Pool using the specified 126 | parameters. 127 | 128 | .PARAMETER Name 129 | The name of the IIS Application Pool to create. 130 | 131 | .PARAMETER PipelineMode 132 | The ASP.Net pipeline mode for the new IIS Application Pool. 133 | Valid values are one of Classic and Integrated. 134 | 135 | .PARAMETER ManagedRuntimeVersion 136 | The .Net Framework Runtime version to use for the new IIS Application Pool. 137 | Valid values are one of v2.0 and v4.0. The default is v2.0. 138 | 139 | .PARAMETER CpuMode 140 | Determines whether or not the IIS Application Pool will allow 32-bit web 141 | applications to be run under it even on a 64-bit machine. 142 | Valid values are one of x86 and x64. The default is x64. 143 | 144 | .PARAMETER IdentityType 145 | The type of identity under which the new IIS Application Pool will run. 146 | Valid values are one of LocalSystem, LocalService, NetworkService, 147 | SpecificUser, and ApplicationPoolIdentity. The default is ApplicationPoolIdentity. 148 | 149 | .PARAMETER Username 150 | An optional parameter that specifies the username under which to run the new 151 | IIS Application Pool. 152 | 153 | If the parameter IdentityType is set to SpecificUser, this parameter can be 154 | used to specify the user account under which the new IIS applaciton pool will 155 | run. 156 | 157 | If IdentityType is set to SpecificUser and a value for this parameter is not 158 | specified, you will be prompted for both a username and password. Otherwise, 159 | you will only be prompted for a password. 160 | 161 | .PARAMETER Interactive 162 | When this parameter is specified, this script will be run interactively. The 163 | username and password will be prompted for using the standard Windows 164 | credential dialog. 165 | 166 | Otherwise, you will be prompted for any necessary credentials at the command 167 | line. 168 | 169 | .EXAMPLE 170 | PS C:\> New-IISAppPool -Name "My Application Pool" 171 | 172 | # This example shows how to create a new IIS Application Pool with the default 173 | # settings. 174 | 175 | .EXAMPLE 176 | PS C:\> New-IISAppPool -Name "My Application Pool" -ManagedRuntimeVersion v4.0 177 | 178 | # This example shows how to create a new IIS Application Pool using the 179 | # .Net Framework 4.0. 180 | 181 | .EXAMPLE 182 | PS C:\> New-IISAppPool -Name "My Application Pool" -PipelineMode Classic 183 | 184 | # This example shows how to create a new IIS Application Pool using the 185 | # Classic Managed Pipeline Mode 186 | 187 | .EXAMPLE 188 | PS C:\> New-IISAppPool -Name "My Application Pool" -IdentityType SpecificUser 189 | 190 | # This example shows how to create a new IIS Application Pool running under a 191 | # specific user account. Using this version of the command, you will be 192 | # prompted for both a username and password. 193 | 194 | .EXAMPLE 195 | PS C:\> New-IISAppPool -Name "My Application Pool" -IdentityType SpecificUser -Username "MyDomain\MyUser" 196 | 197 | # This example shows how to create a new IIS Application Pool running under a 198 | # specific user account. Using this version of the command, you will be 199 | # prompted for only a password. 200 | 201 | .EXAMPLE 202 | PS C:\> New-IISAppPool -Name "My Application Pool" -IdentityType SpecificUser -Interactive 203 | 204 | # This example shows how to create a new IIS Application Pool using the 205 | # Windows Credential dialog to prompt for user credentials. 206 | 207 | 208 | #> 209 | function New-IISAppPool() 210 | { 211 | [CmdletBinding(DefaultParameterSetName='Username')] 212 | Param 213 | ( 214 | [Parameter(Mandatory=$true, Position = 0, ValueFromPipeline=$true)] 215 | [ValidateScript({ 216 | if (Test-Path "IIS:\AppPools\$_") 217 | { 218 | Throw New-Object -TypeName System.ArgumentException -ArgumentList "The IIS Application Pool '$_' already exists.", 'Name' 219 | } 220 | else 221 | { 222 | $true 223 | } 224 | })] 225 | [string] $Name, 226 | 227 | [Parameter(Position=1)] 228 | [Alias('MRV', 'V', 'Runtime')] 229 | [ValidateSet('v2.0', 'v4.0')] 230 | [string] $ManagedRuntimeVersion = 'v2.0', 231 | 232 | [Parameter(Position=2)] 233 | [Alias('Pipeline')] 234 | [ValidateSet('Integrated', 'Classic')] 235 | [string] $PipelineMode = 'Integrated', 236 | 237 | [Parameter(Position=3)] 238 | [Alias('CPU')] 239 | [ValidateSet('x86', 'x64')] 240 | [string] $CpuMode = 'x64', 241 | 242 | [Parameter(Position=4, ParameterSetName='Username')] 243 | [Parameter(Position=4, ParameterSetName='Credential')] 244 | [ValidateSet('LocalSystem', 'LocalService', 'NetworkService', 'SpecificUser', 'ApplicationPoolIdentity')] 245 | [string] $IdentityType = 'ApplicationPoolIdentity', 246 | 247 | [Parameter(ParameterSetName='Username')] 248 | [string] $Username = [string]::Empty, 249 | 250 | [Parameter(ParameterSetName='Credential')] 251 | [System.Management.Automation.PSCredential]$Credential, 252 | 253 | [switch] $Interactive 254 | ) 255 | 256 | [System.Management.Automation.PSCredential] $AppPoolCredential 257 | 258 | if ($IdentityType.ToLowerInvariant() -eq 'SpecificUser'.ToLowerInvariant()) 259 | { 260 | if ($PSCmdlet.ParameterSetName -imatch 'Credential') 261 | { 262 | $AppPoolCredential = $Credential 263 | } 264 | else 265 | { 266 | if ([string]::IsNullOrWhiteSpace($Username)) 267 | { 268 | if ($Interactive) 269 | { 270 | $AppPoolCredential = $Host.UI.PromptForCredential('Application Pool Identity Credentials', 'Please specify the username and password to be used for the Application Pool Identity.', $Username, '', [System.Management.Automation.PSCredentialTypes]::Domain, [System.Management.Automation.PSCredentialUIOptions]::ValidateUserNameSyntax) 271 | } 272 | else 273 | { 274 | $AppPoolCredential = New-Object System.Management.Automation.PSCredential $(Read-Host -Prompt 'Application Pool Identity Username'), $(Read-Host -Prompt 'Application Pool Identity Password' -AsSecureString) 275 | } 276 | } 277 | 278 | if ($Interactive) 279 | { 280 | $AppPoolCredential = $Host.UI.PromptForCredential('Application Pool Identity Password', 'Please enter the password for the specified user to be used for the Application Pool Identity.', $Username, '', [System.Management.Automation.PSCredentialTypes]::Domain, [System.Management.Automation.PSCredentialUIOptions]::ValidateUserNameSyntax) 281 | } 282 | else 283 | { 284 | $AppPoolCredential = New-Object System.Management.Automation.PSCredential $Username, $(Read-Host -Prompt "Application Pool Identity Password for '$Username'" -AsSecureString) 285 | } 286 | } 287 | } 288 | 289 | Write-Verbose 'The following IIS Application Pool will be created:' 290 | Write-Verbose " Application Pool Name: $Name" 291 | Write-Verbose " Application Pool Managed Runtime Version: $ManagedRuntimeVersion" 292 | Write-Verbose " Application Pool CPU Mode: $CpuMode" 293 | Write-Verbose " Application Pool Pipeline Mode: $PipelineMode" 294 | Write-Verbose " Application Pool Identity Type: $IdentityType" 295 | if ($IdentityType -imatch 'SpecificUser') 296 | { 297 | Write-Verbose " Application Pool Identity Username: $Username" 298 | } 299 | 300 | New-WebAppPool $Name 301 | 302 | if ($ManagedRuntimeVersion -eq 'v4.0') 303 | { 304 | Set-ItemProperty "IIS:\AppPools\$Name" managedRuntimeVersion $ManagedRuntimeVersion 305 | } 306 | 307 | if ($PipelineMode -imatch 'Classic') 308 | { 309 | Set-ItemProperty "IIS:\AppPools\$Name" managedPipelineMode 1 310 | } 311 | 312 | if ($CpuMode -imatch 'x86') 313 | { 314 | Set-ItemProperty "IIS:\AppPools\$Name" enable32BitAppOnWin64 $true 315 | } 316 | 317 | switch ($IdentityType.ToLowerInvariant()) 318 | { 319 | 'localsystem' { Set-ItemProperty "IIS:\AppPools\$Name" processModel.identityType 0 } 320 | 'localservice' { Set-ItemProperty "IIS:\AppPools\$Name" processModel.identityType 1 } 321 | 'networkservice' { Set-ItemProperty "IIS:\AppPools\$Name" processModel.identityType 2 } 322 | 'specificuser' 323 | { 324 | Set-ItemProperty "IIS:\AppPools\$Name" processModel.identityType 3 325 | Set-ItemProperty "IIS:\AppPools\$Name" processModel.userName $AppPoolCredential.UserName 326 | Set-ItemProperty "IIS:\AppPools\$Name" processModel.password $(Get-Password -Password $AppPoolCredential.Password) 327 | } 328 | default { Set-ItemProperty "IIS:\AppPools\$Name" processModel.identityType 4 } 329 | } 330 | 331 | Write-Verbose "Application Pool '$Name' was successfully created." 332 | } 333 | 334 | <# 335 | .SYNOPSIS 336 | Creates a new IIS Virtual Directory with the specified name, physical path, and 337 | IIS site and application location using any supplied credentials. 338 | 339 | .DESCRIPTION 340 | This function enhances the standand WebAdministration module's New-WebVirtualDirectory 341 | function by allowing you to specify the credentials that should be used by IIS when 342 | accessing the Virtual Directory. If no credentials are supplied, the standard 343 | New-WebVirtualDirectory method is used to simply create the requested virtual 344 | directory. 345 | 346 | .PARAMETER Name 347 | The name of the virtual directory to create. 348 | 349 | .PARAMETER PhysicalPath 350 | The physical path on the file system for the new virtual directory. The folder specified must already exist. 351 | 352 | .PARAMETER Site 353 | The site name under which the virtual directory should be created. 354 | 355 | .PARAMETER Application 356 | The application under which the virtual directory should be created. 357 | 358 | .PARAMETER Username 359 | The username to impersonate when accessing the virtual directory. If you use this parameter, 360 | the script will prompt you to enter a password. 361 | 362 | .PARAMETER Credential 363 | This parameter allows you to specify credentials that should be impersonated when 364 | accessing the virtual directory. 365 | 366 | .PARAMETER Force 367 | Forces the virtual directory to be created. If the virtual directory already exists, 368 | it will be replaced with the configuration specified to this function. 369 | 370 | .EXAMPLE 371 | C:\PS> New-IISVirtualDirectory -Site "Default Web Site" -Name ContosoVDir -PhysicalPath c:\inetpub\contoso 372 | 373 | This is the same example as shown in the New-WebVirtualDirectory cmdlet help. Using 374 | this syntax with this function results in identical behavior as New-WebVirtualDirectory. 375 | 376 | .EXAMPLE 377 | C:\PS> New-IISVirtualDirecotry -Site "Default Web Site" -Name ContosoVDir -PhysicalPath c:\inetpub\contoso -Username myDomain\MyUsername 378 | 379 | This example will create the same virtual directory as above. Additionally, you 380 | will be prompted for the password for the specified user and those credentials 381 | will be attached to the created virtual directory in order to impersonate the 382 | user when accessing the virtual directory. 383 | 384 | #> 385 | function New-IISVirtualDirectory() 386 | { 387 | [CmdletBinding(DefaultParameterSetName='Username')] 388 | Param 389 | ( 390 | [Parameter(Mandatory=$True, Position = 0, ValueFromPipelineByPropertyName=$True)] 391 | [ValidateNotNullOrEmpty()] 392 | [string] $Name, 393 | 394 | [Parameter(ValueFromPipelineByPropertyName=$True)] 395 | [Alias('Path', 'P')] 396 | [string] $PhysicalPath, 397 | 398 | [Parameter(Mandatory=$True, Position = 1, ValueFromPipelineByPropertyName=$True)] 399 | [ValidateNotNullOrEmpty()] 400 | [Alias('S')] 401 | [string] $Site, 402 | 403 | [Parameter(ParameterSetName='Username')] 404 | [Alias('User', 'U')] 405 | [string] $Username = [string]::Empty, 406 | 407 | [Parameter(ParameterSetName='Credential')] 408 | [System.Management.Automation.PSCredential] $Credential, 409 | 410 | [Parameter(ValueFromPipelineByPropertyName=$TRue)] 411 | [Alias('App', 'A')] 412 | [string] $Application = [string]::Empty, 413 | 414 | [switch] $Force 415 | ) 416 | 417 | Process 418 | { 419 | $local:VDirCred = $Credential 420 | 421 | New-WebVirtualDirectory -Name $Name -PhysicalPath $PhysicalPath -Site $Site -Application $Application -Force:$Force -ErrorAction Stop 422 | 423 | if (-not [string]::IsNullOrWhiteSpace($Username) -or $local:VDirCred) 424 | { 425 | $local:pathToVDir = "IIS:\Sites\$Site" 426 | if (-not [string]::IsNullOrWhiteSpace($Application)) 427 | { 428 | $local:pathToVDir = Join-Path $local:pathToVDir $Application 429 | } 430 | 431 | $local:pathToVDir = Join-Path $local:pathToVDir $Name 432 | 433 | if (-not $local:VDirCred) 434 | { 435 | $local:VDirCred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username, $(Read-Host -Prompt "`r`nPassword for '$Username'" -AsSecureString) 436 | } 437 | 438 | Set-ItemProperty $local:pathToVDir username $local:VDirCred.UserName 439 | Set-ItemProperty $local:pathToVDir password $(Get-Password $local:VDirCred.Password) 440 | } 441 | } 442 | } 443 | 444 | <# 445 | .SYNOPSIS 446 | This function will create a new IIS Application Pool and Website with the 447 | specified settings. 448 | 449 | .DESCRIPTION 450 | This function allows you to specify most of the common settings required for 451 | creating a new IIS Application Pool and Website. 452 | 453 | This function assumes that the website will use Pass-Through Authentication. 454 | 455 | .PARAMETER PhysicalPath 456 | The path, on disk, where the website should be located. If a relative path is 457 | given, this function will assume it should be located on the root drive of 458 | %windir% in the inetpub\wwwroot folder. On most installations of Windows, this 459 | translates to a location under 'C:\inetpub\wwwroot'. 460 | 461 | If you want the site to be located elsewhere, specify an absolute path for 462 | this parameter value. 463 | 464 | If the path specified does not exist, it will be created for you. 465 | 466 | .PARAMETER WebSiteName 467 | This parameter represents the name of the Website, as it will be known in the 468 | IIS Manager Console. 469 | 470 | .PARAMETER AppPoolname 471 | This parameter represents the name of the IIS Application Pool as it will be 472 | known in the IIS Manager Console. 473 | 474 | .PARAMETER AppPoolUser 475 | This parameter allows you to specify the username of the user under which the 476 | IIS Application Pool should run. 477 | 478 | If you don't select an IdentityType and you don't specify this parameter, 479 | you will be prompted for a username and password. 480 | 481 | If you do specify this parameter, you will still be prompted for a password. 482 | 483 | .PARAMETER HostHeader 484 | This parameter allows you to specify the Host Header to be used for the 485 | website binding. The website will only respond to requests that are 486 | directed to the hostname matching the value of this parameter, addressed 487 | to the IP Address specified by IPAddress (if any) and arriving over the 488 | TCP port specified by the Port parameter. 489 | 490 | .PARAMETER IPAddress 491 | This parameter allows you to specify the IP Address for the website binding. 492 | The website will only respond to requests directed to the host specified by 493 | HostHeader, addressed to the value of this parameter, and arriving on the 494 | port speciied by the value of the Port parameter. 495 | 496 | .PARAMETER UseCustomPort 497 | If this parameter is specified, the port specified by the Port parameter 498 | will be used. If the Port parameter is not specified, the default port for 499 | the protocol (HTTP vs. HTTPS) will be used. 500 | 501 | .PARAMETER Port 502 | This parameter allows you to specify a number between 0 and 65535, inclusive. 503 | The website will only respond to requests directed to the host specified by 504 | HostHeader, addressed to IPAddress, and arriving on the port speciied by the 505 | value of this parameter. 506 | 507 | .PARAMETER Ssl 508 | Specifying this parameter enables SSL binding for the site. 509 | 510 | .PARAMETER PipelineMode 511 | The ASP.Net pipeline mode for the new IIS Application Pool. 512 | Valid values are one of Classic and Integrated. 513 | 514 | .PARAMETER ManagedRuntimeVersion 515 | The .Net Framework Runtime version to use for the new IIS Application Pool. 516 | Valid values are one of v2.0 and v4.0. The default is v2.0. 517 | 518 | .PARAMETER CpuMode 519 | Determines whether or not the IIS Application Pool will allow 32-bit web 520 | applications to be run under it even on a 64-bit machine. 521 | Valid values are one of x86 and x64. The default is x64. 522 | 523 | .PARAMETER IdentityType 524 | The type of identity under which the new IIS Application Pool will run. 525 | Valid values are one of LocalSystem, LocalService, NetworkService, 526 | and ApplicationPoolIdentity. The default is ApplicationPoolIdentity. 527 | 528 | This parameter is only applicable when not explicity setting a value 529 | for the AppPoolUser parameter. 530 | 531 | .PARAMETER Interactive 532 | Specifying this parameter indicates that you wish to run this script 533 | interactively. Instead of being prompted for credentials at the command line, 534 | you will instead be prompted using the standard Windows Credentials dialog. 535 | 536 | .EXAMPLE 537 | PS C:\> New-IISWebsiteAndAppPool "WebSite" "WebSite.AppPool" -H "www.mywebsite.com" 538 | 539 | This example creates a new website called 'WebSite' running under the newly created 540 | application pool 'WebSite.AppPool' responding to requests to the host 541 | 'www.mywebiste.com' over the default HTTP TCP port 80. 542 | 543 | #> 544 | function New-IISWebsiteAndAppPool() 545 | { 546 | [CmdletBinding(DefaultParameterSetName='SpecialAppPoolIdentity')] 547 | Param 548 | ( 549 | [Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$True)] 550 | [ValidateNotNullOrEmpty()] 551 | [Alias('Path')] 552 | [string] $PhysicalPath, 553 | 554 | [Parameter(Mandatory=$True, Position=1, ValueFromPipelineByPropertyName=$True)] 555 | [Alias('SiteName', 'S', 'Web', 'W')] 556 | [string] $WebSiteName, 557 | 558 | [Parameter(Position=2, ValueFromPipelineByPropertyName=$True)] 559 | [Alias('AppPool', 'App', 'A')] 560 | [string] $AppPoolName, 561 | 562 | [Parameter(ParameterSetName='UserAppPoolIdentity')] 563 | [Alias('User', 'U')] 564 | [string] $AppPoolUser, 565 | 566 | [Parameter(ParameterSetName='CredentialAppPoolIdentity')] 567 | [Alias('Cred')] 568 | [System.Management.Automation.PSCredential]$Credential, 569 | 570 | [Alias('H')] 571 | [string] $HostHeader, 572 | 573 | [Alias('IP')] 574 | [string] $IPAddress, 575 | 576 | [switch] $UseCustomPort, 577 | 578 | [Alias('P')] 579 | [ValidateScript({ 580 | if ($_ -and $_ -gt 65535) 581 | { 582 | $False 583 | } 584 | else 585 | { 586 | $True 587 | } 588 | })] 589 | [Nullable[uint32]] $Port, 590 | 591 | [Switch] $Ssl, 592 | 593 | [Alias('Pipeline')] 594 | [ValidateSet('Classic', 'Integrated')] 595 | [string] $PipelineMode = 'Classic', 596 | 597 | [Alias('V', 'MRV', 'Runtime')] 598 | [ValidateSet('v2.0', 'v4.0')] 599 | [string] $ManagedRuntimeVersion = 'v2.0', 600 | 601 | [Alias('CPU')] 602 | [ValidateSet('x86', 'x64')] 603 | [string] $CpuMode = 'x64', 604 | 605 | [Parameter(ParameterSetName='SpecialAppPoolIdentity')] 606 | [ValidateSet('LocalSystem', 'LocalService', 'NetworkService', 'ApplicationPoolIdentity')] 607 | [string] $IdentityType = 'ApplicationPoolIdentity', 608 | 609 | [switch] $Interactive 610 | ) 611 | 612 | Process 613 | { 614 | if (-not [System.IO.Path]::IsPathRooted($PhysicalPath)) 615 | { 616 | $wwwroot = [System.IO.Path]::Combine([System.IO.Path]::GetPathRoot($env:SystemRoot), 'inetpub', 'wwwroot') 617 | Write-Verbose "The path '$PhysicalPath' is a relative path. Assuming it should be located relative to '$wwwroot'." 618 | $PhysicalPath = [System.IO.Path]::Combine($wwwroot, $PhysicalPath) 619 | } 620 | 621 | if (-not (Test-Path $PhysicalPath)) 622 | { 623 | Write-Verbose "The location '$PhysicalPath' could not be found." 624 | Write-Verbose "Creating the location '$PhysicalPath'." 625 | New-Item $PhysicalPath -ItemType Directory | Out-Null 626 | Write-Verbose "Created '$PhysicalPath'." 627 | } 628 | 629 | $newAppPoolParams = @{ 630 | 'Name' = $AppPoolName; 631 | 'PipelineMode' = $PipelineMode; 632 | 'ManagedRuntimeVersion' = $ManagedRuntimeVersion; 633 | 'CpuMode' = $CpuMode; 634 | 'Interactive' = $Interactive; 635 | } 636 | 637 | if ($PSCmdlet.ParameterSetName -imatch 'CredentialAppPoolIdentity') 638 | { 639 | $newAppPoolParams.Add('IdentityType', 'SpecificUser') 640 | $newAppPoolParams.Add('Credential', $Credential) 641 | } 642 | elseif ($PSCmdlet.ParameterSetName -imatch 'UserAppPoolIdentity') 643 | { 644 | $newAppPoolParams.Add('IdentityType', 'SpecificUser') 645 | 646 | if (-not [string]::IsNullOrWhiteSpace($AppPoolUser)) 647 | { 648 | 649 | $newAppPoolParams.Add('Username', $AppPoolUser) 650 | } 651 | } 652 | else 653 | { 654 | $newAppPoolParams.Add('IdentityType', $IdentityType) 655 | } 656 | 657 | New-IISAppPool @newAppPoolParams 658 | 659 | # Create the new website 660 | $newWebsiteParams = @{ 661 | 'Name' = $WebSiteName; 662 | 'ApplicationPool' = $AppPoolName; 663 | 'PhysicalPath' = $PhysicalPath; 664 | 'Ssl' = $Ssl 665 | } 666 | 667 | if ($UseCustomPort) 668 | { 669 | Write-Verbose 'The parameter -UseCustomPort was set.' 670 | 671 | if ($Port) 672 | { 673 | Write-Verbose "Using custom port $Port." 674 | $newWebsiteParams.Add('Port', $Port) 675 | } 676 | else 677 | { 678 | Write-Verbose 'Even though -UseCustomPort was set, no port was provided.' 679 | if ($Ssl) 680 | { 681 | Write-Verbose 'SSL was specified, so using port 443.' 682 | $newWebsiteParams.Add('Port', 443) 683 | } 684 | else 685 | { 686 | Write-Verbose 'Using port 80.' 687 | $newWebsiteParams.Add('Port', 80) 688 | } 689 | } 690 | } 691 | 692 | if (-not [string]::IsNullOrWhiteSpace($HostHeader)) 693 | { 694 | $newWebsiteParams.Add('HostHeader', $HostHeader) 695 | } 696 | 697 | if (-not [string]::IsNullOrWhiteSpace($IPAddress)) 698 | { 699 | $newWebsiteParams.Add('IPAddress', $IPAddress) 700 | } 701 | 702 | New-Website @newWebSiteParams 703 | } 704 | } 705 | 706 | 707 | Export-ModuleMember -Function Add-CustomHttpResponseHeader, Get-Password, New-IISWebsiteAndAppPool, Invoke-Ternary, New-IISAppPool, New-IISVirtualDirectory -Alias ?: -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 John Louros 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. -------------------------------------------------------------------------------- /Misc/Automate Windows Security prompt input/Run-Explorer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Open Windows Explorer in the 'local\administrator' credentials 4 | .NOTES 5 | Quickly open a new Windows Explorer Windows using 'local\adminstrator' credentials 6 | #> 7 | 8 | param( 9 | [string]$hostname = "dev.vm-001.local" 10 | ) 11 | 12 | Process 13 | { 14 | # helper function to locate a open program using by a given Window name 15 | Function FindWindow([string]$windowName, [int]$retries = 5, [int]$sleepInterval = 1000) { 16 | 17 | [int]$currentTry = 0; 18 | [bool]$windowFound = $false; 19 | 20 | Do { 21 | $currentTry++; 22 | 23 | Start-Sleep -Milliseconds $sleepInterval 24 | Try { 25 | [Microsoft.VisualBasic.Interaction]::AppActivate($windowName) 26 | $windowFound = $true; 27 | } Catch { 28 | Write-Host " [$currentTry out of $retries] failed to find Window with title '$windowName'" -ForegroundColor Yellow 29 | $windowFound = $false; 30 | } 31 | } While ($currentTry -lt $retries -and $windowFound -eq $false) 32 | 33 | 34 | return $windowFound; 35 | } 36 | 37 | # import required assemblies 38 | Add-Type -AssemblyName Microsoft.VisualBasic 39 | Add-Type -AssemblyName System.Windows.Forms 40 | 41 | 42 | # test if the provided hostname is valid 43 | $testedHostname = Test-Connection $hostname -Count 1 -ErrorAction SilentlyContinue 44 | 45 | if($testedHostname -eq $null) { 46 | Write-Error "the provided hostname could not be resolved '$hostname'" -ErrorAction Stop 47 | } 48 | 49 | $vmRootLocation = Join-Path "\\$($testedHostname.Address)" "\C$\" 50 | 51 | Write-Host "opening Windows Explorer at '$vmRootLocation' using 'local\administrator' credentials!" 52 | explorer /root,$vmRootLocation 53 | 54 | # handle the security prompt to enter username and password 55 | if(FindWindow("Windows Security")) { 56 | Start-Sleep -Milliseconds 250 57 | [System.Windows.Forms.SendKeys]::SendWait('local\administrator{TAB}') 58 | [System.Windows.Forms.SendKeys]::SendWait('Password123{ENTER}') 59 | } 60 | 61 | 62 | Write-Host "done!" 63 | } -------------------------------------------------------------------------------- /Misc/Automate Windows Security prompt input/Run-RemoteDesktop.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Start Remote Desktop with 'local\administrator' credentials 4 | .NOTES 5 | Useful to rapidly connect to a Go Lab VM 6 | #> 7 | 8 | Param( 9 | [string]$hostname = "dev.vm-001.local" 10 | ) 11 | 12 | Process 13 | { 14 | # helper function to locate a open program using by a given Window name 15 | Function FindWindow([string]$windowName, [int]$retries = 5, [int]$sleepInterval = 1000) { 16 | 17 | [int]$currentTry = 0; 18 | [bool]$windowFound = $false; 19 | 20 | Do { 21 | $currentTry++; 22 | 23 | Start-Sleep -Milliseconds $sleepInterval 24 | Try { 25 | [Microsoft.VisualBasic.Interaction]::AppActivate($windowName) 26 | $windowFound = $true; 27 | } Catch { 28 | Write-Host " [$currentTry out of $retries] failed to find Window with title '$windowName'" -ForegroundColor Yellow 29 | $windowFound = $false; 30 | } 31 | } While ($currentTry -lt $retries -and $windowFound -eq $false) 32 | 33 | 34 | return $windowFound; 35 | } 36 | 37 | # import required assemblies 38 | Add-Type -AssemblyName Microsoft.VisualBasic 39 | Add-Type -AssemblyName System.Windows.Forms 40 | 41 | 42 | # test if the provided hostname is valid 43 | $testedHostname = Test-Connection $hostname -Count 1 -ErrorAction SilentlyContinue 44 | 45 | if($testedHostname -eq $null) { 46 | Write-Error "the provided hostname could not be resolved '$hostname'" -ErrorAction Stop 47 | } 48 | 49 | $vmIp = $testedHostname.IPV4Address.IPAddressToString 50 | 51 | # open Remote Desktop with 'local\administrator' 52 | Write-Host "starting connection to '$testedHostname' using 'local\administrator' credentials!" 53 | cmdkey /generic:TERMSRV/$vmIp /user:local\administrator 54 | mstsc /v:$vmIp 55 | 56 | # first prompt to enter the password 57 | if(FindWindow("Windows Security")) { 58 | Start-Sleep -Milliseconds 500 59 | [System.Windows.Forms.SendKeys]::SendWait('Password123{ENTER}') 60 | } 61 | 62 | # second prompt to accept the certificate 63 | if(FindWindow("Remote Desktop Connection")) { 64 | Start-Sleep -Milliseconds 250 65 | [System.Windows.Forms.SendKeys]::SendWait('Y') 66 | } 67 | 68 | 69 | Write-Host "done!" 70 | } -------------------------------------------------------------------------------- /Misc/Automate Windows Security prompt input/Run-SqlTool.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Opens a local instance of the selected SQL tools, using a 'local\administrator' credentials 4 | .NOTES 5 | Useful for profiling Go Lab environments since 'local\administrator' is the default local administrator of those machines 6 | #> 7 | 8 | Param([Switch] $SqlProfiler) 9 | 10 | Process 11 | { 12 | # a new Command Prompt Window should be opened with this title 13 | $newCmdlineWindowTitle = "C:\Windows\System32\cmd.exe" 14 | 15 | # import required assemblies 16 | Add-Type -AssemblyName Microsoft.VisualBasic 17 | Add-Type -AssemblyName System.Windows.Forms 18 | 19 | 20 | Start-Process "cmd.exe" 21 | 22 | Start-Sleep -Milliseconds 1000 23 | [Microsoft.VisualBasic.Interaction]::AppActivate($newCmdlineWindowTitle) 24 | 25 | if($SqlProfiler) { 26 | # open SQL Server Profiler 27 | Write-Output "about to open SQL Server Profiler" 28 | [System.Windows.Forms.SendKeys]::SendWait('runas /netonly /user:local\administrator "C:\Program Files {(}x86{)}\Microsoft SQL Server\110\Tools\Binn\PROFILER.EXE"{ENTER}') 29 | } 30 | else { 31 | # open SQL Server Management Studio 32 | Write-Output "about to open SQL Server Management Studio" 33 | [System.Windows.Forms.SendKeys]::SendWait('runas /netonly /user:local\administrator "C:\Program Files {(}x86{)}\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\Ssms.exe"{ENTER}') 34 | } 35 | 36 | Start-Sleep -Milliseconds 500 37 | [System.Windows.Forms.SendKeys]::SendWait('Password123{ENTER}') 38 | 39 | # close command prompt window 40 | Start-Sleep -Milliseconds 500 41 | [Microsoft.VisualBasic.Interaction]::AppActivate($newCmdlineWindowTitle) 42 | [System.Windows.Forms.SendKeys]::SendWait('exit{ENTER}') 43 | 44 | 45 | Write-Host "done!" 46 | } -------------------------------------------------------------------------------- /Misc/Create schedule task to execute ps1 script/Kill-Process.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | 3 | 4 | # define the process name here 5 | $target = "PROCESS-NAME-TO-KILL" 6 | 7 | 8 | $process = Get-Process $target -ErrorAction SilentlyContinue 9 | 10 | if ($process -ne $null) 11 | { 12 | $process.Kill() 13 | } 14 | -------------------------------------------------------------------------------- /Misc/Create schedule task to execute ps1 script/Kill-Process.vbs: -------------------------------------------------------------------------------- 1 | Dim objShell,objFSO,objFile 2 | 3 | Set objShell=CreateObject("WScript.Shell") 4 | Set objFSO=CreateObject("Scripting.FileSystemObject") 5 | 6 | 'enter the path for your PowerShell Script 7 | strPath="C:\StartupScripts\Kill-Process.ps1" 8 | 9 | 'verify file exists 10 | If objFSO.FileExists(strPath) Then 11 | 'return short path name 12 | set objFile=objFSO.GetFile(strPath) 13 | strCMD="powershell -nologo -command " & Chr(34) & "&{" & objFile.Path & "}" & Chr(34) 14 | 'Uncomment next line for debugging 15 | 'WScript.Echo strCMD 16 | 17 | 'use 0 to hide window 18 | objShell.Run strCMD,0 19 | 20 | Else 21 | 22 | 'Display error message 23 | WScript.Echo "Failed to find " & strPath 24 | WScript.Quit 25 | 26 | End If -------------------------------------------------------------------------------- /Misc/Create schedule task to execute ps1 script/Setup/Create-ScheduleTask-To-Kill-Process.ps1: -------------------------------------------------------------------------------- 1 | & schtasks.exe /create /TN "Kill Process Task" /XML ".\ScheduleTask-To-Kill-Process.xml" -------------------------------------------------------------------------------- /Misc/Create schedule task to execute ps1 script/Setup/ScheduleTask-To-Kill-Process.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlouros/PowerShell-toolbox/e95df6b9bea19620be2dfad8fd13ab39b2e8d123/Misc/Create schedule task to execute ps1 script/Setup/ScheduleTask-To-Kill-Process.xml -------------------------------------------------------------------------------- /Misc/PowerShell 5 Presentation Scripts (April 2015)/Demo-Class_Enum-Script.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5.0 2 | 3 | 4 | # declare a enum 5 | Enum PrtgMode { 6 | On 7 | Off 8 | } 9 | 10 | # define a class 11 | Class WebsiteMonitor 12 | { 13 | #Properties 14 | [Boolean]$prtg 15 | [int]$TIMEOUT = 3000 16 | [string]$TargetNodeCompName 17 | 18 | #Constructor 19 | WebsiteMonitor([string]$target) { 20 | $this.prtg = $false 21 | $this.TargetNodeCompName = $target 22 | 23 | # disable SSL certificate checks (might be needed) 24 | #[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} 25 | } 26 | 27 | #Constructor 28 | WebsiteMonitor([string]$target, [PrtgMode] $setPrtg) { 29 | $this.prtg = $setPrtg -eq [PrtgMode]::On 30 | $this.TargetNodeCompName = $target 31 | 32 | # disable SSL certificate checks (might be needed) 33 | #[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} 34 | } 35 | 36 | #Methods 37 | [Void] AssertWebsiteIsAvailable ([String]$hostHeader, [String]$path) 38 | { 39 | $uri = 'https://' + $this.TargetNodeCompName + $path 40 | 41 | try { 42 | 43 | if (!$this.prtg) { 44 | Write-Host "Verifying Website '$uri' is available. TargetNodeCompName=$($this.TargetNodeCompName) HostHeader=$hostHeader path=$path" 45 | } 46 | 47 | $req = [system.Net.HttpWebRequest]::Create($uri) 48 | if (!([string]::IsNullOrEmpty($hostheader))) { 49 | $req.Host = $hostHeader 50 | } 51 | $req.Timeout = $this.TIMEOUT 52 | $req.UserAgent = 'PRTG/Go Health Check' 53 | $res = $req.getresponse() 54 | $status = $res.statuscode 55 | $content_length = $res.contentlength 56 | $res.close(); 57 | 58 | If (!($status -eq 200 -and $content_length -gt 0)) { 59 | if ($this.prtg) { 60 | Write-Host -nonewline '2:' 61 | } 62 | Write-Host "Verification of '$uri' failed. HTTP Status is '$status' and Content-Length is '$content_length'" 63 | } 64 | } catch [Exception] { 65 | if ($this.prtg) { 66 | Write-Host -nonewline '2:' 67 | } 68 | Write-Host "Verification of '$uri' failed. More info: " $_.Exception.Message 69 | } 70 | } 71 | } 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | # create a new instance of 'WebsiteMonitor' 80 | $monitor = [WebsiteMonitor]::New('VirtualMachine-Name',[PrtgMode]::Off) 81 | 82 | 83 | $sitesToVerify = @( 84 | ('ps1.localhost', '/MagensaDemo/ServiceRelay.asmx'), 85 | ('gwadmin.localhost', '/signin.aspx'), 86 | ('genius.localhost', '/v1/Login.aspx'), 87 | ('manage.localhost', '/MobileAccess/CredentialService.asmx'), 88 | ('transport.localhost', '/v4/TransportService.asmx') 89 | ) 90 | 91 | # call 'AssertWebsiteIsAvailable' method for each entrie in '$sitesToVerify' array 92 | foreach ($value in $sitesToVerify) { 93 | $monitor.AssertWebsiteIsAvailable($value[0],$value[1]) 94 | } 95 | -------------------------------------------------------------------------------- /Misc/PowerShell 5 Presentation Scripts (April 2015)/Demo-CodeAnalysis-Commands.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5.0 2 | 3 | # also requires "Windows Management Framework 5.0 Preview February 2015" check out the link below 4 | # http://blogs.msdn.com/b/powershell/archive/2015/02/18/windows-management-framework-5-0-preview-february-2015-is-now-available.aspx 5 | 6 | # get a list of static code analysis rules 7 | Get-ScriptAnalyzerRule| Out-GridView 8 | 9 | # run code analysis on script 'ClassScript.ps1' located in the current folder 10 | Invoke-ScriptAnalyzer -Path .\ClassScript.ps1 11 | 12 | 13 | # define what rules to include/exclude 14 | Invoke-ScriptAnalyzer -Path .\ClassScript.ps1 -IncludeRule ('AvoidUnitializedVariable', 'UseApprovedVerbs') -ExcludeRule 'UseSingularNouns' -------------------------------------------------------------------------------- /Misc/PowerShell 5 Presentation Scripts (April 2015)/Demo-OneGet-Commands.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5.0 2 | 3 | #List all commands for 'OneGet' powershell module 4 | Get-Command -Module OneGet 5 | 6 | #Get a list of package providers 7 | Get-PackageProvider 8 | 9 | #Register Chocolatey as package source 10 | #Or read PackageSource information if already installed 11 | Get-PackageSource -Provider chocolatey 12 | 13 | #Discover some packages 14 | Find-Package -Name zoomit -AllVersions 15 | 16 | #find package with UI 17 | Find-Package zoomit -AllVersions | Out-Gridview 18 | 19 | #Install a package 20 | Install-Package -Name zoomit -Verbose 21 | 22 | #Show what packages are installed 23 | Get-Package 24 | 25 | #Filter to Chocolatey only 26 | Get-Package -ProviderName Chocolatey 27 | 28 | #find package with UI, pick it and install it 29 | Find-Package zoomit -AllVersions | Out-Gridview -PassThru | Install-Package 30 | 31 | 32 | #get package and uninstall it 33 | Get-Package -Name zoomit | Uninstall-Package -------------------------------------------------------------------------------- /Misc/PowerShell 5 Presentation Scripts (April 2015)/Demo-OurOwnOneGet-Commands.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5.0 2 | 3 | 4 | #register my OneGet Server 5 | Register-PackageSource -Name myChocolateyRepository -Location 'http://john-pc:8000/nuget' -Provider chocolatey -Trusted -Verbose 6 | 7 | #list all packages from this source 8 | Find-Package -Source myChocolateyRepository 9 | 10 | #find package with UI and install the selected one 11 | Find-Package -Source myChocolateyRepository -AllVersions | Out-Gridview -PassThru | Install-Package 12 | 13 | #unregister 14 | Unregister-PackageSource -Name myChocolateyRepository 15 | -------------------------------------------------------------------------------- /Misc/PowerShell 5 Presentation Scripts (April 2015)/Demo-OurPowerShellGet-Commands.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5.0 2 | 3 | #register my PowerShellGet Server 4 | $PowerShellGetServerUrl = 'http://john-pc:8001/nuget' #location of your PowerShellGet server 5 | Register-PackageSource -Name myPowerShellGetRepository -Location $PowerShellGetServerUrl -Provider PSModule -Trusted -Verbose 6 | 7 | #list all packages from this source 8 | Find-Package -Source myPowerShellGetRepository 9 | 10 | #find package with UI and install the selected one 11 | Find-Package -Source myPowerShellGetRepository -AllVersions | Out-Gridview -PassThru | Install-Package 12 | 13 | #get package 'PSReadLine' and uninstall it 14 | Get-Package -Name PSReadLine | Uninstall-Package 15 | 16 | #unregister previously registered PowerShellGet server 17 | Unregister-PackageSource -Name myPowerShellGetRepository 18 | 19 | 20 | #other useful commands 21 | 22 | #list all locations where PowerShell modules can be installed 23 | [Environment]::GetEnvironmentVariable('PSModulePath') 24 | 25 | #lists all commands included in 'PSReadLine' module 26 | Get-Command -Module PSReadLine -------------------------------------------------------------------------------- /Misc/PowerShell 5 Presentation Scripts (April 2015)/Demo-ParseContacts-Commands.ps1: -------------------------------------------------------------------------------- 1 | #template 2 | $TemplateAdr = @' 3 | #CONTACT 4 | ID=11 5 | NAME={Name*:Justynka} 6 | CREATED=1195505237 7 | MAIL={Mail:JUSTYNA66@gmail.com} 8 | ICON=Contact0 9 | 10 | #CONTACT 11 | ID=20 12 | NAME={Name*:Poczta Grupowa} 13 | URL= 14 | CREATED=1347221208 15 | DESCRIPTION= 16 | ACTIVE=YES 17 | MAIL={Mail:xyz.abc.grupa.foo@gmail.com} 18 | PHONE= 19 | FAX= 20 | POSTALADDRESS= 21 | PICTUREURL= 22 | ICON=Contact0 23 | 24 | '@ 25 | 26 | #read 'contacts.txt' contents 27 | $contacts = Get-Content .\contacts.adr 28 | 29 | #parse contacts using the specified template 30 | $contacts | ConvertFrom-String -TemplateContent $TemplateAdr | Format-Table -AutoSize Name, Mail 31 | 32 | 33 | #read more about it at: http://www.powershellmagazine.com/2014/09/09/using-the-convertfrom-string-cmdlet-to-parse-structured-text/ -------------------------------------------------------------------------------- /Misc/PowerShell 5 Presentation Scripts (April 2015)/contacts.adr: -------------------------------------------------------------------------------- 1 | Opera Hotlist version 2.0 2 | Options: encoding = utf8, version=3 3 | 4 | #CONTACT 5 | ID=11 6 | NAME=Justynka 7 | CREATED=1195505237 8 | MAIL=JUSTYNA66@gmail.com 9 | ICON=Contact0 10 | 11 | #CONTACT 12 | ID=12 13 | NAME=Leszek 14 | CREATED=1195677687 15 | MAIL=Leszek@domena.pl 16 | ICON=Contact0 17 | 18 | #CONTACT 19 | ID=13 20 | NAME=Iwona Kwiatkowska 21 | CREATED=1196277590 22 | MAIL=iwon.kwiat@op.pl 23 | ICON=Contact0 24 | 25 | #CONTACT 26 | ID=14 27 | NAME=JUSTYNA66@gmail.com 28 | CREATED=1347061687 29 | MAIL=JUSTYNA66@gmail.com 30 | ICON=Contact0 31 | 32 | #FOLDER 33 | ID=15 34 | NAME=Kosz 35 | CREATED=1195505227 36 | TRASH FOLDER=YES 37 | UNIQUEID=EAF22324295C86499476802CC76DE41E 38 | 39 | - 40 | 41 | #CONTACT 42 | ID=16 43 | NAME=Ania 44 | CREATED=1195505237 45 | MAIL=Ania.Nowak@poczta.com 46 | ICON=Contact0 47 | 48 | #CONTACT 49 | ID=58 50 | NAME=Bartek Bielawski 51 | CREATED=1381258759 52 | MAIL=bartek.bielawski@live.com 53 | ICON=Contact0 54 | 55 | #CONTACT 56 | ID=20 57 | NAME=Poczta Grupowa 58 | URL= 59 | CREATED=1347221208 60 | DESCRIPTION= 61 | ACTIVE=YES 62 | MAIL=xyz.abc.grupa.foo@gmail.com 63 | PHONE= 64 | FAX= 65 | POSTALADDRESS= 66 | PICTUREURL= 67 | ICON=Contact0 -------------------------------------------------------------------------------- /Misc/Wiremock/Download-Start-Wiremock.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | automatically downloads and starts Wiremock 4 | 5 | .PARAMETER Version 6 | version of Wiremock of use 7 | 8 | .PARAMETER Port 9 | port where wiremock will be running on 10 | 11 | .NOTES 12 | Java Runtime environment must be installed and added to your PATH 13 | #> 14 | param( 15 | [ValidateNotNullorEmpty()] 16 | [string] $Version = '2.18.0', 17 | [ValidateNotNullorEmpty()] 18 | [int] $Port = 19257 19 | ) 20 | 21 | if ((Get-Command 'java' -ErrorAction SilentlyContinue) -eq $null) 22 | { 23 | Throw "Unable to find Java in your PATH" 24 | } 25 | 26 | $downloadLocation = Join-Path $env:USERPROFILE 'AppData\Local\Wiremock' 27 | 28 | if (-not(Test-Path $downloadLocation)) { 29 | mkdir $downloadLocation 30 | } 31 | 32 | Push-Location $downloadLocation 33 | 34 | $fileName = "wiremock-standalone-$Version.jar" 35 | $filePath = (Join-Path $downloadLocation $fileName) 36 | 37 | if(-not(Test-Path $filePath)) { 38 | $url = "http://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-standalone/$Version/$fileName" 39 | Write-Output "downloading WireMock $Version from $url" 40 | if ((Invoke-WebRequest -Method Head $url -ErrorAction SilentlyContinue) -eq $null) { 41 | Throw "unable to download wiremock from $url" 42 | } 43 | 44 | Invoke-WebRequest $url -OutFile $filePath 45 | } 46 | $ps = Start-Process java -ArgumentList "-jar $filePath --port $Port" -PassThru 47 | 48 | Start-Sleep -Seconds 1 49 | 50 | $wiremockProcessId = Get-Process -Id $ps.Id -ErrorAction SilentlyContinue 51 | 52 | if ($wiremockProcessId -eq $null) { 53 | Write-Error -Message "wiremock did not start successfully, please ensure port $Port is not being used" -Category OperationStopped -CategoryReason 'port already in use' 54 | } else { 55 | Write-Output "wiremock running on 'http://localhost:$Port'" 56 | } 57 | 58 | Pop-Location -------------------------------------------------------------------------------- /NuGet/CreateAndPublishNuGetPackage.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [parameter(Mandatory=$true)] 3 | [string]$ApiKey, 4 | [parameter(Mandatory=$true)] 5 | [string]$csprojLocation 6 | ) 7 | 8 | # removes existing '*.nupkg' packages in the current folder 9 | Get-ChildItem . | Where-Object { $_.Name -imatch ".nupkg$" } | ForEach-Object { Remove-Item $_.FullName } 10 | 11 | # creates nuget package 12 | ..\NuGet.exe pack $csprojLocation -Prop Configuration=Release 13 | 14 | # publish package 15 | $packageName = Get-ChildItem . | Where-Object { $_.Name -imatch ".nupkg$" } 16 | 17 | Write-Output "`r`nAbout to publish '$packageName'." 18 | $userConfirm = Read-Host 'Do you want to proceed? [Y]es/[N]o' 19 | 20 | if($userConfirm -match 'Y') 21 | { 22 | Write-Output "`r`nPublishing package..." 23 | ..\NuGet.exe push $packageName -ApiKey $ApiKey 24 | } 25 | else 26 | { 27 | Write-Output "`r`nPublish operation skipped by the user." 28 | } -------------------------------------------------------------------------------- /Octopus-Deploy/API/Add-Machine.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | param( 4 | [parameter(Mandatory=$true)] 5 | [System.String] $machineName 6 | ) 7 | <# 8 | .SYNOPSIS 9 | Adds a tentacle machine to the development environment for Octopus Deploy 10 | #> 11 | 12 | $octopusDeployAPIUrl = 'YOUR OCTOPUS SERVER API URL' 13 | $baseMachinesEndpoint = "$octopusDeployAPIUrl/machines" 14 | $discoverMachineEndpoint = "$baseMachinesEndpoint/discover?host=$machineName&port=10933" 15 | 16 | $headers = @{'X-Octopus-ApiKey'='YOUR OCTOPUS API KEY'} 17 | 18 | Write-Output "Discovering - $machineName" 19 | $discoverResponse = Invoke-RestMethod -Uri $discoverMachineEndpoint -Headers $headers -Method GET -ContentType 'application/json' 20 | 21 | Write-Output "Found - $machineName - Thumbprint of: " $discoverResponse.Thumbprint 22 | Write-Output "Adding - $machineName to development environment..." 23 | 24 | $addMachineRequestBody = @{ 25 | Uri = 'https://' + $machineName + ':10933'; 26 | EnvironmentIds = [array]('Environments-1'); 27 | Thumbprint = $discoverResponse.Thumbprint; 28 | CommunicationStyle = 'TentaclePassive'; 29 | Name = "$machineName"; 30 | Roles = ('database-server','web-server'); 31 | } 32 | 33 | $addMachineRequestBodyJSON = ConvertTo-Json -InputObject $addMachineRequestBody -Compress 34 | $addMachineResponse = Invoke-RestMethod -Uri $baseMachinesEndpoint -Headers $headers -Method POST -ContentType 'application/json' -Body $addMachineRequestBodyJSON 35 | 36 | Write-Output "Finished - $machineName tentacle addition to '$octopusDeployAPIUrl'" 37 | -------------------------------------------------------------------------------- /Octopus-Deploy/Create-ScheduledTask.ps1: -------------------------------------------------------------------------------- 1 | #use http://msdn.microsoft.com/en-us/library/windows/desktop/bb736357(v=vs.85).aspx for API reference 2 | 3 | Function Create-ScheduledTask{ 4 | param ( 5 | [string] 6 | $TaskName, 7 | [string] 8 | $RunAsUser, 9 | [string] 10 | $RunAsUserPassword, 11 | [string] 12 | $TaskRun, 13 | [string] 14 | $Schedule, 15 | [string] 16 | $StartTime, 17 | [string] 18 | $StartDate 19 | ) 20 | 21 | $cmdStartDate = if([string]::IsNullOrWhiteSpace($StartDate)){''}else{"/sd $StartDate"} 22 | $cmdStartTime = if([string]::IsNullOrWhiteSpace($StartTime)){''}else{"/st $StartTime"} 23 | $cmdInterval = if([string]::IsNullOrWhiteSpace($Interval)){''}else{"/ri $Interval"} 24 | $cmdDuration = if([string]::IsNullOrWhiteSpace($Duration)){''}else{"/du $Duration"} 25 | $cmdRunAsUser = if((-not [string]::IsNullOrWhiteSpace($RunAsUser)) -and (-not [string]::IsNullOrWhiteSpace($RunAsUserPassword))){"/ru '$RunAsUser' /rp '$RunAsUserPassword'"} else {''} 26 | 27 | if($RunAsUser -match 'System') { 28 | $cmdRunAsUser = "/ru $RunAsUser" 29 | } 30 | 31 | if($Schedule -match 'MINUTE' -or $Schedule -match 'HOURLY' -or $Schedule -match 'ONSTART' -or $Schedule -match 'ONLOGON' -or $Schedule -match 'ONIDLE' -or $Schedule -match 'ONEVENT') { 32 | $cmdInterval = if([string]::IsNullOrWhiteSpace($Interval)){''}else{"/mo $Interval"} 33 | } 34 | 35 | $Command = "schtasks.exe /create $cmdRunAsUser /tn `"$TaskName`" /tr `"'$($TaskRun)'`" /sc $Schedule $cmdStartDate $cmdStartTime /F $cmdInterval $cmdDuration" 36 | 37 | Write-Output $Command 38 | Invoke-Expression $Command 39 | } 40 | 41 | Function Delete-ScheduledTask { 42 | param ( 43 | [string] 44 | $TaskName 45 | ) 46 | 47 | $Command = "schtasks.exe /delete /s localhost /tn `"$TaskName`" /F" 48 | Invoke-Expression $Command 49 | } 50 | 51 | Function Stop-ScheduledTask { 52 | param ( 53 | [string] 54 | $TaskName 55 | ) 56 | 57 | $Command = "schtasks.exe /end /s localhost /tn `"$TaskName`"" 58 | Invoke-Expression $Command 59 | } 60 | 61 | Function Start-ScheduledTask { 62 | param ( 63 | [string] 64 | $TaskName 65 | ) 66 | 67 | $Command = "schtasks.exe /run /s localhost /tn `"$TaskName`"" 68 | Invoke-Expression $Command 69 | } 70 | 71 | Function Enable-ScheduledTask { 72 | param ( 73 | [string] 74 | $TaskName 75 | ) 76 | 77 | $Command = "schtasks.exe /change /s localhost /tn `"$TaskName`" /ENABLE" 78 | Invoke-Expression $Command 79 | } 80 | 81 | Function Check-IfScheduledTaskExists { 82 | param ( 83 | [string] 84 | $taskName 85 | ) 86 | 87 | $schedule = new-object -com Schedule.Service 88 | $schedule.connect() 89 | $tasks = $schedule.getfolder('\').gettasks(0) 90 | 91 | foreach ($task in ($tasks | Select-Object Name)) { 92 | #echo "TASK: $($task.name)" 93 | if($task.Name -eq $taskName) { 94 | #write-output "$task already exists" 95 | return $true 96 | } 97 | } 98 | 99 | return $false 100 | } 101 | 102 | 103 | $taskName = $OctopusParameters['TaskName'] 104 | $runAsUser = $OctopusParameters['RunAsUser'] 105 | $runAsUserPassword = $OctopusParameters['RunAsUserPassword'] 106 | $command = $OctopusParameters['Command'] 107 | $schedule = $OctopusParameters['Schedule'] 108 | $startTime = $OctopusParameters['StartTime'] 109 | $startDate = $OctopusParameters['StartDate'] 110 | $interval = $OctopusParameters['Interval'] 111 | $duration = $OctopusParameters['Duration'] 112 | 113 | if((Check-IfScheduledTaskExists($taskName))){ 114 | Write-Output "$taskName already exists, Tearing down..." 115 | Write-Output "Stopping $taskName..." 116 | Stop-ScheduledTask($taskName) 117 | Write-Output "Successfully Stopped $taskName" 118 | Write-Output "Deleting $taskName..." 119 | Delete-ScheduledTask($taskName) 120 | Write-Output "Successfully Deleted $taskName" 121 | } 122 | 123 | Write-Output "Creating Scheduled Task - $taskName" 124 | Create-ScheduledTask $taskName $runAsUser $runAsUserPassword $command $schedule $startTime $startDate 125 | Write-Output "Successfully Created $taskName" 126 | Enable-ScheduledTask($taskName) 127 | Write-Output "$taskName enabled" -------------------------------------------------------------------------------- /Octopus-Deploy/DACPAC-Deploy-Helpers.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | function Get-SQLServerDataTools-Location { 4 | [CmdletBinding()] 5 | param() 6 | <# 7 | .SYNOPSIS 8 | Gets path for SQL Server Data tools 9 | #> 10 | 11 | Write-Verbose 'Locating SQL Data tools!' 12 | 13 | Write-Verbose 'Trying to locate it in Visual Studio 2012 directory' 14 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\sqlpackage.exe' 15 | 16 | if((Test-Path $SqlPackageLocation) -eq $false) { 17 | Write-Verbose 'Trying to locate it in Visual Studio 2013 directory' 18 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\sqlpackage.exe' 19 | } 20 | 21 | if((Test-Path $SqlPackageLocation) -eq $false) { 22 | Write-Verbose 'Trying to locate it in SQL Server 2014 directory' 23 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft SQL Server\120\DAC\bin\sqlpackage.exe' 24 | } 25 | 26 | if((Test-Path $SqlPackageLocation) -eq $false) { 27 | Write-Verbose 'Trying to locate it in SQL Server 2012 directory' 28 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\sqlpackage.exe' 29 | } 30 | 31 | if((Test-Path $SqlPackageLocation) -eq $false) { 32 | Write-Output "'SqlPackage.exe' was not found on this machine." 33 | Write-Error "Script execution terminated due missing required program 'SQL Server Data Tools'" -ErrorAction Stop 34 | } 35 | 36 | return $SqlPackageLocation 37 | } 38 | 39 | function Apply-ConnectionString-PublishProfile { 40 | param( 41 | [parameter(Mandatory=$true)] 42 | [System.String] $connectionString) 43 | 44 | $pubFile = $(Get-ChildItem . -Recurse | Where-Object { $_.Name -match '.InvasiveMode.' }).FullName 45 | [xml]$xml = Get-Content $pubFile 46 | 47 | Write-Output "Setting connection string value '$connectionString' to publish profile '$pubFile'" 48 | $conn = $xml.GetElementsByTagName('TargetConnectionString').Item(0).InnerText = $connectionString 49 | 50 | $xml.Save($pubFile) 51 | } 52 | 53 | 54 | function Perform-Dacpac-Publish { 55 | param( 56 | [parameter(Mandatory=$true)] 57 | [System.String] $dacpacPackageName, 58 | [Switch] $InvasiveMode) 59 | 60 | 61 | $SqlPackageLocation = Get-SQLServerDataTools-Location -Verbose 62 | 63 | if($InvasiveMode) { 64 | Write-Output "Performing DACPAC publish in 'Invasive mode'" 65 | $publishProfileLocation = $(Get-ChildItem . -Recurse | Where-Object { $_.Name -match '.InvasiveMode.' }).FullName 66 | } else { 67 | Write-Output "Performing DACPAC publish in 'Strict mode'" 68 | $publishProfileLocation = $(Get-ChildItem . -Recurse | Where-Object { $_.Name -match '.StrictMode.' }).FullName 69 | } 70 | 71 | $dacpacLocation = $(Get-ChildItem . | Where-Object { $_.Name -imatch "$dacpacPackageName.dacpac" }).FullName 72 | 73 | if((-not [string]::IsNullOrWhiteSpace($SqlPackageLocation)) -and (-not [string]::IsNullOrWhiteSpace($publishProfileLocation)) -and (-not [string]::IsNullOrWhiteSpace($dacpacLocation))) 74 | { 75 | Write-Output 'Starting DACPAC publish' 76 | & $SqlPackageLocation /pr:$publishProfileLocation /sf:$dacpacLocation /a:Publish 77 | } else { 78 | Write-Error "Unabled to perform DACPAC publish. Please check the following parameters: >>> SQL Data Tools: '$SqlPackageLocation' | Publish profile: '$publishProfileLocation' | DACPAC: '$dacpacLocation' <<<" 79 | } 80 | } -------------------------------------------------------------------------------- /Octopus-Deploy/Replace-WebConfig-ConnectionStringsKeys-With-OctopusVars.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | function Change-WebConfig-ConnectionStringKeys() { 4 | [CmdletBinding()] 5 | param( 6 | [parameter(Mandatory=$true)] 7 | [ValidateScript({Test-Path $_})] 8 | [ValidatePattern("\.config$")] 9 | [string]$xmlFileLocation 10 | ) 11 | 12 | Write-Verbose "Read content from '$xmlFileLocation'" 13 | [xml]$xml = Get-Content $xmlFileLocation 14 | 15 | $connStringsElem = $xml.GetElementsByTagName('connectionStrings'); 16 | 17 | foreach($conn in $connStringsElem.Item(0).add) { 18 | $octoVar = "#{$($conn.name)}" 19 | Write-Verbose "changing '$($conn.name)' to '$octoVar'" 20 | $conn.name = $octoVar 21 | } 22 | 23 | Write-Verbose "Saving '$xmlFileLocation' file..." 24 | $xml.Save($xmlFileLocation) 25 | } 26 | 27 | Change-WebConfig-ConnectionStringKeys 'C:\temp\web.config' -Verbose -------------------------------------------------------------------------------- /Octopus-Deploy/WebDeploy-Helpers.ps1: -------------------------------------------------------------------------------- 1 | function Swap-WebDeploy-Vars-With-Octopus-Vars() 2 | { 3 | [CmdletBinding()] 4 | param() 5 | 6 | Write-Verbose 'Replacing all variables in SetParameters with Octopus variables with the same names.' 7 | 8 | $xmlFile = $(Get-ChildItem . | Where-Object { $_.Name.EndsWith('.SetParameters.xml') }).FullName 9 | 10 | [xml]$xml = Get-Content $xmlFile; 11 | 12 | foreach($node in $xml.SelectNodes('/parameters/setParameter')) 13 | { 14 | $node.value = "#{$($node.name.Replace(' ', '_'))}" 15 | } 16 | 17 | $xml.Save($xmlFile); 18 | } 19 | 20 | 21 | function Run-WebDeploy() 22 | { 23 | [CmdletBinding()] 24 | param() 25 | 26 | Write-Verbose "Looking for a local '.cmd' to run WebDeploy" 27 | 28 | $webDeployCmd = Get-ChildItem . | Where-Object { $_.Name.EndsWith('.cmd') } 29 | $webDeployFile = $webDeployCmd.FullName 30 | 31 | & $webDeployFile /y 32 | } -------------------------------------------------------------------------------- /Performance/RunPerfMonitor-AppServers.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Runs Performance Monitor (perfmon.msc) on the specified server 4 | .NOTES 5 | Performance counters based of information gathered from: 6 | 'Measuring .NET Application Performance' https://msdn.microsoft.com/en-us/library/ff647791.aspx 7 | 'Tuning .NET Application Performance' https://msdn.microsoft.com/en-us/library/ff647813.aspx 8 | #> 9 | 10 | param ( 11 | [Parameter(Mandatory=$True)] 12 | [string]$FileName, 13 | 14 | [ValidateRange(1,30)] 15 | [int]$SampleRate = 15, 16 | 17 | [ValidateSet('Full', 'Basic', 'SqlClient')] 18 | [string]$ReportType = 'Basic', 19 | 20 | [ValidateNotNullOrEmpty()] 21 | [string[]]$AppServers = @( 22 | '44020-D1PRFAPP.MWE.LOCAL', 23 | '44021-D1PRFAPP.MWE.LOCAL', 24 | '44022-D1PRFAPP.MWE.LOCAL', 25 | '44023-D1PRFAPP.MWE.LOCAL', 26 | '44024-D1PRFAPP.MWE.LOCAL', 27 | '44025-D1PRFAPP.MWE.LOCAL', 28 | '44026-D1PRFAPP.MWE.LOCAL', 29 | '44027-D1PRFAPP.MWE.LOCAL', 30 | '44028-D1PRFAPP.MWE.LOCAL') 31 | ) 32 | 33 | Process { 34 | 35 | $counters = @( 36 | # CPU 37 | '\Processor(*)\% Processor Time', 38 | '\Processor(*)\% Privileged Time', 39 | '\System\Processor Queue Length', 40 | '\System\Context Switches/sec', 41 | 42 | 43 | # Memory 44 | '\Memory\Available MBytes', 45 | '\Memory\Page Reads/sec', 46 | '\Memory\Pages/sec', 47 | '\Memory\Cache Bytes', 48 | '\Memory\Cache Faults/sec', 49 | '\Cache\MDL Read Hits %', 50 | 51 | 52 | # Disk I/O 53 | '\PhysicalDisk(*)\Avg. Disk Queue Length', 54 | '\PhysicalDisk(*)\Avg. Disk Read Queue Length', 55 | '\PhysicalDisk(*)\Avg. Disk Write Queue Length', 56 | '\PhysicalDisk(*)\Avg. Disk sec/Read', 57 | '\PhysicalDisk(*)\Avg. Disk sec/Transfer', 58 | '\PhysicalDisk(*)\Avg. Disk sec/Write', 59 | 60 | 61 | # Network I/O 62 | '\Network Interface(*)\Bytes Total/sec', 63 | '\Network Interface(*)\Bytes Received/sec', 64 | '\Network Interface(*)\Bytes Sent/sec', 65 | '\Processor(*)\% Interrupt Time', 66 | 67 | 68 | # CLR 69 | # Memory 70 | '\Process(*)\Private Bytes', 71 | '\.NET CLR Memory(_GLOBAL_)\# Bytes in all Heaps', 72 | '\.NET CLR Memory(_GLOBAL_)\# Gen 0 Collections', 73 | '\.NET CLR Memory(_GLOBAL_)\# Gen 1 Collections', 74 | '\.NET CLR Memory(_GLOBAL_)\# Gen 2 Collections', 75 | '\.NET CLR Memory(_GLOBAL_)\# of Pinned Objects', 76 | '\.NET CLR Memory(_GLOBAL_)\% Time in GC', 77 | '\.NET CLR Memory(_GLOBAL_)\Large Object Heap size', 78 | # Working Set 79 | '\Process(*)\Working Set', 80 | # Exceptions 81 | '\.NET CLR Exceptions(_GLOBAL_)\# of Exceps Thrown / sec', 82 | # Contention 83 | '\.NET CLR LocksAndThreads(_GLOBAL_)\Contention Rate / sec', 84 | '\.NET CLR LocksAndThreads(_GLOBAL_)\Current Queue Length', 85 | # Threading 86 | '\.NET CLR LocksAndThreads(_GLOBAL_)\# of current physical Threads', 87 | # Threading (very verbose) 88 | #'\Thread(*)\% Processor Time', 89 | #'\Thread(*)\Context Switches/sec', 90 | #'\Thread(*)\Thread State', 91 | # Code Access Security 92 | '\.NET CLR Security(_GLOBAL_)\Stack Walk Depth', 93 | '\.NET CLR Security(_GLOBAL_)\Total Runtime Checks', 94 | 95 | 96 | # ASP.Net 97 | # Worker Process 98 | '\ASP.NET\Worker Process Restarts', 99 | # Throughput 100 | '\ASP.NET Applications(__TOTAL__)\Requests/Sec', 101 | '\Web Service(*)\ISAPI Extension Requests/sec', 102 | '\ASP.NET\Requests Current', 103 | '\ASP.NET\Requests Queued', 104 | '\ASP.NET Applications(__TOTAL__)\Requests Executing', 105 | '\ASP.NET Applications(__TOTAL__)\Requests Timed Out', 106 | '\ASP.NET Applications(__TOTAL__)\Requests In Application Queue', 107 | # Response time / latency 108 | '\ASP.NET\Request Execution Time', 109 | # Cache 110 | '\ASP.NET Applications(__TOTAL__)\Cache API Hit Ratio', 111 | '\ASP.NET Applications(__TOTAL__)\Cache API Turnover Rate', 112 | '\ASP.NET Applications(__TOTAL__)\Cache Total Entries', 113 | '\ASP.NET Applications(__TOTAL__)\Cache Total Hit Ratio', 114 | '\ASP.NET Applications(__TOTAL__)\Cache Total Turnover Rate', 115 | '\ASP.NET Applications(__TOTAL__)\Output Cache Entries', 116 | '\ASP.NET Applications(__TOTAL__)\Output Cache Hit Ratio', 117 | '\ASP.NET Applications(__TOTAL__)\Output Cache Turnover Rate' 118 | 119 | 120 | # (optional) CPU 121 | #'\System\Threads', 122 | 123 | # (optional) ASP.Net Errors 124 | #'\ASP.NET Applications(__TOTAL__)\Errors Total/Sec', 125 | #'\ASP.NET Applications(__TOTAL__)\Errors During Execution', 126 | #'\ASP.NET Applications(__TOTAL__)\Errors Unhandled During Execution/Sec', 127 | ) 128 | 129 | if($ReportType -eq 'Basic') { 130 | $counters = @( 131 | '\Processor(*)\% Processor Time', 132 | '\.NET CLR Memory(_GLOBAL_)\% Time in GC', 133 | '\.NET CLR Exceptions(_GLOBAL_)\# of Exceps Thrown / sec', 134 | '\.NET CLR LocksAndThreads(_GLOBAL_)\Contention Rate / sec', 135 | '\ASP.NET Applications(__TOTAL__)\Requests/Sec', 136 | '\ASP.NET\Requests Queued', 137 | '\ASP.NET\Request Execution Time') 138 | } 139 | 140 | if($ReportType -eq 'SqlClient') { 141 | $counters = @( 142 | '\Processor(*)\% Processor Time', 143 | '\.NET Data Provider for SqlServer(*)\NumberOfStasisConnections', 144 | '\.NET Data Provider for SqlServer(*)\NumberOfReclaimedConnections', 145 | '\.NET Data Provider for SqlServer(*)\NumberOfPooledConnections', 146 | '\.NET Data Provider for SqlServer(*)\NumberOfNonPooledConnections', 147 | '\.NET Data Provider for SqlServer(*)\NumberOfInactiveConnectionPools', 148 | '\.NET Data Provider for SqlServer(*)\NumberOfInactiveConnectionPoolGroups', 149 | '\.NET Data Provider for SqlServer(*)\NumberOfFreeConnections', 150 | '\.NET Data Provider for SqlServer(*)\NumberOfActiveConnections', 151 | '\.NET Data Provider for SqlServer(*)\NumberOfActiveConnectionPools', 152 | '\.NET Data Provider for SqlServer(*)\NumberOfActiveConnectionPoolGroups', 153 | '\.NET Data Provider for SqlServer(*)\HardConnectsPerSecond', 154 | '\.NET Data Provider for SqlServer(*)\HardDisconnectsPerSecond', 155 | '\.NET Data Provider for SqlServer(*)\SoftConnectsPerSecond', 156 | '\.NET Data Provider for SqlServer(*)\SoftDisconnectsPerSecond') 157 | } 158 | 159 | 160 | 161 | $outputPath = "C:\PerfLogs\$FileName.blg" 162 | 163 | Write-Output 'running PerfMon in continuous mode, on all specified servers. Output file will be written to '$outputPath' ...' 164 | Write-Output 'Press [Ctrl] + [C] to stop!' 165 | 166 | Get-Counter -Counter $counters -SampleInterval $SampleRate -ComputerName $AppServers -Continuous | 167 | Export-Counter -Path $outputPath -FileFormat 'BLG' 168 | 169 | 170 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PowerShell toolbox 2 | ================= 3 | 4 | This is my personal PowerShell toolbox. 5 | Just a bunch of scripts that I find useful to keep track of. 6 | Some of them haven't been touched in a while, so may require some fixes. 7 | Feel free to contribute, use and abuse this scripts. -------------------------------------------------------------------------------- /SQL Server Install/ConfigFile/SQLServerConfigurationFile.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlouros/PowerShell-toolbox/e95df6b9bea19620be2dfad8fd13ab39b2e8d123/SQL Server Install/ConfigFile/SQLServerConfigurationFile.ini -------------------------------------------------------------------------------- /SQL Server Install/SQLServerInstall.ps1: -------------------------------------------------------------------------------- 1 | Write-Host 'Installing SQL Server 2008 R2' 2 | 3 | \\file.server\share\AutomatedInstall\SQL\Binaries\en_sql_server_2008_r2_standard_x86_x64_ia64\setup.exe /CONFIGURATIONFILE=\\file.server\Share\AutomatedInstall\SQL\ConfigFiles\SQLServerConfigurationFile.ini /IACCEPTSQLSERVERLICENSETERMS | Write-Host 4 | 5 | 6 | 7 | OR 8 | 9 | 10 | 11 | Write-Host 'Installing SQL Server 2008 R2' 12 | 13 | $command = '\\file.server\Share\en_sql_server_2008_r2_standard_x86_x64_ia64\setup.exe /CONFIGURATIONFILE=\\file.server\Share\SQLServerConfigurationFileBasic.ini /IACCEPTSQLSERVERLICENSETERMS' 14 | 15 | $process = [System.Diagnostics.Process]::Start($command) 16 | 17 | $process.WaitForExit() 18 | -------------------------------------------------------------------------------- /SQL/Insert-SeedData.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [ValidateNotNullOrEmpty()] 4 | $serverInstance = 'localhost' 5 | ) 6 | 7 | if (-not (Get-Command 'Invoke-SqlCmd' -ErrorAction SilentlyContinue)) 8 | { 9 | Write-Verbose 'Invoke-SqlCmd not found as a known command. Adding required PSSnapin' 10 | Add-PSSnapin SqlServerCmdletSnapin100 11 | Add-PSSnapin SqlServerCmdletSnapin100 12 | } 13 | 14 | if (-not (Get-Command 'Invoke-SqlCmd' -ErrorAction SilentlyContinue)) { 15 | Write-Error "Unable to resolve 'Inovke-SqlCmd' powershell command. This process can't contiune without it!" -ErrorAction Stop 16 | } 17 | 18 | 19 | $verbosityFlag = ($PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent -eq $true) 20 | 21 | 22 | 23 | $setupScriptFiles = Get-ChildItem .\SetupScripts\ -Include '*.sql' -Recurse 24 | $dataScriptFiles = Get-ChildItem .\DataScripts\ -Include '*.sql' -Recurse 25 | 26 | 27 | 28 | Write-Output "Running 'Pre-Deploy' scripts..." 29 | foreach($preDeployFile in $setupScriptFiles | Where-Object { $_.Name -lt '100'}) 30 | { 31 | Write-Verbose " '$($preDeployFile.Name)'" 32 | Invoke-Sqlcmd -InputFile $preDeployFile.FullName -ServerInstance $serverInstance -Verbose:$verbosityFlag 33 | } 34 | 35 | 36 | Write-Output 'Running data scripts...' 37 | foreach($dataFile in $dataScriptFiles) 38 | { 39 | Write-Verbose " '$($dataFile.Name)'" 40 | Invoke-Sqlcmd -InputFile $dataFile.FullName -ServerInstance $serverInstance -DisableVariables -Verbose:$verbosityFlag 41 | } 42 | 43 | 44 | Write-Output 'Running other setup scripts...' 45 | foreach($setupFile in $setupScriptFiles | Where-Object { $_.Name -ge '100' -and $_.Name -le '899'}) 46 | { 47 | Write-Verbose " '$($setupFile.Name)'" 48 | Invoke-Sqlcmd -InputFile $setupFile.FullName -ServerInstance $serverInstance -Verbose:$verbosityFlag 49 | } 50 | 51 | 52 | Write-Output "Running 'Post-Deploy' scripts..." 53 | foreach($postDeployFile in $setupScriptFiles | Where-Object { $_.Name -gt '899'}) 54 | { 55 | Write-Verbose " '$($postDeployFile.Name)'" 56 | Invoke-Sqlcmd -InputFile $postDeployFile.FullName -ServerInstance $serverInstance -Verbose:$verbosityFlag 57 | } 58 | 59 | 60 | 61 | Write-Verbose 'Execution complete!' 62 | Set-Location $PSScriptRoot -------------------------------------------------------------------------------- /SQL/SetupScripts/001.Pre-Deploy.sql: -------------------------------------------------------------------------------- 1 | USE [DBName] 2 | GO 3 | PRINT 'disabling trigger PreventAlterToDecisionCriterionSet' 4 | GO 5 | DISABLE TRIGGER PreventAlterToDecisionCriterionSet ON DATABASE; 6 | GO 7 | PRINT 'disabling all constraints' 8 | EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all' 9 | GO -------------------------------------------------------------------------------- /SQL/SetupScripts/800.Grant_DOMAIN-Username_Access.sql: -------------------------------------------------------------------------------- 1 | USE [master] 2 | GO 3 | PRINT 'Adding DOMAIN\username login to master' 4 | IF NOT EXISTS (SELECT 1 FROM master.sys.server_principals where name = 'DOMAIN\username') 5 | BEGIN 6 | CREATE LOGIN [DOMAIN\username] FROM WINDOWS WITH DEFAULT_DATABASE=[master] 7 | END 8 | GO 9 | USE [DBName] 10 | GO 11 | PRINT 'Adding DOMAIN\username login to DBName' 12 | IF NOT EXISTS (SELECT 1 FROM sys.sysusers where name = 'DOMAIN\username') 13 | BEGIN 14 | CREATE USER [DOMAIN\username] FOR LOGIN [DOMAIN\username] 15 | END 16 | GO 17 | USE [DBName] 18 | GO 19 | PRINT 'Adding DOMAIN\username db_owner role to DBName' 20 | EXEC sp_addrolemember N'db_owner', N'DOMAIN\username' 21 | GO 22 | -------------------------------------------------------------------------------- /SQL/SetupScripts/900.Post-Deploy.sql: -------------------------------------------------------------------------------- 1 | USE [DBName] 2 | GO 3 | PRINT 'enabling all constraints without checking them' 4 | EXEC sp_msforeachtable @command1='print ''?''', @command2='ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all' 5 | GO 6 | PRINT 'enabling trigger PreventAlterToDecisionCriterionSet' 7 | GO 8 | ENABLE TRIGGER PreventAlterToDecisionCriterionSet ON DATABASE; 9 | GO -------------------------------------------------------------------------------- /Security/Set-AcceptedCryptographicProtocols.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Defines the accepted cryptographic protocols at the OS level (schannel.dll) 4 | .NOTES 5 | Changes Windows registry to define the accepted cryptographic protocols. 6 | Warning, depending on your configuration, some websites might stop working on IE or other applications using 'schannel.dll' 7 | For more information please check https://support.microsoft.com/en-us/kb/245030 8 | #> 9 | 10 | 11 | # set the desired configurations here 12 | $protocols = @{ 13 | 'SSL 2.0'= @{ 14 | 'Server-Enabled' = $false 15 | 'Client-Enabled' = $false 16 | } 17 | 'SSL 3.0'= @{ 18 | 'Server-Enabled' = $false 19 | 'Client-Enabled' = $false 20 | } 21 | 'TLS 1.0'= @{ 22 | 'Server-Enabled' = $false 23 | 'Client-Enabled' = $true 24 | } 25 | 'TLS 1.1'= @{ 26 | 'Server-Enabled' = $true 27 | 'Client-Enabled' = $true 28 | } 29 | 'TLS 1.2'= @{ 30 | 'Server-Enabled' = $true 31 | 'Client-Enabled' = $true 32 | } 33 | } 34 | 35 | 36 | $protocols.Keys | ForEach-Object { 37 | 38 | Write-Output "Configuring '$_'" 39 | 40 | # create registry entries if they don't exist 41 | $rootPath = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\$_" 42 | if(-not (Test-Path $rootPath)) { 43 | New-Item $rootPath 44 | } 45 | 46 | $serverPath = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\$_\Server" 47 | if(-not (Test-Path $serverPath)) { 48 | New-Item $serverPath 49 | 50 | New-ItemProperty -Path $serverPath -Name 'Enabled' -Value 4294967295 -PropertyType 'DWord' 51 | New-ItemProperty -Path $serverPath -Name 'DisabledByDefault' -Value 0 -PropertyType 'DWord' 52 | } 53 | 54 | $clientPath = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\$_\Client" 55 | if(-not (Test-Path $clientPath)) { 56 | New-Item $clientPath 57 | 58 | New-ItemProperty -Path $clientPath -Name 'Enabled' -Value 4294967295 -PropertyType 'DWord' 59 | New-ItemProperty -Path $clientPath -Name 'DisabledByDefault' -Value 0 -PropertyType 'DWord' 60 | } 61 | 62 | # set server settings 63 | if($protocols[$_]['Server-Enabled']) { 64 | Set-ItemProperty -Path $serverPath -Name 'Enabled' -Value 4294967295 65 | Set-ItemProperty -Path $serverPath -Name 'DisabledByDefault' -Value 0 66 | } else { 67 | Set-ItemProperty -Path $serverPath -Name 'Enabled' -Value 0 68 | Set-ItemProperty -Path $serverPath -Name 'DisabledByDefault' -Value 1 69 | } 70 | 71 | # set client settings 72 | if($protocols[$_]['Client-Enabled']) { 73 | Set-ItemProperty -Path $clientPath -Name 'Enabled' -Value 4294967295 74 | Set-ItemProperty -Path $clientPath -Name 'DisabledByDefault' -Value 0 75 | } else { 76 | Set-ItemProperty -Path $clientPath -Name 'Enabled' -Value 0 77 | Set-ItemProperty -Path $clientPath -Name 'DisabledByDefault' -Value 1 78 | } 79 | } -------------------------------------------------------------------------------- /Security/Set-StrongCryptographyDotNet.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Disable known weak cryptographic protocols 4 | .NOTES 5 | Instructs Schannel to disable known weak cryptographic algorithms, cipher suites, and SSL/TLS protocol versions that may be otherwise enabled for better interoperability. 6 | In .Net framework 4.5.2 and below, if strong cryptography is not set, SSL 3.0 or TLS 1.0 will be used by default. 7 | For .Net 4.6.1 strong cryptography is enabled by default, meaning that secure HTTP communications will use TLS 1.0, TLS 1.1 or TLS 1.2. 8 | #> 9 | 10 | 11 | # set strong cryptography on 64 bit .Net Framework 12 | Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 13 | 14 | 15 | # set strong cryptography on 32 bit .Net Framework 16 | Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 17 | -------------------------------------------------------------------------------- /TeamCity/Version-DatabaseProject.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | # used to version SQL Server projects in TeamCity 4 | 5 | function Set-DatabaseProjectVersion() { 6 | [CmdletBinding()] 7 | param( 8 | [parameter(Mandatory=$true)] 9 | [ValidateScript({Test-Path $_})] 10 | [ValidatePattern("\.sqlproj$")] 11 | [string]$sqlProjLocation, 12 | [parameter(Mandatory=$true)] 13 | [string]$versionNumber 14 | ) 15 | 16 | 17 | Write-Verbose "Read content from '$sqlProjLocation'" 18 | [xml]$xml = Get-Content $sqlProjLocation 19 | 20 | [string]$versionTagName = 'DacVersion' 21 | $dacVersion = $xml.GetElementsByTagName($versionTagName) 22 | 23 | if($dacVersion.Count -eq 0) 24 | { 25 | Write-Verbose "Adding 'DacVersion' property to .sqlproj, since it wasn't found!" 26 | 27 | $ns = $xml.GetElementsByTagName('Project').Item(0).NamespaceURI 28 | 29 | $proj = $xml.GetElementsByTagName('PropertyGroup') | Where-Object { $_.GetElementsByTagName('ProjectGuid').Count -gt 0 } 30 | 31 | $proj.AppendChild($xml.CreateElement($versionTagName, $ns)) 32 | 33 | $dacVersion = $proj.GetElementsByTagName($versionTagName) 34 | } 35 | 36 | Write-Verbose "Setting version to '$versionNumber'" 37 | $dacVersion.Item(0).InnerText = $versionNumber 38 | 39 | Write-Verbose 'Saving .sqlproj file...' 40 | $xml.Save($sqlProjLocation) 41 | } 42 | 43 | Set-DatabaseProjectVersion -------------------------------------------------------------------------------- /Visual Studio/Locate-and-Load-DLL.ps1: -------------------------------------------------------------------------------- 1 | Function Load-StashApiDll 2 | { 3 | $dllName = 'Atlassian.Stash.Api.dll' 4 | 5 | $dlls = Get-ChildItem .\Atlassian.Stash.Api\bin\ -Recurse | Where-Object { $_.Name -match $dllName } 6 | 7 | if($dlls.Length -eq 0) 8 | { 9 | Write-Error "Unable to find '$dllName'. Please compile the solution first." -ErrorAction Stop 10 | } 11 | elseif($dlls.Length -gt 1) 12 | { 13 | # if mulitple matches were found, just pick the first one 14 | $dlls = $dlls[0] 15 | } 16 | 17 | Add-Type -Path $dlls.FullName -ErrorAction Stop 18 | 19 | Write-Output "'$dllName' successfully loaded." 20 | } 21 | 22 | Load-StashApiDll 23 | #$stashClient = New-Object Atlassian.Stash.Api.StashClient("http://ptr-cvsd/", "asdassa") -------------------------------------------------------------------------------- /Visual Studio/Manage-Intellitrace.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Start, stops or gets information from Intellitrace stand-alone collector 4 | .NOTES 5 | Using the IntelliTrace stand-alone collector instructions https://msdn.microsoft.com/en-us/library/vstudio/hh398365(v=vs.140).aspx 6 | Warning, Visual Studio Enterprise (or Ultimate) is required to view Intellitrace reports. 7 | 8 | 1) Download IntelliTrace Standalone Collector (IntelliTraceCollector.exe) https://www.microsoft.com/en-us/download/confirmation.aspx?id=44909 9 | 2) Save IntelliTraceCollector.exe to the collector directory 'C:\IntelliTraceCollector' 10 | 3) Run IntelliTraceCollector.exe. This extracts the 'IntelliTraceCollection.cab' file. 11 | 4) Open a command prompt window as an administrator and change directory to 'C:\IntelliTraceCollector' 12 | 5) Use the expand command, including the period (.) at the end, to expand IntelliTraceCollection.cab 13 | expand /f:* IntelliTraceCollection.cab . 14 | 6) Use the Windows icacls command to give the server administrator full permissions to the collector directory 15 | icacls "C:\IntelliTraceCollector" /grant "":F 16 | 7) Give the application pool for the Web app or SharePoint application read and execute permissions to the collector directory 17 | icacls "C:\IntelliTraceCollector" /grant "IIS APPPOOL\MwSmartpaymentsAppPool":RX 18 | 8) On your app’s server, create the .iTrace file directory, for example: 'C:\IntelliTraceLogFiles' 19 | icacls "C:\IntelliTraceLogFiles" /grant "IIS APPPOOL\MwSmartpaymentsAppPool":F 20 | #> 21 | 22 | param( 23 | [Parameter(Position = 0, ValueFromPipeline=$true)] 24 | [ValidateSet('Start', 'Stop', 'GetStatus')] 25 | [string] $Action = 'GetStatus', 26 | 27 | [Parameter(Position = 1)] 28 | [ValidateNotNullOrEmpty()] 29 | [string[]] $AppPools = @('DefaultAppPool') 30 | ) 31 | 32 | 33 | Process { 34 | 35 | $intelInstallDir = 'C:\IntelliTraceCollector' 36 | $intelLogsDir = 'C:\IntelliTraceLogFiles' 37 | 38 | 39 | Import-Module "$intelInstallDir\Microsoft.VisualStudio.IntelliTrace.PowerShell.dll" 40 | 41 | if($Action -eq 'Start') { 42 | 43 | Write-Output 'Starting Intellitrace' 44 | $AppPools | ForEach-Object { 45 | Start-IntelliTraceCollection $_ "$intelInstallDir\collection_plan.ASP.NET.default.xml" $intelLogsDir -Confirm:$false 46 | } 47 | 48 | } elseif ($Action -eq 'Stop') { 49 | 50 | Write-Output "Stopping Intellitrace. Logs can be found at '$intelLogsDir'" 51 | $AppPools | ForEach-Object { 52 | Stop-IntelliTraceCollection $_ -Confirm:$false 53 | } 54 | 55 | } else { 56 | 57 | Write-Output 'Getting Intellitrace status' 58 | $AppPools | ForEach-Object { 59 | Get-IntelliTraceCollectionStatus $_ 60 | } 61 | 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /Visual Studio/Run-NUnitIntegrationTests.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [Alias('NUNIT', 'N')] 4 | [System.String] 5 | [ValidateScript({ 6 | if((Test-Path $_) -eq $false) 7 | { 8 | Throw New-Object -TypeName System.ArgumentException -ArgumentList "Unable to locate NUnit console in the provided path '$_'", 'NUnitConsolePath' 9 | } 10 | })] 11 | $NUnitConsolePath = 'C:\Apps\NUnit-2.6.4\bin\nunit-console.exe', 12 | 13 | [Alias('PATH', 'P')] 14 | [System.String] 15 | [ValidateScript({ 16 | if((Test-Path $_) -eq $false) 17 | { 18 | Throw New-Object -TypeName System.ArgumentException -ArgumentList "The provided test folder location path is invalid '$_'", 'TestsPath' 19 | } 20 | })] 21 | $TestsPath = $(Join-Path $PSScriptRoot '\..' | Resolve-Path) 22 | ) 23 | 24 | $testDlls = Get-ChildItem $(Join-Path $TestsPath '\*') -Include '*.Tests.Integration.dll' -Recurse | Where-Object { $_ -inotmatch '\\obj\\'} | Sort-Object Name -Unique 25 | 26 | if($testDlls -eq $null) 27 | { 28 | Write-Output "`r`n--> Unable to locate any testable binary, for given path '$TestsPath'" 29 | return; 30 | } 31 | 32 | # Run Unit tests for each test dll found 33 | foreach($testDll in $testDlls) 34 | { 35 | Write-Output "`r`n--> Executing '$testDll'`r`n" 36 | & $NUnitConsolePath $($testDll.FullName) '/nologo' 37 | Write-Output '--> Test run complete!' 38 | } -------------------------------------------------------------------------------- /Visual Studio/RunIntegrationTests.ps1: -------------------------------------------------------------------------------- 1 | Set-Location C:\Deploy 2 | 3 | Write-Host 'Run on Test Server!' 4 | 5 | $trxName = 'C:\Deploy\LatestTestResult.trx' 6 | if(Test-Path $trxName) 7 | { 8 | Remove-Item $trxName 9 | } 10 | 11 | & 'C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\mstest.exe' /testcontainer:"C:\Deploy\Library.Integration.Tests.dll" /testsettings:"C:\Deploy\build.testsettings" /resultsfile:"C:\Deploy\LatestTestResult.trx" -------------------------------------------------------------------------------- /Visual Studio/RunTestsWithCoverageData.ps1: -------------------------------------------------------------------------------- 1 | # Note: this script is based on the Microsoft-linked sample at forums.msdn.com regarding ".NET 3.5 Code Coverage" 2 | 3 | $ErrorActionPreference = 'Stop' 4 | 5 | function Copy-InstrumentedAssemblyToTestBinFolders 6 | { 7 | param ( 8 | [string] 9 | $assemblyPath = $(Throw 'Value cannot be null: assemblyPath'), 10 | [string] 11 | $testBinFolders = $(Throw 'Value cannot be null: testBinFolders') 12 | ) 13 | 14 | $testBinFolders | 15 | ForEach-Object { 16 | Write-Debug ('Copying assembly (' + $assemblyPath ` 17 | + ') to folder (' + $_ + ')...') 18 | 19 | Copy-Item $assemblyPath $_ 20 | } 21 | } 22 | 23 | function Get-AssemblyFolders 24 | { 25 | param ( 26 | [Object] 27 | $assemblyPaths = $(Throw 'Value cannot be null: assemblyPaths') 28 | ) 29 | 30 | [string[]] $folders = @() 31 | 32 | $assemblyPaths | 33 | ForEach-Object { 34 | [string] $folder = (Get-Item $_).DirectoryName 35 | 36 | $folders += $folder 37 | } 38 | 39 | return $folders 40 | } 41 | 42 | function Instrument-Assembly 43 | { 44 | param ( 45 | [string] 46 | $assemblyPath = $(Throw 'Value cannot be null: assemblyPath') 47 | ) 48 | 49 | [string] $vsinstr = "${env:ProgramFiles(x86)}" ` 50 | + '\Microsoft Visual Studio 10.0\Team Tools\Performance Tools\x64\VSInstr.exe' 51 | 52 | & $vsinstr "$assemblyPath" /coverage 53 | } 54 | 55 | function Run-Tests 56 | { 57 | param ( 58 | [string] 59 | $assemblyPaths = $(Throw 'Value cannot be null: assemblyPaths'), 60 | [string] 61 | $testSettingsPath 62 | ) 63 | 64 | [string] $mstest = "${env:ProgramFiles(x86)}" ` 65 | + '\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe' 66 | 67 | [string[]] $parameters = @('/nologo') 68 | 69 | $assemblyPaths | 70 | ForEach-Object { 71 | $parameters += ('/testcontainer:"' + $_ + '"') 72 | } 73 | 74 | If ([string]::IsNullOrEmpty($testSettingsPath) -eq $false) 75 | { 76 | $parameters += ('/testsettings:"' + $testSettingsPath + '"') 77 | } 78 | 79 | Write-Debug 'Running tests...' 80 | Write-Host "Parameters: $parameters" 81 | & $mstest $parameters 82 | } 83 | 84 | function Sign-Assembly 85 | { 86 | param ( 87 | [Object] 88 | $assemblyPath = $(Throw 'Value cannot be null: assemblyPath') 89 | ) 90 | 91 | Write-Debug ('Signing assembly (' + $assemblyPath + ')...') 92 | 93 | [string] $sn = "${env:ProgramFiles(x86)}" ` 94 | + '\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sn.exe' 95 | 96 | & $sn -q -Ra "$assemblyPath" '..\ApplicationPages\ProjKey.snk' 97 | } 98 | 99 | function Toggle-CodeCoverageProfiling 100 | { 101 | param ( 102 | [bool] 103 | $enable 104 | ) 105 | 106 | [string] $vsperfcmd = "${env:ProgramFiles(x86)}" ` 107 | + '\Microsoft Visual Studio 10.0\Team Tools\Performance Tools\x64\VSPerfCmd.exe' 108 | 109 | If ($enable -eq $true) 110 | { 111 | Write-Debug 'Starting code coverage profiler...' 112 | 113 | & $vsperfcmd /START:COVERAGE /OUTPUT:Proj.CoverageReport 114 | } 115 | Else 116 | { 117 | Write-Debug 'Stopping code coverage profiler...' 118 | 119 | & $vsperfcmd /SHUTDOWN 120 | } 121 | } 122 | 123 | function Update-GacAssemblyIfNecessary 124 | { 125 | param ( 126 | [string] 127 | $assemblyPath = $(Throw 'Value cannot be null: assemblyPath') 128 | ) 129 | 130 | [string] $baseName = (Get-Item $assemblyPath).BaseName 131 | 132 | Write-Debug ('Checking if assembly (' + $baseName + ') is in the GAC...') 133 | 134 | [string] $gacutil = "${env:ProgramFiles(x86)}" ` 135 | + '\Microsoft SDKs\Windows\v7.0A\Bin\gacutil.exe' 136 | 137 | [string] $numberOfItemsInGac = & $gacutil -l $baseName | 138 | Select-String '^Number of items =' | 139 | ForEach { $_.Line.Split('=')[1].Trim() } 140 | 141 | If ($numberOfItemsInGac -eq '0') 142 | { 143 | Write-Debug ('The assembly (' + $baseName + ') was not found in the GAC.') 144 | } 145 | ElseIf ($numberOfItemsInGac -eq '1') 146 | { 147 | Write-Debug ('Updating GAC assembly (' + $baseName + ')...') 148 | 149 | & $gacutil /if $assemblyPath 150 | } 151 | Else 152 | { 153 | Throw 'Unexpected number of items in the GAC: ' + $numberOfItemsInGac 154 | } 155 | } 156 | 157 | function Main 158 | { 159 | [string] $testSettingsPath = Get-Item '..\build.testsettings' 160 | 161 | [string[]] $assembliesToInstrument = 162 | @( 163 | Get-Item '..\*\Proj*.dll' 164 | ) 165 | 166 | [string[]] $testAssemblies = 167 | @( 168 | Get-Item '..\*\bin\Debug\*Tests.Unit*.dll' 169 | ) 170 | 171 | [string[]] $testBinFolders = Get-AssemblyFolders($testAssemblies) 172 | 173 | $assembliesToInstrument | 174 | ForEach-Object { 175 | Instrument-Assembly $_ 176 | 177 | Sign-Assembly $_ 178 | 179 | Copy-InstrumentedAssemblyToTestBinFolders $_ $testBinFolders 180 | 181 | Update-GacAssemblyIfNecessary $_ 182 | 183 | } 184 | 185 | Toggle-CodeCoverageProfiling $true 186 | 187 | Run-Tests $testAssemblies $testSettingsPath 188 | 189 | Toggle-CodeCoverageProfiling $false 190 | } 191 | 192 | Main 193 | -------------------------------------------------------------------------------- /Visual Studio/SQL Server Projects/BatchDeploy-DACPACs.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param( 3 | [ValidateNotNullOrEmpty()] 4 | [string]$serverInstance = 'localhost' 5 | ) 6 | 7 | Function Resolve-InvokeSqlcmd() { 8 | if (-not (Get-Command 'Invoke-SqlCmd' -ErrorAction SilentlyContinue)) 9 | { 10 | Write-Verbose 'Invoke-SqlCmd not found as a known command. Adding required PSSnapin' 11 | Add-PSSnapin SqlServerCmdletSnapin100 12 | Add-PSSnapin SqlServerCmdletSnapin100 13 | } 14 | 15 | if (-not (Get-Command 'Invoke-SqlCmd' -ErrorAction SilentlyContinue)) { 16 | Write-Error "Unable to resolve 'Invoke-SqlCmd' PowerShell command. This process can't continue without it!" -ErrorAction Stop 17 | } 18 | } 19 | 20 | Function Get-SQLServerDataToolsLocation { 21 | <# 22 | .SYNOPSIS 23 | Gets path for SQL Server Data tools 24 | 25 | .DESCRIPTION 26 | Gets path for SQL Server Data tools 27 | #> 28 | 29 | 30 | # Visual Studio 2012 SQL Package location 31 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\sqlpackage.exe' 32 | 33 | if((Test-Path $SqlPackageLocation) -eq $false) { 34 | # Visual Studio 2013 SQL Package location 35 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\sqlpackage.exe' 36 | } 37 | 38 | if((Test-Path $SqlPackageLocation) -eq $false) { 39 | # SQL Server 2014 SQL Package location 40 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft SQL Server\120\DAC\bin\sqlpackage.exe' 41 | } 42 | 43 | if((Test-Path $SqlPackageLocation) -eq $false) { 44 | # SQL Server 2012 SQL Package location 45 | $SqlPackageLocation = 'C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\sqlpackage.exe' 46 | } 47 | 48 | # Last verification point 49 | if((Test-Path $SqlPackageLocation) -eq $false) { 50 | Write-Host "'SqlPackage.exe' was not found on this machine." 51 | Write-Error "Script execution terminated due missing required program 'SQL Server Data Tools'" -ErrorAction Stop 52 | } 53 | 54 | return $SqlPackageLocation 55 | } 56 | 57 | $verbosityFlag = ($PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent -eq $true) 58 | 59 | Resolve-InvokeSqlcmd 60 | 61 | $SqlPackageLocation = Get-SQLServerDataToolsLocation 62 | 63 | $publishProfiles = Get-ChildItem . -Recurse -Include *.publish.xml 64 | 65 | 66 | 67 | Write-Verbose "Running 'DeleteMockedDatabases.sql' on '$serverInstance'..." 68 | Invoke-Sqlcmd -InputFile $(Join-Path ($(Get-Item .).FullName) 'DeleteMockedDatabases.sql') -ServerInstance $serverInstance -Verbose:$verbosityFlag 69 | 70 | 71 | 72 | Write-Verbose "Running 'CreateDatabases.sql' on '$serverInstance'..." 73 | Invoke-Sqlcmd -InputFile $(Join-Path ($(Get-Item .).FullName) 'CreateDatabases.sql') -ServerInstance $serverInstance -Verbose:$verbosityFlag 74 | 75 | Write-Verbose "Running 'CreateLinkedServers.sql' on '$serverInstance'..." 76 | Invoke-Sqlcmd -InputFile $(Join-Path ($(Get-Item .).FullName) 'CreateLinkedServers.sql') -ServerInstance $serverInstance -Verbose:$verbosityFlag 77 | 78 | 79 | foreach($publishProf in $publishProfiles) 80 | { 81 | $dacpac = Get-ChildItem $publishProf.Directory -Recurse -Include "$($publishProf.Directory.Name).dacpac" 82 | 83 | if($dacpac -eq $null) { 84 | Write-Error "dacpac for '$($publishProf.Directory.Name)' was not found. Make sure the solution was built!" -ErrorAction Continue 85 | continue 86 | } 87 | 88 | & $SqlPackageLocation /pr:"$($publishProf.FullName)" /sf:"$($dacpac.FullName)" /a:Publish 89 | Write-Output '-----------------------------------------------------------------------------' 90 | } 91 | 92 | Set-Location $PSScriptRoot 93 | -------------------------------------------------------------------------------- /Visual Studio/SQL Server Projects/BuildPostDeploymentScript.ps1: -------------------------------------------------------------------------------- 1 | # This script will be run as a pre-build event for database projects. 2 | # powershell -NoProfile -ExecutionPolicy RemoteSigned -file $(ProjectDir)Post Deployment Scripts\BuildPostDeploymentScript.ps1 3 | 4 | Write-Output 'BEGIN generating post-deployment script references . . .'; 5 | Write-Output "`r`n"; 6 | 7 | $dataFolderPath = '..\..\Post Deployment Scripts'; 8 | $postDeploymentScriptFileName = 'PostDeploymentScript.sql'; 9 | $postDeploymentScriptPath = "..\..\Post Deployment Scripts\$postDeploymentScriptFileName"; 10 | 11 | 12 | Write-Output 'Looping through folder: ' $dataFolderPath; 13 | 14 | # Use 'here string' to write comment header to file. 15 | $postDeploymentScript_HeaderComments =@" 16 | /* 17 | Post-Deployment Script Template 18 | -------------------------------------------------------------------------------------- 19 | This file contains SQL statements that will be appended to the build script. 20 | Use SQLCMD syntax to include a file in the post-deployment script. 21 | Example: :r .\myfile.sql 22 | Use SQLCMD syntax to reference a variable in the post-deployment script. 23 | Example: :setvar TableName MyTable 24 | SELECT * FROM [`$(TableName)] 25 | -------------------------------------------------------------------------------------- 26 | */`r`n 27 | "@; 28 | 29 | # Output comment header to target file. 30 | $postDeploymentScript_HeaderComments | Out-File -filePath $postDeploymentScriptPath -encoding utf8; 31 | 32 | # Get only sql files in data folder. 33 | $sqlScripts = @(Get-ChildItem $dataFolderPath -Recurse -Include *.sql -Exclude PostDeploymentScript.sql) | Sort-Object; 34 | 35 | # Output number of files found. 36 | Write-Output 'Found ' $sqlScripts.Count ' files.' 37 | 38 | # Add each data script file to the post-deployment script. 39 | foreach ($script in $sqlScripts) 40 | { 41 | # Output file name. 42 | Write-Output 'Adding reference for: ' $script "`r`n to " $postDeploymentScriptPath; 43 | 44 | $sqlScriptPath = "PRINT N'Executing post deploymenty script: "; 45 | $sqlScriptPath += $script.Name; 46 | $sqlScriptPath += "';`r`n"; 47 | 48 | # Add carriage-return/new-line and 'r:'. 49 | $sqlScriptPath += ':r "'; 50 | $sqlScriptPath += $script; 51 | $sqlScriptPath += '"'; 52 | 53 | $sqlScriptPath += "`r`nPRINT N'Done execution of: "; 54 | $sqlScriptPath += $script.Name; 55 | $sqlScriptPath += "';`r`n"; 56 | 57 | $sqlScriptPath | Out-File -filePath $postDeploymentScriptPath -append -encoding utf8; 58 | } 59 | 60 | #Write-Output (Get-ChildItem $dataFolderPath -Recurse).Count; 61 | 62 | # Done. 63 | Write-Output "`r`n"; 64 | Write-Output 'DONE generating sql script references for ' $postDeploymentScriptPath "`r`n"; 65 | -------------------------------------------------------------------------------- /Web/Get-ImagesFromWebsite.ps1: -------------------------------------------------------------------------------- 1 | $downloadFolder = "C:\Downloaded Images\" 2 | $searchFor = "funny pictures" 3 | $nrOfImages = 12 4 | 5 | 6 | Add-Type -AssemblyName System.Web 7 | 8 | $webClient = New-Object System.Net.WebClient 9 | 10 | $searchQuery = [System.Web.HttpUtility]::UrlEncode($searchFor) 11 | 12 | $url = "http://www.bing.com/images/search?q=$searchQuery&first=0&count=$nrOfImages&qft=+filterui%3alicense-L2_L3_L4" 13 | 14 | $webpage = $webclient.DownloadString($url) 15 | 16 | $regex = "[(http(s)?):\/\/(www\.)?a-z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-z0-9@:%_\+.~#?&//=]*)((.jpg(\/)?)|(.png(\/)?)){1}(?!([\w\/]+))" 17 | 18 | $listImgUrls = $webpage | Select-String -pattern $regex -Allmatches | ForEach-Object {$_.Matches} | Select-Object $_.Value -Unique 19 | 20 | 21 | if((Test-Path $downloadFolder) -eq $false) 22 | { 23 | Write-Output "Creating '$downloadFolder'..." 24 | 25 | New-Item -ItemType Directory -Path $downloadFolder | Out-Null 26 | } 27 | 28 | foreach($imgUrlString in $listImgUrls) 29 | { 30 | [Uri]$imgUri = New-Object System.Uri -ArgumentList $imgUrlString 31 | 32 | $imgFile = [System.IO.Path]::GetFileName($imgUri.LocalPath) 33 | 34 | $imgSaveDestination = Join-Path $downloadFolder $imgFile 35 | 36 | Write-Output "Downloading '$imgUrlString' to '$imgSaveDestination'..." 37 | 38 | $webClient.DownloadFile($imgUri, $imgSaveDestination) 39 | } -------------------------------------------------------------------------------- /WebDeploy/Fetch-SetParameters.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | Param( 4 | [Parameter(Mandatory=$true)] 5 | [string]$AppName, 6 | [string]$TargetEnvironment = 'localhost', 7 | [string]$PackageLocation = $PSScriptRoot, 8 | [string]$StashFilesRestUrl = 'http://STASH_URL/rest/api/1.0/projects/POW/repos/REPOSITORY_NAME/files/ApplicationsEnvironmentSettings?limit=1000', 9 | [string]$StashSettingsLocationUrl = 'http://STASH_URL/projects/PROJECT_NAME/repos/REPOSITORY_NAME/browse/ApplicationsEnvironmentSettings/{0}?raw', 10 | [switch]$AllowDefaultSettings 11 | ) 12 | 13 | Function Find-SettingsFileOnStash { 14 | param( 15 | [string]$TargetEnvironment, 16 | [string]$AppName, 17 | [string]$FilesStashRestUrl) 18 | 19 | return (Invoke-RestMethod -Uri $FilesStashRestUrl -Method Get).values | Where-Object { $_ -match $AppName -and $_ -match $TargetEnvironment } 20 | } 21 | 22 | Function Download-SettingsFileFromStash { 23 | param( 24 | [string]$settingsFile, 25 | [string]$StashSettingsLocationUrl, 26 | [string]$targetDeploymentFolder) 27 | 28 | $targetFileLocation = Join-Path $targetDeploymentFolder $settingsFile 29 | 30 | $webClient = New-Object System.Net.WebClient 31 | $fileDownloadUrl = [string]::Format($StashSettingsLocationUrl, $settingsFile) 32 | $webClient.DownloadFile($fileDownloadUrl, $targetFileLocation) 33 | $webClient.Dispose(); 34 | } 35 | 36 | Write-Host 'Initializing WebDeploy powershell script with the following input parameters:' 37 | Write-Host " - Application name -> '$AppName'" 38 | Write-Host " - Target environment -> '$TargetEnvironment'" 39 | Write-Host " - Package location -> '$PackageLocation'" 40 | Write-Host " - Stash files REST url -> '$StashFilesRestUrl'" 41 | Write-Host " - Stash settings location url -> '$StashSettingsLocationUrl'" 42 | if($AllowDefaultSettings) { 43 | Write-Host " -> Allowing default settings. If no environment settings can be found, 'localhost' settings will be used instead!" 44 | } 45 | Write-Host "`r`n" 46 | 47 | if ((Test-Path $PackageLocation) -eq $false) { Write-Error "Unreachable 'package location'" -ErrorAction Stop } 48 | 49 | 50 | # Get Application deployment parameters location 51 | $settingsMatch = Find-SettingsFileOnStash $TargetEnvironment $AppName $StashFilesRestUrl 52 | 53 | if($AllowDefaultSettings -and ($settingsMatch.Count -eq 0)) { 54 | Write-Warning "Couldn't find '$TargetEnvironment'. Trying with 'localhost' settings instead!" 55 | 56 | $settingsMatch = Find-SettingsFileOnStash 'localhost' $AppName $StashFilesRestUrl 57 | } 58 | 59 | if($settingsMatch.Count -eq 0) { Write-Error 'Settings file not found. Verify your input parameters.' -ErrorAction Stop } 60 | if($settingsMatch.Count -gt 1) { Write-Error "Too many file matches found. Please clean up our 'EnvironmentSettings' location." -ErrorAction Stop } 61 | 62 | 63 | # delete default SetParameters file 64 | $defaultSettingsFile = (Get-Item $PackageLocation).GetFiles() | Where-Object { $_.Name -match 'SetParameters.xml' } 65 | Write-Host "Removing default '*SetParameters.xml' file which is '$defaultSettingsFile'`r`n" 66 | Remove-Item $defaultSettingsFile.FullName -ErrorAction Stop 67 | 68 | 69 | # copy the targetd SetParameters file 70 | Write-Host "Downloading settings file from Stash`r`n" 71 | Download-SettingsFileFromStash $settingsMatch $StashSettingsLocationUrl $PackageLocation 72 | 73 | 74 | # rename the targetd SetParameters file 75 | $newSettingsFile = (Get-Item $PackageLocation).GetFiles() | Where-Object { $settingsMatch.EndsWith($_.Name) } 76 | Write-Host "Renaming environment specific '*SetParameters.xml' file with '$newSettingsFile' to '$defaultSettingsFile'" 77 | Move-Item $newSettingsFile.FullName $defaultSettingsFile.FullName -------------------------------------------------------------------------------- /WebDeploy/Install-WebPackage.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | param( 4 | [string]$targetServer, 5 | [switch]$interActiveMode 6 | ) 7 | 8 | Function Get-WebDeployCmdFile { 9 | # Get Application WebDeploy cmd file 10 | $webDeployCmdMatch = (Get-Item .).GetFiles() | Where-Object { $_.Name.EndsWith('.cmd') } 11 | 12 | if($webDeployCmdMatch.Count -eq 0) { 13 | Write-Error 'WebDeploy .cmd file not found. Missing package files.' -ErrorAction Stop 14 | } 15 | if($webDeployCmdMatch.Count -gt 1) { 16 | Write-Error 'Too many .cmd files found. Deployment can not proceed' -ErrorAction Stop 17 | } 18 | $currDir = (Get-Item -Path '.\').FullName 19 | return Join-Path $currDir $webDeployCmdMatch.Name 20 | } 21 | 22 | Function Verify-SetParametersFileExist { 23 | # Check if 'SetParameters file exist' 24 | $setParamMatch = (Get-Item .).GetFiles() | Where-Object { $_.Name -match 'SetParameters.xml' } 25 | 26 | if($setParamMatch.Count -eq 0) { 27 | Write-Error 'SetParameters file not found. Missing package files.' -ErrorAction Stop 28 | } 29 | if($setParamMatch.Count -gt 1) { 30 | Write-Error 'Too many SetParameters files found. Deployment can not proceed' -ErrorAction Stop 31 | } 32 | } 33 | 34 | Function Execute-WebDeploy { 35 | Param( 36 | [parameter(Mandatory=$true)] 37 | [ValidateNotNullOrEmpty()] 38 | [System.String]$webDeployCmd, 39 | [parameter(Mandatory=$true)] 40 | [ValidateNotNullOrEmpty()] 41 | [System.String]$targetComputerName, 42 | [parameter(Mandatory=$true)] 43 | [Switch]$interActiveMode) 44 | 45 | 46 | Write-Output "Deploying to '$targetComputerName'" 47 | if($interActiveMode -eq $true) { 48 | $userConfirm = Read-Host 'Do want you proceed? [Y/N]' 49 | } else { 50 | $userConfirm = 'y' 51 | } 52 | 53 | if(($userConfirm -match 'y') -eq $false) { 54 | # Skip 55 | Write-Output "Skipping deployment on server '$targetComputerName'" -ForegroundColor Gray 56 | } else { 57 | # Execute WebDeploy 58 | Write-Output "Starting WebDeploy execution on '$targetComputerName'" -ForegroundColor Green 59 | $cmdOutput = & $webDeployCmd /y /m:$targetComputerName 2>&1 #| Out-Host 60 | 61 | foreach($msg in $cmdOutput) { 62 | Write-Output $msg 63 | } 64 | 65 | if(($cmdOutput | Where-Object { $_.GetType() -match 'System.Management.Automation.ErrorRecord' })) { 66 | Write-Output "WebDeployment unsucessfull, please check logged messages on 'Log.txt' file." 67 | Throw 'Terminating Script Execution!' 68 | } 69 | } 70 | } 71 | 72 | Function Get-Servers 73 | { 74 | $matches = (Get-Item .).GetFiles() | Where-Object { $_.Name -match 'Servers.txt' } 75 | 76 | if($matches.Count -eq 0) { 77 | Write-Output "Could find any 'Servers.txt' file" -ErrorAction Stop 78 | return 79 | } 80 | if($matches.Count -gt 1) { 81 | Write-Output "Too many files matching 'Servers.txt' found. Skipping this step" 82 | return 83 | } 84 | 85 | Get-Content $matches -ErrorAction Continue 86 | } 87 | 88 | Function Get-ScriptDirectory { 89 | Split-Path $script:MyInvocation.MyCommand.Path 90 | } 91 | 92 | # 93 | # main script execution 94 | # 95 | 96 | Set-Location (Get-ScriptDirectory) 97 | $logFile = Join-Path (Get-ScriptDirectory) 'log.txt' 98 | 99 | Start-Transcript $logFile 100 | 101 | Try 102 | { 103 | Write-Output 'Executing custom WebPackage installer!' 104 | 105 | $webDeployCmd = Get-WebDeployCmdFile 106 | 107 | if((Test-Path $webDeployCmd) -eq $false) { 108 | Write-Error "WebDeploy cmd file not found. Verify your build output location. Parsed the follwing path: '$webDeployCmd'" -ErrorAction Stop 109 | } 110 | 111 | Verify-SetParametersFileExist 112 | 113 | if([string]::IsNullOrWhiteSpace($targetServer) -eq $false) { 114 | Execute-WebDeploy $webDeployCmd $targetServer -interActiveMode:$interActiveMode 115 | } else { 116 | Write-Output "No 'targetServer' param specified. Moving on to next operation" 117 | } 118 | 119 | # parse and use "Servers.txt" 120 | [System.Object[]]$servers = Get-Servers 121 | 122 | $serverCount = $servers.Count 123 | [int]$serverIdx = 0; 124 | 125 | while($serverIdx -lt $serverCount) 126 | { 127 | $targetServerName = $servers.Get($serverIdx) 128 | 129 | Write-Output $targetServerName 130 | # move to next server index 131 | $serverIdx++; 132 | 133 | Execute-WebDeploy $webDeployCmd $targetServerName -interActiveMode:$interActiveMode 134 | #Write-Output "Starting deployment on server '$currentServer'" 135 | } 136 | 137 | # If interactive mode is off, don't ask for other servers 138 | $askForNewDeploy = $interActiveMode; 139 | while($askForNewDeploy -eq $true) { 140 | $userWantsToProceed = Read-Host 'Do want you deploy to another machine? [Y/N]' 141 | 142 | if(($userWantsToProceed -match 'y') -eq $false) { 143 | $askForNewDeploy = $false 144 | } else { 145 | $desiredServer = Read-Host 'Please enter the server name you want to deploy to: ' 146 | 147 | Execute-WebDeploy $webDeployCmd $desiredServer 148 | } 149 | } 150 | 151 | Write-Output "We are done here! Check the log file at: '$logFile'" -ForegroundColor Gray 152 | 153 | } 154 | Finally 155 | { 156 | Stop-Transcript 157 | } -------------------------------------------------------------------------------- /WebDeploy/Modify-SetParameters.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4.0 2 | 3 | param( 4 | [string]$xmlLocation, 5 | [System.Collections.Hashtable]$valuesTable 6 | ) 7 | 8 | Function Change-SetParameterValue 9 | { 10 | param ([xml]$xmlDoc, [string]$paramName, [string]$newValue) 11 | 12 | # XPath query 13 | $checkParam = $xmlDoc.SelectSingleNode("/parameters/setParameter[@name='$paramName']") 14 | 15 | if($checkParam -ne $null) 16 | { 17 | Write-Host "Setting '$paramName' with value '$newValue'" 18 | $checkParam.Value=$newValue 19 | } 20 | else { Write-Host "Parameter '$paramName' not found!" -ForegroundColor Yellow } 21 | } 22 | 23 | [xml]$xml = Get-Content $xmlLocation; 24 | 25 | if($xml -eq $null) { Write-Error 'Unable to get XML document, please check directory path' -ErrorAction Stop } 26 | 27 | Change-SetParameterValue $xml 'IIS Web Application Name' '%DeployIisAppPath%' 28 | Change-SetParameterValue $xml 'Smtp Configuration' 'smtp.server.dev' 29 | Change-SetParameterValue $xml 'Environment' 'Debug' 30 | 31 | foreach($tblKey in $valuesTable.Keys) 32 | { 33 | $tblValue = $valuesTable[$tblKey] 34 | 35 | Change-SetParameterValue $xml $tblKey $tblValue 36 | } 37 | 38 | $emptyParams = $xml.SelectNodes("/parameters/setParameter[@value='']") 39 | if($emptyParams.Count -gt 0) 40 | { 41 | Write-Host 'The following parameters were not modified: ' 42 | 43 | foreach($blank in $emptyParams) 44 | { 45 | Write-Host $blank.name 46 | } 47 | 48 | Write-Error "Deployment won't be successful due to blank values." -ErrorAction Stop 49 | } 50 | 51 | $xml.Save($xmlLocation); --------------------------------------------------------------------------------