简体   繁体   中英

How to Start a process that interacts with the server's desktop in ASP.NET 3.5 through IIS7?

There are lots of answers, try this-that, but nothing works. Access denied. We are starting an application on the server, and automating it to do certain Quick tasks. Of course I can start it... (but it cannot run hidden, it must run in a real-desktop mode).

I've tried all manner of different elevation/impersonation techniques. Yes I've selected the IIS-Interact with desktop box. In the web.config I've got the impersonation flag...

Here is relevant code with some commented out attempts:

private const int WM_CLOSE = 16;
private const int BN_CLICKED = 245;
private const int LB_GETTEXT = 0x0189;
private const int LB_GETTEXTLEN = 0x018A; 
private const int WM_SETTEXT = 0X000C;

public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

WindowsImpersonationContext impersonationContext; 

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowTextLength(IntPtr hWnd);

[DllImport("user32.dll")]
protected static extern bool IsWindowVisible(IntPtr hWnd);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetProcessWindowStation();

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetThreadDesktop(int dwThreadId);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetCurrentThreadId();

public void findOurProcess(string filePath)
{
    IntPtr hwnd = IntPtr.Zero;
    IntPtr hwnd_select = IntPtr.Zero;
    IntPtr hwndChild = IntPtr.Zero;
    DateTime timer;
    TimeSpan diff;
    int processid;
    string username = "Programmer";

    clsImpersonate cls = new clsImpersonate();
    try
    {
        IntPtr token = cls.ImpersonateUser(username, Environment.MachineName, "RoboMan");
        using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(token))
        {

            //Process process = new Process();
            //ProcessStartInfo info = new ProcessStartInfo();
            //info.FileName = fileName;
            //info.Arguments = argument;

            //process.StartInfo = info;
            //process.Start();

            //if (impersonateValidUser("Programmer", "", "Roboman"))
            //if (impersonateValidUser(username, "DESKTOP", "Roboman"))
            //{
            ProcessStartInfo psi = new ProcessStartInfo("OUR PROCESS");
            //psi.UserName = username;
            //psi.Domain = Environment.MachineName;
            //psi.Password = new System.Security.SecureString();
            //psi.Password.AppendChar('R');
            //psi.Password.AppendChar('o');
            //psi.Password.AppendChar('b');
            //psi.Password.AppendChar('o');
            //psi.Password.AppendChar('m');
            //psi.Password.AppendChar('a');
            //psi.Password.AppendChar('n');
            psi.Arguments = "-batch";
            psi.WorkingDirectory = "OUR DIRECTORY";
            psi.UseShellExecute = false;

            //myProcess.StartInfo.CreateNoWindow = true;  //Maybe?
            //myProcess.Start();

            //The following security adjustments are necessary to give the new 
            //process sufficient permission to run in the service's window station
            //and desktop. This uses classes from the AsproLock library also from 
            //Asprosys.

            //IntPtr hWinSta = GetProcessWindowStation();
            //WindowStationSecurity ws = new WindowStationSecurity(hWinSta,
            //  System.Security.AccessControl.AccessControlSections.Access);
            ////ws.AddAccessRule(new WindowStationAccessRule(username,
            //  //  WindowStationRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
            //ws.AddAccessRule(new WindowStationAccessRule(username,
            //    WindowStationRights.CreateDesktop, System.Security.AccessControl.AccessControlType.Allow));
            //ws.AcceptChanges();

            //IntPtr hDesk = GetThreadDesktop(GetCurrentThreadId());
            //DesktopSecurity ds = new DesktopSecurity(hDesk,
            //    System.Security.AccessControl.AccessControlSections.Access);
            //ds.AddAccessRule(new DesktopAccessRule(username,
            //    DesktopRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
            //ds.AcceptChanges();

            using (Process process = Process.Start(psi))
            {
                processid = process.Id;
            }

the cls.ImpersonateUser The above attempts to run an elevated section of code as another user. But fails. You can see I've attempted to use this version as well. ImpersonateValidUser Example The AsProSys code would also throw an Access-denied exception right on the ws.AcceptChanges();

WebServers run as Windows Services. And Windows services are by default prohibited from accessing the Desktop as of Windows Vista .

In addition to the general Service Limitations, webservers are also customary run in the most limited userrights possible. Readaccess to it's programm and content directory is about the best they get. They are always on, so they are highly vulnerable to hacking.

As I understand currently you try to start a Dekstop applciation from a Webserver. And that is pretty much a no-go. If that did work, I would first wonder how quickly I can uninstall it. And then how I did not manage to limits right in the first place to prevent this. For every admin that will ever have to run your Webpage: Stop trying to do that!

Instead just have a Helper application that is normally installed on the Windows. Have it start automatically via the TaskSheduler on user login. and have it and the WebServer communicate via Pipes, the Loopback device or similar IPC ways that are acceptable for a WebServer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM