3

I am an occasional casual programmer (for about 60 years now!). I wrote 2 functional SNMP PowerShell desktop shortcut scripts 4 years ago. Now I am writing two scripts for my old Windows 10 system: one to Enable the Ethernet port and one to Disable it. The scripts actually work fine, but I have come across one anomaly that is mind boggling. Here is the "Enable" test case script; the "Disable" script just changes Enable-NetAdapter to Disable-NetAdapter.

When one of these scripts CHANGES the status of the NetAdapter, in approximately 4 seconds the light on the RJ45 connector responds appropriately and the Network Icon on the task bar changes appropriately.

# Windows 10
# C:\WINDOWS\System32\WindowsPowerShell\v1.0\

$adapterName = "Ethernet"
$adapter = Get-NetAdapter -Name $adapterName

# TEST STATUS REPORT:
Write-Host "Adapter Status: "$adapter.Status

Enable-NetAdapter -Name $adapterName -Confirm:$false

Start-Sleep -Seconds 10
Write-Host "Adapter Status: "$adapter.Status

# Try it again just for kicks ...
Enable-NetAdapter -Name $adapterName -Confirm:$false
Start-Sleep -Seconds 10
Write-Host "Adapter Status: "$adapter.Status

Start-Sleep -Seconds 5

The weird part is that: Whatever Status is reported in the first command that fetches the Ethernet status (Correctly!) is ALWAYS the Status reported in every following instance of the $adapter.Status command. This looks like nonsense to me in the case where the Status of the Ethernet port actually changes?

ServiceController status does not correctly reflect the actual service status Has an interesting note: "The ServiceController.Status property is not always live; it is lazily evaluated the first time it is requested, but (unless requested) only that time, subsequent queries to Status will not normally check the actual service. To force this, add: sc.Refresh();"

This might explain what is happening in PowerShell, but in the PowerShell ISE window:

" Get-NetAdapter -Name Ethernet. " options list shows "Status", but does NOT show "Refresh". I tried $adapter.Refresh both in the ISE and in the script, but it seems to be ignored.

Google AI flat-out couldn't process the question no matter how I refined it.

I would like to be able to validate 'change-of-state' in my script. Is that possible?

EDIT: Ahhh! I just figured out how to add my final explanation code ...

# Windows 10
# Enter this script with Ethernet ** CONNECTED **

$adapterName = "Ethernet"
$adapter = Get-NetAdapter -Name $adapterName

write-host "    Adapter Status:  "$adapter.Status
# Reports:  Adapter Status:   Up  (Actual Status)

Disable-NetAdapter -Name $adapterName -Confirm:$false
Start-Sleep -Seconds 5

write-host "Adapter Status: "(Get-NetAdapter -Name Ethernet).Status
# Reports:  Adapter Status:  Disabled  <-- CORRECT!

write-host "Adapter Status:  "$adapter.Status
# Reports:  Adapter Status:   Up       <-- WRONG !!!

Start-Sleep -Seconds 30

<#### Screen Output:
Adapter Status:   Up
Adapter Status:  Disabled
Adapter Status:   Up
####>

This proves that embedding the 'command' in an assignment has not been accomplished ... perhaps because I do not know the proper syntax. I would like to be able to do that if possible.

EDIT2: FYI I tried the following assignment with added parentheses, but it did NOT change anything ...

$adapter = (Get-NetAdapter -Name $adapterName)

FINAL ANSWER: Syntax - (untested Google AI answer): In windows 10 how do I make an assignment of a PowerShell command to a variable so that when the variable is used it executes the command and not merely returns the previous result of the command?

# Assign the command as a script block
$GetTimeCommand = { Get-Date -Format 'HH:mm:ss' }
# Execute the command at different times
Write-Host "Current time (1st execution):"& $GetTimeCommand
Start-Sleep -Seconds 2 # Wait for 2 seconds
Write-Host "Current time (2nd execution):"& $GetTimeCommand
1
  • I see what you were asking now... you were looking to store a expression to invoke later. What you've correctly used is called script block or anonymous function. Commented Oct 26 at 10:27

1 Answer 1

2

Get-NetAdapter outputs a CimInstance of the MSFT_NetAdapter class and said class doesn't have a .Refresh() method, see the Methods section in the linked documentation. For context, updating the state of your net adapter (enable / disable) doesn't update the object in place. The get and enable NetAdapter cmdlets are practically the same as using Get-CimInstance with Invoke-CimMethod:

# GET
$adapterName = 'Ethernet'

$getCimInstanceSplat = @{
    Namespace = 'root/StandardCimv2'
    Query     = "SELECT * FROM MSFT_NetAdapter WHERE Name='${adapterName}'"
}
$ciminstance = Get-CimInstance @getCimInstanceSplat

# ENABLE
$ciminstance | Invoke-CimMethod -MethodName Enable

ServiceController is a completely different type of object, it represents a Windows Service, and it indeed has a .Refresh() method. For context, Get-Service outputs this kind of objects:

$service = Get-Service myService
$service | Stop-Service
$service.Refresh()
$service.Status # Should be `Stopped`

In your case, you need to re-query your net adapter to get the updated status accordingly:

$adapterName = 'Ethernet'
$adapter = Get-NetAdapter -Name $adapterName
Write-Host 'Adapter Status: '$adapter.Status
Enable-NetAdapter -Name $adapterName -Confirm:$false
$adapter = Get-NetAdapter -Name $adapterName # Re-query
Write-Host 'Adapter Status: '$adapter.Status # Should be `Up`

Following the last edit, you were looking to store a expression in a variable to invoke later. What you've correctly used is called script block or anonymous function. It's a clever way to avoid the re-assignment and works great in this case.

If you want to take it a step further, you could use a function that returns the value of .Status property. In the end, the code is very similar:

function Get-NetAdapterStatus {
    param(
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string] $Name = 'Ethernet')

    (Get-NetAdapter -Name $Name).Status
}

Write-Host "Adapter Status: '$(Get-NetAdapterStatus)'."
# etc...
Sign up to request clarification or add additional context in comments.

6 Comments

Yes. To further comment, it helps to think of it that Get-NetAdapter method does not return a reference to the actual hardware. It returns the values of the hardware properties at that point in time.
I only included the link to the ServiceController article to prove that I did research the question prior to posting, and it is EXTREMELY similar to the weird results I was getting.
The last code section does resolve the question ... mostly. However the REAL problem is either a SYNTAX problem in the ASSIGNMENTS or sheer PowerShell insanity???
I'm not sure what you mean by syntax problem in the assignments, can you clarify?
Sorry, I don't know how to add an additional Discussion section. I want to elaborate on the ASSIGNMENT SYNTAX with another CODE section ... but I can't hit the "Enter" key ... Being primarily a LINUX user I expected the #adapter assignment to encapsulate the COMMAND, but it DOESN'T! It actually encapsulates the RESULTS of the command. Is there a special syntax to encapsulate the command so that when the assignment is used it runs the command and not just echoes the previous results? I want to publish the tested code that demonstrates this explicitly ...
I'm not near my pc right now but you can edit your own question, add to it and I'll @ you with a response once I'm back

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.