I am attempting to upgrade an existing system from Windows XP Professional / IIS 5.1 to Windows 7 Ultimate (32-bit) / IIS 7.5. The original system ran a classic ASP website (only available to the localhost) that used 'ASPExec' to launch desktop applications on the local machine (.bat, .cmd, .exe, etc). Under Windows 7 Ultimate / IIS 7.5, the applications fail to launch from the ASP page.
As tests (The end goal is not to launch notepad), I have tried:
<%
Set Executor = Server.CreateObject("ASPExec.Execute")
Executor.Application = "notepad.exe"
Executor.ShowWindow = True
strResult = Executor.ExecuteWinApp
%>
I have also tried:
<%
Set wshell = CreateObject("WScript.Shell")
wshell.run "notepad.exe"
Set wshell = Nothing
%>
Both methods will cause notepad.exe to show in the Windows Process list, but fail to launch the application on the desktop. This is true for any .exe I try to run, and .bat or .cmd files simply fail to do anything.
With IIS 5.1, the original author of the ASP application used the "Allow Service to Interact with the Desktop" option on the "IIS Admin" service and "World Wide Web Publishing" service to make this work. All issues aside with allowing desktop interactive services, IIS 7 no longer uses the "IIS Admin" service, so this is not an option.
I am looking for either a workaround from the Windows/IIS side or another option in ASP that might acheive the same desired end result.
You won't be able to do this with Windows 7/IIS 7.5. The reason this worked was because you were running IIS5.1. Back in the days of IIS5.0/5.1 you had three different process models:
In Process (or Low Isolation mode) - where every site ran inside the inetinfo.exe process
Pooled Process - sites ran in an external surrogate process inside COM+
Out of Process (or High Isolation mode) - where each site runs inside it's own COM+ process
Most likely your IIS5.1 instance is configured to run in "In Process" mode and under the SYSTEM account. Because you can configure the IIS service to interact with the desktop, and because your Classic ASP script is being executed inside this process it is able to launch executables and they appear on the desktop.
In IIS7 life is different. Your code will run inside an application pool process which is spun up on demand. There is no way to configure pool processes (w3wp.exe) and allow them to interact with the desktop, even if running under the local system account.
Also unlike IIS6 you can't configure IIS7 to behave as if it's IIS5; IIS7 is a bottom up rewrite with a new architecture.
A possible workaround would be to write a simple WCF service with a HTTP endpoint that starts when the user logs on (hosted in a Windows app that hides or minimises itself to the notification area). You could then make calls to this service from your Classic ASP code using something like MSXML2.ServerXMLHttp and get the WCF service to launch these processes on your behalf.
This archived copy of chapter 29 of Keith Brown's "The .NET Developers Guide to Windows Security" explains the machinations involved in getting a service application to interact with the desktop:
The .NET Developers Guide to Windows Security - chapter 29 - How to Display a User Interface from a Daemon (source: archive.org)
Quote:
Option one is to get yourself into the interactive window station, and
option two is to have a process already in the interactive window
station display a UI for you.
An easy way to put a daemon in the interactive window station
(WinSta0) so it can have its own user interface is to package it as a
service that runs as SYSTEM and check the box that says, "Allow
service to interact with the desktop." This tells the SCM to launch
your service process in the SYSTEM logon session (WhatIsALogonSession)
and to attach your process to WinSta0 instead of the noninteractive
window station in which the SYSTEM daemons normally run,
Service-0x0-0x3e7$.
This is what you probably have already on your XP box. But as I explained, there is no way to configure worker processes to do this because you can't configure the "Allow service to interact with the desktop." flag, even though you can configure a pool to run as the local SYSTEM account. When the book was written this applied to Windows 2000/2003. With the advent of Windows Vista/2008 and onwards you have the added complication of UAC and getting past that as well.
What you should consider instead is option two: Use two processes
instead of just one. One process must be launched in the interactive
user's logon session and WinSta0. It should contain all the user
interface elements you need, and it can connect to your daemon process
using any secure form of interprocess communication you're comfortable
with
This is essentially what I've suggested.
Related
Here is situation:
I have a large collection of videos on a computer, and it will be hooked up to my TV. I would like to make an app to open my videos on my computer from my mobile device (Yes, I know it exists, I am just working on it for fun)
So I have setup a web service, and an app to consume said webservice. The webservice gathers a list of folders/files, and sends them to my device as well as can take in a file path and open it with the default program using System.Diagnostics.Process.Start(path)
When I am using IISExpress, it works fine, but I would like to use IIS. When I use IIS, I open the video file and hear it playing in the background, but it doesn't show up on the monitor. VLC appears in the task manager, and when I kill it, the sound stops.
I'm assuming the issue is the identity under which the app pool is being run, but when I tried to change the identity, it didn't make any difference. If it helps, I am running Windows 8. Does anybody have any thoughts on how I can make the app pool run under my identity, or open the process on the desktop of the active user, rather than open it under the app pool's name?
This is something rather difficult to implement due to Windows session isolation. IIS as well as its worker processes are in session 0, while your logon session is usually > 0. Via native Win32 API it is possible for something in session 0 to launch executable in other sessions, but I don't think it is worth the while.
Please use IIS Express, as it runs in your logon session directly, and don't need to cross the session boundary at all.
With regards to the Process.Start() problem I think in addition to changing the identity of the application pool you also need to go to Services under Administrative Tools and check the box "Allow the service to interact with desktop" under the Log On tab for the World Wide Web Publishing service. I think this has already been addressed in the following question: System.Diagnostics.Process.Start not work from an IIS
Now, if I had to put an app like this together I would try I slightly different approach: in addition to what you have already, I would build a small desktop app that autostarts and sits in the system tray when you log onto your desktop. It will listen for messages from the asp.net application on named pipes or tcp or something similar and start the processes from within the correct user context. That seems a more stable approach, which will also allow you to separate the web server from the desktop where the videos will be played.
I have two web services running in IIS 7 (on Windows 7). I need to attach to one of these services to debug using VS 2012. But when I choose Attach To Process in Visual Studio, there is no w3wp.exe process to attach to (even if I select to Show processes from all users).
TaskMgr also shows no w3wp.exe.
What is running the service then? I know it's running because I see relevant errors in my browser.
This sounds awfully like your web service is running under either the built-in "Cassini" web server (WebDev.WebServer40.EXE) or IIS Express (iisexpress.exe).
If this isn't the case then it sounds like the "full fat" IIS7 worker process for the web service in question has shut down due to its idle timeout.
Finally if you need to attach to an IIS7 worker process you need to launch Visual Studio as an administrator, i.e. right click on the VS icon on your start menu and choose "Run as Administrator".
I have an ASP.NET application on Windows 2008 R2 (.NET Framework 4.0, IIS 7.5) and I want to run a console application when I click a button on a web page. Here is the code:
protected void btnUpdate_Click(object sender, EventArgs e)
{
string fileLocation = #"D:\DTDocs\App_Code\LoadDTDocsXML.exe";
ProcessStartInfo oStartInfo = new ProcessStartInfo();
oStartInfo.FileName = fileLocation;
oStartInfo.UseShellExecute = false;
Process.Start(oStartInfo);
}
When I run ASP.NET application from within Visual Studio 2010 (with its internal IIS), the console application run Ok. But when I run the ASP.NET application outside the VS 2010, I haven't an error but the console application doesn't make his job (it must create an xml file on the disk).
I think the problem is the configuration of IIS 7.5, I don't know exact to which account I must give access rights to the folders involved in my console application.
In IIS 7.5, I set Physical Path Credential for Specific User = my windows account, but that not solve the problem.
Thanks.
Just to add to the other 2 answers - Do you really need to run an exe from your webserver?
I've had to do it in the past and it's almost always the option of last resort - It weakens your security considerably (Now all someone has to do to run executables on your system is find a single flaw in your code) and has a whole host of other problems (the webserver isn't "logged on" to the server so it doesn't have a desktop, impersonation is a real pain in the a$$ to get working properly (assuming you're going to run the executable with different permissions to the webserver), etc.
If there's any other way to accomplish your goal, it'll almost certainly be simpler.
An option we went for was to have a new app with a WCF endpoint that the webserver can communicate with. So, when someone pushes the button, the WS call's our app via WCF and tells it to run various commands. This way, you've got:
Clean seperation between web and console code.
A dodgy console app won't take down the webserver & vice-versa
If the console app is long-running, this allows you to stagger your releases for website/console app so that you don't kill the app mid-execution just because you need up upodate some CSS and publish.
Huge security benefits - web server can't run executables even if compromised.
The WCF app will be able to closely examine requests to decide if they're valid before execution.
Be aware that however you do it, if someone malicious works out what's going on and can kick off the process, they could probably DoS you with almost zero effort - Make sure that this method is locked down TIGHT.
Edit: having read your comments above, I think you're hitting the "desktop" issue. When launching an executable from the server, the app will never be visible to the logged on user as the logged on user's desktop isn't accessible from IIS and vice-versa. This is very similar to the issue of having a GUI on a windows service.
This may also be of interest.
the first problem I see is security/file access. when running from within VS the server and client are the same machine under your credentials. when run in testing/production environment the server and client are physically different machines and IIS will run the website under restricted permissions. therefore there is a very good chance that IIS cannot access the file at D:... because of security.
the next issue is running a console app from the website. console is another form of UI just like html and a WPF. personally I wouldn't execute the console from the web (unless there was no other choice). I would integrate the API into the web application. 2 UIs sharing the same logic.
ASP.NET Dev Server runs under credentials of current user (it's you).
IIS 7.5 runs ASP.NET applications under user specified in application pool settings -- usually ApplicationPoolIdentity (to which you can refer as user "IIS AppPool\[ApplicationPoolName]", when configuring file permissions). You can also change it to "Network Service" (Default value in IIS 7.0).
Please check, which identity is configured for your application pool, and give this user required permissions.
When I run System.Diagnostics.Process.Start from my console application it works but the same code when I run from my web service hosted in IIS doesn't work.
Is it some thing to do with ASP.Net privileges?? if yes how can I configure it from my C# code.
ASP.NET Web page and server control code executes in the context of the ASP.NET worker process on the Web server. If you use the Start method in an ASP.NET Web page or server control, the new process executes on the Web server with restricted permissions. The process does not start in the same context as the client browser, and does not have access to the user desktop.
http://msdn.microsoft.com/en-us/library/0w4h05yb.aspx
- Give permission for ASP.NET worker process account
to interact with desktop or allow ASP.NET worker process to run in SYSTEM account.
To know how to allow worker process to run in SYSTEM account
and to know the default permissions of ASPNET account, check this article
INFO: Process and Request Identity in ASP.NET: http://support.microsoft.com/default.aspx?scid=kb;en-us;317012
- Enable IIS Admin Service to interact with desktop
To configure this, follow this steps.
a. Open Control Panel and follow these steps:
For Windows NT: click Services.
For Windows 2000, Windows XP, and .NET Server: click Administrative Tools, and then click Services.
b. Double-click IIS Admin Service.
c. On the Log On tab, select the Allow Service to Interact with Desktop check box.
Remember to run IIS Admin Service as a local system.
d. Stop and restart the IIS Admin Service.
Changing the AppPool worked for me.
IIS > Application Pools
Select Advance Setting for the website
Change Identity to LocalSystem
Restart IIS
I had a similar problem, and the ability to access the desktop from the service wasn't the problem. It worked fine when not impersonating another user, but when trying to run the process as a different user it failed.
The first thing to do when it won't start is find out all the information you can about the problem. The first question is whether Process.Start returned true or false. Secondly, did you get any kind of exception when trying to start the process.
Before you can investigate fully it relevant to know whether Process.Start was run using UseShellExecute or not - this has to be false for impersonation, but otherwise you can choose whether to use it and it calls different Win32 functions depending on this setting.
If you're doing a process that needs to run as another user, don't bother trying to use .NET impersonation - the StartInfo username, password, domain are what you need to set. However, under IIS you've got some additional lockdown, and the only solution I found on Windows Server 2008 actually involved some Win32 calls and implementations of abstract security libraries. Many of the scenarios you can run into are outlined here: http://asprosys.blogspot.co.uk/2009/03/perils-and-pitfalls-of-launching.html
The sample code from that page shows how to call the library and add Windows Station and Desktop access to a user before starting a process as that user. This was what I needed to get Process.Start to work from IIS, having ruled out UAC, DEP and any other three letter acronym I could think of ;)
I had tried upper solutions but didn't work for me. What I need was, a command should run via Windows Command Prompt as Administration.
Below the codes that didn't work but need to execute:
Process sysProcess = new Process();
sysProcess.StartInfo.FileName = "cmd.exe";
sysProcess.StartInfo.Verb = "runas";
sysProcess.StartInfo.CreateNoWindow = true;
sysProcess.StartInfo.RedirectStandardInput = true;
sysProcess.StartInfo.RedirectStandardOutput = true;
sysProcess.StartInfo.RedirectStandardError = true;
sysProcess.StartInfo.UseShellExecute = false;
sysProcess.Start();
sysProcess.StandardInput.WriteLine("cal.exe");
sysProcess.StandardInput.Flush();
sysProcess.StandardInput.Close();
//localProcess.WaitForExit();
sysProcess.StandardOutput.ReadToEnd();
Solution:
It was an API project and when I Enable SSL from project's properties and debug tab (see, Image 1 and Image 2).
Image 1:
Visual Studio 2019
Image 2:
Visual Studio 2022
This solution will works on any Web App projects.
If you are application is running windows 7 then you can't. basically services running session 0 and user desktop running session 1 so you can't communicate from session 0 to session 1. even if you try to communicate from win logon process (which is used to start the user session for every new user) you can't get some local information (browser settings like local storaage information)
For me what is working is something like this:
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = true;
psi.LoadUserProfile = true;
psi.WorkingDirectory = sender.Server.MapPath("../");// This line solved my problem
psi.FileName = sender.Server.MapPath("../myexecutable.exe");
psi.Arguments = "Myargument1 Myargument2";
Process.Start(psi);
`
I have an ASP.NET website and when I press F5 it automatically attaches to the ASP.NET Development Server, how do I attach to IIS worker process instead when I press F5?
Debug->Attach To Process...
Select the aspnet_wp.exe process from the list.
If you're running IIS > version 5 the process will be w3wp.exe, and there will be one for every app pool (so if you don't know which app pool you're hitting, you'll need to attach to all of them).
open project properties, go to the web tab and choose the option for IIS.
That actually starts an instance of the app in IIS and attaches the debugger. If you only wanted to attach to an existing IIS instance, choose attach to process from the debug menu.
Debug -> Attach to Process from the VS menu.
In order to know to which w3wp.exe process to attach you can use the following command on a 2008 server
c:\%systemroot%\system32\inetsrv\appcmd list wp
While on windows 2003 it is
c:\%systemroot%\system32\cscript iisapp.vbs
For more info see IIS Application pool PID.
However if you have access to the task manager (taskmgr.exe) you can see there directly the name of the process along with the process ID, and in most cases the "user name" column of the process will be the same as the application pool name, (of course you have to set these columns to be visible in task manager in order to view the information).
But note that all of the methods will display only the processes that are currently running, which means that if your particular process has shut down due to idle time you have first to use the site in order to bring the process up in the list.
Also if the application is a "Web Garden" (which has more than one w3wp.exe) then even after attaching to the correct process there is still no guarantee that the breakpoints will be hit, since traffic to the site might be directed to another process.
Also note that if you attach to an application that runs in release mode, it will now instead run in debug mode, which means for example that there will be no timeout limitations (which might be a bit of a problem if you are actually trying to troubleshoot a timeout error).
If you want to attach to a remote process here is the best practice:
Make sure that the firewall is not blocking by opening the relevant ports or completely disabling it (just remember to turn it on again when done).
You should have a windows domain account with administrative privileges on the remote machine or have an account - with the same username and password as the local machine which is running VS - on the remote machine.
On the machine that has VS installed navigate to (Visual Studio Install path)\Microsoft Visual Studio (current version number)\Common7\IDE\Remote Debugger(Remote Machine Version), and copy and paste this folder to the remote machine or share this folder so that it is accessible from the remote machine.
On the remote machine log in as the same user as the local machine (see step 2) from there navigate to the copied or shared folder of step 3, and right click on "msvsmon.exe" and from the context menu select "Run As Administrator".
The Remote Monitor should start up and claim that it started a server usually by the name of (user)#(remote machine) or any other name.
In VS select Debug -> Attach To Process from the menu, leave the transport on "Default" and for the "Qualifier Name" enter the name from step 5.
If everything goes correctly this will bring up the list of processes on the remote machine.
Of course there is a lot more in this subject, and for debugging native code the process might be even simpler, but the steps I have listed here should work in every case.
For farther information you can take a look on http://www.codeproject.com/KB/aspnet/IISRemoteDebugging.aspx or on the MSDN, as well as many posts on this site.
Hope this will help.
Or you can use one of the Attach to IIS plugins to Visual Studio.
My preferred extension is VSCommands (for VS 2010 - 2012 or 2013, but not 2015 yet) or ReAttach (works in 2017).
go to the properties of the web application. Select the "Start Options" section, and change from "USe default web server" to "use custom server". Enter "http://localhost" in the base url.
(assumes VS 2008)