Recycle IIS7 Application Pool with C# - c#

I have read through all of the threads on here on how to do this programmatically but I can not get it to work. A little background on how my code works.
You log in to the site and choose App Pool monitor. There is a drop down that allows you to choose the server you are looking for. I have a stored procedure that will pull the app pools from that server and display them in a grid. I then have this code that I am testing:
while (rdr.Read())
{
string appPool = rdr["AppPoolName"].ToString();
string permission = rdr["Permission"].ToString();
string serverIP = rdr["ServerIP"].ToString();
if (permission == "E")
{
lblErrorStart.Visible = false;
using (var serverManager = ServerManager.OpenRemote(serverIP))
{
ApplicationPool poolName = serverManager.ApplicationPools[appPool];
poolName.Stop();
lblSuccess.Visible = true;
}
}
else
{
lblErrorStart.Visible = true;
}
}
The reader I have created pools the AppPoolName, ServerIP, and Permission from SQL.
I use a DirectoryEntry for IIS6 and it works great but it will not work for IIS7.
using (DirectoryEntry w3svc = new DirectoryEntry(string.Format("IIS://" + serverIP + "/W3SVC/AppPools/" + appPool)))
{
w3svc.Invoke("Recycle", null);
lblSuccess.Visible = true;
}
Any help would be appreciated.
EDIT: The exception I get with the Directory Services is System.Runtime.InteropServices.COMException

How do you know it's not working? How would you really know if the app pool has been recycled or not? We had this issue several months ago and tried to figure out a way to see if it's really recycling or not. We turned on tracing in IIS but it didn't log any messages, which we thought meant it wasn't working. What we did then, was create a dummy service and a console app that would ping that service every 0.5 a second. Then, we recycled the AppPool that was hosting the service, and oddly enough, we saw a delay in the ping response, which meant it actually did recycle.
Try changing w3svc.Invoke("Recycle", null); to w3svc.Invoke("Stop", null);. If that stops the AppPool, then you can be almost sure that Recycle will work just fine. Note that invoking a Recycle operation does not block, so if your code depends on the AppPool to be up and running after a recycle, you need to check for its state before continuing.
Edit:
Give this a shot:
In the Windows Features window, make sure IIS 6 Management Compatibility is enabled.
Open up the Start menu and type in "services", then press Enter. Make sure IIS Admin Service is running. Now try to invoke the command and see if it works.

Related

how to use Microsoft.Web.Administration properly to start an application pool from a web page?

I was tasked to find a way to restart an application pool from a web page. The IIS is hosted by our own IT department, so any security settings needed will be changed if necessary.
I am using Microsoft.Web.Administration.dll and trying this for my local IIS (7.5):
ServerManager serverManager = new ServerManager();
ApplicationPoolCollection applicationPoolCollection = serverManager.ApplicationPools;
foreach (ApplicationPool applicationPool in applicationPoolCollection)
{
appPoolNames.Add(applicationPool.Name);
// If the applicationPool is stopped, restart it.
if (applicationPool.State == ObjectState.Stopped)
{
applicationPool.Start();
}
}
// CommitChanges to persist the changes to the ApplicationHost.config.
serverManager.CommitChanges();
If I put this logic in a winform and run as local admin, my app pool in local IIS will be started. However, if I put the same logic in a webpage, it fails with error at this line with error:
if (applicationPool.State == ObjectState.Stopped)
Exception: System.ComponentModel.Win32Exception: Access is denied
I think this is due to security, but I already give a local admin user to my app pool. Is there a way to achieve this in a web page?
I assume the web page is not in the same application pool as the one you are trying to restart, which would not be a good idea (because the web page would suddenly lose its process host). So assuming it is a different application pool, then it is the identity of the web page's application pool which matters - this will need to have permissions to restart the target application pool.

link app with windows service like shut down so that process never end?

link app with windows process so that when user terminated or end the process it says used by another process and also need to insert it into system file like shutdown file using c sharp so that my app never end or terminates
i tried that material but not usefull
this.ShowInTaskbar = false;
I also tried that code in click:
WindowsImpersonationContext ctx = null;
if (!WindowsIdentity.GetCurrent().IsSystem)
{
ctx = WindowsIdentity.Impersonate(System.IntPtr.Zero);
}
string thisuser = WindowsIdentity.GetCurrent().Name;
But have a look at image it is still present in process, what I want is that my process never stops.
what I want is that my process never stops.
To ensure that your process is always running and is started when Windows boots it's easiest to create a windows service instead. It will probably still show up somewhere in task manager and could be killed manually by the user. But windows will try to keep it running.
How to create a service:
https://msdn.microsoft.com/en-us/library/zt39148a(v=vs.110).aspx
And if you need other programs to communicate with your service I find it easy to use a WCF service instead.
https://msdn.microsoft.com/en-us/library/bb386386.aspx

How to get name of current IIS app pool programatically, not ActiveDirectory

I am running into a situation with my Web API where the only option I can think of right now is to recycle the app pool while I dig through and find out the real cause of the problem. In the mean time I need a way to recycle the app pool after a condition is met. I thought I found the solution here: http://www.codeproject.com/Tips/780076/Recycle-Application-Pool-s-in-IIS-Server-Using-C
// Needs Microsoft.Web.Administration NuGet
public static void RecycleAppPool()
{
ServerManager serverManager = new ServerManager();
ApplicationPool appPool = serverManager.ApplicationPools["Test_AppPool"];
if (appPool != null)
{
if (appPool.State == ObjectState.Stopped)
{
appPool.Start();
}
else
{
appPool.Recycle();
}
}
}
There are 2 problems with this:
1) I am getting an error when trying to run this code: "Filename: redirection.config Error: Cannot read configuration file due to insufficient permissions" I am getting this error in localhost, but I assume I'll also get it in my hosted Azure environment? Can I get around this?
2) The second problem is I may not know what the name of the app pool is, so I need to figure that out programatically. I've found something like this:http://www.logue.com.ar/blog/2008/02/find-and-recycle-current-application-pool-programmatically-for-iis-6/ but that uses ActiveDirectory and I will not have the login details for the AD at my host... at least not that I know of... again this is hosted in an Azure Website.
So the question is, how do I get the name and of the current app pool in Azure and recycle it?
As a side note, I'm doing this in my Global.asax in the Application_EndRequest after Flushing the current Response. Is there a better way?
So far the closest I could find is (found here: https://stackoverflow.com/a/1081902/550975)
HttpRuntime.UnloadAppDomain();
which just restarts the app, not the app pool. This may however serve my purposes... we'll see. I'm still hoping someone has the actual answer, and I will mark it as the Accepted Answer if such a thing ever occurs.

Windows Server 2008 R2 remote service installation: How to execute program after RDP Connection in C#?

I want to remotely start a program on a Win2k8R2 Server, Web Edition, which installs Windows services.
Service installation is afaik only possible if there's a "screen>0" - that means a user must be logged in to do that (I read somewhere that the login dialog window is representing "screen 0", correct me if I'm wrong here).
So to get a screen, I open up a RDP connection and then trigger the setup exe which installs everything silently.
I made it run on Windows Server 2003 already. On 2008 R2 though it doesn't work anymore.
I assume there may be some security policy or even completely other technique to achieve what I want.
Here's the code:
this.axMsRdpClient7 = new AxMSTSCLib.AxMsRdpClient7();
// ... some GUI stuff happens here..
axMsRdpClient7.Server = hostname;
axMsRdpClient7.UserName = username;
axMsRdpClient7.AdvancedSettings.Compress = -1;
axMsRdpClient7.AdvancedSettings2.DisplayConnectionBar = true;
axMsRdpClient7.AdvancedSettings7.ClearTextPassword = userpassword;
axMsRdpClient7.AdvancedSettings2.EncryptionEnabled = -1;
// Set start program information. vvv THIS IS NOT GOING TO BE EXECUTED vvv
axMsRdpClient7.SecuredSettings.StartProgram = executablePath + " " + arguments;
axMsRdpClient7.SecuredSettings.WorkDir = workingDirectory;
// ... here I'm attaching some events like OnDisconnect...
// Start connection
axMsRdpClient7.Connect();
// Now the startprogram should be executed, but doesn't.
// (at this time its ok that I have to manually log off to reach disconnect. Except you have a better idea to disconnect after startprogram finishes)
while (axMsRdpClient7.Connected != 0)
{
Application.DoEvents();
Thread.Sleep(1);
}
// End connection
axMsRdpClient7.Disconnect();
Anyone knows why StartProgram is not being executed? I don't have any error, it just doesn't start.
Or anyone knows a better method to remotely install services?
Thanks in advance!
You should not need to call Disconnect(). When using the StartProgram approach you are using what used to be called the 'Alternate Shell' approach. This means that when the program terminates, the session is automatically closed/disconnected.
See http://msdn.microsoft.com/en-us/library/ms861803.aspx, search for 'AlternateShell'.
I recently wrote an ActiveX library that initiates an Windows 2008 RDS session using the StartProgram parameter. Once the user closes the program that is started automatically when the RDS session starts, the RDS session automatically terminates. So you shouldn't need the looping mechanism nor the call to Disconnect() with your approach.
In my code, for user credentials, I specify the domain as well. Is your user account a Windows Domain account? If so you probably need to specify that as well.
Additionally, I set the following parameters:
// server authentication is required - set Auth level to 2
AdvancedSettings7.AuthenticationLevel := 2;
// use CredSsp if the client supports it.
AdvancedSettings7.EnableCredSspSupport := True;
// setting PublicMode to false allows the saving of credentials, which prevents
// prompting the user to log in
AdvancedSettings7.PublicMode := False;
HTH

How to start a process from an IIS hosted WCF service?

I would like to run a process from an intranet client on the WCF service side. In my case a client asks a server to create a new process on the server's machine under the provided credentials. WCF service is hosted on IIS 7.5 and I start a process using this code
var processInfo = new ProcessStartInfo("C:\\Windows\\System32\\notepad.exe")
{
UserName = "some user",
Password = MakeSecureString("some password"),
UseShellExecute = false,
LoadUserProfile = true
};
Process process = Process.Start(processInfo);
This code works if I host WCF service as a self-hosted console application running under admin user and I see the notepad started under another user. It fails on IIS with no exception, but process is immediately terminated
process.HasExited = true;
process.ExitCode = -1073741502;
On IIS WCF application is running under the user with admin rights and has got full trust defined in web.config. I cannot use self hosted application as it doesn't support easy continuous delivery (like WebDeploy with IIS web farms).
Q: How can I start a process on a server side from WCF service hosted on IIS?
EDIT:
I stumbled upon this post, with similar issues and I tried all the methods there, including all possible variations for Process.Start and P/Invoke with CreateProcessWithLogonW and CreateProcessAsUser I also tried granting additional permissions to users. Non of this would work with the error messages identical to the ones the guy had posted.
Oleksii, the point is that if you host the WCF service in a console application, there is a windows session (a user logged in and Windows Explorer loaded) for that user and the notepad is opened and shown for that user, so you see it in the UI.
when you host your WCF service in IIS, being a server, IIS requires and allows no user interaction and works also if no user is logged in; in that context there is no UI to host your notepad or other UI enabled applications, you could execute a process for elaboration or other batch jobs but not render a windows UI application, because Windows Explorer is not loaded for you and there is no place to render your process's UI.
here is what I use to call GnuPGP to do encryption. How does your setup compare?
private int ExecuteCommand(string arguments, string passPhrase, int timeout)
{
Process processObject;
ProcessStartInfo pInfo = new ProcessStartInfo(_executablePath, arguments);
pInfo.CreateNoWindow = true;
pInfo.UseShellExecute = false;
pInfo.RedirectStandardInput = true;
pInfo.RedirectStandardOutput = true;
pInfo.RedirectStandardError = true;
processObject = Process.Start(pInfo);
if (!string.IsNullOrEmpty(passPhrase))
{
processObject.StandardInput.WriteLine(passPhrase);
processObject.StandardInput.Flush();
}
string result = processObject.StandardOutput.ReadToEnd();
string error = processObject.StandardError.ReadToEnd();
if (!processObject.WaitForExit(timeout))
{
throw new TimeoutException("GnuPG operation timeout. Waited " + timeout + " milliseconds ");
}
int exitcode = processObject.ExitCode;
Error = error;
Output = result;
return exitcode;
}
There's an apppool setting to make sure it loads the user profile.
loadUserProfile Optional Boolean attribute.
Specifies whether IIS loads the user profile for the application pool identity. Setting
this value to false causes IIS to revert to IIS 6.0 behavior. IIS 6.0 does not load the
user profile for an application pool identity.
The default value is false.
That along with being a domain user as the identity with enough permissions might work?? I know that at a minimum the user will need a user profile.
That said, it's a little bit of an odd architecture. It seems like a better arch would be to have a persistent process like a windows service that the site communicates with but I'm not sure what your constraints are.
Hope that helps.

Categories

Resources