IIS and Web Servers
Unload IIS AppPool without Admin Privilege
Gravatar is a globally recognized avatar based on your email address. Unload IIS AppPool without Admin Privilege
  Markus Winhard
  All
  Sep 18, 2021 @ 06:19am

Is it possible to force unloading of an IIS AppPool when I'm not a member of the Administrators group? E.g., by creating some file on disk or by changing the timestamp of some file?

I need this to update a vfp mtdll that's loaded by a asp.net webforms page.

I used to call iisreset but now I have to update my vfp mtdll on a machine where I'm not a member of the Administrators group.

TIA,

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Sep 18, 2021 @ 02:10pm

You can't unload the app pool without admin, but you can unload the application, which should be enough to unload any loaded DLLs including COM DLLs unless they are locked. To do this 'touch' the web.config file. I think you can also change or add a DLL file in the /bin folder which has the same effect.

Note that your account has to have rights to write in the Web folder for this to work too, so you already need to have some elevated security that allows the local account running the site to modify files in the web folder...

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Sep 19, 2021 @ 03:58am

Hi Rick,

just tested your suggestion. I opended web.config in notepad, inserted and removed a space character, then saved it.

Unfortunately my vfp mtdll is still locked. I cannot rename or overwrite it. The "file in use" messagebox says "The action can't be completed because the file is open in IIS Worker Process".

Is there another way to unload/restart/recycle the IIS AppPool?

Can the asp.net webforms page unload/restart/recycle it's own AppPool on purpose?

More ideas?

TIA, Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Sep 19, 2021 @ 10:52am

Only using the IIS Admin objects, which requires admin rights. You could also kill the process, but that too requires Admin rights.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Sep 21, 2021 @ 02:19am

My new idea is a c# windows service that uses these IIS Admin objects. And a c# exe that calls some method of the windows service, that accepts the IIS AppPool to restart as a parameter.

The admins will install the service for me if I show them my source code.

The only sample of using IIS Admin objects I'm aware of is https://west-wind.com/presentations/WebServerConfig/WebServerConfig.htm Using c#, is there a better way in the meantime?

The second problem is I have no idea of windows services and how to call them from an exe with less privilege. 😉

TIA,

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Sep 21, 2021 @ 11:36am

Yeah external process with messaging is the way to go.

.NET has some built in support for services. There's a library called TopShelf that helps with that if you don't want to do it by hand. There are built in classes but you have to handle the service registration yourself.

I think I have an ancient blog post on this (for hosting a SignalR server as a Windows Service):

https://weblog.west-wind.com/posts/2013/Sep/04/SelfHosting-SignalR-in-a-Windows-Service

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Sep 22, 2021 @ 08:15pm

Let's say I have built a windows service using c#. It's installed and running with SYSTEM privilege.

I assume "external process with messaging" is the way how I can call methods on that service from a c# client exe running under a limited user account on the same machine.

Can you please talk a bit more on this?

TIA,

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Sep 23, 2021 @ 12:31pm

I don't think you can use SendMessage to kill Application Pools - they are control by the IIS Host manager that manages the running services. If you hard kill it that manager will just fire up a new one right away again, so in order to do this you need to use the IIS Admin object to shut it down.

Here's a really old post that shows you how you can do this:

A tiny Utility to recycle an IIS Application Pool.

There are also Powershell objects that you can use from the WebAdministration Module:

Import-Module WebAdministration
Stop-WebAppPool "WebConnection"

# Do what you need to

Start-WebAppPool "WebConnection"

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Sep 25, 2021 @ 11:53pm

Nice little code snippet. 😃 Thank you very much!

Let's assume I have my windows service up and running. It's running under the SYSTEM account. It has a method with your code to recycle an AppPool.

Now I have to trigger this method from a c# exe, that's running under a non-privileged interactive user account. How do I do this?

TIA,

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Sep 27, 2021 @ 10:21am

You need some sort of interprocess messaging to make this work. I like Named Pipes for this.

Here are a few blog posts:

Single Instance WPF applications with Named Pipes for forwarding (for .NET)

10 uses for wwDotnetBridge (look for the Named Pipe Section in the PDF) (for FoxPro)

Another - perhaps simpler - option is to use one or more files in a special folder both the service and your app have access to and write a file that the service checks for every few seconds (or whenever). If the file is found it can read the app pool and shut it down. Problem with this is that it's constantly churning at the file system - named pipes will be much quicker.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Dec 8, 2021 @ 12:58pm

Finally found the time to work on this again. I'm using your NamedPipeManager class from Single Instance WPF applications with Named Pipes for forwarding (for .NET)

I can send messages thru the namend pipe as long as server and client are running under the same user account. When the server is running with elevated admin privilege, there's an access denied exception on Connect().

Same behavior when running the server inside a windows service (which is what I need), no matter which user account the service is running under.

How can the server tell windows security that everyone is allowed to write to the name pipe?

TIA, Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Dec 8, 2021 @ 01:59pm

I believe you can set permissions on the pipe CTOR. You might need a different overload.

You may still run into issues though with Windows Firewall in locked down environments but that at least should pop up UI that you can accept/dismiss or take appropriate action via Firewall rules.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Dec 8, 2021 @ 02:21pm

Looks like that's it. Tweaking the NamedPipeServerStream() constructor security makes your NamedPipeManager server usable not only as the current user, but also in a windows service and with elevated privilege. 😃

PipeSecurity security = new PipeSecurity();
SecurityIdentifier networkSid = new SecurityIdentifier(WellKnownSidType.NetworkSid, null);
security.AddAccessRule(new PipeAccessRule(networkSid, PipeAccessRights.FullControl, AccessControlType.Deny));
SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(everyoneSid, PipeAccessRights.ReadWrite, AccessControlType.Allow));

using (var server = new NamedPipeServerStream(
    pipeName as string,
    PipeDirection.InOut,
    1,
    PipeTransmissionMode.Byte,
    PipeOptions.None,
    0,
    0,
    security))

Just in case you want to add this to your sample code, I added the first AddAccessRule() to restrict access from the local network. This one is not neccessary.

Thank you very much!

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Dec 8, 2021 @ 03:40pm

How do I write to the named pipe form VFP? Tried code from VfpX, but it doesn't work reliable.

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Dec 8, 2021 @ 06:30pm

wwDotnetBridge or create a small .NET component that does it.

There's an example in this SW Fox session white paper:

10 use cases for wwDotnetBridge

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Dec 10, 2021 @ 06:54am

In this special situation I'd rather not depend on COM or external libraries. I've found a way to write to the Named Pipe created in C# from VFP.

LPARAMETERS cPipeName, cMessage
LOCAL hPipe, nPipeMode, nResult, nBytesWritten
hPipe = CreateFile(cPipeName, BITOR(GENERIC_WRITE, GENERIC_READ), BITOR(FILE_SHARE_WRITE, FILE_SHARE_READ), 0, OPEN_EXISTING, 0, 0)
nPipeMode = BITOR(PIPE_READMODE_BYTE, PIPE_WAIT)
nResult = SetNamedPipeHandleState(hPipe, @nPipeMode, 0, 0)
nBytesWritten=0
nResult = WriteFile(hPipe, @cMessage, LEN(cMessage), @nBytesWritten, 0)
CloseHandle(hPipe)

I left out #DEFINEs, API declarations and error handling to keep the code readable. 😉

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Markus Winhard
  Jul 23, 2022 @ 07:39am

Hi Rick,

your solution works way better than our old solutions did. And it's 100% stable. 😃 Thank you very much again for all your ideas and code.

Therefore we want to install our Windows service at all customers' machines. But the C# code in the service requires that IIS 6 Metabase Compatibility is installed.

root = new DirectoryEntry("IIS://LOCALHOST/W3SVC/AppPools/" + appPoolName);
root.Invoke("Recycle");

Our installer is written in VFP9. Is there a way to install IIS 6 Metabase Compatibility from VFP code that runs with admin privilege?

TIA,

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Jul 23, 2022 @ 04:32pm

Not without Admin rights.

With Admin rights you can use Powershell:

Enable-WindowsOptionalFeature -Online -FeatureName IIS-IIS6ManagementCompatibility
Enable-WindowsOptionalFeature -Online -FeatureName IIS-Metabase

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Markus Winhard
  Rick Strahl
  Jul 24, 2022 @ 04:34am

Hi Rick,

thank you for the idea. Just saw that I can query if it's already installed, too. 😃

Get-WindowsOptionalFeature -Online -FeatureName IIS-IIS6ManagementCompatibility

That's great for interactive use. But how do I call this from vfp code and check the result?

Any ideas?

TIA,

Markus

Gravatar is a globally recognized avatar based on your email address. re: Unload IIS AppPool without Admin Privilege
  Rick Strahl
  Markus Winhard
  Jul 24, 2022 @ 10:21am

These are Powershell applets so you'd have to shell out and run powershell with the command.

I'm also not sure if you can query these values without Admin privileges.

There are equivalent dism commands that will also do this that you can directly invoke instead of going through Powershell, but you have to look up the syntax.

Double checked and unfortunately even the read commands require Admin privileges to run...

Maybe via WMI or if you can figure out where in the registry it writes out what components are installed you can check that way.

Don't really understand why this is useful though: Regardless of what you do using the IIS Admin objects (Metabase) requires admin rights, so it's not like you could do this without elevation anyway.

+++ Rick ---

© 1996-2022