How to set IP, Subnet Mask and GW on Windows 10 IoT Enterprise 2019 LTSC from Windows Forms C# EXE (.NET Framework 4.7) or Win32 C++ DLL?

Kris Kazmar 11 Reputation points
2022-05-25T19:27:48.437+00:00

I'm porting an Industrial Control application to Windows 10 IoT Enterprise 2019 LTSC. The application is a Windows Forms C# EXE (.NET Framework 4.7+) invoking a multi-threaded Win32 C++ DLL. Since UI OS access is purposely restricted, I need to be able to set the IP address, subnet mask and gateway from our application UI. We have no preference for whether it's located in either C# or C++, but we greatly prefer that the UAC prompt does NOT appear. After extensive searching and testing, I'm not sure what to try next. The following has been tried so far:

try
{
ProcessStartInfo ProcStartInfo = new ProcessStartInfo();
ProcStartInfo.FileName = "netsh";
ProcStartInfo.Arguments = "interface ip set address \"Ethernet\" static " + IpAddrAryToStr(IpAddrAry) + " " +
IpAddrAryToStr(SubnetMaskAry); // IpAddrAryToStr() string output is in the format of 10.0.0.1
string DefaultGatewayStr = IpAddrAryToStr(DefaultGatewayAry); // For us, 255.255.255.255 represents no gateway
if (DefaultGatewayStr != "255.255.255.255")
ProcStartInfo.Arguments += " " + DefaultGatewayStr;
else
ProcStartInfo.Arguments += " " + IpAddrAryToStr(IpAddrAry); // clears the gateway if the same as the IP address
ProcStartInfo.Verb = "runas";
Process Proc = Process.Start(ProcStartInfo);
while (!Proc.WaitForExit(100)); //+++ Seems to cause a lockup if the UAC prompt is okayed too quickly
Console.WriteLine("netsh exit code = " + Proc.ExitCode);
}
catch
{
Console.WriteLine("netsh command failed or UAC prompt not Okayed");
}

The above generally works, but it causes the UAC prompt to appear, which is not desired and the Wait for Exit while loop locks up sometimes if the UAC prompt is okayed too quickly.

Second method:

MacAddrStr = "00E04C6821FE";

// Get the network interface
RetCode = -4;
NetworkInterface NetIf = null;
foreach (NetworkInterface Ni in NetworkInterface.GetAllNetworkInterfaces())
if (Ni.GetPhysicalAddress().ToString() == MacAddrStr)
{
NetIf = Ni;
break;
}
if (NetIf == null)
return RetCode;
Console.WriteLine("Ni found, MAC=" + MacAddrStr);

// Set the IP settings
RetCode = -5;
ManagementClass MgmtClass = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection MgmtObjCollection = MgmtClass.GetInstances();
foreach (ManagementObject MgmtObj in MgmtObjCollection)
{
if (MgmtObj["settingID"].ToString() == NetIf.Id)
{
Console.WriteLine("MgmtObj found, ID=" + MgmtObj["settingID"].ToString());
try
{
ManagementBaseObject RetMgmtObj;

        // Set the IP address and subnet mask
        ManagementBaseObject MgmtObjIp = MgmtObj.GetMethodParameters("EnableStatic");
        MgmtObjIp["IPAddress"] = new string[] { IpAddrAryToStr(IpAddrAry) };  // IpAddrAryToStr() string output is in the format of 10.0.0.1
        MgmtObjIp["SubnetMask"] = new string[] { IpAddrAryToStr(SubnetMaskAry) };
        RetMgmtObj = MgmtObj.InvokeMethod("EnableStatic", MgmtObjIp, null);
        Console.WriteLine("Set IP Result=" + IpAddrAryToStr(IpAddrAry) + " " +
            IpAddrAryToStr(SubnetMaskAry) + " 0x" +
        Convert.ToUInt32(RetMgmtObj.Properties["ReturnValue"].Value).ToString("X")); ;// Prints an error value of 0x80070005, which is access denied

        // Set the Default Gateway - set to the same as IP address to clear
        string DefaultGatewayStr = IpAddrAryToStr(DefaultGatewayAry);
        if (DefaultGatewayStr == "255.255.255.255")  // For us, 255.255.255.255 represents no gateway
            DefaultGatewayStr = IpAddrAryToStr(IpAddrAry); // clears the gateway if the same as the IP address
        ManagementBaseObject MgmtObjGw = MgmtObj.GetMethodParameters("SetGateways");
        MgmtObjGw["DefaultIPGateway"] = new string[] { DefaultGatewayStr };
        MgmtObjGw["GatewayCostMetric"] = new int[] { 1 };
        RetMgmtObj = MgmtObj.InvokeMethod("SetGateways", MgmtObjGw, null);
        Console.WriteLine("Set GW Result=" + DefaultGatewayStr + " 0x" +
        Convert.ToUInt32(RetMgmtObj.Properties["ReturnValue"].Value).ToString("X")); // Prints an error value also, 67 as I remember

        RetCode = 0;
        break;
    }
    catch (Exception Ex)
    {
        Console.WriteLine("Ex=" + Ex.ToString());
        break;
    }
}

}

Developer technologies | C++
Developer technologies | C#
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Sean Liming 4,766 Reputation points Volunteer Moderator
    2022-05-27T22:30:15.14+00:00

    UAC is not needed in an Embedded/IoT system. Does disabling UAC resolve the problem.


  2. Limitless Technology 44,766 Reputation points
    2022-05-31T07:30:56.587+00:00

    Hello KrisKazmar,

    By default UAC is intended as a protection and notification measure for the security of the system and health of the OS, as well company/user content and assets. It is expected that may have some behavioral settings (such as the "accepted too quick") to prevent fooling the user, or unwantedly passing the notification or acceptance.

    In this case scenario, it is understandable what you are trying to achieve and why, but it is still not expected as UAC behavior, therefor any workarounds or bypassed are expected to be problematic or unstable. In other words, that would be considered a "not recommended" implementation.

    The best way in this case, would be to disable the UAC for these specific devices, as they are not expected to be interacted with unless Administrator. For this you can use a registry GPO setting, for the next path/key:

    Path:HKEY_LOCAL_MACHINE > Software > Microsoft > Windows > Current Version > Policies > System
    Key: EnableLUA
    Value: 0 (disabled)


    --If the reply is helpful, please Upvote and Accept as answer--


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.