0

I've been using a cmd/batch file to create a locationid variable based on what IP range the computer is in. I need to do a similar function using powershell. Any advise would be welcomed.

As an example of the code I'm using in the batch file:

For /F "Delims==" %%G In ('Set octet 2^>NUL')Do Set "%%G="
For /F "Tokens=2 Delims=:" %%G In (
'"%__AppDir__%ipconfig.exe 2>NUL|%__Appdir__%find.exe "IPv4""'
)Do For /F "Tokens=1-4Delims=. " %%H In ("%%G"
)Do Set "octet1=%%H"&Set "octet2=%%I"&Set "octet3=%%J"&Set "octet4=%%K"
Set octet>NUL 2>&1||(Echo IPConfig failed to retrieve an IP address.
Pause&GoTo :EOF)
Set "BuildingLOC="
If %octet1% Equ 10 If Defined octet2 (
If %octet2% GEq 6 If %octet2% LEq 7 Set "BuildingLOC=VM" 
If %octet2% GEq 10 If %octet2% LEq 19 Set "BuildingLOC=ADM"
)
  • Does the answer Lucas gave for this question do what you want? https://stackoverflow.com/a/44685122/4190564 – Darin Apr 12 '22 at 02:35

1 Answers1

0

Working with IP Octets:

function Get-HostIP {
    [CmdletBinding()]
    [OutputType([string])]
    param ()
    # https://stackoverflow.com/a/44685122/4190564
    $Return = ( 
        Get-NetIPConfiguration | Where-Object {
            $null -ne $_.IPv4DefaultGateway -and $_.NetAdapter.Status -ne "Disconnected"
        }
    ).IPv4Address.IPAddress
    return $Return
}
Function Get-IPOctets {
    [CmdletBinding()]
    [OutputType([int[]])]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$IPAddress
    )
    if( $IPAddress -match '(?<Octet1>\d+)\.(?<Octet2>\d+)\.(?<Octet3>\d+)\.(?<Octet4>\d+)') {
        return $Matches.Octet1, $Matches.Octet2, $Matches.Octet3, $Matches.Octet4
    } else {
        return 0, 0, 0, 0
    }
}
$Octet1, $Octet2, $Octet3, $Octet4 = Get-IPOctets (Get-HostIP)
if($Octet1 -eq 10) {
    switch ($Octet2) {
        {$_ -in 6..7} {$BuildingLOC = 'VM'; break}
        {$_ -in 10..19} {$BuildingLOC = 'ADM'; break}
        default {$BuildingLOC = 'Other'; break}
    }
} else {
    $BuildingLOC = 'Invalid'
}
Write-Host "IPType: $BuildingLOC"

Working with first 3 letters of Computer Name:

if($HostName = [System.Net.Dns]::GetHostName()) {
    if($HostName.Substring(0, 3) -eq 'ABC') {
        Write-Host "Computer name matches"
    } else {
        Write-Host "Computer name does not match "
    }
} else {
    Write-Host "No computer name"
}

EDIT:

Initially missed the question on setx /m in the comment, so here is few options related to Environment variables.

SetEnvironmentVariable/GetEnvironmentVariable:

Take a look at the examples in this answer. Note that 'Path' is the variable name in the examples, but use any name you desire. For the SetEnvironmentVariable $Value is the value being saved. And also note that there are 3 places, Process/Machine/User, in the GetEnvironmentVariable examples, which is where the variable is stored or retrieved from. I like these example because the full reference to target locations is given, but if you look through examples in this question, you can see that it can be shorted to 'Process', 'Machine', and 'User'.

  1. Process: I believe this is just temporary storage and the same as using $Env:MyVar. GetEnvironmentVariable can read whatever is in current session's memory, but anything set by SetEnvironmentVariable will be lost as soon as the current PowerShell session is closed.
  2. Machine: These variables will be available to all users, and will remain available even after a reboot. But probably not available through $Env:MyVar in the current script's session.
  3. User: Available to only the current user, and will remain available even after a reboot. But probably not available through $Env:MyVar in the current script's session.

setx.exe:

Any executable file can be ran from PowerShell, but there are a few things to be aware of. If you look through this answer I gave a few days ago you can see:

  1. You can download EchoArgs from ss64.com, execute EchoArgs instead of your exe file, setx in this case, record the pattern for the parameters passed to EchoArgs, then in PowerShell build an EchoArgs line that outputs the exact same parameter pattern, and finally replace in PowerShell EchoArgs with your exe file, setx in this case.
  2. Farther down in the question I introduce the use of the --% parameter/operator that causes PowerShell to stop processing the line and pass it as is.
  3. And then I explain how you can use environment variables to dynamically replace parts of the line after the --% parameter/operator.

A far shorter, but similar answer, can be found here. BUT, if you look Lance's answer in the same question, you can see that he uses Start-Process -FilePath $RunPath -ArgumentList $MyArgsText to start the exe file and pass arguments to it. I still haven't taken time to experiment with Start-Process, but it looks like an interesting alternative.

REG.EXE:

Another exe file you could use is REG.EXE. If you take a look at this page you can see Machine, Process, and User described, which includes the registry keys where environment variables are stored. I actually stopped using setx in batch files a long time ago because I ran into values that setx would fail to store, but REG.EXE has no problem with.

Here are some examples I found in some batch files I have:

REG ADD    "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V "EnableUAC" /T "REG_SZ" /D "Yes" /F>NUL 2>&1
REG ADD    "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V "%%A" /T REG_EXPAND_SZ /D "%~2" /F
REG DELETE "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V "TemporaryMachineName" /F>NUL 2>&1

And one from a PowerShell script:

REG QUERY  "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V "PSModuleTest" 2>$null

PowerShell Registry:

I'm not going to get into editing the registry through PowerShell, but just be aware that Get-ItemPropertyValue/Set-ItemPropertyValue, Get-ItemProperty/Set-ItemProperty, Get-ChildItem/Set-ChildItem, and Get-Item/Set-Item are common built-in PowerShell commands for doing this.

For more control, and more effort on your part, you can use the following family of commands: [RegistryKey]::OpenRemoteBaseKey, [RegistryKey]::OpenBaseKey, $BaseKey.OpenSubKey, $SubKey.SetValue, $SubKey.GetValue, $SubKey.DeleteValue, and many others.

Darin
  • 1,423
  • 1
  • 10
  • 12
  • Thank you so much for this extremely fast reply! To my "newbie eyes", your code certainly looks good. I will give it a test this morning. Will I need to use setx /m to make the variable a somewhat permanent setting ? – Scott Patrick Apr 13 '22 at 10:10
  • @ScottPatrick, not sure how new you are to PowerShell. A good working environment that probably most people a using in Windows is Visual Studio Code, and in VSCode they add the PowerShell extension. There are 2 primary versions of PowerShell, the one that Windows 10 comes with is version 5.1.x.x, and you can download and install version 7.2.x. BUT, when it comes to VSCode, I find 7.2.x wants to take over and have problems switching. I found a portable version 7.2.x and use it instead for testing. This code appears compatible with both versions. – Darin Apr 13 '22 at 11:50
  • The powershell code for Working with Octects that you provided worked like a charm. Now I just have to figure the best way to commit it to the registry or the machine environment to make it "active now, and remain for future use". I appreciate the recommendation for Visual Studio but that will be a long bit of learning. – Scott Patrick Apr 13 '22 at 20:23
  • @ScottPatrick, sorry I missed your question on setx. I've updated the question with an edit at the end to include info and alternatives. – Darin Apr 14 '22 at 22:35