Published November 2, 2017
I’ve been working on a project that requires the executable to change the static IP Addresses on the host computer’s network adapter to enable direct communication when operations using specific devices on unique subnets are invoked. In this instance, the system operator uses a portable computing device (Windows 7) to connect to a switch that interconnects a group of devices on a statically configured network.
This seems simple enough, but as I worked through all of the different conditions encountered I realized that while the task is simple in concept (and simple in execution, for the most part) there are a few “gotchas” that are best avoided.
First and foremost, I learned to never change the address of a network adapter unless that adapter is connected to some other Ethernet device. Changing the static address of an inactive device (the “Media disconnected” state when queried through ipconfig) often gives unexpected results.
Second, the Network Adapter can always be set to a static IP as long as it is connected - it can be changed from DHCP to a static IP and then reassigned static IPs as many times as required.
Third, if the Network Adapter is connected to a network with a DHCP server, changing the adapter from static IP to DHCP will cause an immediate lookup and new DHCP address assignment.
Fourth, if the adapter is connected to a network without a DHCP server, changing from static to DHCP will not result in an immediate address change - Windows will continue to use the last static address assigned until the adapter is connected to a network with a DHCP server (the card will then get a new IP assignment from the server) OR the computer is power cycled OR the network adapter is disabled and then re-enabled. On a power cycle or disable/re-enable, if the adapter is connected to a DHCP enabled network then the DHCP server will assign an IP or, if the network card is connected to a network without DHCP or not connected at all, Windows will assign an IP address using the APIPA (Automatic Private IP Addressing) protocol (the 169.254.xxx.xxx address space).
Programs on Windows (Vista and newer) are not allowed to change the properties of a network adapter unless they operate with elevated privileges. Typically, a user with Administrative privileges is required. However, Windows has defined a User Access Control (UAC) group called Network Configuration Operators that also has the ability to update network adapter properties. To add a user to the Network Configuration Operators group, use Control Panel->Administrative Tools->Computer Management->Local Users and Groups->Groups. Then double-click Network Configuration Operators to add a user to that group. Now, processes running under that user account will be able to set network adapter properties.
Granting Elevated Privileges
To allow a LabVIEW executable running under a standard user account (which is the way most applications should execute) to operate with elevated privileges requires the following. First, the user account must be a member of the Network Configuration Operator UAC Group to change the IP Address. Second, the application that needs to change network adapter properties requires starting with an elevated execution level. For a standard user, the “requestedExecutionLevel” requested should be “highestAvailable”. That property is set in the manifest embedded in the executable created by the LabVIEW application builder. This manifest is built with the default level of ”asInvoker” which means the application will start with the same privileges as the standard user. To use the privileges granted as part of the Network Configuration Operators group the manifest file must be extracted from the exe, the requestedExecutionLevel must be set to highestAvailable, and the manifest must be re-embedded in the exe. This is all accomplished with the Manifest Tool (mt.exe) which ships as part of the Windows SDK. The tool is not difficult to use but the command syntax can a be a little hard to remember.
Manifest Tool Screen
Typical Manifest File
SetIPAddress.lvclass provides a simple user interface to set a network adapter (identified by name, such as “Local Area Connection”) to either a static IPv4 address or DHCP configuration. To accomplish this, the class uses the .NET Framework System.Net.NetworkInformation.NetworkInterface to retrieve information about the installed network adapters and uses the Win32_NetworkAdapterConfiguration Windows Management Interface class called from the .NET Framework System.Management.ManagementClass to set the static IP addresses using the EnableStatic method. The target network adapter is returned to DHCP Enabled using a Netshell command. The Win32_NetworkAdapterConfiguration EnableDHCP method would not reset the adapter unless the user was logged in as Admin. The Netshell command works for both Admin access and for users who are part of the Network Configuration Operators group.
The Manifest Tool is a wrapper around the mt.exe tool that makes it more convenient to use from LabVIEW. Typically, I include the Main.vi of this toolkit in a post-build VI called by the application builder so new builds always have the updated manifest required. Note: mt.exe is part of the Windows SDK and must be obtained from a Microsoft source. It can be downloaded as part of the Windows SDK (https://www.microsoft.com/en-us/download/) or, if your development machine has Visual Studio, there will typically be a copy somewhere in Program Files (x86) or Program Files.
The Manifest Tool expects a copy of mt.exe in its root folder to work as distributed.
I also explored the idea of using the Powershell application that’s typically distributed with Windows. Powershell is a powerful system administration and management tool that is often used for tasks such as manipulation of network adapters. I ran into a fundamental problem trying to use the .NET System.Management.Automation.Powershell namespace. This toolset apparently relies heavily on the use of .NET Generics (templated method calls) and LabVIEW does not support calling .NET generic functions/methods. This could be mitigated by writing a wrapper assembly around the Powershell .NET interface, but that would require distributing the assembly along with the LabVIEW code and/or LabVIEW executable. Also, in strict user control environments, I have found strongly signing and deploying .NET assemblies (dlls) to the global assembly cache (GAC) is the most reliable way to avoid permission issues at execution time. Unfortunately, the LabVIEW installer doesn’t support installation to the GAC so some other tool (I use Visual Studio) must be used build the assembly installer. So using the System.Management.ManagementClass seemed the cleanest solution.