Skip to content

Instantly share code, notes, and snippets.

@NotMyself
Last active September 8, 2025 04:51
Show Gist options
  • Save NotMyself/e06a373889117f321bf72bb0a020c0b1 to your computer and use it in GitHub Desktop.
Save NotMyself/e06a373889117f321bf72bb0a020c0b1 to your computer and use it in GitHub Desktop.
With Claude Code: Starting prompt, criticism, rewritten prompt and generated assets.

Yesterday, I posted a prompt that I had worked on for a couple hours requesting feedback. It didn't get much attention.

So I decided to use Claude to give me some feedback on it. This post documents the process I used to get what I wanted by the end of the day. I post it here for others who are looking for successful techniques to adopt or those who are just curious how other people use Claude.

The original prompt: 1.set-up-local-iis.md

This prompt was collaboratively generated with Claude. I do not have the original prompt used, but I basically told Claude it was an expert prompt engineer and to interview me about a powershell script I wanted to create a prompt to generate.

I then hand edit the prompt to add a bunch of detail that I thought was relevant.

Once I was satisfied with the prompt, I cleared the context and entered this prompt:

You are an expert Claude code prompt engineer. You strive for concise prompts that contain all the details needed and nothing more. You are to evaluate a prompt located at prompts\set-up-local-iis.md, write a critique in prompts\set-up-local-iis-criticism.md and rewrite the prompt to prompts\new-set-up-local-iis.md addressing your critiqued items.

This resulted in these two files:

This identified many redundancies and things Claude didn't think were needed. Reduced the prompt by 70%. I was skeptical, but I ran it anyway.

execute prompts\new-set-up-local-iis.md

At this point, I started a feedback loop with Claude. I would run the script, encounter an error, prompt Claude to address it. In this process, I discovered several details I had not considered.

  1. I left out the detail that the database is hosted in Azure.
  • Azure has some limitations on how you access hosted database remotely.
  1. My work environment has some constraints as well.

Once I got all of the missing details resolved. I deleted the scripts and prompted this:

 execute prompts\new-set-up-local-iis.md some config json files already exist but may need to be updated.

This resulted in these files:

I ran the scripts and they do exactly what I wanted them to do. So I promtped this:

/readme completely rewrite local-iis-config\README.md documenting usage of the scripts found in that directory.

Note: /readme is a custom command I have created for generating readmes the way I like. That is for another post.

Finally, I committed everything to source control and now nobody in my team has to spend 2 days figuring out how to get our code base running locally again.

Lessons Learned:

  1. Include all details in the original prompt. Leaving out the azure hosted db led directly to an extremely irritating feedback loop that generated tons of test scripts and noise trying to get the identity model right.
  2. Feedback loops become more and more ineffective the longer they go on. Claude regularly forgot I didn't want to use the powershell web management module and suggested it repeatedly. It even tried to just start using it at one point.
  3. Claude would start to go off to generate scripts to fix things, interrupting and directing it to focus on the setup script seemed to get out of this pattern.

Set Up Local IIS for Admin Portal

Role

You are a windows system configuration expert who works only using powershell scripts, you are creating a script with the goal of getting the Admin Portal web application to run under IIS locally on port 80 with https.

Key Goals

  • Site runs when I hit F5 in Visual Studio
  • Site default url is https://poop-admin-dev.cpmpany.com
  • Site runs in IIS
  • Site is configured pfx based certificate for https
  • Application consumes environment variables for secrets
  • Site uses the environment connection string override of the Company.Core Config object to inject a connection string for the database server SERVER stored in an environment variable ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION

Environment

The script MUST run without error in this environment

  • Windows 11 Business 24H2 26100.4946

  • Windows Terminal 1.23.12371.0

    • Hosting PowerShell 7.5.2
  • ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION already exists as a system environment variable on this machine but script should check and create it if not.

Tools

The following tools should be used to configure IIS

  • $env:SystemRoot\System32\inetsrv\appcmd.exe
  • Do not use the web administration powershell module
    • It does not reliably work in powershell 7

Expected Deliverables

setup-iis-for-admin-portal-locally.ps1

The main script that does the work of setting up iis.

  • name: setup-iis-for-admin-portal-locally.ps1
  • location: .\local-iis-config\
  • ux: user MUST be presented with progress as the script completes steps
  • quality: MUST be consise and only include steps to meet the key goals while respecting the security concerns

create-a-config-for-environement.ps1

A utility script that will gather configuration information from the system as well as prompt the user for needed config values.

  • name: create-a-config-for-environement.ps1
  • location: .\local-iis-config\
  • ux: user MUST be presented with progress as the script completes steps
  • quality: MUST be consise and only include steps to meet the key goals while respecting the security concerns

Features

  • Powershell Commandlet
  • Fully Documented in the script for discoverability
  • Implement force and whatif params
  • consumes a config file
  • validates the schema of the config file
  • Enabling IIS Features and Management Tools if not available
  • Import the PFX Certificate and capture thumbprint
  • Create IIS Application Pool
  • Create the IIS Website
  • Configure HTTPS Binding
  • Configure Current User Permissions
    • Add user to IIS_IUSRS group
    • Set user permission on source directory
    • Grant user permission to IIS configuration for debugging
  • Configure IIS for Development
    • Enable detailed errors for debugging
    • Disable output caching for development
    • Enable anonymous authentication

config-schema.json

A json schema file that MUST be used to validate the script's configuration file.

  • name: config-schema.json
  • location: .\local-iis-config\

team-config.json

The team config json is a template that the team can use to execute the script.

  • name: team-config.json
  • location: .\local-iis-config\

me-config.json

My config json for this local environment

  • name: team-config.json
  • location: .\local-config\
  • pfx cert: C:\Users\Me\Desktop\cert.pfx
  • solution location: ~\src\Admin-Portal
  • web project location: ~\src\Admin-Portal\Company.Admin

Mandatory Steps

  • first research IIS configuration strategies in windows 11 business
  • once setup is complete, a security scan MUST be done of the changes and written to at the root of the Admin-Portal directory

Security Concerns

  • No secrets are written to files anywhere
  • DB connection string ONLY available as an envornment variable

Samples

Web.config

<appSettings>
  <add key="PrimaryConnectionStringEnvironmentVariable" value="ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION" />
</appSettings>

config-schema.json

The config file MUST use a schema defined like this.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "IIS HTTPS Local Development Configuration",
  "description": "Configuration schema for setting up IIS with HTTPS for local development debugging",
  "type": "object",
  "required": [
    "CertificatePath",
    "ProjectPath", 
    "SiteName",
    "AppPoolName",
    "ProjectUrl",
    "DatabaseEnvironmentVariable"
  ],
  "properties": {
    "CertificatePath": {
      "type": "string",
      "description": "Path to the PFX certificate file (absolute or relative to solution root)",
      "examples": [
        "C:\\Users\\Username\\Desktop\\certificate.pfx",
        "./certificates/app-cert.pfx",
        "../shared/certificates/dev-cert.pfx"
      ]
    },
    "ProjectPath": {
      "type": "string",
      "description": "Path to the ASP.NET project directory (absolute or relative to solution root)",
      "examples": [
        "C:\\Source\\MyApp\\WebProject",
        "./Company.Admin",
        "./src/WebApp"
      ]
    },
    "SiteName": {
      "type": "string",
      "description": "IIS site name to create",
      "pattern": "^[a-zA-Z0-9_-]+$",
      "examples": ["admin-portal", "my-app-dev", "local-site"]
    },
    "AppPoolName": {
      "type": "string", 
      "description": "IIS application pool name to create",
      "pattern": "^[a-zA-Z0-9_-]+$",
      "examples": ["admin-portal-debug-pool", "my-app-pool", "dev-pool"]
    },
    "ProjectUrl": {
      "type": "string",
      "format": "uri",
      "description": "HTTPS URL where the application will be accessible",
      "pattern": "^https://",
      "examples": [
        "https://poop-admin-dev.company.com",
        "https://localhost:8443",
        "https://myapp-dev.company.com"
      ]
    },
    "DatabaseEnvironmentVariable": {
      "type": "string",
      "description": "Name of the environment variable containing the database connection string",
      "examples": [
        "ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION",
        "DATABASE_CONNECTION_STRING",
        "MY_APP_DB_CONNECTION"
      ]
    },
    "Environment": {
      "type": "string",
      "description": "Environment name for identification",
      "enum": ["Development", "Testing", "Staging"],
      "default": "Development"
    },
    "Description": {
      "type": "string",
      "description": "Human-readable description of this configuration"
    },
    "Features": {
      "type": "object",
      "description": "Feature flags for development settings",
      "properties": {
        "DebugMode": {
          "type": "boolean",
          "description": "Enable compilation debug mode",
          "default": true
        },
        "DetailedErrors": {
          "type": "boolean", 
          "description": "Show detailed error messages",
          "default": true
        },
        "OutputCaching": {
          "type": "boolean",
          "description": "Enable output caching",
          "default": false
        },
        "AnonymousAuthentication": {
          "type": "boolean",
          "description": "Enable anonymous authentication",
          "default": true
        }
      },
      "additionalProperties": false
    },
    "IIS": {
      "type": "object",
      "description": "IIS-specific configuration settings",
      "properties": {
        "HttpPort": {
          "type": "integer",
          "description": "HTTP port number",
          "minimum": 1,
          "maximum": 65535,
          "default": 80
        },
        "HttpsPort": {
          "type": "integer",
          "description": "HTTPS port number", 
          "minimum": 1,
          "maximum": 65535,
          "default": 443
        },
        "ManagedRuntimeVersion": {
          "type": "string",
          "description": ".NET Framework runtime version",
          "enum": ["v2.0", "v4.0"],
          "default": "v4.0"
        },
        "Enable32BitAppOnWin64": {
          "type": "boolean",
          "description": "Enable 32-bit applications on 64-bit Windows",
          "default": false
        },
        "IdleTimeout": {
          "type": "string",
          "description": "Application pool idle timeout (HH:mm:ss format)",
          "pattern": "^\\d{2}:\\d{2}:\\d{2}$",
          "default": "00:00:00"
        },
        "PeriodicRestartTime": {
          "type": "string",
          "description": "Application pool periodic restart time (HH:mm:ss format)",
          "pattern": "^\\d{2}:\\d{2}:\\d{2}$", 
          "default": "00:00:00"
        }
      },
      "additionalProperties": false
    },
    "Security": {
      "type": "object",
      "description": "Security-related configuration settings",
      "properties": {
        "CustomErrorsMode": {
          "type": "string",
          "description": "Custom errors mode",
          "enum": ["On", "Off", "RemoteOnly"],
          "default": "Off"
        },
        "CompilationDebug": {
          "type": "boolean",
          "description": "Enable compilation debug mode",
          "default": true
        },
        "RemoveServerHeader": {
          "type": "boolean",
          "description": "Remove IIS server header",
          "default": false
        }
      },
      "additionalProperties": false
    },
    "Metadata": {
      "type": "object",
      "description": "Metadata about this configuration",
      "properties": {
        "CreatedBy": {
          "type": "string",
          "description": "Who created this configuration"
        },
        "CreatedDate": {
          "type": "string",
          "format": "date",
          "description": "When this configuration was created"
        },
        "Purpose": {
          "type": "string",
          "description": "Purpose of this configuration"
        },
        "Notes": {
          "type": "array",
          "description": "Additional notes about this configuration",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}

team-config.json

The team config json is a template that the team can use to execute the script.

{
  "$schema": "./config-schema.json",
  "CertificatePath": "./certificates/team-dev-cert.pfx",
  "ProjectPath": "./Company.Admin",
  "SiteName": "admin-portal",
  "AppPoolName": "admin-portal-debug-pool",
  "ProjectUrl": "https://poop-admin-dev.company.com",
  "DatabaseEnvironmentVariable": "ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION",
  "Environment": "Development",
  "Description": "Team shared configuration using relative paths",
  "Features": {
    "DebugMode": true,
    "DetailedErrors": true,
    "OutputCaching": false,
    "AnonymousAuthentication": true
  },
  "IIS": {
    "HttpPort": 80,
    "HttpsPort": 443,
    "ManagedRuntimeVersion": "v4.0",
    "Enable32BitAppOnWin64": false,
    "IdleTimeout": "00:00:00",
    "PeriodicRestartTime": "00:00:00"
  },
  "Security": {
    "CustomErrorsMode": "Off",
    "CompilationDebug": true,
    "RemoveServerHeader": false
  },
  "Metadata": {
    "CreatedBy": "Claude Code",
    "CreatedDate": "2025-01-16",
    "Purpose": "Team shared IIS HTTPS local development setup with relative paths",
    "Notes": [
      "This configuration uses relative paths for team sharing",
      "Place certificate file in ./certificates/ directory",
      "This configuration is for LOCAL DEVELOPMENT ONLY",
      "Do not commit certificate files to source control"
    ]
  }
}

my-config.json

{
  "$schema": "./config-schema.json",
  "CertificatePath": "C:\\Users\\me\\Desktop\\cert.pfx",
  "ProjectPath": "C:\\Users\\me\\src\\Admin-Portal\\Company.Admin",
  "SiteName": "admin-portal",
  "AppPoolName": "admin-portal-debug-pool",
  "ProjectUrl": "https://poop-admin-dev.company.com",
  "DatabaseEnvironmentVariable": "ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION",
  "Environment": "Development",
  "Description": "Local development configuration for Company.Admin on Bobby's machine",
  "Features": {
    "DebugMode": true,
    "DetailedErrors": true,
    "OutputCaching": false,
    "AnonymousAuthentication": true
  },
  "IIS": {
    "HttpPort": 80,
    "HttpsPort": 443,
    "ManagedRuntimeVersion": "v4.0",
    "Enable32BitAppOnWin64": false,
    "IdleTimeout": "00:00:00",
    "PeriodicRestartTime": "00:00:00"
  },
  "Security": {
    "CustomErrorsMode": "Off",
    "CompilationDebug": true,
    "RemoveServerHeader": false
  },
  "Metadata": {
    "CreatedBy": "Claude Code",
    "CreatedDate": "2025-01-16",
    "Purpose": "IIS HTTPS local development debugging setup",
    "Notes": [
      "This configuration is for LOCAL DEVELOPMENT ONLY",
      "Do not use these settings in production environments",
      "Visual Studio debugging works without admin privileges after setup"
    ]
  }
}

Critique of set-up-local-iis.md

Overall Assessment

The prompt is overly verbose and contains excessive implementation details that belong in the solution, not the prompt. It mixes requirements with implementation, reducing clarity and flexibility.

Strengths

  1. Clear objective (IIS setup for local development)
  2. Specific environment details (Windows 11, PowerShell 7.5.2)
  3. Well-defined deliverables with clear naming
  4. Security considerations explicitly stated

Critical Issues

1. Excessive Schema Documentation (Lines 119-322)

  • Problem: 203 lines of JSON schema example dominates the prompt
  • Impact: Obscures actual requirements, creates cognitive overload
  • Fix: Provide high-level schema requirements, let implementer design details

2. Redundant Configuration Examples (Lines 324-415)

  • Problem: Three full JSON config examples totaling 91 lines
  • Impact: Repetitive, doesn't add new requirements
  • Fix: One concise example showing key fields only

3. Mixed Requirements and Implementation

  • Problem: Combines what needs to be done with how to do it
  • Impact: Constrains solution unnecessarily, reduces flexibility
  • Fix: Focus on requirements, let implementer choose approach

4. Unclear Priority of Goals

  • Problem: Lists many features without indicating which are critical vs nice-to-have
  • Impact: Implementer may focus on wrong aspects
  • Fix: Prioritize requirements (must-have, should-have, nice-to-have)

5. Contradictory Instructions

  • Problem: Says "consise" but provides verbose examples; typo in "consise"
  • Impact: Mixed signals about expected output
  • Fix: Model the behavior you want - be concise in the prompt itself

6. Overly Prescriptive Tool Choice

  • Problem: Mandates appcmd.exe without explaining why
  • Impact: May miss better solutions
  • Fix: State the constraint (PowerShell 7 compatibility) and let implementer choose

7. Unnecessary Implementation Details

  • Problem: Features list (lines 54-73) reads like a task list
  • Impact: Blurs line between requirements and implementation
  • Fix: State what the script must achieve, not step-by-step how

8. Vague Security Scan Requirement

  • Problem: "security scan MUST be done" without specifics
  • Impact: Unclear what constitutes compliance
  • Fix: Define specific security checks or remove if not critical

Recommendations

  1. Reduce by 70%: Cut from 416 lines to ~120 lines
  2. Separate concerns: Requirements doc vs implementation guidance
  3. Prioritize clarity: Lead with critical requirements
  4. Remove examples: Keep only essential ones, make them minimal
  5. Fix typos: "consise" → "concise", "environement" → "environment"
  6. Structure hierarchy: Use clear sections for must/should/could requirements
  7. Remove duplication: Don't repeat information across sections
  8. Focus on outcomes: What success looks like, not how to achieve it

Configure IIS for Local Development

Create PowerShell scripts to set up IIS for the Company.Admin ASP.NET application with HTTPS support.

Requirements

Must Have

  • Site accessible at https://poop-admin-dev.company.com
  • Works with Visual Studio F5 debugging
  • Uses PFX certificate for HTTPS
  • Database connection string from environment variable ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION
  • Database connection string format 'Server=[server];Database=[database];User Id=[user id];Password=[password];Encrypt=true;TrustServerCertificate=true;Connection Timeout=30;'
  • Runs with PowerShell 7.5.2 on Windows 11

Should Have

  • Progress feedback during execution
  • Configuration validation
  • Idempotent execution (safe to run multiple times)
  • Non-admin Visual Studio debugging support

Constraints

  • No secrets in files
  • Use appcmd.exe for IIS configuration (PowerShell IIS module unreliable in PS7)
  • .NET Framework 4.8 application
  • When running powershell commands use NoProfile flag

Deliverables

1. setup-iis-for-admin-portal-locally.ps1

Main setup script in .\local-iis-config\

  • Reads configuration from JSON file
  • Validates or Creates database environment variable
  • Enables required IIS features
  • Creates app pool and site
  • App pool should use the LocalSystem Identity
  • Configures HTTPS binding
  • Sets permissions for debugging

2. create-a-config-for-environment.ps1

Configuration helper in .\local-iis-config\

  • Gathers system information
  • Prompts for missing values
  • Validates against schema
  • Saves configuration file

3. config-schema.json

JSON schema in .\local-iis-config\ defining:

  • Required: CertificatePath, ProjectPath, SiteName, AppPoolName, ProjectUrl, DatabaseEnvironmentVariable, DatabaseServer, DatabaseName DatabaseUserId, DatabasePassword
  • Optional: IIS settings (ports, runtime version), Features (debug mode, error handling)

4. Configuration Files

  • team-config.json: Template with relative paths
  • my-config.json: My specific configuration
    • Certificate: C:\Users\Me\Desktop\cert.pfx
    • Project: ~\src\admin-portal\Company.Admin

Context

The application reads the database environment variable name from Web.config:

<add key="PrimaryConnectionStringEnvironmentVariable" value="ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION" />

Success Criteria

  • Application runs locally with HTTPS
  • Application can connect to database
  • Visual Studio can attach debugger
  • Environment variable provides database connection
  • No hardcoded secrets
#Requires -Version 7.0
<#
.SYNOPSIS
Creates or updates a configuration file for IIS setup of TailorWell.Admin.
.DESCRIPTION
This script helps create a personalized configuration file by gathering
system information and prompting for required values. It validates the
configuration against the JSON schema and saves it to a specified file.
.PARAMETER OutputFile
Name of the output configuration file. Defaults to "[username]-config.json".
.PARAMETER Template
Path to a template configuration file to use as a starting point.
.PARAMETER Interactive
Prompt for all values, even if defaults are available.
.EXAMPLE
.\create-a-config-for-environment.ps1
.\create-a-config-for-environment.ps1 -OutputFile "my-config.json"
.\create-a-config-for-environment.ps1 -Template "team-config.json" -Interactive
#>
param(
[string]$OutputFile = "$($env:USERNAME.ToLower())-config.json",
[string]$Template,
[switch]$Interactive
)
$ErrorActionPreference = "Stop"
# Helper functions
function Write-Step {
param([string]$Message)
Write-Host "`n═══ $Message ═══" -ForegroundColor Cyan
}
function Write-Prompt {
param([string]$Message)
Write-Host "→ $Message" -ForegroundColor Yellow -NoNewline
}
function Write-Success {
param([string]$Message)
Write-Host "✓ $Message" -ForegroundColor Green
}
function Write-Info {
param([string]$Message)
Write-Host "ℹ $Message" -ForegroundColor Blue
}
function Read-Value {
param(
[string]$Prompt,
[string]$Default,
[switch]$Required,
[switch]$Secure
)
$displayDefault = if ($Default) { " [$Default]" } else { "" }
Write-Prompt "$Prompt$displayDefault`: "
if ($Secure) {
$secureValue = Read-Host -AsSecureString
if ($secureValue.Length -eq 0 -and $Default) {
return $Default
}
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureValue)
$value = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
} else {
$value = Read-Host
}
if ([string]::IsNullOrWhiteSpace($value)) {
if ($Default) {
return $Default
} elseif ($Required) {
Write-Host "This value is required." -ForegroundColor Red
return Read-Value -Prompt $Prompt -Default $Default -Required:$Required -Secure:$Secure
}
}
return $value
}
function Test-CertificateFile {
param([string]$Path)
if (-not (Test-Path $Path)) {
return $false
}
try {
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($Path)
return $true
} catch {
return $false
}
}
function Get-DefaultProjectPath {
# Try to find the project path relative to this script
$scriptDir = Split-Path -Parent $PSScriptRoot
$projectPath = Join-Path $scriptDir "Company.Admin"
if (Test-Path $projectPath) {
return $projectPath
}
return $null
}
function Get-SystemInfo {
$info = @{
Username = $env:USERNAME
MachineName = $env:COMPUTERNAME
WindowsVersion = (Get-CimInstance Win32_OperatingSystem).Caption
PowerShellVersion = $PSVersionTable.PSVersion.ToString()
IISInstalled = Test-Path "$env:SystemRoot\System32\inetsrv\appcmd.exe"
}
return $info
}
function Validate-Configuration {
param([hashtable]$Config)
$errors = @()
# Validate required fields
$requiredFields = @(
'certificatePath',
'projectPath',
'siteName',
'appPoolName',
'projectUrl',
'databaseEnvironmentVariable',
'databaseServer',
'databaseName',
'databaseUserId',
'databasePassword'
)
foreach ($field in $requiredFields) {
if (-not $Config.ContainsKey($field) -or [string]::IsNullOrWhiteSpace($Config[$field])) {
$errors += "Missing required field: $field"
}
}
# Validate certificate path
if ($Config.certificatePath -and -not (Test-Path $Config.certificatePath)) {
$errors += "Certificate file not found: $($Config.certificatePath)"
}
# Validate project path
if ($Config.projectPath -and -not (Test-Path $Config.projectPath)) {
$errors += "Project path not found: $($Config.projectPath)"
}
# Validate URL format
if ($Config.projectUrl -and $Config.projectUrl -notmatch '^https://') {
$errors += "Project URL must start with https://"
}
# Validate ports
if ($Config.iisSettings) {
if ($Config.iisSettings.httpPort -and ($Config.iisSettings.httpPort -lt 1 -or $Config.iisSettings.httpPort -gt 65535)) {
$errors += "HTTP port must be between 1 and 65535"
}
if ($Config.iisSettings.httpsPort -and ($Config.iisSettings.httpsPort -lt 1 -or $Config.iisSettings.httpsPort -gt 65535)) {
$errors += "HTTPS port must be between 1 and 65535"
}
}
return $errors
}
# Main script
try {
Write-Host "`n╔════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ IIS Configuration Creator for TailorWell.Admin ║" -ForegroundColor Cyan
Write-Host "╚════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
# Display system information
Write-Step "System Information"
$sysInfo = Get-SystemInfo
foreach ($key in $sysInfo.Keys) {
Write-Info "$key`: $($sysInfo[$key])"
}
if (-not $sysInfo.IISInstalled) {
Write-Host "`n⚠ WARNING: IIS does not appear to be installed!" -ForegroundColor Yellow
Write-Host " You will need to install IIS before running the setup script." -ForegroundColor Yellow
}
# Load template or create new configuration
$config = @{}
if ($Template -and (Test-Path $Template)) {
Write-Step "Loading template configuration"
$templateContent = Get-Content $Template -Raw | ConvertFrom-Json
foreach ($prop in $templateContent.PSObject.Properties) {
$config[$prop.Name] = $prop.Value
}
Write-Success "Template loaded from $Template"
} else {
# Load defaults from schema
$schemaPath = Join-Path $PSScriptRoot "config-schema.json"
if (Test-Path $schemaPath) {
Write-Step "Loading configuration schema"
$schema = Get-Content $schemaPath -Raw | ConvertFrom-Json
# Extract defaults from schema
foreach ($prop in $schema.properties.PSObject.Properties) {
if ($prop.Value.default) {
$config[$prop.Name] = $prop.Value.default
}
}
# Handle nested IIS settings defaults
if ($schema.properties.iisSettings) {
$config['iisSettings'] = @{}
foreach ($iisProp in $schema.properties.iisSettings.properties.PSObject.Properties) {
if ($iisProp.Value.default) {
$config.iisSettings[$iisProp.Name] = $iisProp.Value.default
}
}
}
# Handle nested features defaults
if ($schema.properties.features) {
$config['features'] = @{}
foreach ($featureProp in $schema.properties.features.properties.PSObject.Properties) {
if ($featureProp.Value.default) {
$config.features[$featureProp.Name] = $featureProp.Value.default
}
}
}
Write-Success "Schema defaults loaded"
}
}
# Gather configuration values
Write-Step "Configuration Settings"
Write-Host "Please provide the following configuration values:" -ForegroundColor White
# Certificate configuration
Write-Host "`n[Certificate Configuration]" -ForegroundColor Magenta
$defaultCertPath = if ($config.certificatePath) { $config.certificatePath } else { "" }
$certPath = Read-Value -Prompt "Certificate path (.pfx file)" -Default $defaultCertPath -Required
# Expand environment variables and tilde
$certPath = $certPath.Replace('~', $HOME)
$certPath = [System.Environment]::ExpandEnvironmentVariables($certPath)
$config['certificatePath'] = $certPath
# Check if certificate needs a password
$needsPassword = $false
try {
$testCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$testCert.Import($certPath)
} catch {
$needsPassword = $true
}
if ($needsPassword -or $Interactive) {
$certPassword = Read-Value -Prompt "Certificate password (leave empty if none)" -Secure
$config['certificatePassword'] = if ($certPassword) { $certPassword } else { $null }
} else {
$config['certificatePassword'] = $null
}
# Project configuration
Write-Host "`n[Project Configuration]" -ForegroundColor Magenta
$defaultProjectPath = if ($config.projectPath) {
$config.projectPath
} else {
Get-DefaultProjectPath
}
$projectPath = Read-Value -Prompt "Project path (Company.Admin directory)" -Default $defaultProjectPath -Required
$projectPath = $projectPath.Replace('~', $HOME)
$projectPath = [System.Environment]::ExpandEnvironmentVariables($projectPath)
$config['projectPath'] = $projectPath
# Site configuration
Write-Host "`n[IIS Site Configuration]" -ForegroundColor Magenta
$config['siteName'] = Read-Value -Prompt "Site name" -Default $config.siteName -Required
$config['appPoolName'] = Read-Value -Prompt "Application pool name" -Default $config.appPoolName -Required
$config['projectUrl'] = Read-Value -Prompt "Project URL" -Default $config.projectUrl -Required
# Database configuration
Write-Host "`n[Database Configuration]" -ForegroundColor Magenta
$config['databaseEnvironmentVariable'] = Read-Value -Prompt "Database environment variable name" -Default $config.databaseEnvironmentVariable -Required
$config['databaseServer'] = Read-Value -Prompt "Database server" -Default $config.databaseServer -Required
$config['databaseName'] = Read-Value -Prompt "Database name" -Default $config.databaseName -Required
$config['databaseUserId'] = Read-Value -Prompt "Database user ID" -Default $config.databaseUserId -Required
$config['databasePassword'] = Read-Value -Prompt "Database password" -Required -Secure
# IIS Settings (optional)
if ($Interactive -or -not $config.iisSettings) {
Write-Host "`n[IIS Settings (Optional)]" -ForegroundColor Magenta
if (-not $config.iisSettings) {
$config['iisSettings'] = @{}
}
$config.iisSettings['httpPort'] = [int](Read-Value -Prompt "HTTP port" -Default ($config.iisSettings.httpPort ?? 8080))
$config.iisSettings['httpsPort'] = [int](Read-Value -Prompt "HTTPS port" -Default ($config.iisSettings.httpsPort ?? 443))
$config.iisSettings['runtimeVersion'] = Read-Value -Prompt "Runtime version (v4.0 or v2.0)" -Default ($config.iisSettings.runtimeVersion ?? "v4.0")
$config.iisSettings['pipelineMode'] = Read-Value -Prompt "Pipeline mode (Integrated or Classic)" -Default ($config.iisSettings.pipelineMode ?? "Integrated")
$enable32Bit = Read-Value -Prompt "Enable 32-bit apps (true/false)" -Default ($config.iisSettings.enable32BitApps ?? "false")
$config.iisSettings['enable32BitApps'] = $enable32Bit -eq "true"
$config.iisSettings['identityType'] = Read-Value -Prompt "Identity type" -Default ($config.iisSettings.identityType ?? "LocalSystem")
}
# Features (optional)
if ($Interactive -or -not $config.features) {
Write-Host "`n[Features (Optional)]" -ForegroundColor Magenta
if (-not $config.features) {
$config['features'] = @{}
}
$enableDebug = Read-Value -Prompt "Enable debug mode (true/false)" -Default ($config.features.enableDebugMode ?? "true")
$config.features['enableDebugMode'] = $enableDebug -eq "true"
$enableErrors = Read-Value -Prompt "Enable detailed errors (true/false)" -Default ($config.features.enableDetailedErrors ?? "true")
$config.features['enableDetailedErrors'] = $enableErrors -eq "true"
$addHosts = Read-Value -Prompt "Add hosts file entry (true/false)" -Default ($config.features.addHostsEntry ?? "true")
$config.features['addHostsEntry'] = $addHosts -eq "true"
$validateCert = Read-Value -Prompt "Validate certificate (true/false)" -Default ($config.features.validateCertificate ?? "true")
$config.features['validateCertificate'] = $validateCert -eq "true"
}
# Validate configuration
Write-Step "Validating Configuration"
$errors = Validate-Configuration -Config $config
if ($errors.Count -gt 0) {
Write-Host "Configuration validation failed:" -ForegroundColor Red
foreach ($err in $errors) {
Write-Host " ✗ $err" -ForegroundColor Red
}
throw "Configuration validation failed"
}
Write-Success "Configuration is valid"
# Save configuration
Write-Step "Saving Configuration"
$outputPath = Join-Path $PSScriptRoot $OutputFile
# Convert to JSON with proper formatting
$jsonConfig = $config | ConvertTo-Json -Depth 10
Set-Content -Path $outputPath -Value $jsonConfig -Encoding UTF8
Write-Success "Configuration saved to $outputPath"
# Display summary
Write-Host "`n╔════════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "║ Configuration Created Successfully ║" -ForegroundColor Green
Write-Host "╚════════════════════════════════════════════════════════════╝" -ForegroundColor Green
Write-Host "`nConfiguration Summary:" -ForegroundColor Cyan
Write-Host " • Site Name: $($config.siteName)" -ForegroundColor White
Write-Host " • Project URL: $($config.projectUrl)" -ForegroundColor White
Write-Host " • Database: $($config.databaseServer)\$($config.databaseName)" -ForegroundColor White
Write-Host " • Output File: $outputPath" -ForegroundColor White
Write-Host "`nNext Steps:" -ForegroundColor Yellow
Write-Host " 1. Review the configuration file: $OutputFile" -ForegroundColor White
Write-Host " 2. Run as Administrator: .\setup-iis-for-admin-portal-locally.ps1 -ConfigFile $OutputFile" -ForegroundColor White
Write-Host " 3. Open Visual Studio and start debugging" -ForegroundColor White
} catch {
Write-Host "`n✗ Error: $_" -ForegroundColor Red
exit 1
}
#Requires -RunAsAdministrator
#Requires -Version 7.0
<#
.SYNOPSIS
Sets up IIS for local TailorWell.Admin development with HTTPS support.
.DESCRIPTION
This script configures IIS with an application pool, site, and HTTPS binding
for the TailorWell.Admin ASP.NET application. It reads configuration from a
JSON file and sets up the database connection through an environment variable.
.PARAMETER ConfigFile
Path to the JSON configuration file. Defaults to "bobby-config.json" in the same directory.
.PARAMETER SkipValidation
Skip configuration validation steps.
.EXAMPLE
.\setup-iis-for-admin-portal-locally.ps1
.\setup-iis-for-admin-portal-locally.ps1 -ConfigFile "team-config.json"
#>
param(
[string]$ConfigFile = "$PSScriptRoot\me-config.json",
[switch]$SkipValidation
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "Continue"
# Helper functions
function Write-Step {
param([string]$Message)
Write-Host "`n[$([datetime]::Now.ToString('HH:mm:ss'))] $Message" -ForegroundColor Cyan
}
function Write-Success {
param([string]$Message)
Write-Host "✓ $Message" -ForegroundColor Green
}
function Write-Warning {
param([string]$Message)
Write-Host "⚠ $Message" -ForegroundColor Yellow
}
function Write-Error {
param([string]$Message)
Write-Host "✗ $Message" -ForegroundColor Red
}
function Test-Administrator {
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Test-IISInstalled {
return Test-Path "$env:SystemRoot\System32\inetsrv\appcmd.exe"
}
function Invoke-AppCmd {
param(
[string]$Arguments,
[switch]$IgnoreError
)
$appcmd = "$env:SystemRoot\System32\inetsrv\appcmd.exe"
$result = & $appcmd $Arguments.Split(' ') 2>&1
if ($LASTEXITCODE -ne 0 -and -not $IgnoreError) {
throw "appcmd failed: $result"
}
return $result
}
# Main script
try {
Write-Step "Starting IIS Setup for TailorWell.Admin"
if (-not (Test-Administrator)) {
throw "This script must be run as Administrator. Please restart PowerShell as Administrator."
}
if (-not (Test-IISInstalled)) {
throw "IIS is not installed. Please install IIS with ASP.NET support first."
}
Write-Step "Loading configuration from $ConfigFile"
if (-not (Test-Path $ConfigFile)) {
throw "Configuration file not found: $ConfigFile"
}
$config = Get-Content $ConfigFile -Raw | ConvertFrom-Json
Write-Success "Configuration loaded successfully"
if (-not $SkipValidation) {
Write-Step "Validating configuration"
if (-not (Test-Path $config.certificatePath)) {
throw "Certificate file not found: $($config.certificatePath)"
}
Write-Success "Certificate file found"
if (-not (Test-Path $config.projectPath)) {
throw "Project path not found: $($config.projectPath)"
}
Write-Success "Project path found"
if ([string]::IsNullOrWhiteSpace($config.databaseServer) -or $config.databaseServer -eq "YOUR_DATABASE_SERVER") {
throw "Database server not configured. Please update the configuration file with actual database credentials."
}
if ([string]::IsNullOrWhiteSpace($config.databaseUserId) -or $config.databaseUserId -eq "YOUR_USER_ID") {
throw "Database user ID not configured. Please update the configuration file with actual database credentials."
}
if ([string]::IsNullOrWhiteSpace($config.databasePassword) -or $config.databasePassword -eq "YOUR_PASSWORD") {
throw "Database password not configured. Please update the configuration file with actual database credentials."
}
Write-Success "Database configuration validated"
}
Write-Step "Setting up database environment variable"
$connectionString = "Server=$($config.databaseServer);Database=$($config.databaseName);User Id=$($config.databaseUserId);Password=$($config.databasePassword);Encrypt=true;TrustServerCertificate=true;Connection Timeout=30;"
$env:ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION = $connectionString
[System.Environment]::SetEnvironmentVariable(
$config.databaseEnvironmentVariable,
$connectionString,
[System.EnvironmentVariableTarget]::User
)
Write-Success "Environment variable '$($config.databaseEnvironmentVariable)' set"
Write-Step "Enabling required IIS features"
$features = @(
"IIS-WebServerRole",
"IIS-WebServer",
"IIS-CommonHttpFeatures",
"IIS-HttpErrors",
"IIS-HttpRedirect",
"IIS-ApplicationDevelopment",
"IIS-NetFxExtensibility45",
"IIS-HealthAndDiagnostics",
"IIS-HttpLogging",
"IIS-Security",
"IIS-RequestFiltering",
"IIS-Performance",
"IIS-WebServerManagementTools",
"IIS-ManagementConsole",
"IIS-IIS6ManagementCompatibility",
"IIS-Metabase",
"IIS-ASPNET45",
"IIS-NetFxExtensibility",
"IIS-ISAPIExtensions",
"IIS-ISAPIFilter"
)
foreach ($feature in $features) {
Write-Host " Enabling $feature..." -NoNewline
Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart -WarningAction SilentlyContinue | Out-Null
Write-Host " Done" -ForegroundColor Green
}
Write-Success "IIS features enabled"
Write-Step "Registering ASP.NET with IIS"
Write-Host " Registering ASP.NET 4.0..." -NoNewline
$aspnetRegPath = "$env:WINDIR\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe"
if (Test-Path $aspnetRegPath) {
& $aspnetRegPath -iru | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Host " Configuring handler mappings..." -NoNewline
Invoke-AppCmd "set config -section:system.webServer/handlers /accessPolicy:Read,Script,Execute" -IgnoreError | Out-Null
Write-Host " Done" -ForegroundColor Green
} else {
Write-Warning "ASP.NET registration tool not found"
}
Write-Success "ASP.NET registration complete"
Write-Step "Clearing ASP.NET temporary files"
$tempPaths = @(
"$env:WINDIR\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files",
"$env:WINDIR\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files",
"$env:TEMP\Temporary ASP.NET Files",
"$env:LOCALAPPDATA\Temp\Temporary ASP.NET Files"
)
foreach ($tempPath in $tempPaths) {
if (Test-Path $tempPath) {
Write-Host " Clearing $([System.IO.Path]::GetFileName($tempPath))..." -NoNewline
try {
Get-ChildItem $tempPath -Recurse -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Write-Host " Done" -ForegroundColor Green
} catch {
Write-Host " Skipped (in use)" -ForegroundColor Yellow
}
}
}
Write-Success "Temporary files cleared"
Write-Step "Resetting IIS"
Write-Host " Stopping IIS..." -NoNewline
iisreset /stop /noforce | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Host " Starting IIS..." -NoNewline
iisreset /start | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Success "IIS reset complete"
Write-Step "Configuring Application Pool"
$existingPool = Invoke-AppCmd "list apppool /name:$($config.appPoolName)" -IgnoreError
if ($existingPool -and $existingPool -notlike "*ERROR*") {
Write-Warning "Removing existing application pool"
Invoke-AppCmd "stop apppool /apppool.name:$($config.appPoolName)" -IgnoreError | Out-Null
Invoke-AppCmd "delete apppool /apppool.name:$($config.appPoolName)"
}
Write-Host " Creating application pool..." -NoNewline
Invoke-AppCmd "add apppool /name:$($config.appPoolName)" | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Host " Configuring pool settings..." -NoNewline
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /managedRuntimeVersion:$($config.iisSettings.runtimeVersion)" | Out-Null
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /managedPipelineMode:$($config.iisSettings.pipelineMode)" | Out-Null
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /enable32BitAppOnWin64:$($config.iisSettings.enable32BitApps.ToString().ToLower())" | Out-Null
if ($config.iisSettings.identityType -eq "LocalSystem") {
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /processModel.identityType:LocalSystem" | Out-Null
} elseif ($config.iisSettings.identityType -eq "NetworkService") {
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /processModel.identityType:NetworkService" | Out-Null
} elseif ($config.iisSettings.identityType -eq "LocalService") {
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /processModel.identityType:LocalService" | Out-Null
} else {
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /processModel.identityType:ApplicationPoolIdentity" | Out-Null
}
Invoke-AppCmd "set apppool /apppool.name:$($config.appPoolName) /recycling.periodicRestart.time:00:00:00" | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Success "Application pool '$($config.appPoolName)' created"
Write-Step "Configuring IIS Site"
$existingSite = Invoke-AppCmd "list site /name:$($config.siteName)" -IgnoreError
if ($existingSite -and $existingSite -notlike "*ERROR*") {
Write-Warning "Removing existing site"
Invoke-AppCmd "stop site /site.name:$($config.siteName)" -IgnoreError | Out-Null
Invoke-AppCmd "delete site /site.name:$($config.siteName)" -IgnoreError | Out-Null
}
$cleanPath = $config.projectPath.Replace('/', '\').TrimEnd('\')
if (-not (Test-Path $cleanPath)) {
throw "Physical path does not exist: $cleanPath"
}
Write-Host " Finding available site ID..." -NoNewline
$allSites = Invoke-AppCmd "list sites" -IgnoreError
$usedIds = @(1)
foreach ($line in $allSites) {
if ($line -match 'id:(\d+)') {
$usedIds += [int]$matches[1]
}
}
$siteId = 2
while ($usedIds -contains $siteId) {
$siteId++
}
Write-Host " Using ID: $siteId" -ForegroundColor Green
Write-Host " Creating site with application..." -NoNewline
$createCmd = "add site /name:$($config.siteName) /id:$siteId /physicalPath:$cleanPath /bindings:http/*:$($config.iisSettings.httpPort):"
Invoke-AppCmd $createCmd | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Host " Setting application pool..." -NoNewline
Invoke-AppCmd "set site $($config.siteName) /applicationDefaults.applicationPool:$($config.appPoolName)" | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Host " Configuring ASP.NET modules..." -NoNewline
Invoke-AppCmd "set config $($config.siteName) /section:system.webServer/modules /runAllManagedModulesForAllRequests:true" -IgnoreError | Out-Null
Invoke-AppCmd "set config $($config.siteName) /section:system.webServer/handlers /accessPolicy:Read,Script" -IgnoreError | Out-Null
Write-Host " Done" -ForegroundColor Green
Write-Success "Site '$($config.siteName)' created with ID $siteId"
Write-Step "Configuring HTTPS certificate"
$certPassword = if ($config.certificatePassword) {
ConvertTo-SecureString -String $config.certificatePassword -AsPlainText -Force
} else {
$null
}
$cert = Import-PfxCertificate -FilePath $config.certificatePath -CertStoreLocation Cert:\LocalMachine\My -Password $certPassword
Write-Success "Certificate imported (Thumbprint: $($cert.Thumbprint))"
$uri = [System.Uri]$config.projectUrl
$hostname = $uri.Host
Invoke-AppCmd "set site /site.name:$($config.siteName) /+bindings.[protocol='https',bindingInformation='*:$($config.iisSettings.httpsPort):$hostname']" | Out-Null
$bindingInfo = netsh http show sslcert hostnameport="${hostname}:$($config.iisSettings.httpsPort)" 2>$null
if ($bindingInfo -notlike "*error*" -and $bindingInfo -notlike "*not found*") {
Write-Warning "Removing existing SSL certificate binding"
netsh http delete sslcert hostnameport="${hostname}:$($config.iisSettings.httpsPort)" | Out-Null
}
$appId = "{$([guid]::NewGuid().ToString().ToUpper())}"
netsh http add sslcert hostnameport="${hostname}:$($config.iisSettings.httpsPort)" certhash=$($cert.Thumbprint) appid="$appId" certstorename=MY | Out-Null
Write-Success "HTTPS binding configured for $hostname"
if ($config.features.addHostsEntry) {
Write-Step "Updating hosts file"
$hostsFile = "$env:SystemRoot\System32\drivers\etc\hosts"
$hostsContent = Get-Content $hostsFile -Raw
$hostEntry = "127.0.0.1`t$hostname"
if ($hostsContent -notmatch [regex]::Escape($hostname)) {
Add-Content -Path $hostsFile -Value "`n$hostEntry" -Encoding ASCII
Write-Success "Added hosts file entry for $hostname"
} else {
Write-Warning "Hosts file entry already exists for $hostname"
}
}
Write-Step "Setting permissions for debugging"
$projectDir = $config.projectPath
$acl = Get-Acl $projectDir
$permission = "IIS_IUSRS", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$permission = $currentUser, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
Set-Acl -Path $projectDir -AclObject $acl
Write-Success "Permissions configured for debugging"
Write-Step "Starting IIS components"
Write-Host " Starting application pool..." -NoNewline
try {
$poolStatus = Invoke-AppCmd "list apppool /name:$($config.appPoolName) /state" -IgnoreError
if ($poolStatus -notlike "*Started*") {
Invoke-AppCmd "start apppool /apppool.name:$($config.appPoolName)" | Out-Null
Write-Host " Started" -ForegroundColor Green
} else {
Write-Host " Already running" -ForegroundColor Green
}
} catch {
Write-Host " Failed" -ForegroundColor Red
Write-Warning "Could not start application pool: $_"
}
Write-Host " Starting site..." -NoNewline
try {
$siteStatus = Invoke-AppCmd "list site /name:$($config.siteName) /state" -IgnoreError
if ($siteStatus -notlike "*Started*") {
Invoke-AppCmd "start site /site.name:$($config.siteName)" | Out-Null
Write-Host " Started" -ForegroundColor Green
} else {
Write-Host " Already running" -ForegroundColor Green
}
} catch {
Write-Host " Failed" -ForegroundColor Red
Write-Warning "Could not start site: $_"
}
Start-Sleep -Seconds 2
$finalPoolStatus = Invoke-AppCmd "list apppool /name:$($config.appPoolName)" -IgnoreError
if ($finalPoolStatus -like "*Started*") {
Write-Success "Application pool and site started successfully"
} else {
Write-Warning "Application pool may not be running properly. Check Event Viewer for errors."
}
Write-Step "Testing site accessibility"
Write-Host " Testing HTTP response..." -NoNewline
Start-Sleep -Seconds 2
try {
$testUrl = "http://localhost:$($config.iisSettings.httpPort)/"
$response = Invoke-WebRequest -Uri $testUrl -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
Write-Host " Success (Status: $($response.StatusCode))" -ForegroundColor Green
Write-Success "Site is accessible at $testUrl"
} catch {
if ($_.Exception.Response.StatusCode -eq 500) {
Write-Host " Site responds but has errors (500)" -ForegroundColor Yellow
Write-Warning "Site is returning 500 errors. Check:"
Write-Warning " - Application has been built (DLLs in bin folder)"
Write-Warning " - Web.config is valid"
Write-Warning " - Database connection is configured"
Write-Warning " - Check Event Viewer for detailed errors"
} else {
Write-Host " Failed" -ForegroundColor Red
Write-Warning "Could not access site: $_"
}
}
Write-Host "`n" -NoNewline
Write-Host "═══════════════════════════════════════════════════════════" -ForegroundColor Green
Write-Host " IIS Setup Complete!" -ForegroundColor Green
Write-Host "═══════════════════════════════════════════════════════════" -ForegroundColor Green
Write-Host "`n Site URL: $($config.projectUrl)" -ForegroundColor Cyan
Write-Host " App Pool: $($config.appPoolName)" -ForegroundColor Cyan
Write-Host " Site Name: $($config.siteName)" -ForegroundColor Cyan
Write-Host " Project: $($config.projectPath)" -ForegroundColor Cyan
Write-Host "`n Next Steps:" -ForegroundColor Yellow
Write-Host " 1. Open Visual Studio and load the solution" -ForegroundColor White
Write-Host " 2. Set Company.Admin as the startup project" -ForegroundColor White
Write-Host " 3. Press F5 to debug or Ctrl+F5 to run" -ForegroundColor White
Write-Host " 4. Navigate to $($config.projectUrl)" -ForegroundColor White
Write-Host "`n═══════════════════════════════════════════════════════════" -ForegroundColor Green
} catch {
Write-Error "Setup failed: $_"
exit 1
}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "IIS Local Configuration Schema",
"description": "Configuration schema for setting up IIS for local Company.Admin development",
"type": "object",
"properties": {
"certificatePath": {
"type": "string",
"description": "Path to the PFX certificate file for HTTPS",
"pattern": "^.*\\.pfx$"
},
"certificatePassword": {
"type": ["string", "null"],
"description": "Password for the PFX certificate (if required)"
},
"projectPath": {
"type": "string",
"description": "Path to the Company.Admin project directory"
},
"siteName": {
"type": "string",
"description": "Name of the IIS site",
"default": "AdminPortalDev"
},
"appPoolName": {
"type": "string",
"description": "Name of the IIS application pool",
"default": "admin-portal-dev-pool"
},
"projectUrl": {
"type": "string",
"description": "URL for accessing the application",
"pattern": "^https://.*",
"default": "https://poop-admin-dev.company.com"
},
"databaseEnvironmentVariable": {
"type": "string",
"description": "Environment variable name containing database connection string",
"default": "ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION"
},
"databaseServer": {
"type": "string",
"description": "SQL Server instance name or address"
},
"databaseName": {
"type": "string",
"description": "Database name",
"default": "IBS"
},
"databaseUserId": {
"type": "string",
"description": "Database user ID for SQL authentication"
},
"databasePassword": {
"type": "string",
"description": "Database password for SQL authentication"
},
"iisSettings": {
"type": "object",
"description": "Optional IIS configuration settings",
"properties": {
"httpPort": {
"type": "integer",
"description": "HTTP port (redirect to HTTPS)",
"default": 8080,
"minimum": 1,
"maximum": 65535
},
"httpsPort": {
"type": "integer",
"description": "HTTPS port",
"default": 443,
"minimum": 1,
"maximum": 65535
},
"runtimeVersion": {
"type": "string",
"description": ".NET Framework runtime version",
"default": "v4.0",
"enum": ["v4.0", "v2.0"]
},
"pipelineMode": {
"type": "string",
"description": "IIS pipeline mode",
"default": "Integrated",
"enum": ["Integrated", "Classic"]
},
"enable32BitApps": {
"type": "boolean",
"description": "Enable 32-bit applications",
"default": false
},
"identityType": {
"type": "string",
"description": "Application pool identity type",
"default": "ApplicationPoolIdentity",
"enum": ["ApplicationPoolIdentity", "LocalSystem", "LocalService", "NetworkService", "SpecificUser"]
}
},
"additionalProperties": false
},
"features": {
"type": "object",
"description": "Optional feature flags",
"properties": {
"enableDebugMode": {
"type": "boolean",
"description": "Enable debug compilation in Web.config",
"default": true
},
"enableDetailedErrors": {
"type": "boolean",
"description": "Show detailed error messages",
"default": true
},
"addHostsEntry": {
"type": "boolean",
"description": "Add entry to hosts file for custom domain",
"default": true
},
"validateCertificate": {
"type": "boolean",
"description": "Validate certificate before installing",
"default": true
}
},
"additionalProperties": false
}
},
"required": [
"certificatePath",
"projectPath",
"siteName",
"appPoolName",
"projectUrl",
"databaseEnvironmentVariable",
"databaseServer",
"databaseName",
"databaseUserId",
"databasePassword"
],
"additionalProperties": false
}
{
"certificatePath": "~/Desktop/cert.pfx",
"certificatePassword": null,
"projectPath": "~/src/Admin-Portal/Company.Admin",
"siteName": "AdminPortalDev",
"appPoolName": "admin-portal-dev-pool",
"projectUrl": "https://poop-admin-dev.company.com",
"databaseEnvironmentVariable": "ADMIN_PORTAL_V8_PRIMARY_DB_CONNECTION",
"databaseServer": "YOUR_DATABASE_SERVER",
"databaseName": "Admin",
"databaseUserId": "YOUR_USER_ID",
"databasePassword": "YOUR_PASSWORD",
"iisSettings": {
"httpPort": 8080,
"httpsPort": 443,
"runtimeVersion": "v4.0",
"pipelineMode": "Integrated",
"enable32BitApps": false,
"identityType": "LocalSystem"
},
"features": {
"enableDebugMode": true,
"enableDetailedErrors": true,
"addHostsEntry": true,
"validateCertificate": true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment