Tag Archive for: Program

Advanced Template Module Generator Tool

<#
.SYNOPSIS
Advanced Template Module Generator Tool

.DESCRIPTION
This script provides an interactive tool to generate a comprehensive structure for a PowerShell module,
including advanced features like dependency management, script analyzer settings, and extensive testing setup.

.NOTES
File Name      : AdvancedTemplateModuleGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\AdvancedTemplateModuleGenerator.ps1
#>

function Show-Menu {
    Clear-Host
    Write-Host "=== Advanced Template Module Generator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Set Module Details"
    Write-Host "2. Add Public Function"
    Write-Host "3. Add Private Function"
    Write-Host "4. Add Module Dependencies"
    Write-Host "5. Configure Build Settings"
    Write-Host "6. Configure Test Settings"
    Write-Host "7. Generate Module Files"
    Write-Host "8. Exit"
}

function Set-ModuleDetails {
    $script:moduleName = Read-Host "Enter the name of the module"
    $script:moduleDescription = Read-Host "Enter a brief description of the module"
    $script:moduleAuthor = Read-Host "Enter the author's name"
    $script:moduleVersion = Read-Host "Enter the module version (e.g., 1.0.0)"
    $script:moduleLicense = Read-Host "Enter the module license (e.g., MIT)"
    $script:moduleProjectUri = Read-Host "Enter the project URI (optional)"
    Write-Host "Module details set successfully." -ForegroundColor Green
}

function Add-PublicFunction {
    $functionName = Read-Host "Enter the name of the public function"
    $script:publicFunctions += $functionName
    Write-Host "Public function '$functionName' added." -ForegroundColor Green
}

function Add-PrivateFunction {
    $functionName = Read-Host "Enter the name of the private function"
    $script:privateFunctions += $functionName
    Write-Host "Private function '$functionName' added." -ForegroundColor Green
}

function Add-ModuleDependencies {
    do {
        $dependencyName = Read-Host "Enter the name of the module dependency (or press Enter to finish)"
        if ($dependencyName -ne "") {
            $dependencyVersion = Read-Host "Enter the required version (leave blank for any version)"
            $script:moduleDependencies += [PSCustomObject]@{
                Name = $dependencyName
                Version = $dependencyVersion
            }
            Write-Host "Dependency added: $dependencyName $dependencyVersion" -ForegroundColor Green
        }
    } while ($dependencyName -ne "")
}

function Set-BuildSettings {
    $script:usePSScriptAnalyzer = (Read-Host "Use PSScriptAnalyzer for code analysis? (Y/N)") -eq 'Y'
    $script:useplatyPS = (Read-Host "Use platyPS for documentation generation? (Y/N)") -eq 'Y'
    Write-Host "Build settings configured." -ForegroundColor Green
}

function Set-TestSettings {
    $script:usePester = (Read-Host "Use Pester for testing? (Y/N)") -eq 'Y'
    $script:useCodeCoverage = (Read-Host "Include code coverage in tests? (Y/N)") -eq 'Y'
    Write-Host "Test settings configured." -ForegroundColor Green
}

function Generate-ModuleFiles {
    if ([string]::IsNullOrWhiteSpace($script:moduleName)) {
        Write-Host "Please set module details first." -ForegroundColor Yellow
        return
    }

    $modulePath = Join-Path -Path $PWD -ChildPath $script:moduleName
    New-Item -Path $modulePath -ItemType Directory -Force | Out-Null

    # Create module manifest
    $manifestPath = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psd1"
    $manifestParams = @{
        Path = $manifestPath
        RootModule = "$($script:moduleName).psm1"
        ModuleVersion = $script:moduleVersion
        Author = $script:moduleAuthor
        Description = $script:moduleDescription
        FunctionsToExport = $script:publicFunctions
        PowerShellVersion = '5.1'
    }
    if ($script:moduleLicense) { $manifestParams['LicenseUri'] = $script:moduleLicense }
    if ($script:moduleProjectUri) { $manifestParams['ProjectUri'] = $script:moduleProjectUri }
    if ($script:moduleDependencies) {
        $manifestParams['RequiredModules'] = $script:moduleDependencies | ForEach-Object {
            if ($_.Version) { @{ModuleName = $_.Name; ModuleVersion = $_.Version} } else { $_.Name }
        }
    }
    New-ModuleManifest @manifestParams

    # Create module script file
    $modulePSM1Path = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psm1"
    $modulePSM1Content = @"
# Dot source public/private functions
`$public = @(Get-ChildItem -Path `$PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue)
`$private = @(Get-ChildItem -Path `$PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue)

foreach (`$import in @(`$public + `$private)) {
    try {
        . `$import.FullName
    } catch {
        Write-Error -Message "Failed to import function `$(`$import.FullName): `$_"
    }
}

# Export public functions
Export-ModuleMember -Function `$public.BaseName
"@
    Set-Content -Path $modulePSM1Path -Value $modulePSM1Content

    # Create Public and Private folders
    New-Item -Path (Join-Path -Path $modulePath -ChildPath "Public") -ItemType Directory -Force | Out-Null
    New-Item -Path (Join-Path -Path $modulePath -ChildPath "Private") -ItemType Directory -Force | Out-Null

    # Create function files
    foreach ($function in $script:publicFunctions) {
        $functionPath = Join-Path -Path $modulePath -ChildPath "Public\$function.ps1"
        $functionContent = @"
function $function {
    <#
    .SYNOPSIS
    Brief description of $function

    .DESCRIPTION
    Detailed description of $function

    .PARAMETER Param1
    Description of Param1

    .EXAMPLE
    $function -Param1 Value
    Explanation of the example

    .NOTES
    Additional notes about the function
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=`$true)]
        [string]`$Param1
    )

    begin {
        # Initialize any prerequisites
    }

    process {
        # Main function logic
    }

    end {
        # Cleanup or final actions
    }
}
"@
        Set-Content -Path $functionPath -Value $functionContent
    }

    foreach ($function in $script:privateFunctions) {
        $functionPath = Join-Path -Path $modulePath -ChildPath "Private\$function.ps1"
        $functionContent = @"
function $function {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=`$true)]
        [string]`$Param1
    )

    # Function logic here
}
"@
        Set-Content -Path $functionPath -Value $functionContent
    }

    # Create tests folder and files
    $testsFolderPath = Join-Path -Path $modulePath -ChildPath "Tests"
    New-Item -Path $testsFolderPath -ItemType Directory -Force | Out-Null

    if ($script:usePester) {
        $testFilePath = Join-Path -Path $testsFolderPath -ChildPath "$($script:moduleName).Tests.ps1"
        $testFileContent = @"
`$ModuleName = '$($script:moduleName)'
`$ModuleManifestPath = "`$PSScriptRoot\..\`$ModuleName.psd1"

Describe "`$ModuleName Module Tests" {
    BeforeAll {
        `$Module = Import-Module `$ModuleManifestPath -PassThru -Force
    }

    It "Module manifest is valid" {
        Test-ModuleManifest -Path `$ModuleManifestPath | Should -Not -BeNullOrEmpty
        `$? | Should -Be `$true
    }

    It "Module can be imported" {
        `$Module | Should -Not -BeNullOrEmpty
    }

    Context "Function Tests" {
        # Add tests for each function
        $(foreach ($function in $script:publicFunctions) {
@"
        It "$function exists" {
            Get-Command $function -Module `$ModuleName | Should -Not -BeNullOrEmpty
        }

"@
        })
    }
}
"@
        Set-Content -Path $testFilePath -Value $testFileContent
    }

    # Create build configuration
    $buildFolderPath = Join-Path -Path $modulePath -ChildPath "Build"
    New-Item -Path $buildFolderPath -ItemType Directory -Force | Out-Null

    $buildFilePath = Join-Path -Path $buildFolderPath -ChildPath "build.ps1"
    $buildFileContent = @"
param (
    [switch]`$Test,
    [switch]`$Analyze,
    [switch]`$Documentation
)

`$ModuleName = '$($script:moduleName)'
`$ModuleRoot = "`$PSScriptRoot\.."
`$OutputPath = "`$ModuleRoot\Output"

# Clean and create output directory
if (Test-Path -Path `$OutputPath) {
    Remove-Item -Path `$OutputPath -Recurse -Force
}
New-Item -Path `$OutputPath -ItemType Directory -Force | Out-Null

# Copy module files to output directory
Copy-Item -Path "`$ModuleRoot\`$ModuleName.psd1" -Destination `$OutputPath
Copy-Item -Path "`$ModuleRoot\`$ModuleName.psm1" -Destination `$OutputPath
Copy-Item -Path "`$ModuleRoot\Public" -Destination `$OutputPath -Recurse
Copy-Item -Path "`$ModuleRoot\Private" -Destination `$OutputPath -Recurse

if (`$Test) {
    # Run Pester tests
    `$testResults = Invoke-Pester -Path "`$ModuleRoot\Tests" -PassThru
    if (`$testResults.FailedCount -gt 0) {
        throw "One or more tests failed."
    }
}

if (`$Analyze) {
    # Run PSScriptAnalyzer
    `$analysisResults = Invoke-ScriptAnalyzer -Path `$OutputPath -Recurse
    if (`$analysisResults) {
        `$analysisResults | Format-Table
        throw "PSScriptAnalyzer found one or more issues."
    }
}

if (`$Documentation) {
    # Generate documentation using platyPS
    Import-Module platyPS
    New-MarkdownHelp -Module `$ModuleName -OutputFolder "`$OutputPath\docs" -Force
}

Write-Host "Build completed successfully." -ForegroundColor Green
"@
    Set-Content -Path $buildFilePath -Value $buildFileContent

    # Create PSScriptAnalyzer settings file
    if ($script:usePSScriptAnalyzer) {
        $analyzerSettingsPath = Join-Path -Path $modulePath -ChildPath "PSScriptAnalyzerSettings.psd1"
        $analyzerSettingsContent = @"
@{
    Severity = @('Error', 'Warning')
    ExcludeRules = @('PSUseShouldProcessForStateChangingFunctions')
    Rules = @{
        PSAvoidUsingCmdletAliases = @{
            Whitelist = @('Where', 'Select')
        }
    }
}
"@
        Set-Content -Path $analyzerSettingsPath -Value $analyzerSettingsContent
    }

    Write-Host "Module files generated successfully at: $modulePath" -ForegroundColor Green
}

# Initialize variables
$script:moduleName = ""
$script:moduleDescription = ""
$script:moduleAuthor = ""
$script:moduleVersion = ""
$script:moduleLicense = ""
$script:moduleProjectUri = ""
$script:publicFunctions = @()
$script:privateFunctions = @()
$script:moduleDependencies = @()
$script:usePSScriptAnalyzer = $false
$script:useplatyPS = $false
$script:usePester = $false
$script:useCodeCoverage = $false

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-8)"

    switch ($choice) {
        "1" { Set-ModuleDetails }
        "2" { Add-PublicFunction }
        "3" { Add-PrivateFunction }
        "4" { Add-ModuleDependencies }
        "5" { Set-BuildSettings }
        "6" { Set-TestSettings }
        "7" { Generate-ModuleFiles }
        "8" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "8") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "8")

This Advanced Template Module Generator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Enhanced functions to:
    • Set detailed module information (including license and project URI)
    • Add public and private functions
    • Specify module dependencies
    • Configure build and test settings

Key features:

  1. Advanced Module Manifest Generation:
    • Includes more detailed module information
    • Supports specifying module dependencies
  2. Comprehensive Module Structure:
    • Creates a more robust folder structure including build and test directories
  3. Enhanced Function File Generation:
    • Generates more detailed function templates
  4. Build Script Generation:
    • Creates a build.ps1 script for module building, testing, and documentation generation
  5. Test Configuration:
    • Sets up Pester tests with placeholders for each public function
    • Optionally includes code coverage settings
  6. PSScriptAnalyzer Integration:
    • Generates a PSScriptAnalyzer settings file
    • Includes PSScriptAnalyzer in the build process
  7. Documentation Support:
    • Optionally sets up platyPS for documentation generation
  8. Dependency Management:
    • Allows specifying module dependencies with version requirements

This tool is particularly useful for:

  • Experienced PowerShell module developers
  • Teams working on larger PowerShell projects
  • Developers who want to follow best practices in module development

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to:
    • Set detailed module information
    • Add public and private functions
    • Specify dependencies and configure build/test settings
    • Generate the module files
  3. Review the generated module structure and customize as needed

This advanced script provides a more comprehensive starting point for PowerShell module development, incorporating best practices and tools commonly used in professional PowerShell module projects.

Template Module Generator Tool

<#
.SYNOPSIS
Template Module Generator Tool

.DESCRIPTION
This script provides an interactive tool to generate a basic structure for a PowerShell module,
including the module manifest, public and private function files, and a basic test file.

.NOTES
File Name      : TemplateModuleGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\TemplateModuleGenerator.ps1
#>

function Show-Menu {
    Clear-Host
    Write-Host "=== Template Module Generator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Set Module Details"
    Write-Host "2. Add Public Function"
    Write-Host "3. Add Private Function"
    Write-Host "4. Generate Module Files"
    Write-Host "5. Exit"
}

function Set-ModuleDetails {
    $script:moduleName = Read-Host "Enter the name of the module"
    $script:moduleDescription = Read-Host "Enter a brief description of the module"
    $script:moduleAuthor = Read-Host "Enter the author's name"
    $script:moduleVersion = Read-Host "Enter the module version (e.g., 1.0.0)"
    Write-Host "Module details set successfully." -ForegroundColor Green
}

function Add-PublicFunction {
    $functionName = Read-Host "Enter the name of the public function"
    $script:publicFunctions += $functionName
    Write-Host "Public function '$functionName' added." -ForegroundColor Green
}

function Add-PrivateFunction {
    $functionName = Read-Host "Enter the name of the private function"
    $script:privateFunctions += $functionName
    Write-Host "Private function '$functionName' added." -ForegroundColor Green
}

function Generate-ModuleFiles {
    if ([string]::IsNullOrWhiteSpace($script:moduleName)) {
        Write-Host "Please set module details first." -ForegroundColor Yellow
        return
    }

    $modulePath = Join-Path -Path $PWD -ChildPath $script:moduleName
    New-Item -Path $modulePath -ItemType Directory -Force | Out-Null

    # Create module manifest
    $manifestPath = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psd1"
    New-ModuleManifest -Path $manifestPath `
        -RootModule "$($script:moduleName).psm1" `
        -ModuleVersion $script:moduleVersion `
        -Author $script:moduleAuthor `
        -Description $script:moduleDescription `
        -FunctionsToExport $script:publicFunctions

    # Create module script file
    $modulePSM1Path = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psm1"
    $modulePSM1Content = @"
# Dot source public/private functions
`$public = @(Get-ChildItem -Path `$PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue)
`$private = @(Get-ChildItem -Path `$PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue)

foreach (`$import in @(`$public + `$private)) {
    try {
        . `$import.FullName
    } catch {
        Write-Error -Message "Failed to import function `$(`$import.FullName): `$_"
    }
}

# Export public functions
Export-ModuleMember -Function `$public.BaseName
"@
    Set-Content -Path $modulePSM1Path -Value $modulePSM1Content

    # Create Public and Private folders
    New-Item -Path (Join-Path -Path $modulePath -ChildPath "Public") -ItemType Directory -Force | Out-Null
    New-Item -Path (Join-Path -Path $modulePath -ChildPath "Private") -ItemType Directory -Force | Out-Null

    # Create function files
    foreach ($function in $script:publicFunctions) {
        $functionPath = Join-Path -Path $modulePath -ChildPath "Public\$function.ps1"
        $functionContent = @"
function $function {
    <#
    .SYNOPSIS
    Brief description of $function

    .DESCRIPTION
    Detailed description of $function

    .PARAMETER Param1
    Description of Param1

    .EXAMPLE
    $function -Param1 Value
    Explanation of the example

    .NOTES
    Additional notes about the function
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=`$true)]
        [string]`$Param1
    )

    begin {
        # Initialize any prerequisites
    }

    process {
        # Main function logic
    }

    end {
        # Cleanup or final actions
    }
}
"@
        Set-Content -Path $functionPath -Value $functionContent
    }

    foreach ($function in $script:privateFunctions) {
        $functionPath = Join-Path -Path $modulePath -ChildPath "Private\$function.ps1"
        $functionContent = @"
function $function {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=`$true)]
        [string]`$Param1
    )

    # Function logic here
}
"@
        Set-Content -Path $functionPath -Value $functionContent
    }

    # Create a basic test file
    $testsFolderPath = Join-Path -Path $modulePath -ChildPath "Tests"
    New-Item -Path $testsFolderPath -ItemType Directory -Force | Out-Null
    $testFilePath = Join-Path -Path $testsFolderPath -ChildPath "$($script:moduleName).Tests.ps1"
    $testFileContent = @"
`$ModuleName = '$($script:moduleName)'
`$ModuleManifestPath = "`$PSScriptRoot\..\`$ModuleName.psd1"

Describe "`$ModuleName Module Tests" {
    It "Module manifest is valid" {
        Test-ModuleManifest -Path `$ModuleManifestPath | Should -Not -BeNullOrEmpty
        `$? | Should -Be `$true
    }

    It "Module can be imported" {
        Import-Module `$ModuleManifestPath
        Get-Module `$ModuleName | Should -Not -BeNullOrEmpty
    }

    # Add more tests for your functions here
}
"@
    Set-Content -Path $testFilePath -Value $testFileContent

    Write-Host "Module files generated successfully at: $modulePath" -ForegroundColor Green
}

# Initialize variables
$script:moduleName = ""
$script:moduleDescription = ""
$script:moduleAuthor = ""
$script:moduleVersion = ""
$script:publicFunctions = @()
$script:privateFunctions = @()

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-5)"

    switch ($choice) {
        "1" { Set-ModuleDetails }
        "2" { Add-PublicFunction }
        "3" { Add-PrivateFunction }
        "4" { Generate-ModuleFiles }
        "5" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "5") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "5")

This Template Module Generator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to:
    • Set module details (name, description, author, version)
    • Add public functions
    • Add private functions
    • Generate module files

Key features:

  1. Module Manifest Generation:
    • Creates a .psd1 file with basic module information
  2. Module Script File (.psm1) Generation:
    • Creates a .psm1 file that dot-sources public and private functions
  3. Function File Generation:
    • Creates separate .ps1 files for each public and private function
    • Generates a basic function template with comment-based help for public functions
  4. Directory Structure Creation:
    • Creates a module folder with Public and Private subfolders
  5. Basic Test File Generation:
    • Creates a simple Pester test file for the module

This tool is particularly useful for:

  • PowerShell module developers starting new projects
  • Anyone learning to create PowerShell modules
  • Developers who want to quickly scaffold a new module structure

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to:
    • Set the module details
    • Add public and private functions as needed
    • Generate the module files
  3. Review the generated module structure in the specified directory

This script provides a quick and easy way to create a basic PowerShell module structure, following best practices for module organization. It saves time in setting up the initial files and folders, allowing developers to focus on writing the actual module functionality.

CSV File Validator Tool

<#
.SYNOPSIS
CSV File Validator Tool

.DESCRIPTION
This script provides a tool to validate CSV files, check for structural issues,
analyze data types, and provide detailed information about the CSV content.

.NOTES
File Name      : CSVValidator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\CSVValidator.ps1
#>

function Show-Menu {
    Clear-Host
    Write-Host "=== CSV File Validator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Validate CSV File"
    Write-Host "2. Analyze CSV Structure"
    Write-Host "3. Check for Data Inconsistencies"
    Write-Host "4. Generate CSV Summary"
    Write-Host "5. Compare Two CSV Files"
    Write-Host "6. Exit"
}

function Validate-CSVFile {
    $filePath = Read-Host "Enter the path to the CSV file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        $csv = Import-Csv $filePath
        $rowCount = $csv.Count
        $columnCount = ($csv | Get-Member -MemberType NoteProperty).Count

        Write-Host "CSV is valid." -ForegroundColor Green
        Write-Host "Number of rows: $rowCount"
        Write-Host "Number of columns: $columnCount"

        $headers = ($csv | Get-Member -MemberType NoteProperty).Name
        Write-Host "Headers: $($headers -join ', ')"

        $size = (Get-Item $filePath).Length
        Write-Host "File Size: $size bytes"
    }
    catch {
        Write-Host "Invalid CSV. Error details:" -ForegroundColor Red
        Write-Host $_.Exception.Message
    }
}

function Analyze-CSVStructure {
    $filePath = Read-Host "Enter the path to the CSV file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        $csv = Import-Csv $filePath
        $headers = ($csv | Get-Member -MemberType NoteProperty).Name

        Write-Host "CSV Structure Analysis:" -ForegroundColor Yellow
        foreach ($header in $headers) {
            $values = $csv.$header | Where-Object { $_ -ne "" }
            $dataType = Guess-DataType $values
            $uniqueValues = ($values | Select-Object -Unique).Count
            $nullCount = ($csv.$header | Where-Object { $_ -eq "" }).Count

            Write-Host "`nColumn: $header"
            Write-Host "  Data Type: $dataType"
            Write-Host "  Unique Values: $uniqueValues"
            Write-Host "  Null/Empty Values: $nullCount"
            Write-Host "  Sample Values: $($values | Select-Object -First 5 -Unique)"
        }
    }
    catch {
        Write-Host "Error analyzing CSV structure: $_" -ForegroundColor Red
    }
}

function Guess-DataType($values) {
    $sampleSize = [Math]::Min($values.Count, 100)
    $sample = $values | Select-Object -First $sampleSize

    $isNumeric = $sample | ForEach-Object { $_ -as [double] } | Where-Object { $_ -ne $null }
    $isDate = $sample | ForEach-Object { $_ -as [datetime] } | Where-Object { $_ -ne $null }

    if ($isNumeric.Count -eq $sampleSize) { return "Numeric" }
    elseif ($isDate.Count -eq $sampleSize) { return "Date" }
    else { return "String" }
}

function Check-DataInconsistencies {
    $filePath = Read-Host "Enter the path to the CSV file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        $csv = Import-Csv $filePath
        $headers = ($csv | Get-Member -MemberType NoteProperty).Name

        Write-Host "Checking for Data Inconsistencies:" -ForegroundColor Yellow
        foreach ($header in $headers) {
            $values = $csv.$header
            $dataType = Guess-DataType $values

            $inconsistencies = @()
            switch ($dataType) {
                "Numeric" {
                    $inconsistencies = $values | Where-Object { $_ -ne "" -and ($_ -as [double]) -eq $null }
                }
                "Date" {
                    $inconsistencies = $values | Where-Object { $_ -ne "" -and ($_ -as [datetime]) -eq $null }
                }
            }

            if ($inconsistencies.Count -gt 0) {
                Write-Host "`nInconsistencies found in column '$header' (Expected $dataType):"
                Write-Host ($inconsistencies | Select-Object -First 5) -ForegroundColor Red
                if ($inconsistencies.Count -gt 5) {
                    Write-Host "... and $($inconsistencies.Count - 5) more."
                }
            }
        }
    }
    catch {
        Write-Host "Error checking data inconsistencies: $_" -ForegroundColor Red
    }
}

function Generate-CSVSummary {
    $filePath = Read-Host "Enter the path to the CSV file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        $csv = Import-Csv $filePath
        $rowCount = $csv.Count
        $headers = ($csv | Get-Member -MemberType NoteProperty).Name

        Write-Host "CSV Summary:" -ForegroundColor Yellow
        Write-Host "File: $filePath"
        Write-Host "Total Rows: $rowCount"
        Write-Host "Total Columns: $($headers.Count)"
        Write-Host "`nColumn Summary:"

        foreach ($header in $headers) {
            $values = $csv.$header
            $nonEmptyValues = $values | Where-Object { $_ -ne "" }
            $uniqueValues = ($nonEmptyValues | Select-Object -Unique).Count
            $nullCount = ($values | Where-Object { $_ -eq "" }).Count
            $dataType = Guess-DataType $nonEmptyValues

            Write-Host "`n$header:"
            Write-Host "  Data Type: $dataType"
            Write-Host "  Unique Values: $uniqueValues"
            Write-Host "  Null/Empty Count: $nullCount"
            Write-Host "  Fill Rate: $([math]::Round(($rowCount - $nullCount) / $rowCount * 100, 2))%"

            if ($dataType -eq "Numeric") {
                $numericValues = $nonEmptyValues | ForEach-Object { $_ -as [double] }
                $min = ($numericValues | Measure-Object -Minimum).Minimum
                $max = ($numericValues | Measure-Object -Maximum).Maximum
                $avg = ($numericValues | Measure-Object -Average).Average
                Write-Host "  Min: $min"
                Write-Host "  Max: $max"
                Write-Host "  Average: $([math]::Round($avg, 2))"
            }
        }
    }
    catch {
        Write-Host "Error generating CSV summary: $_" -ForegroundColor Red
    }
}

function Compare-CSVFiles {
    $filePath1 = Read-Host "Enter the path to the first CSV file"
    $filePath2 = Read-Host "Enter the path to the second CSV file"

    if (-not (Test-Path $filePath1) -or -not (Test-Path $filePath2)) {
        Write-Host "One or both files not found." -ForegroundColor Red
        return
    }

    try {
        $csv1 = Import-Csv $filePath1
        $csv2 = Import-Csv $filePath2

        $headers1 = ($csv1 | Get-Member -MemberType NoteProperty).Name
        $headers2 = ($csv2 | Get-Member -MemberType NoteProperty).Name

        Write-Host "Comparing CSV Files:" -ForegroundColor Yellow
        Write-Host "File 1: $filePath1"
        Write-Host "File 2: $filePath2"

        Write-Host "`nColumn Comparison:"
        $commonHeaders = $headers1 | Where-Object { $headers2 -contains $_ }
        $uniqueHeaders1 = $headers1 | Where-Object { $headers2 -notcontains $_ }
        $uniqueHeaders2 = $headers2 | Where-Object { $headers1 -notcontains $_ }

        Write-Host "Common Columns: $($commonHeaders -join ', ')"
        Write-Host "Columns only in File 1: $($uniqueHeaders1 -join ', ')"
        Write-Host "Columns only in File 2: $($uniqueHeaders2 -join ', ')"

        Write-Host "`nRow Count Comparison:"
        Write-Host "File 1 Row Count: $($csv1.Count)"
        Write-Host "File 2 Row Count: $($csv2.Count)"

        Write-Host "`nData Comparison for Common Columns:"
        foreach ($header in $commonHeaders) {
            $diff = Compare-Object $csv1.$header $csv2.$header
            if ($diff) {
                Write-Host "Differences found in column '$header':"
                Write-Host "  Values only in File 1: $($diff | Where-Object { $_.SideIndicator -eq '<=' } | Select-Object -ExpandProperty InputObject)"
                Write-Host "  Values only in File 2: $($diff | Where-Object { $_.SideIndicator -eq '=>' } | Select-Object -ExpandProperty InputObject)"
            }
            else {
                Write-Host "No differences found in column '$header'"
            }
        }
    }
    catch {
        Write-Host "Error comparing CSV files: $_" -ForegroundColor Red
    }
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-6)"

    switch ($choice) {
        "1" { Validate-CSVFile }
        "2" { Analyze-CSVStructure }
        "3" { Check-DataInconsistencies }
        "4" { Generate-CSVSummary }
        "5" { Compare-CSVFiles }
        "6" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "6") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "6")

This CSV File Validator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to perform various CSV-related tasks:
    • Validate CSV files and provide basic statistics
    • Analyze and display the structure of CSV files
    • Check for data inconsistencies
    • Generate a comprehensive summary of the CSV content
    • Compare two CSV files

Key features:

  1. CSV Validation:
    • Checks if the CSV is valid and can be parsed
    • Provides row count, column count, headers, and file size
  2. CSV Structure Analysis:
    • Analyzes each column for data type, unique values, and null/empty values
    • Provides sample values for each column
  3. Data Inconsistency Check:
    • Identifies values that don’t match the expected data type for each column
  4. CSV Summary Generation:
    • Provides a comprehensive summary of the CSV, including data types, unique values, fill rates, and basic statistics for numeric columns
  5. CSV Comparison:
    • Compares two CSV files for structural differences and data discrepancies

This tool is particularly useful for:

  • Data analysts validating CSV datasets
  • QA engineers checking CSV file integrity
  • Developers working with CSV data imports/exports
  • Anyone needing to quickly analyze or compare CSV files

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to select the desired function
  3. Provide the path to the CSV file(s) when prompted
  4. Review the output for validation results, structure analysis, inconsistencies, summaries, or file comparisons

This script provides a comprehensive set of tools for working with CSV files, making it easier to validate, understand, and compare CSV data without having to manually inspect the files or use multiple tools.

CSV Generator Tool

<#
.SYNOPSIS
CSV Generator Tool

.DESCRIPTION
This script provides an interactive tool to create CSV structures, add columns and rows,
and export the resulting CSV to a file.

.NOTES
File Name      : CSVGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\CSVGenerator.ps1
#>

# Global variables
$script:csvData = @()
$script:columns = @()
$script:csvFilePath = "$env:USERPROFILE\Desktop\Generated_CSV_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"

function Show-Menu {
    Clear-Host
    Write-Host "=== CSV Generator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Define Columns"
    Write-Host "2. Add Row"
    Write-Host "3. View Current CSV Structure"
    Write-Host "4. Import Data from JSON"
    Write-Host "5. Generate Sample Data"
    Write-Host "6. Export CSV to File"
    Write-Host "7. Exit"
}

function Define-Columns {
    $script:columns = @()
    do {
        $columnName = Read-Host "Enter column name (or press Enter to finish)"
        if ($columnName -ne "") {
            $script:columns += $columnName
        }
    } while ($columnName -ne "")

    Write-Host "Columns defined: $($script:columns -join ', ')" -ForegroundColor Green
}

function Add-Row {
    if ($script:columns.Count -eq 0) {
        Write-Host "Please define columns first." -ForegroundColor Yellow
        return
    }

    $row = @{}
    foreach ($column in $script:columns) {
        $value = Read-Host "Enter value for '$column'"
        $row[$column] = $value
    }

    $script:csvData += [PSCustomObject]$row
    Write-Host "Row added successfully." -ForegroundColor Green
}

function View-CurrentCSV {
    if ($script:csvData.Count -eq 0) {
        Write-Host "No data available. Please add some rows first." -ForegroundColor Yellow
        return
    }

    $script:csvData | Format-Table -AutoSize
}

function Import-FromJSON {
    $jsonPath = Read-Host "Enter the path to the JSON file"
    if (-not (Test-Path $jsonPath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        $jsonData = Get-Content $jsonPath -Raw | ConvertFrom-Json
        
        if ($jsonData -is [Array]) {
            $script:columns = $jsonData[0].PSObject.Properties.Name
            $script:csvData = $jsonData
        }
        else {
            $script:columns = $jsonData.PSObject.Properties.Name
            $script:csvData = @($jsonData)
        }

        Write-Host "Data imported successfully from JSON." -ForegroundColor Green
        Write-Host "Columns: $($script:columns -join ', ')" -ForegroundColor Green
        Write-Host "Number of rows: $($script:csvData.Count)" -ForegroundColor Green
    }
    catch {
        Write-Host "Error importing JSON: $_" -ForegroundColor Red
    }
}

function Generate-SampleData {
    if ($script:columns.Count -eq 0) {
        Write-Host "Please define columns first." -ForegroundColor Yellow
        return
    }

    $rowCount = Read-Host "Enter the number of sample rows to generate"
    if (-not [int]::TryParse($rowCount, [ref]$null)) {
        Write-Host "Invalid number. Please enter a valid integer." -ForegroundColor Red
        return
    }

    $script:csvData = @()

    for ($i = 1; $i -le [int]$rowCount; $i++) {
        $row = @{}
        foreach ($column in $script:columns) {
            $row[$column] = Get-SampleValue $column $i
        }
        $script:csvData += [PSCustomObject]$row
    }

    Write-Host "$rowCount sample rows generated successfully." -ForegroundColor Green
}

function Get-SampleValue($columnName, $rowNumber) {
    switch -Regex ($columnName.ToLower()) {
        "id|number" { return $rowNumber }
        "name" { return "Name$rowNumber" }
        "date" { return (Get-Date).AddDays($rowNumber).ToString("yyyy-MM-dd") }
        "email" { return "user$rowNumber@example.com" }
        "phone" { return "555-0$rowNumber" }
        "address" { return "$rowNumber Main St" }
        "city" { return "City$rowNumber" }
        "country" { return "Country$rowNumber" }
        "amount|price" { return [math]::Round((Get-Random -Minimum 10 -Maximum 1000), 2) }
        default { return "Value$rowNumber" }
    }
}

function Export-CSVToFile {
    if ($script:csvData.Count -eq 0) {
        Write-Host "No data to export. Please add some rows first." -ForegroundColor Yellow
        return
    }

    try {
        $script:csvData | Export-Csv -Path $script:csvFilePath -NoTypeInformation
        Write-Host "CSV exported successfully to: $script:csvFilePath" -ForegroundColor Green
    }
    catch {
        Write-Host "Error exporting CSV: $_" -ForegroundColor Red
    }
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-7)"

    switch ($choice) {
        "1" { Define-Columns }
        "2" { Add-Row }
        "3" { View-CurrentCSV }
        "4" { Import-FromJSON }
        "5" { Generate-SampleData }
        "6" { Export-CSVToFile }
        "7" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "7") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "7")

This CSV Generator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to interactively build CSV structures:
    • Define columns
    • Add rows manually
    • View the current CSV structure
    • Import data from JSON
    • Generate sample data
    • Export the CSV to a file

Key features:

  1. Column Definition:
    • Allows users to define custom column names
  2. Manual Data Entry:
    • Supports adding rows manually with guided input for each column
  3. Data Visualization:
    • Provides a view of the current CSV structure in a tabular format
  4. JSON Import:
    • Allows importing data from a JSON file to quickly populate the CSV
  5. Sample Data Generation:
    • Automatically generates sample data based on column names
    • Supports common data types like IDs, names, dates, emails, etc.
  6. CSV Export:
    • Exports the generated data to a CSV file

This tool is particularly useful for:

  • Developers needing to create test data in CSV format
  • Data analysts creating sample datasets
  • QA engineers generating CSV files for testing
  • Anyone needing to quickly create structured CSV data

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to build your CSV structure:
    • Start by defining columns
    • Add rows manually, import from JSON, or generate sample data
    • View the current structure at any time
  3. When finished, export the CSV to a file

This script provides a user-friendly way to create CSV structures without having to manually write CSV syntax or use spreadsheet software. It’s especially helpful for creating test data or sample datasets quickly and easily.

XML File Validator Tool

<#
.SYNOPSIS
XML File Validator Tool

.DESCRIPTION
This script provides a tool to validate XML files, check for syntax errors,
analyze the structure, and perform various XML-related tasks.

.NOTES
File Name      : XMLValidator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\XMLValidator.ps1
#>

Add-Type -AssemblyName System.Xml.Linq

function Show-Menu {
    Clear-Host
    Write-Host "=== XML File Validator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Validate XML File"
    Write-Host "2. Analyze XML Structure"
    Write-Host "3. Search XML"
    Write-Host "4. Compare Two XML Files"
    Write-Host "5. Validate Against XSD Schema"
    Write-Host "6. Exit"
}

function Validate-XMLFile {
    $filePath = Read-Host "Enter the path to the XML file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        [xml]$xml = Get-Content $filePath
        Write-Host "XML is valid." -ForegroundColor Green

        $size = (Get-Item $filePath).Length
        $elementCount = $xml.SelectNodes("//*").Count
        $attributeCount = $xml.SelectNodes("//@*").Count

        Write-Host "File Size: $size bytes"
        Write-Host "Number of Elements: $elementCount"
        Write-Host "Number of Attributes: $attributeCount"
    }
    catch [System.Xml.XmlException] {
        Write-Host "Invalid XML. Error details:" -ForegroundColor Red
        Write-Host $_.Exception.Message
    }
}

function Analyze-XMLStructure {
    $filePath = Read-Host "Enter the path to the XML file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        [xml]$xml = Get-Content $filePath
        $structure = Get-XMLStructure $xml.DocumentElement
        Write-Host "XML Structure:" -ForegroundColor Yellow
        $structure | ForEach-Object { Write-Host $_ }
    }
    catch {
        Write-Host "Error analyzing XML structure: $_" -ForegroundColor Red
    }
}

function Get-XMLStructure($element, $indent = "") {
    $output = @()
    $output += "$indent$($element.Name)"
    
    if ($element.Attributes.Count -gt 0) {
        $attributes = $element.Attributes | ForEach-Object { "$($_.Name)='$($_.Value)'" }
        $output += "$indent  Attributes: $($attributes -join ', ')"
    }
    
    foreach ($child in $element.ChildNodes) {
        if ($child.NodeType -eq [System.Xml.XmlNodeType]::Element) {
            $output += Get-XMLStructure $child "$indent  "
        }
        elseif ($child.NodeType -eq [System.Xml.XmlNodeType]::Text) {
            $output += "$indent  Text: $($child.Value.Trim())"
        }
    }
    
    return $output
}

function Search-XML {
    $filePath = Read-Host "Enter the path to the XML file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    $searchTerm = Read-Host "Enter the search term (element or attribute name)"

    try {
        [xml]$xml = Get-Content $filePath
        $results = $xml.SelectNodes("//*[local-name()='$searchTerm'] | //@*[local-name()='$searchTerm']")
        
        if ($results.Count -eq 0) {
            Write-Host "No results found for: $searchTerm" -ForegroundColor Yellow
        }
        else {
            Write-Host "Search Results:" -ForegroundColor Green
            foreach ($result in $results) {
                Write-Host "XPath: $($result.XPath)"
                if ($result.NodeType -eq [System.Xml.XmlNodeType]::Element) {
                    Write-Host "Element Value: $($result.InnerXml)"
                }
                elseif ($result.NodeType -eq [System.Xml.XmlNodeType]::Attribute) {
                    Write-Host "Attribute Value: $($result.Value)"
                }
                Write-Host "---"
            }
        }
    }
    catch {
        Write-Host "Error searching XML: $_" -ForegroundColor Red
    }
}

function Compare-XMLFiles {
    $filePath1 = Read-Host "Enter the path to the first XML file"
    $filePath2 = Read-Host "Enter the path to the second XML file"

    if (-not (Test-Path $filePath1) -or -not (Test-Path $filePath2)) {
        Write-Host "One or both files not found." -ForegroundColor Red
        return
    }

    try {
        $xml1 = [System.Xml.Linq.XDocument]::Load($filePath1)
        $xml2 = [System.Xml.Linq.XDocument]::Load($filePath2)

        $differences = Compare-XmlDocs $xml1 $xml2

        if ($differences.Count -eq 0) {
            Write-Host "The XML files are identical." -ForegroundColor Green
        }
        else {
            Write-Host "Differences found:" -ForegroundColor Yellow
            foreach ($diff in $differences) {
                Write-Host "XPath: $($diff.XPath)"
                Write-Host "File 1 Value: $($diff.Value1)"
                Write-Host "File 2 Value: $($diff.Value2)"
                Write-Host "---"
            }
        }
    }
    catch {
        Write-Host "Error comparing XML files: $_" -ForegroundColor Red
    }
}

function Compare-XmlDocs($doc1, $doc2) {
    $differences = @()
    $elements1 = $doc1.Descendants()
    $elements2 = $doc2.Descendants()

    foreach ($element in $elements1) {
        $xpath = $element.XPathSelectElement($element.GetAbsoluteXPath())
        $otherElement = $doc2.XPathSelectElement($xpath.GetAbsoluteXPath())

        if ($null -eq $otherElement) {
            $differences += @{XPath = $xpath.GetAbsoluteXPath(); Value1 = $element.Value; Value2 = "Element not found"}
        }
        elseif ($element.Value -ne $otherElement.Value) {
            $differences += @{XPath = $xpath.GetAbsoluteXPath(); Value1 = $element.Value; Value2 = $otherElement.Value}
        }

        foreach ($attr in $element.Attributes()) {
            $otherAttr = $otherElement?.Attribute($attr.Name)
            if ($null -eq $otherAttr) {
                $differences += @{XPath = "$($xpath.GetAbsoluteXPath())/@$($attr.Name)"; Value1 = $attr.Value; Value2 = "Attribute not found"}
            }
            elseif ($attr.Value -ne $otherAttr.Value) {
                $differences += @{XPath = "$($xpath.GetAbsoluteXPath())/@$($attr.Name)"; Value1 = $attr.Value; Value2 = $otherAttr.Value}
            }
        }
    }

    foreach ($element in $elements2) {
        $xpath = $element.XPathSelectElement($element.GetAbsoluteXPath())
        $otherElement = $doc1.XPathSelectElement($xpath.GetAbsoluteXPath())

        if ($null -eq $otherElement) {
            $differences += @{XPath = $xpath.GetAbsoluteXPath(); Value1 = "Element not found"; Value2 = $element.Value}
        }

        foreach ($attr in $element.Attributes()) {
            $otherAttr = $otherElement?.Attribute($attr.Name)
            if ($null -eq $otherAttr) {
                $differences += @{XPath = "$($xpath.GetAbsoluteXPath())/@$($attr.Name)"; Value1 = "Attribute not found"; Value2 = $attr.Value}
            }
        }
    }

    return $differences
}

function Validate-XMLAgainstXSD {
    $xmlPath = Read-Host "Enter the path to the XML file"
    $xsdPath = Read-Host "Enter the path to the XSD schema file"

    if (-not (Test-Path $xmlPath) -or -not (Test-Path $xsdPath)) {
        Write-Host "One or both files not found." -ForegroundColor Red
        return
    }

    try {
        $xmlReader = [System.Xml.XmlReader]::Create($xmlPath)
        $schemaReader = [System.Xml.XmlReader]::Create($xsdPath)
        $schema = [System.Xml.Schema.XmlSchema]::Read($schemaReader, $null)

        $settings = New-Object System.Xml.XmlReaderSettings
        $settings.ValidationType = [System.Xml.ValidationType]::Schema
        $settings.Schemas.Add($schema) | Out-Null

        $settings.ValidationEventHandler = {
            param($sender, $e)
            Write-Host "Validation Error: $($e.Message)" -ForegroundColor Red
        }

        $validatingReader = [System.Xml.XmlReader]::Create($xmlPath, $settings)
        while ($validatingReader.Read()) { }

        Write-Host "XML is valid according to the XSD schema." -ForegroundColor Green
    }
    catch {
        Write-Host "Error validating XML against XSD: $_" -ForegroundColor Red
    }
    finally {
        if ($null -ne $xmlReader) { $xmlReader.Close() }
        if ($null -ne $schemaReader) { $schemaReader.Close() }
        if ($null -ne $validatingReader) { $validatingReader.Close() }
    }
}

# Extension method to get absolute XPath
Add-Type @"
using System.Xml.Linq;
using System.Linq;

public static class XElementExtensions
{
    public static string GetAbsoluteXPath(this XElement element)
    {
        if (element == null)
            return string.Empty;

        var ancestors = element.AncestorsAndSelf().Reverse().ToList();
        return "/" + string.Join("/", ancestors.Select(e => e.Name.LocalName));
    }
}
"@

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-6)"

    switch ($choice) {
        "1" { Validate-XMLFile }
        "2" { Analyze-XMLStructure }
        "3" { Search-XML }
        "4" { Compare-XMLFiles }
        "5" { Validate-XMLAgainstXSD }
        "6" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "6") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "6")

This XML File Validator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to perform various XML-related tasks:
    • Validate XML files and provide basic statistics
    • Analyze and display the structure of XML files
    • Search for specific elements or attributes within XML files
    • Compare two XML files and highlight differences
    • Validate XML against an XSD schema

Key features:

  1. XML Validation:
    • Checks if the XML is syntactically valid
    • Provides file size, number of elements, and number of attributes
  2. XML Structure Analysis:
    • Displays a hierarchical view of the XML structure
    • Shows element names, attributes, and text content
  3. XML Search:
    • Allows searching for specific elements or attributes within the XML
    • Displays the XPath and value of found elements/attributes
  4. XML Comparison:
    • Compares two XML files
    • Highlights differences, including added, removed, or modified elements and attributes
  5. XSD Schema Validation:
    • Validates an XML file against an XSD schema
    • Reports any validation errors

This tool is particularly useful for:

  • Developers working with XML data
  • QA engineers validating XML outputs
  • Data analysts examining XML structures
  • Anyone needing to quickly validate, analyze, or compare XML files

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to select the desired function
  3. Provide the path to the XML file(s) when prompted
  4. Review the output for validation results, structure analysis, search results, file comparisons, or schema validation

This script provides a comprehensive set of tools for working with XML files, making it easier to validate, understand, and compare XML data without having to manually parse the files or use multiple tools.

JSON File Validator Tool

<#
.SYNOPSIS
JSON File Validator Tool

.DESCRIPTION
This script provides a tool to validate JSON files, check for syntax errors,
and provide detailed information about the JSON structure.

.NOTES
File Name      : JSONValidator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\JSONValidator.ps1
#>

function Show-Menu {
    Clear-Host
    Write-Host "=== JSON File Validator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Validate JSON File"
    Write-Host "2. Analyze JSON Structure"
    Write-Host "3. Search JSON"
    Write-Host "4. Compare Two JSON Files"
    Write-Host "5. Exit"
}

function Validate-JSONFile {
    $filePath = Read-Host "Enter the path to the JSON file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        $content = Get-Content $filePath -Raw
        $json = ConvertFrom-Json $content -ErrorAction Stop
        Write-Host "JSON is valid." -ForegroundColor Green

        $size = (Get-Item $filePath).Length
        $objectCount = ($content | Select-String -Pattern "{" -AllMatches).Matches.Count
        $arrayCount = ($content | Select-String -Pattern "\[" -AllMatches).Matches.Count

        Write-Host "File Size: $size bytes"
        Write-Host "Number of Objects: $objectCount"
        Write-Host "Number of Arrays: $arrayCount"
    }
    catch {
        Write-Host "Invalid JSON. Error details:" -ForegroundColor Red
        Write-Host $_.Exception.Message
    }
}

function Analyze-JSONStructure {
    $filePath = Read-Host "Enter the path to the JSON file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    try {
        $json = Get-Content $filePath -Raw | ConvertFrom-Json
        $structure = Get-JSONStructure $json
        Write-Host "JSON Structure:" -ForegroundColor Yellow
        $structure | ForEach-Object { Write-Host $_ }
    }
    catch {
        Write-Host "Error analyzing JSON structure: $_" -ForegroundColor Red
    }
}

function Get-JSONStructure($obj, $path = "", $depth = 0) {
    $output = @()
    $indent = "  " * $depth

    if ($obj -is [System.Management.Automation.PSCustomObject]) {
        $output += "$indent$path {}"
        $obj.PSObject.Properties | ForEach-Object {
            $newPath = if ($path) { "$path.$($_.Name)" } else { $_.Name }
            $output += Get-JSONStructure $_.Value $newPath ($depth + 1)
        }
    }
    elseif ($obj -is [Array]) {
        $output += "$indent$path []"
        if ($obj.Count -gt 0) {
            $output += Get-JSONStructure $obj[0] "$path[0]" ($depth + 1)
        }
    }
    else {
        $type = if ($null -eq $obj) { "null" } else { $obj.GetType().Name }
        $output += "$indent$path : $type"
    }

    return $output
}

function Search-JSON {
    $filePath = Read-Host "Enter the path to the JSON file"
    if (-not (Test-Path $filePath)) {
        Write-Host "File not found." -ForegroundColor Red
        return
    }

    $searchKey = Read-Host "Enter the key to search for"

    try {
        $json = Get-Content $filePath -Raw | ConvertFrom-Json
        $results = Search-JSONRecursive $json $searchKey
        
        if ($results.Count -eq 0) {
            Write-Host "No results found for key: $searchKey" -ForegroundColor Yellow
        }
        else {
            Write-Host "Search Results:" -ForegroundColor Green
            $results | ForEach-Object {
                Write-Host "Path: $($_.Path)"
                Write-Host "Value: $($_.Value)"
                Write-Host "---"
            }
        }
    }
    catch {
        Write-Host "Error searching JSON: $_" -ForegroundColor Red
    }
}

function Search-JSONRecursive($obj, $searchKey, $currentPath = "") {
    $results = @()

    if ($obj -is [System.Management.Automation.PSCustomObject]) {
        $obj.PSObject.Properties | ForEach-Object {
            $newPath = if ($currentPath) { "$currentPath.$($_.Name)" } else { $_.Name }
            if ($_.Name -eq $searchKey) {
                $results += @{Path = $newPath; Value = $_.Value}
            }
            $results += Search-JSONRecursive $_.Value $searchKey $newPath
        }
    }
    elseif ($obj -is [Array]) {
        for ($i = 0; $i -lt $obj.Count; $i++) {
            $newPath = "${currentPath}[$i]"
            $results += Search-JSONRecursive $obj[$i] $searchKey $newPath
        }
    }

    return $results
}

function Compare-JSONFiles {
    $filePath1 = Read-Host "Enter the path to the first JSON file"
    $filePath2 = Read-Host "Enter the path to the second JSON file"

    if (-not (Test-Path $filePath1) -or -not (Test-Path $filePath2)) {
        Write-Host "One or both files not found." -ForegroundColor Red
        return
    }

    try {
        $json1 = Get-Content $filePath1 -Raw | ConvertFrom-Json
        $json2 = Get-Content $filePath2 -Raw | ConvertFrom-Json

        $differences = Compare-ObjectRecursive $json1 $json2

        if ($differences.Count -eq 0) {
            Write-Host "The JSON files are identical." -ForegroundColor Green
        }
        else {
            Write-Host "Differences found:" -ForegroundColor Yellow
            $differences | ForEach-Object {
                Write-Host "Path: $($_.Path)"
                Write-Host "File 1 Value: $($_.Value1)"
                Write-Host "File 2 Value: $($_.Value2)"
                Write-Host "---"
            }
        }
    }
    catch {
        Write-Host "Error comparing JSON files: $_" -ForegroundColor Red
    }
}

function Compare-ObjectRecursive($obj1, $obj2, $path = "") {
    $differences = @()

    if ($obj1 -is [System.Management.Automation.PSCustomObject] -and $obj2 -is [System.Management.Automation.PSCustomObject]) {
        $allProperties = $obj1.PSObject.Properties.Name + $obj2.PSObject.Properties.Name | Select-Object -Unique
        foreach ($prop in $allProperties) {
            $newPath = if ($path) { "$path.$prop" } else { $prop }
            if ($obj1.PSObject.Properties.Name -notcontains $prop) {
                $differences += @{Path = $newPath; Value1 = ""; Value2 = $obj2.$prop}
            }
            elseif ($obj2.PSObject.Properties.Name -notcontains $prop) {
                $differences += @{Path = $newPath; Value1 = $obj1.$prop; Value2 = ""}
            }
            else {
                $differences += Compare-ObjectRecursive $obj1.$prop $obj2.$prop $newPath
            }
        }
    }
    elseif ($obj1 -is [Array] -and $obj2 -is [Array]) {
        $maxLength = [Math]::Max($obj1.Length, $obj2.Length)
        for ($i = 0; $i -lt $maxLength; $i++) {
            $newPath = "${path}[$i]"
            if ($i -ge $obj1.Length) {
                $differences += @{Path = $newPath; Value1 = ""; Value2 = $obj2[$i]}
            }
            elseif ($i -ge $obj2.Length) {
                $differences += @{Path = $newPath; Value1 = $obj1[$i]; Value2 = ""}
            }
            else {
                $differences += Compare-ObjectRecursive $obj1[$i] $obj2[$i] $newPath
            }
        }
    }
    elseif ($obj1 -ne $obj2) {
        $differences += @{Path = $path; Value1 = $obj1; Value2 = $obj2}
    }

    return $differences
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-5)"

    switch ($choice) {
        "1" { Validate-JSONFile }
        "2" { Analyze-JSONStructure }
        "3" { Search-JSON }
        "4" { Compare-JSONFiles }
        "5" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "5") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "5")

This JSON File Validator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to perform various JSON-related tasks:
    • Validate JSON files and provide basic statistics
    • Analyze and display the structure of JSON files
    • Search for specific keys within JSON files
    • Compare two JSON files and highlight differences

Key features:

  1. JSON Validation:
    • Checks if the JSON is syntactically valid
    • Provides file size, number of objects, and number of arrays
  2. JSON Structure Analysis:
    • Displays a hierarchical view of the JSON structure
    • Shows types of values (object, array, string, number, etc.)
  3. JSON Search:
    • Allows searching for specific keys within the JSON
    • Displays the path and value of found keys
  4. JSON Comparison:
    • Compares two JSON files
    • Highlights differences, including added, removed, or modified values

This tool is particularly useful for:

  • Developers working with JSON data
  • QA engineers validating JSON outputs
  • Data analysts examining JSON structures
  • Anyone needing to quickly validate, analyze, or compare JSON files

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to select the desired function
  3. Provide the path to the JSON file(s) when prompted
  4. Review the output for validation results, structure analysis, search results, or file comparisons

This script provides a comprehensive set of tools for working with JSON files, making it easier to validate, understand, and compare JSON data without having to manually parse the files or use multiple tools.

JSON Generator Tool

<#
.SYNOPSIS
JSON Generator Tool

.DESCRIPTION
This script provides an interactive tool to create JSON structures, add objects, arrays,
and key-value pairs, and export the resulting JSON to a file.

.NOTES
File Name      : JSONGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\JSONGenerator.ps1
#>

# Global variables
$script:jsonObject = @{}
$script:currentPath = @()
$script:jsonFilePath = "$env:USERPROFILE\Desktop\Generated_JSON_$(Get-Date -Format 'yyyyMMdd_HHmmss').json"

function Show-Menu {
    Clear-Host
    Write-Host "=== JSON Generator Tool ===" -ForegroundColor Cyan
    Write-Host "Current Path: $(if ($script:currentPath.Count -eq 0) { 'Root' } else { $script:currentPath -join '.' })"
    Write-Host "1. Add Key-Value Pair"
    Write-Host "2. Add Object"
    Write-Host "3. Add Array"
    Write-Host "4. Move to Parent"
    Write-Host "5. View Current JSON Structure"
    Write-Host "6. Export JSON to File"
    Write-Host "7. Exit"
}

function Add-KeyValuePair {
    $key = Read-Host "Enter the key"
    $value = Read-Host "Enter the value"

    # Try to convert the value to appropriate type
    if ($value -eq "true" -or $value -eq "false") {
        $value = [System.Convert]::ToBoolean($value)
    }
    elseif ($value -match "^\d+$") {
        $value = [int]$value
    }
    elseif ($value -match "^\d*\.\d+$") {
        $value = [double]$value
    }

    $current = Get-CurrentObject
    $current[$key] = $value
    Write-Host "Key-Value pair added." -ForegroundColor Green
}

function Add-Object {
    $key = Read-Host "Enter the key for the new object"
    $current = Get-CurrentObject
    $current[$key] = @{}
    $script:currentPath += $key
    Write-Host "Object added and set as current path." -ForegroundColor Green
}

function Add-Array {
    $key = Read-Host "Enter the key for the new array"
    $current = Get-CurrentObject
    $current[$key] = @()
    $script:currentPath += $key
    Write-Host "Array added and set as current path." -ForegroundColor Green

    do {
        $addItem = Read-Host "Do you want to add an item to the array? (Y/N)"
        if ($addItem -eq 'Y') {
            $item = Read-Host "Enter the item value"
            # Try to convert the value to appropriate type
            if ($item -eq "true" -or $item -eq "false") {
                $item = [System.Convert]::ToBoolean($item)
            }
            elseif ($item -match "^\d+$") {
                $item = [int]$item
            }
            elseif ($item -match "^\d*\.\d+$") {
                $item = [double]$item
            }
            $current[$key] += $item
            Write-Host "Item added to array." -ForegroundColor Green
        }
    } while ($addItem -eq 'Y')
}

function Move-ToParent {
    if ($script:currentPath.Count -eq 0) {
        Write-Host "Already at root level." -ForegroundColor Yellow
        return
    }
    $script:currentPath = $script:currentPath[0..($script:currentPath.Count - 2)]
    Write-Host "Moved to parent." -ForegroundColor Green
}

function Get-CurrentObject {
    $current = $script:jsonObject
    foreach ($key in $script:currentPath) {
        $current = $current[$key]
    }
    return $current
}

function View-CurrentJSON {
    $jsonString = $script:jsonObject | ConvertTo-Json -Depth 10
    Write-Host "Current JSON Structure:" -ForegroundColor Yellow
    Write-Host $jsonString
}

function Export-JSONToFile {
    try {
        $jsonString = $script:jsonObject | ConvertTo-Json -Depth 10
        $jsonString | Out-File -FilePath $script:jsonFilePath -Encoding UTF8
        Write-Host "JSON exported successfully to: $script:jsonFilePath" -ForegroundColor Green
    }
    catch {
        Write-Host "Error exporting JSON: $_" -ForegroundColor Red
    }
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-7)"

    switch ($choice) {
        "1" { Add-KeyValuePair }
        "2" { Add-Object }
        "3" { Add-Array }
        "4" { Move-ToParent }
        "5" { View-CurrentJSON }
        "6" { Export-JSONToFile }
        "7" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "7") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "7")

This JSON Generator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to interactively build JSON structures:
    • Add key-value pairs
    • Add nested objects
    • Add arrays and array items
    • Navigate the JSON structure (move to parent)
  3. Ability to view the current JSON structure at any time.
  4. Option to export the generated JSON to a file.

Key features:

  • Interactive JSON creation process
  • Support for nested objects and arrays
  • Automatic type conversion for values (boolean, integer, double, string)
  • Hierarchical navigation within the JSON structure
  • Real-time viewing of the current JSON structure
  • Export functionality to save the generated JSON

This tool is particularly useful for:

  • Developers who need to create JSON structures for testing or configuration purposes
  • Anyone learning about JSON structure and wanting to experiment with creating JSON documents
  • System administrators who need to generate JSON files for various applications
  • Quality Assurance professionals creating JSON test data

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to build your JSON structure:
    • Add key-value pairs for simple data
    • Add objects for nested structures
    • Add arrays for lists of items
    • Use the “Move to Parent” option to navigate back up the JSON tree
  3. View the current JSON structure at any time to check your progress
  4. When finished, export the JSON to a file

This script provides a user-friendly way to create JSON structures without having to manually write JSON syntax. It’s especially helpful for those who are new to JSON or need to quickly generate JSON files without writing them by hand. The tool also handles proper nesting and type conversion, ensuring that the generated JSON is valid and properly formatted.

XML Generator Tool

<#
.SYNOPSIS
XML Generator Tool

.DESCRIPTION
This script provides an interactive tool to create XML structures, add elements and attributes,
and export the resulting XML to a file.

.NOTES
File Name      : XMLGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\XMLGenerator.ps1
#>

# Global variables
$script:xmlDoc = New-Object System.Xml.XmlDocument
$script:currentElement = $null
$script:xmlFilePath = "$env:USERPROFILE\Desktop\Generated_XML_$(Get-Date -Format 'yyyyMMdd_HHmmss').xml"

function Show-Menu {
    Clear-Host
    Write-Host "=== XML Generator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Create Root Element"
    Write-Host "2. Add Child Element"
    Write-Host "3. Add Attribute to Current Element"
    Write-Host "4. Add Text to Current Element"
    Write-Host "5. Move to Parent Element"
    Write-Host "6. View Current XML Structure"
    Write-Host "7. Export XML to File"
    Write-Host "8. Exit"
}

function Create-RootElement {
    $rootName = Read-Host "Enter the name for the root element"
    $root = $script:xmlDoc.CreateElement($rootName)
    $script:xmlDoc.AppendChild($root) | Out-Null
    $script:currentElement = $root
    Write-Host "Root element '$rootName' created." -ForegroundColor Green
}

function Add-ChildElement {
    if ($null -eq $script:currentElement) {
        Write-Host "No current element selected. Please create a root element first." -ForegroundColor Yellow
        return
    }

    $childName = Read-Host "Enter the name for the child element"
    $child = $script:xmlDoc.CreateElement($childName)
    $script:currentElement.AppendChild($child) | Out-Null
    $script:currentElement = $child
    Write-Host "Child element '$childName' added to current element." -ForegroundColor Green
}

function Add-Attribute {
    if ($null -eq $script:currentElement) {
        Write-Host "No current element selected. Please create an element first." -ForegroundColor Yellow
        return
    }

    $attrName = Read-Host "Enter the name of the attribute"
    $attrValue = Read-Host "Enter the value of the attribute"
    $script:currentElement.SetAttribute($attrName, $attrValue)
    Write-Host "Attribute '$attrName' added to current element." -ForegroundColor Green
}

function Add-Text {
    if ($null -eq $script:currentElement) {
        Write-Host "No current element selected. Please create an element first." -ForegroundColor Yellow
        return
    }

    $text = Read-Host "Enter the text content for the current element"
    $script:currentElement.InnerText = $text
    Write-Host "Text added to current element." -ForegroundColor Green
}

function Move-ToParentElement {
    if ($null -eq $script:currentElement -or $script:currentElement -eq $script:xmlDoc.DocumentElement) {
        Write-Host "Already at the root level or no element selected." -ForegroundColor Yellow
        return
    }

    $script:currentElement = $script:currentElement.ParentNode
    Write-Host "Moved to parent element." -ForegroundColor Green
}

function View-CurrentXML {
    if ($null -eq $script:xmlDoc.DocumentElement) {
        Write-Host "XML structure is empty. Please create a root element first." -ForegroundColor Yellow
        return
    }

    $xmlString = $script:xmlDoc.OuterXml
    $xmlFormatted = Format-XML $xmlString
    Write-Host "Current XML Structure:" -ForegroundColor Yellow
    Write-Host $xmlFormatted
}

function Format-XML([string]$xmlString) {
    $stringWriter = New-Object System.IO.StringWriter
    $xmlWriter = New-Object System.Xml.XmlTextWriter($stringWriter)
    $xmlWriter.Formatting = [System.Xml.Formatting]::Indented
    $xmlDoc = New-Object System.Xml.XmlDocument
    $xmlDoc.LoadXml($xmlString)
    $xmlDoc.WriteContentTo($xmlWriter)
    $xmlWriter.Flush()
    $stringWriter.Flush()
    return $stringWriter.ToString()
}

function Export-XMLToFile {
    if ($null -eq $script:xmlDoc.DocumentElement) {
        Write-Host "XML structure is empty. Please create a root element first." -ForegroundColor Yellow
        return
    }

    try {
        $script:xmlDoc.Save($script:xmlFilePath)
        Write-Host "XML exported successfully to: $script:xmlFilePath" -ForegroundColor Green
    }
    catch {
        Write-Host "Error exporting XML: $_" -ForegroundColor Red
    }
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-8)"

    switch ($choice) {
        "1" { Create-RootElement }
        "2" { Add-ChildElement }
        "3" { Add-Attribute }
        "4" { Add-Text }
        "5" { Move-ToParentElement }
        "6" { View-CurrentXML }
        "7" { Export-XMLToFile }
        "8" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "8") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "8")

This XML Generator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to interactively build XML structures:
    • Create a root element
    • Add child elements
    • Add attributes to elements
    • Add text content to elements
    • Navigate the XML structure (move to parent element)
  3. Ability to view the current XML structure at any time.
  4. Option to export the generated XML to a file.

Key features:

  • Interactive XML creation process
  • Hierarchical element creation and navigation
  • Support for adding attributes and text content
  • Real-time viewing of the current XML structure
  • XML formatting for better readability
  • Export functionality to save the generated XML

This tool is particularly useful for:

  • Developers who need to create XML structures for testing or configuration purposes
  • Anyone learning about XML structure and wanting to experiment with creating XML documents
  • System administrators who need to generate XML files for various applications
  • Quality Assurance professionals creating XML test data

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu options to build your XML structure:
    • Start by creating a root element
    • Add child elements, attributes, and text as needed
    • Use the “Move to Parent Element” option to navigate back up the XML tree
  3. View the current XML structure at any time to check your progress
  4. When finished, export the XML to a file

This script provides a user-friendly way to create XML structures without having to manually write XML syntax. It’s especially helpful for those who are new to XML or need to quickly generate XML files without writing them by hand.

SEO Checker Tool

<#
.SYNOPSIS
SEO Checker Tool

.DESCRIPTION
This script analyzes a webpage for various SEO elements and provides a report.

.NOTES
File Name      : SEOChecker.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, Internet connectivity
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\SEOChecker.ps1
#>

# Import required modules
Add-Type -AssemblyName System.Web

# Global variables
$script:reportPath = "$env:USERPROFILE\Desktop\SEO_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

function Show-Menu {
    Clear-Host
    Write-Host "=== SEO Checker Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze Website"
    Write-Host "2. View Last Report"
    Write-Host "3. Exit"
}

function Analyze-Website {
    $url = Read-Host "Enter the website URL to analyze (include http:// or https://)"
    
    if (-not ($url -match "^https?://")) {
        Write-Host "Invalid URL. Please include http:// or https://" -ForegroundColor Red
        return
    }

    Write-Host "`nAnalyzing $url..." -ForegroundColor Yellow

    try {
        $response = Invoke-WebRequest -Uri $url -UseBasicParsing
        $content = $response.Content
        $statusCode = $response.StatusCode

        $results = @{
            URL = $url
            StatusCode = $statusCode
            Title = Get-Title $content
            MetaDescription = Get-MetaDescription $content
            HeaderTags = Get-HeaderTags $content
            ImageAltTags = Get-ImageAltTags $content
            WordCount = Get-WordCount $content
            LoadTime = Measure-LoadTime $url
            MobileFriendly = Test-MobileFriendly $url
            SSL = Test-SSL $url
        }

        Generate-Report $results
    }
    catch {
        Write-Host "Error analyzing website: $_" -ForegroundColor Red
    }
}

function Get-Title($content) {
    if ($content -match "<title>(.*?)</title>") {
        return $matches[1]
    }
    return "No title found"
}

function Get-MetaDescription($content) {
    if ($content -match '<meta name="description" content="(.*?)"') {
        return $matches[1]
    }
    return "No meta description found"
}

function Get-HeaderTags($content) {
    $headers = @{}
    for ($i = 1; $i -le 6; $i++) {
        $count = ([regex]::Matches($content, "<h$i")).Count
        if ($count -gt 0) {
            $headers["H$i"] = $count
        }
    }
    return $headers
}

function Get-ImageAltTags($content) {
    $images = [regex]::Matches($content, '<img [^>]*alt="([^"]*)"')
    return @{
        TotalImages = $images.Count
        ImagesWithAlt = ($images | Where-Object { $_.Groups[1].Value -ne "" }).Count
    }
}

function Get-WordCount($content) {
    $text = $content -replace '<[^>]+>', '' -replace '&nbsp;', ' '
    $words = $text -split '\s+' | Where-Object { $_ -ne '' }
    return $words.Count
}

function Measure-LoadTime($url) {
    $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
    Invoke-WebRequest -Uri $url -UseBasicParsing | Out-Null
    $stopwatch.Stop()
    return [math]::Round($stopwatch.Elapsed.TotalSeconds, 2)
}

function Test-MobileFriendly($url) {
    # This is a basic check. For a more accurate test, you'd need to use Google's Mobile-Friendly Test API
    $userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1"
    $response = Invoke-WebRequest -Uri $url -UserAgent $userAgent -UseBasicParsing
    return $response.StatusCode -eq 200
}

function Test-SSL($url) {
    return $url.StartsWith("https://")
}

function Generate-Report($results) {
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SEO Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 0 auto; padding: 20px; }
        h1, h2 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .good { color: green; }
        .warning { color: orange; }
        .bad { color: red; }
    </style>
</head>
<body>
    <h1>SEO Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>
    <p>URL: $($results.URL)</p>

    <h2>General Information</h2>
    <table>
        <tr><th>Status Code</th><td>$($results.StatusCode)</td></tr>
        <tr><th>Title</th><td>$($results.Title)</td></tr>
        <tr><th>Meta Description</th><td>$($results.MetaDescription)</td></tr>
        <tr><th>Word Count</th><td>$($results.WordCount)</td></tr>
        <tr><th>Load Time</th><td>$($results.LoadTime) seconds</td></tr>
        <tr><th>Mobile Friendly</th><td>$(if ($results.MobileFriendly) { "Yes" } else { "No" })</td></tr>
        <tr><th>SSL</th><td>$(if ($results.SSL) { "Yes" } else { "No" })</td></tr>
    </table>

    <h2>Header Tags</h2>
    <table>
        $(foreach ($header in $results.HeaderTags.GetEnumerator()) {
            "<tr><th>$($header.Key)</th><td>$($header.Value)</td></tr>"
        })
    </table>

    <h2>Images</h2>
    <table>
        <tr><th>Total Images</th><td>$($results.ImageAltTags.TotalImages)</td></tr>
        <tr><th>Images with Alt Text</th><td>$($results.ImageAltTags.ImagesWithAlt)</td></tr>
    </table>

    <h2>Recommendations</h2>
    <ul>
        $(if ($results.Title.Length -gt 60) { "<li class='warning'>Title is too long ($(($results.Title).Length) characters). Keep it under 60 characters.</li>" })
        $(if ($results.Title.Length -lt 30) { "<li class='warning'>Title is too short ($(($results.Title).Length) characters). Aim for 30-60 characters.</li>" })
        $(if ($results.MetaDescription.Length -gt 160) { "<li class='warning'>Meta description is too long ($(($results.MetaDescription).Length) characters). Keep it under 160 characters.</li>" })
        $(if ($results.MetaDescription.Length -lt 50) { "<li class='warning'>Meta description is too short ($(($results.MetaDescription).Length) characters). Aim for 50-160 characters.</li>" })
        $(if ($results.WordCount -lt 300) { "<li class='warning'>Content might be too short ($($results.WordCount) words). Aim for at least 300 words.</li>" })
        $(if ($results.LoadTime -gt 3) { "<li class='warning'>Page load time is slow ($($results.LoadTime) seconds). Aim for under 3 seconds.</li>" })
        $(if (-not $results.MobileFriendly) { "<li class='bad'>Page may not be mobile-friendly. Consider optimizing for mobile devices.</li>" })
        $(if (-not $results.SSL) { "<li class='bad'>Site is not using SSL. Consider switching to HTTPS for better security and SEO.</li>" })
        $(if ($results.ImageAltTags.ImagesWithAlt -lt $results.ImageAltTags.TotalImages) { "<li class='warning'>Not all images have alt text. Add alt text to improve accessibility and SEO.</li>" })
    </ul>
</body>
</html>
"@

    $reportContent | Out-File -FilePath $script:reportPath
    Write-Host "Report generated and saved to: $script:reportPath" -ForegroundColor Green
}

function View-LastReport {
    if (Test-Path $script:reportPath) {
        Start-Process $script:reportPath
    } else {
        Write-Host "No report found. Please analyze a website first." -ForegroundColor Yellow
    }
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-3)"

    switch ($choice) {
        "1" { Analyze-Website }
        "2" { View-LastReport }
        "3" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "3") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "3")

This SEO Checker Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various SEO elements of a webpage:
    • Page title
    • Meta description
    • Header tags (H1 to H6)
    • Image alt tags
    • Word count
    • Page load time
    • Mobile-friendliness (basic check)
    • SSL implementation
  3. A report generation function that creates an HTML report with the analysis results and recommendations.
  4. Option to view the last generated report.

Key features:

  • Analyzes important on-page SEO elements
  • Provides a visual HTML report with color-coded recommendations
  • Checks for mobile-friendliness and SSL implementation
  • Measures page load time
  • Offers suggestions for improvement based on common SEO best practices

This tool is particularly useful for:

  • Website owners who want to perform a basic SEO check
  • Digital marketers analyzing website SEO elements
  • Web developers ensuring they’ve implemented basic SEO best practices
  • Anyone learning about SEO and wanting to analyze real websites

To use this script effectively:

  1. Run the script in PowerShell
  2. Choose to analyze a website by entering its URL
  3. Review the generated HTML report
  4. Use the recommendations to improve the website’s SEO

Please note that this is a basic SEO checker and doesn’t cover all aspects of SEO. For a comprehensive SEO analysis, you would need to consider many more factors and potentially use more advanced APIs and tools. However, this script provides a good starting point for basic on-page SEO analysis.

Advanced Password Generator Tool

<#
.SYNOPSIS
Advanced Password Generator Tool

.DESCRIPTION
This script provides an advanced password generation tool with features including
customizable generation criteria, password strength evaluation, password history,
and additional utility functions.

.NOTES
File Name      : AdvancedPasswordGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\AdvancedPasswordGenerator.ps1
#>

# Import required modules
Add-Type -AssemblyName System.Web

# Global variables
$script:passwordHistory = @()
$script:maxHistorySize = 10
$script:passwordFilePath = Join-Path -Path $env:USERPROFILE -ChildPath "Documents\PasswordGeneratorHistory.txt"

function Show-Menu {
    Clear-Host
    Write-Host "=== Advanced Password Generator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Generate Password"
    Write-Host "2. Set Password Options"
    Write-Host "3. View Current Settings"
    Write-Host "4. View Password History"
    Write-Host "5. Evaluate Password Strength"
    Write-Host "6. Generate Passphrase"
    Write-Host "7. Export Password History"
    Write-Host "8. Exit"
}

function Set-PasswordOptions {
    $script:passwordLength = Read-Host "Enter password length (default is 16)"
    if ([string]::IsNullOrWhiteSpace($script:passwordLength)) { $script:passwordLength = 16 }
    
    $script:includeUppercase = Read-Host "Include uppercase letters? (Y/N, default is Y)"
    $script:includeUppercase = ($script:includeUppercase -ne 'N')
    
    $script:includeLowercase = Read-Host "Include lowercase letters? (Y/N, default is Y)"
    $script:includeLowercase = ($script:includeLowercase -ne 'N')
    
    $script:includeNumbers = Read-Host "Include numbers? (Y/N, default is Y)"
    $script:includeNumbers = ($script:includeNumbers -ne 'N')
    
    $script:includeSpecialChars = Read-Host "Include special characters? (Y/N, default is Y)"
    $script:includeSpecialChars = ($script:includeSpecialChars -ne 'N')

    $script:excludeSimilarChars = Read-Host "Exclude similar characters (O, 0, I, l, 1)? (Y/N, default is N)"
    $script:excludeSimilarChars = ($script:excludeSimilarChars -eq 'Y')
    
    Write-Host "Password options updated." -ForegroundColor Green
}

function View-CurrentSettings {
    Write-Host "`nCurrent Password Generation Settings:" -ForegroundColor Yellow
    Write-Host "Password Length: $script:passwordLength"
    Write-Host "Include Uppercase: $($script:includeUppercase ? 'Yes' : 'No')"
    Write-Host "Include Lowercase: $($script:includeLowercase ? 'Yes' : 'No')"
    Write-Host "Include Numbers: $($script:includeNumbers ? 'Yes' : 'No')"
    Write-Host "Include Special Characters: $($script:includeSpecialChars ? 'Yes' : 'No')"
    Write-Host "Exclude Similar Characters: $($script:excludeSimilarChars ? 'Yes' : 'No')"
    Write-Host ""
}

function Generate-Password {
    $characterSet = @()
    if ($script:includeUppercase) { $characterSet += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.ToCharArray() }
    if ($script:includeLowercase) { $characterSet += 'abcdefghijklmnopqrstuvwxyz'.ToCharArray() }
    if ($script:includeNumbers) { $characterSet += '0123456789'.ToCharArray() }
    if ($script:includeSpecialChars) { $characterSet += '!@#$%^&*()_+-=[]{}|;:,.<>?'.ToCharArray() }

    if ($script:excludeSimilarChars) {
        $characterSet = $characterSet | Where-Object { $_ -notin 'O', '0', 'I', 'l', '1' }
    }

    if ($characterSet.Count -eq 0) {
        Write-Host "Error: No character set selected. Please update your settings." -ForegroundColor Red
        return
    }

    $password = -join (1..$script:passwordLength | ForEach-Object { Get-Random -InputObject $characterSet })
    
    Write-Host "`nGenerated Password:" -ForegroundColor Green
    Write-Host $password
    Write-Host ""

    $strength = Evaluate-PasswordStrength -Password $password
    Write-Host "Password Strength: $strength" -ForegroundColor Yellow

    Add-ToPasswordHistory -Password $password

    $saveToFile = Read-Host "Do you want to save this password to a file? (Y/N)"
    if ($saveToFile -eq 'Y') {
        $fileName = "GeneratedPassword_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
        $filePath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\$fileName"
        $password | Out-File -FilePath $filePath
        Write-Host "Password saved to: $filePath" -ForegroundColor Green
    }
}

function Evaluate-PasswordStrength {
    param ([string]$Password)

    $score = 0

    if ($Password.Length -ge 12) { $score += 2 }
    elseif ($Password.Length -ge 8) { $score += 1 }

    if ($Password -cmatch "[A-Z]") { $score += 1 }
    if ($Password -cmatch "[a-z]") { $score += 1 }
    if ($Password -match "\d") { $score += 1 }
    if ($Password -match "[^a-zA-Z0-9]") { $score += 1 }

    switch ($score) {
        0 { return "Very Weak" }
        1 { return "Weak" }
        2 { return "Moderate" }
        3 { return "Strong" }
        4 { return "Very Strong" }
        default { return "Extremely Strong" }
    }
}

function Add-ToPasswordHistory {
    param ([string]$Password)

    $script:passwordHistory = @($Password) + $script:passwordHistory
    if ($script:passwordHistory.Count -gt $script:maxHistorySize) {
        $script:passwordHistory = $script:passwordHistory[0..($script:maxHistorySize - 1)]
    }
}

function View-PasswordHistory {
    if ($script:passwordHistory.Count -eq 0) {
        Write-Host "Password history is empty." -ForegroundColor Yellow
        return
    }

    Write-Host "`nPassword History (Most Recent First):" -ForegroundColor Yellow
    for ($i = 0; $i -lt $script:passwordHistory.Count; $i++) {
        Write-Host "$($i + 1). $($script:passwordHistory[$i])"
    }
    Write-Host ""
}

function Generate-Passphrase {
    $wordList = @("apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange", "papaya", "quince", "raspberry", "strawberry", "tangerine", "ugli", "vanilla", "watermelon", "xigua", "yuzu", "zucchini")
    $passphrase = -join ((1..4 | ForEach-Object { Get-Random -InputObject $wordList }) -join "-")
    
    Write-Host "`nGenerated Passphrase:" -ForegroundColor Green
    Write-Host $passphrase
    Write-Host ""

    Add-ToPasswordHistory -Password $passphrase
}

function Export-PasswordHistory {
    if ($script:passwordHistory.Count -eq 0) {
        Write-Host "Password history is empty. Nothing to export." -ForegroundColor Yellow
        return
    }

    $script:passwordHistory | Out-File -FilePath $script:passwordFilePath
    Write-Host "Password history exported to: $script:passwordFilePath" -ForegroundColor Green
}

# Initialize default settings
$script:passwordLength = 16
$script:includeUppercase = $true
$script:includeLowercase = $true
$script:includeNumbers = $true
$script:includeSpecialChars = $true
$script:excludeSimilarChars = $false

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-8)"

    switch ($choice) {
        "1" { Generate-Password }
        "2" { Set-PasswordOptions }
        "3" { View-CurrentSettings }
        "4" { View-PasswordHistory }
        "5" { 
            $pwToEvaluate = Read-Host "Enter a password to evaluate"
            $strength = Evaluate-PasswordStrength -Password $pwToEvaluate
            Write-Host "Password Strength: $strength" -ForegroundColor Yellow
        }
        "6" { Generate-Passphrase }
        "7" { Export-PasswordHistory }
        "8" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "8") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "8")

This Advanced Password Generator Tool includes:

  1. A menu-driven interface with expanded options.
  2. Enhanced functions for password generation and management:
    • Customizable password generation with more options
    • Password strength evaluation
    • Password history tracking
    • Passphrase generation
    • Export functionality for password history
  3. Additional features:
    • Option to exclude similar characters (O, 0, I, l, 1) for improved readability
    • Passphrase generation using a predefined word list
    • Ability to evaluate the strength of any given password
    • Password history with a configurable size limit
    • Export functionality to save password history to a file

Key features:

  • More flexible and customizable password generation
  • Built-in password strength evaluation
  • Password history tracking for easy reference
  • Passphrase generation as an alternative to traditional passwords
  • Ability to export password history for backup or review
  • Enhanced user interface with more options and information

This tool is particularly useful for:

  • System administrators requiring advanced password management capabilities
  • Security professionals needing to generate and evaluate various types of passwords
  • Users who want a comprehensive tool for creating and managing strong passwords
  • IT professionals implementing or reviewing password policies

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the expanded menu to access various features
  3. Customize password generation settings as needed
  4. Generate passwords or passphrases
  5. Use the password strength evaluation feature to check existing passwords
  6. Manage and export password history as required

This advanced script provides a more comprehensive approach to password generation and management, offering additional features for security-conscious users and professionals.