vmware-better-network-resolve.psm1

function Resolve-VMWareHost {
    param (
        [Parameter(Mandatory = $True, ParameterSetName = "auto")]
        [switch]
        $Auto,
        [Parameter(Mandatory = $True, ParameterSetName = "auto")]
        [Parameter(Mandatory = $True, ParameterSetName = "manual")]
        [String]$User,
        [Parameter(Mandatory = $True, ParameterSetName = "auto")]
        [Parameter(Mandatory = $True, ParameterSetName = "manual")]
        [SecureString]$Password,
        [Parameter(Mandatory = $true, ParameterSetName = "manual")]
        [switch]$Manual,
        [Parameter(Mandatory = $true, ParameterSetName = "manual")]
        [String]$Id,
        [Parameter(Mandatory = $true, ParameterSetName = "manual")]
        [String]$HostName
    )

    $APIUrl = 'http://127.0.0.1:8697/api'
    function Get-VMWarePath {
        $Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\VMware, Inc.\VMware Workstation'
        $Name = 'InstallPath'
        $InstallPath = (Get-ItemProperty -Path "Registry::$Key" -ErrorAction Stop).$Name
        return $InstallPath
    }

    function Get-VMs {
        $Header = (Get-BasicAuthHeader -User $User -Password $Password)
        try {
            $vms = Invoke-RestMethod "${APIUrl}/vms" -Method Get -Headers $Header
        }
        catch [System.Exception] {
            Write-Host "Get All VM Failed, check your Credential." -ForegroundColor Red
            Write-Host "Stopping VMREST service..." -ForegroundColor Yellow
            Stop-VMRest
            return
        }
        $pattern = [regex]"^[a-zA-Z][-\.a-zA-Z0-9]{1,}$"
        $legalMatch = [regex]"[a-zA-Z][-\.a-zA-Z0-9]{1,}"
        Write-Host '--------------------------------------------------------------------------------------------------' -ForegroundColor Blue
        foreach ($vm in $vms) {
            Add-Member -InputObject $vm -Name "hostname" -Value $vm.path.split('\')[-1].replace(' ', '-').replace('.vmx', '').toLower() -MemberType NoteProperty
            if (-not($vm.hostname -match $pattern)) {
                Write-Host 'Found an machine name contain illegal character, consider to rename it or resolve it manually.' -ForegroundColor Red
                Write-Host "Machine ID is : " -NoNewline -ForegroundColor Yellow
                Write-Host $vm.id -ForegroundColor Red -NoNewline
                Write-Host ", it's path like this '" -ForegroundColor Yellow -NoNewline
                Write-Host $legalMatch.Matches($vm.path) -ForegroundColor Red -NoNewline
                Write-Host "'" -ForegroundColor Yellow
                $vm.PSObject.Properties.Remove('hostname')
            }
            $vm.PSObject.Properties.Remove('path')
        }
        return $vms
    }

    function Start-VMRest {
        $VMRest = "$(Get-VMWarePath)vmrest.exe"
        Start-Job -ScriptBlock { & $args[0] } -Name "VMRest" -ArgumentList $VMRest
    }

    function Stop-VMRest {
        Stop-Job -Name "VMRest" | Select-Object "Command" | Write-Host
    }

    function Get-BasicAuthHeader {
        param (
            [Parameter(Mandatory = $True)][String]$User,
            [Parameter(Mandatory = $True)][SecureString]$Password
        )
        $plainPWD = [System.Management.Automation.PSCredential]::new('_', $Password).GetNetworkCredential().Password
        $Bytes = [System.Text.Encoding]::UTF8.GetBytes("${User}:${plainPWD}")
        $Auth = [System.Convert]::ToBase64String($Bytes)
        return @{Accpet = "*/*"; Authorization = "Basic ${Auth}"; "Accept-Charset" = "utf8" }
    }

    Write-Host '--------------------------------------------------------------------------------------------------' -ForegroundColor Blue
    Write-Host 'Starting VMREST service...' -ForegroundColor Yellow
    Start-VMRest
    $Header = (Get-BasicAuthHeader -User $User -Password $Password)
    $hosts = Get-Content C:\Windows\System32\drivers\etc\hosts
    $parse = $True
    $resolve = ""
    $hosts | ForEach-Object {
        if ($_.Contains("#VMWare-Better-Network-Resolve")) {
            $parse = $false
        }
        if ($parse) {
            $resolve += "$_`n"
        }
        if ($_.Contains("#End-VMWare-Better-Network-Resolve")) {
            $parse = $True
        }
    }
    $resolve += "#VMWare-Better-Network-Resolve`n"
    $vms = Get-VMs
    if (-not $vms) {
        return
    }
    Write-Host '--------------------------------------------------------------------------------------------------' -ForegroundColor Blue
    $vms | ForEach-Object {
        if ($_.hostname) {
            if ($_.id.equals($Id)) {
                $_.hostname = $HostName
            }
            $vmHostName = $_.hostname
            $vmId = $_.id
            try {
                $Uri = "$APIUrl/vms/$vmId/ip"
                $data = Invoke-RestMethod $Uri -Headers $Header
                $Ip = $data.ip
                $resolve += "$Ip $vmHostName`n"
                Write-Host "Resolve hostname `"" -ForegroundColor Yellow -NoNewline
                Write-Host $vmHostName -ForegroundColor Green -NoNewline
                Write-Host "`" to IP `"" -ForegroundColor Yellow -NoNewline
                Write-Host $Ip -ForegroundColor Green -NoNewline
                Write-Host "`", it's ID is `"" -ForegroundColor Yellow -NoNewline
                Write-Host $vmId -ForegroundColor Green -NoNewline
                Write-Host "`"." -ForegroundColor Yellow
            }
            catch [System.Exception] {
                Write-Host "Machine `"" -ForegroundColor Yellow -NoNewline
                Write-Host $vmId -ForegroundColor Red -NoNewline
                Write-Host "`" is not powered on, skip it." -ForegroundColor Yellow
            }
        }
    }
    Write-Host '--------------------------------------------------------------------------------------------------' -ForegroundColor Blue
    $resolve += "#End-VMWare-Better-Network-Resolve"
    $resolve_encode = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($resolve))
    Write-Host "Stopping VMREST service..." -ForegroundColor Yellow
    Stop-VMRest
    try {
        Write-Host "Request For Administrator Privilege..." -ForegroundColor Yellow
        $Command = "`$se=`"$resolve_encode`"`n`$s=[System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String(`$se))`n`$s|Out-File -FilePath C:\Windows\System32\drivers\etc\hosts`n"
        # $resolve | Out-File -FilePath C:\Windows\System32\drivers\etc\hosts
        $bytes = [System.Text.Encoding]::Unicode.GetBytes($Command)
        $encodedCommand = [Convert]::ToBase64String($bytes)
        Start-Process -FilePath powershell -Verb runas -ArgumentList "-encodedCommand $encodedCommand"
        Write-Host "All Machine auto resolved." -ForegroundColor Green
    }
    catch [System.Exception] {
        Write-Host "Could not save hostname resolve configuration, consider run as administrator." -ForegroundColor Red
    }

}

function Set-VMHostAuto {
    Write-Host "This Operation Need Your VMREST Credentials, make sure you create it before." -ForegroundColor Yellow
    Write-Host "If you haven't create your credentials, take a reference from this site: https://docs.vmware.com/cn/VMware-Workstation-Pro/16.0/com.vmware.ws.using.doc/GUID-C3361DF5-A4C1-432E-850C-8F60D83E5E2B.html" -ForegroundColor Yellow
    Resolve-VMWareHost -Auto 
}

function Set-VMHostManual {
    param(
        [Parameter(Mandatory = $true, ParameterSetName = "manual")]
        [String]$Id,
        [Parameter(Mandatory = $true, ParameterSetName = "manual")]
        [String]$HostName
    )
    Write-Host "This Operation Need Your VMREST Credentials, make sure you create it before." -ForegroundColor Yellow
    Write-Host "If you haven't create your credentials, take a reference from this site: https://docs.vmware.com/cn/VMware-Workstation-Pro/16.0/com.vmware.ws.using.doc/GUID-C3361DF5-A4C1-432E-850C-8F60D83E5E2B.html" -ForegroundColor Yellow
    Resolve-VMWareHost -Manual -Id $Id -HostName $HostName
}