loxia01 / PSInternetConnectionSharing

This PowerShell Module provides simple functions to control Windows Internet Connection Sharing (ICS) from command line.
45 stars 8 forks source link

Run `Get-Ics -AllConnections` get exception #5

Closed GetStart13 closed 4 months ago

GetStart13 commented 5 months ago

When I run Get-Ics with -AllConnections, I get follow exception:

PS C:\WINDOWS\system32> Get-Ics  -AllConnections
使用“1”个参数调用“Invoke”时发生异常:“获取“INetSharingConfigurationForINetConnection”时发生异常:“指定的转换无效
。””
所在位置 C:\Program Files\WindowsPowerShell\Modules\PSInternetConnectionSharing\PSInternetConnectionSharing.psm1:262 字
符: 17
+ ...             $connectionConfig = $netShare.INetSharingConfigurationFor ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : GetValueInvocationException

ConnectionName ICSEnabled
-------------- ----------
Conn              False
传入的连接          False
WLAN                False
以太网 2            False
以太网              False

I found it the connect "传入的连接" can not be set ICS, I don't know if it is use to bluetooth connect, I think we should just deal with connection which can be set ICS only, so I add try...catch for this scenario:

if ($ConnectionNames)
{
    $output = foreach ($connectionName in $ConnectionNames)
    {
        try
        {
            $connection = $connections | Where-Object {$netShare.NetConnectionProps.Invoke($_).Name -eq $connectionName}
            $connectionConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($connection)

            if ($connectionConfig.SharingEnabled)
            {
                [pscustomobject]@{
                    ConnectionName = $connectionName
                        ICSEnabled = $true
                    ConnectionType = if ($connectionConfig.SharingConnectionType -eq 0) { 'Public' } else { 'Private' }
                }
            }
            else
            {
                [pscustomobject]@{ConnectionName = $connectionName; ICSEnabled = $false}
            }
        }
        catch {
          [pscustomobject]@{ConnectionName = $connectionName; ICSEnabled = 'Invalid'}
        }
    }
}

then I rerun command, output:

PS C:\WINDOWS\system32> Get-Ics  -AllConnections

ConnectionName ICSEnabled
-------------- ----------
Conn               False
传入的连接        Invalid
WLAN                False
以太网 2            False
以太网              False

should I add this try...catch?

loxia01 commented 5 months ago

Thanks for your report. I have one question, what output do you get when trying Set-Ics for the problematic connection?

GetStart13 commented 5 months ago

Thanks for your report. I have one question, what output do you get when trying Set-Ics for the problematic connection?

It will throw follow exception, and then I cannot connect to internet unless I run Set-Ics and Disable-Ics for my connection, Output:

PS C:\WINDOWS\system32> Set-Ics 传入的连接 WLAN
使用“1”个参数调用“Invoke”时发生异常:“获取“INetSharingConfigurationForINetConnection”时发生异常:“指定的转换无效
。””
所在位置 C:\Program Files\WindowsPowerShell\Modules\PSInternetConnectionSharing\PSInternetConnectionSharing.psm1:112 字
符: 17
+ ...             $publicConnectionConfig = $netShare.INetSharingConfigurat ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : GetValueInvocationException

不能对 Null 值表达式调用方法。
所在位置 C:\Program Files\WindowsPowerShell\Modules\PSInternetConnectionSharing\PSInternetConnectionSharing.psm1:142 字
符: 17
+                 $publicConnectionConfig.EnableSharing(0)
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [],RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
loxia01 commented 5 months ago

Ok, could you run this and post result for connection 传入的连接:

        regsvr32 /s hnetcfg.dll
        $netShare = New-Object -ComObject HNetCfg.HNetShare

        $connections = @($netShare.EnumEveryConnection)
        $connections | ForEach-Object { $netShare.NetConnectionProps.Invoke($_) }
GetStart13 commented 5 months ago

Ok, could you run this and post result for connection 传入的连接:

        regsvr32 /s hnetcfg.dll
        $netShare = New-Object -ComObject HNetCfg.HNetShare

        $connections = @($netShare.EnumEveryConnection)
        $connections | ForEach-Object { $netShare.NetConnectionProps.Invoke($_) }

Oh, I am confused, I am absolutely new to powershell, I don't know how to run it for the connection 传入的连接, I just run the commands in powershell, output:

PS C:\WINDOWS\system32> regsvr32 /s hnetcfg.dll
PS C:\WINDOWS\system32> $netShare = New-Object -ComObject HNetCfg.HNetShare
PS C:\WINDOWS\system32> $connections = @($netShare.EnumEveryConnection)
PS C:\WINDOWS\system32> $connections | ForEach-Object { $netShare.NetConnectionProps.Invoke($_) }

Guid            : {5A63CDF7-F4B6-4FC8-A08B-E938C42ED619}
Name            : 以太网 2
DeviceName      : TAP-Windows Adapter V9
Status          : 7
MediaType       : 3
Characteristics : 4105

Guid            : {ACC16325-5A3E-48B9-9396-649EF04F23CD}
Name            : 以太网
DeviceName      : Realtek PCIe GbE Family Controller
Status          : 7
MediaType       : 3
Characteristics : 4105

Guid            : {7EAB04F6-9A6C-4545-9E32-1A140C07C0E1}
Name            : WLAN
DeviceName      : Intel(R) Dual Band Wireless-AC 3168
Status          : 2
MediaType       : 3
Characteristics : 4105

Guid            : {44393EFC-29C4-25E4-B684-F168B398A2B4}
Name            : Conn
DeviceName      : Conn Tunnel
Status          : 2
MediaType       : 3
Characteristics : 4105

What do you want to detect? If is MediaType, I remember the connection's MediaType of 传入的连接 is different with others

loxia01 commented 5 months ago

Ok thanks. Connection 传入的连接 did not seem to show up in the output. Anyway you are sure you cannot set ICS for connection 传入的连接, not even manually in Control Panel Network Connections?

GetStart13 commented 5 months ago

Ok thanks. Connection 传入的连接 did not seem to show up in the output. Anyway you are sure you cannot set ICS for connection 传入的连接, not even manually in Control Panel Network Connections?

No, I cannot set it, there is no internet connection share button in Control Panel Network Connections. Now I cannot find it, maybe it was deleted when I run Set-Ics for it, I'm trying to recreate it.

loxia01 commented 5 months ago

Ok, thanks. I will try to add a try & catch statement both for Get-Ics and Set-Ics to display a cleaner error message when encountering an incompatible internet connection like yours. However, I am hesitant to add an 'invalid' value to the Get-Ics output. I will think about it (of course you can add it in your own module version).

GetStart13 commented 5 months ago

Thank you for improve. If the connection reappear, I will provide more information.

GetStart13 commented 5 months ago

Ok, could you run this and post result for connection 传入的连接:

        regsvr32 /s hnetcfg.dll
        $netShare = New-Object -ComObject HNetCfg.HNetShare

        $connections = @($netShare.EnumEveryConnection)
        $connections | ForEach-Object { $netShare.NetConnectionProps.Invoke($_) }

Hi, I recreate the problematic connection 传入的连接(Incoming Connection), this is my create steps:

The desciptions maybe different with your computer, because it is not English in my computer, please let me know if you don't understand my description in any way. I rerun the commands, output:

Guid            : {ACC16325-5A3E-48B9-9396-649EF04F23CD}
Name            : 以太网
DeviceName      : Realtek PCIe GbE Family Controller
Status          : 7
MediaType       : 3
Characteristics : 4105

Guid            : {7EAB04F6-9A6C-4545-9E32-1A140C07C0E1}
Name            : WLAN
DeviceName      : Intel(R) Dual Band Wireless-AC 3168
Status          : 2
MediaType       : 3
Characteristics : 4105

Guid            : {89150B9F-9B5C-11D1-A91F-00805FC1270E}
Name            : 传入的连接
DeviceName      :
Status          : 0
MediaType       : 0
Characteristics : 37
loxia01 commented 5 months ago

Thanks. I was not able to create it on my system, but I can see the connection misses a DeviceName. I already filter out null values for Status so I can also add a filter for DeviceName:

$connectionsProps = $connections | ForEach-Object {$netShare.NetConnectionProps.Invoke($_)} | Where-Object Status -NE $null | Where-Object DeviceName -NE $null

But I will also add a try, catch statement.

GetStart13 commented 5 months ago

Thanks. I was not able to create it on my system, but I can see the connection misses a DeviceName. I already filter out null values for Status so I can also add a filter for DeviceName:

$connectionsProps = $connections | ForEach-Object {$netShare.NetConnectionProps.Invoke($_)} | Where-Object Status -NE $null | Where-Object DeviceName -NE $null

But I will also add a try, catch statement.

Hello, I'm coming again, thanks for your improved code, I do it in my local module, the connection 传入的连接 didn't showed when I run Get-Ics, and it shouldn't be showed I think because it cannot be set ICS. This is properties panel of the problemtic connection 传入的连接: 3dece0507f4966b3262f41eb6bcb1d1b

But there might be a misunderstanding about Set-Ics output (I also filter out null values for DeviceName in Set-Ics), output:

PS C:\WINDOWS\system32> Set-Ics 传入的连接 以太网
Set-Ics : Cannot find a network connection with name '传入的连接'.
所在位置 行:1 字符: 1
+ Set-Ics 传入的连接 以太网
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (:) [Set-Ics], PSArgumentException
    + FullyQualifiedErrorId : ConnectionNotFound,Set-Ics

I feel it maybe inappropriate because it tell me cannot find the connection but I can find it in the "Network Connection" panel, so I remove the null values filter for DeviceName in Set-Ics, and add a elseif statement to describe this sitruation:

Get-Variable PublicConnectionName, PrivateConnectionName | ForEach-Object {
    if ($connectionsProps.Name -notcontains $_.Value)
    {
        $exception = New-Object PSArgumentException "Cannot find a network connection with name '$($_.Value)'."
        $PSCmdlet.ThrowTerminatingError((New-Object ErrorRecord -Args $exception, 'ConnectionNotFound', 13, $null))
    }
    elseif (($connectionsProps | Where-Object Name -EQ $_.Value).DeviceName -eq $null)
    {
        $exception = New-Object PSArgumentException "Cannot set ICS for this ICS-Invaild network connection which name '$($_.Value)'."
        $PSCmdlet.ThrowTerminatingError((New-Object ErrorRecord -Args $exception, 'ConnectionICSInvaild', 12, $null))
    }
    else { $_.Value = $connectionsProps | Where-Object Name -EQ $_.Value | Select-Object -ExpandProperty Name }
}

In addtion, 传入的连接 connection cannot be found when I run Get-NetAdapter. At the beginning, I want to judge if it's a ICS available connection by if it can be found in Get-NetAdapter, but I see it will cause the script execution speed to slow down, and the main reason is that I don't know whether the ICS is related to the NetAdapter. I am confused.

loxia01 commented 5 months ago

Ok, I can see your point here in getting a correct and informative error message. Thanks. I will be implementing something like it. Regarding Get-NetAdapter I used that command to get the connections in the first versions of the module, but changed to this approach for some reason I don't remember now.

loxia01 commented 5 months ago

Do you think "invalid" connections shall show up at all in the output for Get-Ics -AllConnections?

GetStart13 commented 5 months ago

Do you think "invalid" connections shall show up at all in the output for Get-Ics -AllConnections?

I'm uncertain because I don't know if there is any method to ensure that invalid connections cannot be set ICS (I'm not sure if the DeviceName property is a reliable indicator). If there is a way, then I believe we should list the invalid connections and indicate that they are invalid for ICS. However, if it’s not possible to make such a determination, then I don't think they should be listed because we don't know what are them.

loxia01 commented 4 months ago

I have updated the module with error handling for connections that are not ICS settable. Get-Ics -AllConnections now outputs those connections, but with a null value (blank) for property ICSEnabled.

If you want you can download and test before I make a release. https://raw.githubusercontent.com/loxia01/PSInternetConnectionSharing/master/PSInternetConnectionSharing.psm1

Just replace the .psm file in your module folder.

GetStart13 commented 4 months ago

I tested them, Set-Ics runs well, but Get-Ics seems have a problem, it output false, not blank:

PS C:\WINDOWS\system32> Get-Ics -AllConnections

ConnectionName ICSEnabled
-------------- ----------
Conn               False
传入的连接          False
WLAN                False
以太网 2            False
以太网              False

PS C:\WINDOWS\system32> Set-Ics 传入的连接 WLAN
Set-Ics : ICS is not possible to set for connection '传入的连接'.
所在位置 行:1 字符: 1
+ Set-Ics 传入的连接 WLAN
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Set-Ics], RuntimeException
    + FullyQualifiedErrorId : MethodInvocationException,Set-Ics

PS C:\WINDOWS\system32>

I want to know why, so I print them ($connectionConfig):

PS C:\WINDOWS\system32> Get-Ics -AllConnections
Conn: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}

ConnectionName ICSEnabled
-------------- ----------
WLAN                False
Conn               False
传入的连接          False
传入的连接: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
以太网 2            False
以太网 2: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
以太网: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
WLAN: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
以太网              False

PS C:\WINDOWS\system32>
loxia01 commented 4 months ago

Thanks for testing.

If you replace the try, catch statements on lines 273 and 274 with only this:

$connectionConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($connection)

What happens now if you run Get-Ics -AllConnections? You should get an error message.

GetStart13 commented 4 months ago

Thanks for testing.

If you replace the try, catch statements on lines 273 and 274 with only this:

$connectionConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($connection)

What happens now if you run Get-Ics -AllConnections? You should get an error message.

Yes, I will get an error like previous.

loxia01 commented 4 months ago

Ok, then I don't know why you get the False output value. It should work. Could you post the error message?

GetStart13 commented 4 months ago

Of course, message:

PS C:\WINDOWS\system32> Get-Ics -AllConnections
使用“1”个参数调用“Invoke”时发生异常:“获取“INetSharingConfigurationForINetConnection”时发生异常:“指定的转换无效
。””
所在位置 C:\Program Files\WindowsPowerShell\Modules\PSInternetConnectionSharing\PSInternetConnectionSharing.psm1:273 字
符: 17
+ ...             $connectionConfig = $netShare.INetSharingConfigurationFor ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : GetValueInvocationException

ConnectionName ICSEnabled
-------------- ----------
Conn               False
传入的连接          False
WLAN                False
以太网 2            False
以太网              False

PS C:\WINDOWS\system32>
GetStart13 commented 4 months ago

Because the parameter of $connectionConfi.SharingEnabled is False, I don't know why, I think it should be null because connection 传入的连接 cause an error, but the $connectionConfi still represent as an Object.

GetStart13 commented 4 months ago

Now I know why. When the error was catched, value of parameter $connectionConfig was refer to last loop, I use a parameter $debugName to debug it:

if ($ConnectionNames)
{
    $output = foreach ($connectionName in $ConnectionNames)
    {
        $connection = $connections | Where-Object {$netShare.NetConnectionProps.Invoke($_).Name -eq $connectionName}
        #$connectionConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($connection)
        try   { 
            $connectionConfig = $netShare.INetSharingConfigurationForINetConnection.Invoke($connection) 
            $debugName = $connectionName
        }
        catch { if (-not $AllConnections) { Write-Warning "ICS is not settable for connection '${connectionName}'." } }
        $debugName + ": " + $connectionName + ": " + ($connectionConfig | ConvertTo-Json)

        if ($connectionConfig.SharingEnabled -eq 1)
        {
            [pscustomobject]@{
                ConnectionName = $connectionName
                    ICSEnabled = $true
                ConnectionType = if ($connectionConfig.SharingConnectionType -eq 0) { 'Public' } else { 'Private' }
            }
        }
        else
        {
            [pscustomobject]@{
                ConnectionName = $connectionName
                    ICSEnabled = if ($connectionConfig.SharingEnabled -eq 0) { $false } else { $null }
            }
        }
    }
}

Then I run it, it output:

PS C:\WINDOWS\system32> Get-Ics -AllConnections
Conn: Conn: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}

ConnectionName ICSEnabled
-------------- ----------
WLAN                False
Conn               False
传入的连接          False
Conn: 传入的连接: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
以太网 2            False
以太网 2: 以太网 2: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
以太网: 以太网: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
WLAN: WLAN: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}
以太网              False

PS C:\WINDOWS\system32>

You can see, in the loop of 传入的连接, it still output the value which was setted in Conn loop:

传入的连接          False
Conn: 传入的连接: {
    "SharingEnabled":  false,
    "SharingConnectionType":  0,
    "InternetFirewallEnabled":  true
}

I dono't know why powershell (or .NET) don't refresh the parameter, it should be undifined like JavaScript.

loxia01 commented 4 months ago

Ok, thanks for all tests! I will take a look at this as soon as I can (have another thing to look at right now).

GetStart13 commented 4 months ago

Ok, thanks for all tests! I will take a look at this as soon as I can (have another thing to look at right now).

Wow, you're welcome, I have to sleep now, the time is over 5:00 am, good morning and good night.

loxia01 commented 4 months ago

Hi, have been busy sorry. Yeah I made a simple error (because I couldn't test). Of course the variable $connectionConfig must be updated/set in the catch block otherwise it takes the value of the last item in the loop before. Updated catch block code:

catch
{
    $connectionConfig = $null
    if (-not $AllConnections) { Write-Warning "ICS is not settable for connection '${connectionName}'." }
}
loxia01 commented 4 months ago

https://raw.githubusercontent.com/loxia01/PSInternetConnectionSharing/master/PSInternetConnectionSharing.psm1

GetStart13 commented 4 months ago

haha, don't be sorry, thanks you improve the script although you are busy. Now everything goes well!

PS C:\WINDOWS\system32> Get-Ics -AllConnections

ConnectionName ICSEnabled
-------------- ----------
Conn               False
传入的连接
WLAN                False
以太网 2            False
以太网              False

PS C:\WINDOWS\system32> Set-Ics 传入的连接 WLAN
Set-Ics : ICS is not possible to set for connection '传入的连接'.
所在位置 行:1 字符: 1
+ Set-Ics 传入的连接 WLAN
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Set-Ics], RuntimeException
    + FullyQualifiedErrorId : MethodInvocationException,Set-Ics

PS C:\WINDOWS\system32> Disable-Ics
PS C:\WINDOWS\system32> 

My purpose at the beginning is reset the ICS to fix my network problem to connect to the internet, the connection 传入的连接 cause the connection Conn cannot connect to internet, but if I enable the ICS (whatever which connection) and then disable it, the internet connect successfully, my cmd script:

@echo off
PowerShell -Command "Start-Process PowerShell -Verb RunAs -ArgumentList '$connections = Get-Ics -AllConnections | Where-Object ICSEnabled -NE $null | Select-Object -ExpandProperty ConnectionName; Set-Ics -PublicConnectionName $connections[0] -PrivateConnectionName $connections[1]; Disable-Ics'"

Now my script works, thank you

loxia01 commented 4 months ago

Good to hear it is working! And thanks for reporting and all your testing. I will close this issue and then release v1.4.1.