-1

Is it possible to make a .NET application always an admin while being run on a user account without a UAC popup? I've spent some time searching for this capability but haven't found any satisfactory answers.

For some background info, users are running a test application in a manufacturing environment where a dongle is plugged into a USB(to serial) port. Sometimes windows messes up the COM port and cycling the port can resolve the issue. We have discovered we can do this programmatically with admin privileges, but we do not want the users to be admins, and we also don't want the users to deal with a UAC popup or, god forbid, click "no" on the UAC popup to disable our capabilities and mess up the entire process.

How do I force my .NET application to run as administrator? I have found this old thread but their solutions all require the user to be admin or the usual UAC popup.

Is there something we can do to enable this capability or are we forever chained to the UAC prompt? We do own these machines and control the applications and users running on them.

EDIT: We are cycling the COM port using this method:

string ComPortName { get; set; } = "USB Serial Port (COM12)";
 

    private void button1_Click(object sender, EventArgs e)
    {
        SelectQuery query = new SelectQuery("Win32_PnPEntity", "Name=" + '"' + ComPortName + '"');
        ManagementObjectSearcher myDevices = new ManagementObjectSearcher(query);

        foreach (ManagementObject item in myDevices.Get())
        {
            textBox1.AppendText("Disabling port " + ComPortName + Environment.NewLine);
            ManagementBaseObject inParams = item.InvokeMethod("Disable", null, null);
            Thread.Sleep(3000);
            textBox1.AppendText("Enabling port " + ComPortName + Environment.NewLine);
            ManagementBaseObject UWFEnable = item.InvokeMethod("Enable", null, null);
            Thread.Sleep(3000);
            textBox1.AppendText("Finished cycling port " + ComPortName);
        }
    }
Plaje
  • 65
  • 9
  • 3
    Um, no - that would defy the whole purpose of limiting user accounts. – Adrian Mole Apr 07 '22 at 12:36
  • 4
    If you find a way of doing it please inform Microsoft to close the security issue. – Ralf Apr 07 '22 at 12:37
  • 1
    `their solutions all require the user to be admin or the usual UAC popup` -- Yes, that's how this works. Without such protections, anyone could impersonate an administrator and do whatever the hell they wanted with your machine or any other. – Robert Harvey Apr 07 '22 at 12:37
  • I don't see the security concern with allowing an application that we control on a machine that we own to have admin rights while the user running it does not. If anything, giving the user admin rights would be less secure. – Plaje Apr 07 '22 at 12:42
  • 1
    Can you make a service out of your program running under the service account? Or is the functionality you describe dependent on the user context? – Ralf Apr 07 '22 at 12:46
  • 1
    I suppose we could make a service. It sounds like you are suggesting we make an admin service to provide this functionality and then have the application send a reset port command or similar action? – Plaje Apr 07 '22 at 12:50
  • @RobertHarvey nobody is "impersonating" an admin, we ourselves have the admin rights we need but we want the application to run as an admin while the user remains a user, without the UAC popup. – Plaje Apr 07 '22 at 12:56
  • I didn't make that assertion. – Robert Harvey Apr 07 '22 at 12:56
  • @RobertHarvey well, the idea that a specific application we write cannot have elevated privileges without user consent seems a bit off to me. These are our machines, not theirs. – Plaje Apr 07 '22 at 13:03
  • 1
    If it's going to work at all, it will be by impersonating a user with administrative privileges that the system already recognizes. Some ideas [here](https://www.codeproject.com/Articles/14358/User-Impersonation-in-NET). – Robert Harvey Apr 07 '22 at 13:10
  • @Plaje you know better what's actually needed then me. I had more in mind that the whole dongle handling can move into the service but that might not be what you need. But what you said sounds reasonable. A service must be setup by an admin beforehand so the security considerations are already fulfilled. – Ralf Apr 07 '22 at 13:20
  • @Ralf there is too much existing code to move the entire dongle handling off the main application but a service would be a plausible idea. I'll be messing around with yours and Robert Harvey's suggestions to see if one of them is workable – Plaje Apr 07 '22 at 13:36
  • @Plaje it's a huge problem, no matter whose machine this is - if it was possible to bypass UAC, all malware would do it. Especially in this time period, you really *shouldn't* be asking to disable UAC. As for `too much existing code to move` you shouldn't have written that code in the first place. UAC was introduced 15-20 years ago. It's nothing unusual either- both MacOS and Linux have similar mechanisms. If you really think you don't need UAC, have the domain admin disable it on the machines - and watch their reaction. – Panagiotis Kanavos Apr 07 '22 at 13:46
  • @Plaje mobile applications also ask for permissions before accessing *anything*. You could follow the same model and create an installer that asks for permission to use the serial port. That's *far* safer than allowing the application to run as admin. In a UWP application you can [specify the permission in the app manifest and use the port through the SerialDevice class](https://learn.microsoft.com/en-us/uwp/api/Windows.Devices.SerialCommunication?redirectedfrom=MSDN&view=winrt-22000). It may be possible to do the same in non-UWP apps if packaged properly – Panagiotis Kanavos Apr 07 '22 at 13:58
  • @PanagiotisKanavos What you are saying is not true. In a mobile device once the application has been allowed permissions it does not need to ask again every time it is opened. We can add permissions to a program if it were possible to do this. Maybe we should run our application from a cell phone instead of windows 10. – Plaje Apr 07 '22 at 16:35
  • @Plaje as for Windows messing up the port, it's not Windows, it's the crappy drivers provided by all Serial-over-USB vendors. I know, I've used Serial ports before. 6 of them, to connect to radios. I discovered serious driver bugs right from the start that required fixes by FTDI itself (the chip vendor) - the serial port couldn't handle CTS/RTS automatically. It took almost a month to persuade them to just test their port using the MSDN sample, to persuade them that we weren't idiots. What would they do at this point, blame Microsoft? When the actual Serial port sample failed only on FTDI? – Panagiotis Kanavos Apr 07 '22 at 17:35
  • 1
    So the solution to your *real* problem, the crappy serial drivers, is for the vendor to fix them. That may not be possible, unless a lot of money is at stake, or you can threaten them with damages. They may not even know hot to fix the issue, their job is to sell devices not drivers. – Panagiotis Kanavos Apr 07 '22 at 17:39
  • Thanks @PanagiotisKanavos, I've had my own terrible experiences with FTDI components. It is entirely possible this issue is caused by their drivers as well. We could potentially look into redesigning the dongle with another device. – Plaje Apr 07 '22 at 17:59
  • 1
    @Plaje Had my share - and even a bit more - of crappy hadware controllers that are a real mess to put at work as datasheet let us expect it. CAN drivers, serial devices, PCI bridges, and so on. Despite being a quite big company, we never managed to make the manufacturers to redesign either their driver, their datasheets or their products... Because, technically, we buy maybe 0.01% of their production "only". So we learnt to: 1) Scold the electronics engineers for choosing a component without asking software engineers (and let them test it) 2) Work around flaws as we can to fix up the mess. – Wisblade Apr 09 '22 at 15:26
  • Would need to know the exact, technical specifics of what "Sometimes windows messes up the COM port" means. (Simply stating "it doesn't work" doesn't really help, because that doesn't explain _how_ it doesn't work.) – Bill_Stewart Apr 18 '22 at 20:23
  • @Bill_Stewart the port becomes unusable. It still shows up in device manager, but attempts to open a serial communication on the port causes one of 4 errors containing the following strings: "element not found", "device attached to the system is not functioning", "denied", and "The port 'COM#' does not exist". I do not know the rest of the errors strings for all of those, but our applications have known for a long time to capture those errors. – Plaje Apr 20 '22 at 15:15

2 Answers2

4

You can't, not without at least an UAC prompt. This is totally unavoidable, otherwise Windows wouldn't have any security if it was possible - it MUST be totally impossible, not just "difficult", to bypass UAC.

Some clues to solve anyway your problem:

  • You can force your application to always ask for elevation (i.e. make it to require administrative privileges) since the first step. Dangerous, but at least, you won't mess the whole software chain: it would be elevated from start.
  • You can ask for UAC only when it's really needed (for example, when launching a particular sub-process, or launching your own application in elevated mode while keeping context). Obviously, you'll ask again and again until the elevated subprocess is created: if user click on "No", then you try again to launch it. Annoying, but again, you won't mess up the whole process.
  • You can write a Windows service, that will run under administrative privileges, to perform the COM cycle task you need. Then, you can invoke this service from non-elevated user space, without requiring any elevation. I would recommend this solution.
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Wisblade
  • 1,483
  • 4
  • 13
1

No, you cannot.

Imagine the user is a standard user - e.g. a 5 year old daughter

She cannot just become an administrator.

If anyone could just become an administrator - then there's no point in having security. And Windows NT is a secure operating system.

Solution to your problem

The easiest way to solve your problem is to grant Everyone permission to do the thing. Because in order to do it: someone needs permission.

We have discovered we can do this programmatically with admin privileges

You don't mention what actions you are taking programmatically, or what Windows API you're calling.

  • If it involves a registry key, or file, or service
  • Grant Modify permission
  • to the Users group (or the Everyone group if you prefer)

This way the user's then have permission to do these things.

There's no shame in granting your users permissions to do the thing - it's what you want them to do. They should have permissions to do it.

If you care about defense-in-depth, you could follow the priciple of least privilege, and rather than granting everyone permission to do the thing, you can grant it to one user:

  • the user that a service runs as
  • the user that a scheduled task runs as

And then you only need to worry about your program communicating with a service (asking it to do the thing), or trigger the scheduled task (so that it can do the thing).

This way it's only the service/task that has permissions - and you grant that service/task the Modify permission on the thing that your standard users are currently denied from.

Imagine Windows XP

Imagine how you would have solved this before UAC:

  • the user is a standard user
  • and there is no UAC convenience feature to help them elevate to an administrator

In that case you would have to do one of the above:

  • grant everyone permission to the registry key, or folder
  • create a service or scheduled task that does have permission: and have your program ask them to do it
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • > "You don't mention what actions you are taking programmatically, or what Windows API you're calling." I absolutely did mention it - we need to cycle a USB to serial port to recover it during program execution during the manufacturing process. If you know of a way to do this without admin rights then by all means bring that process to this thread – Plaje Apr 07 '22 at 16:26
  • *"we need to cycle a USB to serial port to recover"* What does that mean? Is it an external USB hub, and you are controlling a relay that cuts power to the hub, and then turns it back on? Are you calling a Windows function? Are you using a setup program that came with your USB device? Is it a virtual COM port driver supplied by your USB device. ***WHAT*** are you doing? – Ian Boyd Apr 07 '22 at 16:28
  • In order to *"cycle"* a USB serial port: are you deleting a registry key? Are you rebooting the computer? Are you sending `WM_DEVICECHAGE` to all top-level windows? Are you using the SetupDI APIs to disable a hardware device? ***WHAT*** are you doing? – Ian Boyd Apr 07 '22 at 16:29
  • It is a custom in-house USB to serial dongle we use to communicate to a test device, that occupies a COM port that sometimes gets corrupted. We have found that we can disable and then enable the COM port to correct this issue in most or all cases. – Plaje Apr 07 '22 at 16:30
  • *"We have found that we can disable and then enable the COM port to correct this issue in most or all cases"* How are you disabling and enabling the COM port? Are you calling a function? Are you unplugging the device? Are you calling `CreateFile` on the physical `\\.\USB7\PK2834` device, and sending it command? ***WHAT*** are you doing? – Ian Boyd Apr 07 '22 at 16:32
  • Updated the OP with a sample code section of what we are doing – Plaje Apr 07 '22 at 16:38
  • Also, we do not necessarily want the users to be able to enable or disable the COM port themselves (outside of our application) so granting the user elevated permissions is not necessarily the best option, although it is a consideration. What we were thinking is more of what you would see on your cell phone: the application asks for permissions to access files, the user grants it, then the application doesn't have to pop up another UAC next time it runs. Why this capability apparently exists on cell phones but not windows 10 I am not sure, and in our case, it is our PC not the user's. – Plaje Apr 07 '22 at 17:11
  • *"Also, we do not necessarily want the users to be able to enable or disable the COM port themselves (outside of our application) so granting the user elevated permissions is not necessarily the best option, although it is a consideration."* I agree that giving them **Administrator** *all the time* just to solve an *intermittent* problem is not good. But the reality is that you **do** want users to be able to enable/disable the COM port - a user decides they need to do it, they need permission. – Ian Boyd Apr 07 '22 at 18:00
  • 1
    Given that you are driving WMI, there's probably no easy set of registry keys, or files/folders that you could grant them permission to. The better option is to write a service, or scheduled task, that does the action **for** them. You install that on every workstation, and then either a) start the scheduled task from code, b) start the service from code, or c) have the service run all the time and send it a message over a named pipe that you want it to do its thing. – Ian Boyd Apr 07 '22 at 18:02
  • Well we would prefer that the user not have permission and our application does honestly. The users do not own the machines and as this is a yield issue we would rather not exacerbate the problem by instructing the users to take extra steps during a problem and/or lengthen the test time. Ideally the issue would be silently dealt with by the application as quickly as possible and without user intervention, and without the user being able to muck up the process. – Plaje Apr 07 '22 at 18:17
  • upvoted your posts as it does offer some potential solutions, however the other guy had already posted his answer before yours and so was marked answer. I do appreciate you taking the time to go through this though. – Plaje Apr 08 '22 at 16:59
  • "Well we would prefer that the user not have permission and our application does" - that is not possible on Windows, because an application runs _as a specific user_. – Bill_Stewart Apr 18 '22 at 20:25