I heard good things about the AutoHotKey community so I am hoping you guys can help me with this :
How to create a script that changes the location (Category) of all network profiles from "public" (0) to "private" (1) and handles variables like the random generated folder names for each network?
Also the amount of folders will increase with time as the device will connect to more networks...
Create script that handles registry variables
Create script that handles registry variables
- Attachments
-
- Unbenannt.png (77.61 KiB) Viewed 5361 times
Re: Create script that handles registry variables
Thanks to Lexikos and HotKeyIt who showed me the proper way to do this
Run this as administrator:
Using the COM interface to do this is better than manipulating the registry directly because:
Run this as administrator:
Code: Select all
#NoEnv
#NoTrayIcon
SetBatchLines, -1
NetworkListManager := ComObjCreate("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}")
IEnumNetworkConnections := NetworkListManager.GetNetworks(NLM_ENUM_NETWORK_ALL := 3)
for INetwork in IEnumNetworkConnections
INetwork.SetCategory(1) ; NLM_NETWORK_CATEGORY_PRIVATE
- it's an actual documented way(!)
- if you're connected to a network at the time of running the script, the active network's designated category will change on-the-fly - when changing the active network's Registry key, IIRC reconnection or a restart is required to effect change
Re: Create script that handles registry variables
GMX (a German email provider) offers to connect to a members media center using WebDav.qwerty12 wrote:Thanks to Lexikos and HotKeyIt who showed me the proper way to do this
Run this as administrator:SpoilerUsing the COM interface to do this is better than manipulating the registry directly because:
- it's an actual documented way(!)
- if you're connected to a network at the time of running the script, the active network's designated category will change on-the-fly - when changing the active network's Registry key, IIRC reconnection or a restart is required to effect change
After mapping the network-drive (to Z:) I've searched the registry for any changes and came up with this:
Code: Select all
Windows Registry Editor Version 5.00
[HKEY_USERS\S-1-5-21-1277220127-497109434-765616382-1000\Network\Z]
"RemotePath"="https://webdav.mc.gmx.net"
"UserName"="<member@gmx.de>"
"ProviderName"="Web Client Network"
"ProviderType"=dword:002e0000
"ConnectionType"=dword:00000001
"DeferFlags"=dword:00000001
Thx for listening.
Re: Create script that handles registry variables
No, that's something different. I've not tested it, but DriveMap should allow you to map a WebDAV server to a drive letter from an AutoHotkey script (and the changes should take effect then and there).BoBo wrote:Question: would qwerty12's method allow that on-the-fly change/setting, instead of doing any RegWrite/explorer-refresh workaround?
Thx for listening.
Re: Create script that handles registry variables
Thxqwerty12 wrote:No, that's something different. I've not tested it, but DriveMap should allow you to map a WebDAV server to a drive letter from an AutoHotkey script (and the changes should take effect then and there).BoBo wrote:Question: would qwerty12's method allow that on-the-fly change/setting, instead of doing any RegWrite/explorer-refresh workaround?
Thx for listening.
Re: Create script that handles registry variables
Thank you very much! But there still is a problem: I am connected to a VPN via the TAP Adapter which uses the "public" profile and my firewall is precisely configured that way.qwerty12 wrote:Thanks to Lexikos and HotKeyIt who showed me the proper way to do this
Run this as administrator:Using the COM interface to do this is better than manipulating the registry directly because:Code: Select all
#NoEnv #NoTrayIcon SetBatchLines, -1 NetworkListManager := ComObjCreate("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}") IEnumNetworkConnections := NetworkListManager.GetNetworks(NLM_ENUM_NETWORK_ALL := 3) for INetwork in IEnumNetworkConnections INetwork.SetCategory(1) ; NLM_NETWORK_CATEGORY_PRIVATE
- it's an actual documented way(!)
- if you're connected to a network at the time of running the script, the active network's designated category will change on-the-fly - when changing the active network's Registry key, IIRC reconnection or a restart is required to effect change
So maybe there is a way to make an exception for OpenVPN but force everything else to use "private"?
Re: Create script that handles registry variables
You could avoid specific connections by connection name:Thouldre wrote: So maybe there is a way to make an exception for OpenVPN but force everything else to use "private"?
Code: Select all
for INetwork in ComObjCreate("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}").GetNetworks(3) { ; NLM_ENUM_NETWORK_ALL
if (INetwork.GetName() == "<name of specific connection name>") { ; use MsgBox % INetwork.GetName() inside a loop like this one if you want to find out your available choices
INetwork.SetCategory(0) ; NLM_NETWORK_CATEGORY_PUBLIC
; or comment the above line to leave the setting as it is, instead of forcing the Public category to be set, and just
continue
} else {
INetwork.SetCategory(1) ; NLM_NETWORK_CATEGORY_PRIVATE
}
}
Code: Select all
VarSetCapacity(adapterGuid, 16), VarSetCapacity(adapterGuidStr, 140), adapters := GetAdaptersAddresses()
for INetwork in ComObjCreate("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}").GetNetworks(1) { ; NLM_ENUM_NETWORK_CONNECTED
for k, v in INetwork.GetNetworkConnections() {
try if ((INetworkConnection := ComObjQuery(k, "{DCB00005-570F-4A9B-8D69-199FDBA5723B}"))) {
if (DllCall(NumGet(NumGet(INetworkConnection+0)+12*A_PtrSize), "Ptr", INetworkConnection, "Ptr", &adapterGuid) == 0) { ; ::GetAdapterId
if (DllCall("ole32\StringFromGUID2", "Ptr", &adapterGuid, "WStr", adapterGuidStr, "Int", 68)) {
if (adapters[adapterGuidStr].Description == "<name of network adapter>") { ; also look at FriendlyName instead of Description
INetwork.SetCategory(0) ; NLM_NETWORK_CATEGORY_PUBLIC
noop := "or comment the above line to leave the setting as it is, instead of forcing the Public category to be set" ; for lack of a better option in AutoHotkey...
} else {
INetwork.SetCategory(1) ; NLM_NETWORK_CATEGORY_PRIVATE
}
}
}
ObjRelease(INetworkConnection)
}
}
}
; just me: https://autohotkey.com/boards/viewtopic.php?t=18768
GetAdaptersAddresses()
{
; initial call to GetAdaptersAddresses to get the size needed
If (DllCall("iphlpapi.dll\GetAdaptersAddresses", "UInt", 2, "UInt", 0, "Ptr", 0, "Ptr", 0, "UIntP", Size) = 111) ; ERROR_BUFFER_OVERFLOW
If !(VarSetCapacity(Buf, Size, 0))
Return "Memory allocation failed for IP_ADAPTER_ADDRESSES struct"
; second call to GetAdapters Addresses to get the actual data we want
If (DllCall("iphlpapi.dll\GetAdaptersAddresses", "UInt", 2, "UInt", 0, "Ptr", 0, "Ptr", &Buf, "UIntP", Size) != 0) ; NO_ERROR
Return "Call to GetAdaptersAddresses failed with error: " . A_LastError
Addr := &Buf
Adapters := {}
While (Addr) {
AdapterName := StrGet(NumGet(Addr + 8, A_PtrSize, "Uptr"), "CP0")
Description := StrGet(NumGet(Addr + 8, A_PtrSize * 7, "UPtr"), "UTF-16")
FriendlyName := StrGet(NumGet(Addr + 8, A_PtrSize * 8, "UPtr"), "UTF-16")
Adapters[AdapterName] := {Description: Description, FriendlyName: FriendlyName}
Addr := NumGet(Addr + 8, "UPtr") ; *Next
}
Return Adapters
}
Re: Create script that handles registry variables
Thank you, thank you, thank you! I really appreciate your time! It's working as hoped!
I decided to use a combination of the first and the third script. First one always at startup and the third as a scheduled task triggered when connected to a new network.
I hope you can answer this question: How to execute a script automatically at startup before a user logs in?
I decided to use a combination of the first and the third script. First one always at startup and the third as a scheduled task triggered when connected to a new network.
I hope you can answer this question: How to execute a script automatically at startup before a user logs in?
Re: Create script that handles registry variables
Good to hear (and thanks for the Task Scheduler idea)Thouldre wrote:Thank you, thank you, thank you! I really appreciate your time! It's working as hoped!
I decided to use a combination of the first and the third script. First one always at startup and the third as a scheduled task triggered when connected to a new network.
Hmm, what are you trying to do? I wrote a mishmash of functions for running AutoHotkey on the logon screen's desktop, but that might be overkill for your purposes - you might be able to get away with just having Task Scheduler to just start a simple script in the services session...I hope you can answer this question: How to execute a script automatically at startup before a user logs in?
Re: Create script that handles registry variables
I've converted the .ahk to .exe and created an scheduled task to run it when a user logs in. That works, but I need to run the .exe at startup not at login which means before a user even has to login.
I ticked "run whether user is logged on or not" and switched the trigger from user logon to startup but unfortunately that is not working... Why?
I ticked "run whether user is logged on or not" and switched the trigger from user logon to startup but unfortunately that is not working... Why?
Re: Create script that handles registry variables
Assuming it's this script you want to run and that your task scheduler settings set to run the script as a user with enough privileges, Task Scheduler might be starting your script before the Network List Service service is started. I don't really know enough about what's going on here to be able to give you a definitive answer. Other than waiting for the service to start, you can use your original idea of manipulating the registry directly (not tested):Thouldre wrote:I ticked "run whether user is logged on or not" and switched the trigger from user logon to startup but unfortunately that is not working... Why?
Code: Select all
Loop, Reg, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles, K
{
currKey := A_LoopRegKey . "\" . A_LoopRegSubKey "\" . A_LoopRegName
RegRead, ProfileName, %currKey%, ProfileName
if (!ErrorLevel) {
if (ProfileName != "<name of profile>") {
RegWrite, REG_DWORD, %currKey%, CategoryType, 0
RegWrite, REG_DWORD, %currKey%, Category, 1 ; private network: set to 0 for a public designated one
}
}
}
Re: Create script that handles registry variables
Thanks, the script is working but unfortunately not as a scheduled task. At least now I know the issue lies with task scheduler!
Thank you for your time and work! You were a huge help! Thanks!
Thank you for your time and work! You were a huge help! Thanks!
Re: Create script that handles registry variables
I still have a small question if you don't mind: How to completely disable or hide the following question of Windows or maybe just click automatically yes?
- Attachments
-
- asdasd.jpg (25.15 KiB) Viewed 5222 times
Re: Create script that handles registry variables
Sorry, I don't know - I keep my UAC level at the highest, which disables that window automatically, but, erm, doing that might be a bit drastic for that purpose....Thouldre wrote:How to completely disable or hide the following question of Windows or maybe just click automatically yes?
Re: Create script that handles registry variables
I've created a scheduled task to take care of that which means this prompt is not only unnecessary it's also a security risk if accidentally clicked.
Found the solution! If somebody has or is going to have the same issue, just add the following registry key:
Found the solution! If somebody has or is going to have the same issue, just add the following registry key:
Code: Select all
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Network\NewNetworkWindowOff
-
- Posts: 20
- Joined: 05 Jul 2015, 17:51
Re: Create script that handles registry variables
I have a slightly different problem, and this looks like a good starting point for fixing it. I have a 2003 DC and all my PCs are beating the DC to booting, and not properly connecting to the domain. Their connections show up as "Network #" and a profile of "public". If I disable/re-enable the connection, the connection connects with the proper "Domain" profile (contoso.local). I guess if there doesn't exist a "domain" connection, reset all network adapters? Does the GetNetworks() differentiate between "private" and "domain"? I tried for INetwork in ComObjCreate("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}").GetNetworks(2) and it returns the same value as "3" (all the public connections).
-
- Posts: 20
- Joined: 05 Jul 2015, 17:51
Re: Create script that handles registry variables
Ok, so I got this far:
Spoiler
But GetName nor GetDescription return what the disable/enable commands are expecting. Any way to disable/enable connections with inetwork?Re: Create script that handles registry variables
Sorry, I didn't see this. Look at the second script here. If you replace what's inside the if (DllCall("ole32\StringFromGUID2", "Ptr", &adapterGuid, "WStr", adapterGuidStr, "Int", 68)) { block with MsgBox % adapters[adapterGuidStr].FriendlyName you should, hopefully, see the name netsh is expecting.
EDIT: No problem, eekhelpspike. I'm glad you managed to devise a solution. Sadly, running as admin is annoying, but IMHO, it's for the better in this case
EDIT: No problem, eekhelpspike. I'm glad you managed to devise a solution. Sadly, running as admin is annoying, but IMHO, it's for the better in this case
Last edited by qwerty12 on 29 Sep 2017, 09:58, edited 1 time in total.
-
- Posts: 20
- Joined: 05 Jul 2015, 17:51
Re: Create script that handles registry variables
No problem! Thanks for responding.qwerty12 wrote:Sorry, I didn't see this. Look at the second script here. If you replace what's inside the if (DllCall("ole32\StringFromGUID2", "Ptr", &adapterGuid, "WStr", adapterGuidStr, "Int", 68)) { block with MsgBox % adapters[adapterGuidStr].FriendlyName you should, hopefully, see the name netsh is expecting.
Excellent. Got this working:
Code: Select all
VarSetCapacity(adapterGuid, 16), VarSetCapacity(adapterGuidStr, 140), adapters := GetAdaptersAddresses()
for INetwork in ComObjCreate("{DCB00C01-570F-4A9B-8D69-199FDBA5723B}").GetNetworks(1) { ; NLM_ENUM_NETWORK_CONNECTED
if (INetwork.GetCategory() <> 2) {
for k, v in INetwork.GetNetworkConnections() {
try if ((INetworkConnection := ComObjQuery(k, "{DCB00005-570F-4A9B-8D69-199FDBA5723B}"))) {
if (DllCall(NumGet(NumGet(INetworkConnection+0)+12*A_PtrSize), "Ptr", INetworkConnection, "Ptr", &adapterGuid) == 0) { ; ::GetAdapterId
if (DllCall("ole32\StringFromGUID2", "Ptr", &adapterGuid, "WStr", adapterGuidStr, "Int", 68)) {
NetworkToReset := adapters[adapterGuidStr].FriendlyName
;MsgBox % NetworkToReset
Sleep,500
RunWait, netsh interface set interface "%NetworkToReset%" DISABLED,,hide
Sleep,5000
RunWait, netsh interface set interface %NetworkToReset% ENABLED,,hide
Sleep,2000
}
}
ObjRelease(INetworkConnection)
}
}
}
}
GetAdaptersAddresses()
{
; initial call to GetAdaptersAddresses to get the size needed
If (DllCall("iphlpapi.dll\GetAdaptersAddresses", "UInt", 2, "UInt", 0, "Ptr", 0, "Ptr", 0, "UIntP", Size) = 111) ; ERROR_BUFFER_OVERFLOW
If !(VarSetCapacity(Buf, Size, 0))
Return "Memory allocation failed for IP_ADAPTER_ADDRESSES struct"
; second call to GetAdapters Addresses to get the actual data we want
If (DllCall("iphlpapi.dll\GetAdaptersAddresses", "UInt", 2, "UInt", 0, "Ptr", 0, "Ptr", &Buf, "UIntP", Size) != 0) ; NO_ERROR
Return "Call to GetAdaptersAddresses failed with error: " . A_LastError
Addr := &Buf
Adapters := {}
While (Addr) {
AdapterName := StrGet(NumGet(Addr + 8, A_PtrSize, "Uptr"), "CP0")
Description := StrGet(NumGet(Addr + 8, A_PtrSize * 7, "UPtr"), "UTF-16")
FriendlyName := StrGet(NumGet(Addr + 8, A_PtrSize * 8, "UPtr"), "UTF-16")
Adapters[AdapterName] := {Description: Description, FriendlyName: FriendlyName}
Addr := NumGet(Addr + 8, "UPtr") ; *Next
}
Return Adapters
}
Thank you so much, qwerty12!