0
votes

I have an ASPX web application written in C# in which I call a desktop application running on the cloud web server machine from a button on the web page using a ProcessStartInfo object. The application (SetTags) was failing with a security violation when trying to access a Registry key in HKCU/Software. To get around this, I changed the ProcessStartInfo verb from 'open' to 'runas' and set UseShellExecute to true, which should start the desktop application with Administrator privilege. UAC has been turned off on the cloud server machine. However, the desktop application crashes with a security exception recorded in the event log as follows

Exception Info: System.Security.SecurityException
   at System.ThrowHelper.ThrowSecurityException(System.ExceptionResource)
   at Microsoft.Win32.RegistryKey.OpenSubKey(System.String, Boolean)
   at Global.Common..cctor()

Exception Info: System.TypeInitializationException
   at Global.Common.ShowUserError(System.String, System.String)
   at SetTagsNS.Program.Main(System.String[])

The crash happens before any data can be written to a log file and the Common.ShowUserError code does not contain any explicit Registry calls. It is as follows:

public static void ShowUserError(string sMsg, string sCaption = "")
    {
        if (CallingArgs == null) MessageBox.Show(sMsg, sCaption);
        else
            if (CallingArgs.GetUpperBound(0) != -1)
            {
                if(sErrFile!="") 
                {
                    StreamWriter Err = new StreamWriter(sErrFile,true); // 2nd param = true to append error
                    // Redirect standard error from the console to the error file.
                    Console.SetError(Err);
                    Err.Close();
                }
                else Console.Error.Write(sMsg);
            }

            else MessageBox.Show(sMsg, sCaption);
    }

The desktop application is built in C# using VS2013 as Windows application rather than a console application, but with the option of not showing any windows if it is launched with command line arguments. A console is attached to the application to record messages when the application is launched with command line arguments. This is done in order to use the same code base for a web application and a desktop application.

The desktop application can be run successfully on the cloud web server (Server2016 OS) from an administrator account from a .bat file using the same parameters as used when it is called from aspx page. runas /trustlevel=0x20000 is used to make the application run with only basic user privilege

What can I do to allow to allow the desktop application access to the Registry when it is called from an aspx page?

1
"This is done in order to use the same code base for a web application and a desktop application.". Shared code libraries in each application (could be managed using Nuget packages, for ease) would arguably be a less fraught way of achieving this. Or a Web API which both applications can call in order to access the required functionality. IMHO, if I may be so bold, this process of trying open a desktop app in a web request context is a bonkers way of trying to achieve that goal.ADyson
There are a lot us following the 'bonkers' way as the result of the Google query 'c# run .bat file from asp.net" indicates. It looks as though giving the application pool the web app belongs to Administrator rights solves the problem. Although the app is built as a desktop application it does not not show any windows when run from a command line. More details when it's finally sorted.SimonKravis
Yes but my point was that running a bat file (or other app) from asp.net is the wrong approach in the first place. You're starting from the wrong viewpoint by searching for that. Lots of people smoke 40-a-day too, it doesn't automatically make it a good idea. There are easier and better ways to share functionality between different applications, those being code libraries, or a 3rd application, usually an API which provides the functionality to both.ADyson

1 Answers

0
votes

The key to allowing executables running on a web server to behave like the same executable running on the desktop and using the registry is to give the Application Pool in which the web app runs the Identity a privileged account, such as Administrator, rather than the default of ApplicationPoolIdentity. This allows access to the Registry, but other things which desktop apps may use, such as special folder locations (eg AppData) may still be different. (It may be opening a security hole but in my case the server contains no sensitive data.) Then using the runas verb in Process.StartInfo allows the executable to behave as a desktop executable does.

In retrospect, the suggestion that the web app should simply share some of the code base (as suggested) would probably have been less work, but as I am very familiar with desktop app development I thought that the best approach would be simply to remove the UI when running the exe from a command line, and just let the web app deal with the interface. As ever, experience keeps a dear school. Once the pitfalls are known (registry access, special folders, any UI interaction) it's certainly possible to operate in this way. Judging from the number of people wanting to find out why bat files run on a web server desktop but not when run from a web app these differences should be more widely known.