Какой-либо способ получить доступ к кэшу ядра IIS из ASP.NET?

Python.

, Хотя странный путь Python имеет дело с объемом, был упомянут, худшее последствие его, я чувствую, то, что это допустимо:

import random

def myFunction():

    if random.choice(True, False):
        myString = "blah blah blah"

    print myString

таким образом, в, если блок является тем же объемом как остальная часть функции, означая, что объявление переменной может произойти внутри condional ответвления и быть получено доступ за пределами них. Большинство языков или предотвратит Вас делающий это или по крайней мере предложит Вам некоторый строгий режим.

Эта функция будет иногда успешно выполняться и иногда выдавать исключение. Хотя это - изобретенный пример, это могло привести к некоторым тонким проблемам.

6
задан Robert Claypool 28 December 2015 в 21:21
поделиться

2 ответа

Да, можно программно перечислять и удалять элементы из кэша ядра IIS.

Предостережения:

  • нетривиальный синтаксический анализ текста, необходимый для перечисления
  • много уродливых P / Invoke, необходимых для удаления
  • Кроме того, вам понадобится как минимум средний уровень доверия (и, возможно, полное доверие) для выполнения ниже.
  • Удаление не будет работать в режиме интегрированного конвейера IIS.
  • Перечисление, вероятно, не будет работать в IIS6

Перечисление:

Единственный известный мне способ перечисления кэша ядра IIS - это приложение командной строки, доступное в IIS7 и более поздних версиях (хотя вы могли бы скопировать вспомогательную DLL NETSH из V7 в систему V6 - не пробовали).

netsh http show cachestate

См. Документация MSDN по команде show cachestate для получения более подробной информации. Вы можете превратить это в «API» путем выполнения процесса и анализа результатов текста.

Важное предупреждение: я никогда не видел, чтобы это приложение командной строки действительно возвращало что-либо на моем сервере, даже для приложений, работающих в классическом режиме. Не знаю почему, но приложение действительно работает, как я могу видеть из других сообщений в Интернете. (например, http://chrison.net/ViewingTheKernelCache.aspx )

Если у вас ужасная аллергия на создание процесса и вы чувствуете себя амбициозно, команды NETSH реализуются библиотеками DLL с документированным интерфейсом Win32, поэтому вы может написать код, который притворяется NETSH.exe и напрямую вызывает вспомогательную DLL-библиотеку IIS NETSH. Вы можете использовать документацию в MSDN в качестве отправной точки для этого подхода. Предупреждение: олицетворение NETSH нетривиально сложно, поскольку интерфейс двусторонний: NETSH вызывает DLL, а DLL - обратно в NETSH. И вам все равно придется анализировать вывод текста, поскольку интерфейс NETSH основан на тексте, а не на объектах, как PowerShell или WMI. Если бы это был я, я бы просто создал процесс NETSH. ; -)

Возможно, что оснастка IIS7 PowerShell может поддерживать эту функцию в будущем (что означает более легкий программный доступ, чем описанные выше взломы), но AFAIK только NETSH поддерживает эту функцию сегодня.

Недействительность :

У меня для вас хорошие и плохие новости.

Хорошие новости: как только вы узнаете URL-адрес элемента, который хотите извлечь из кеша ядра IIS, для его удаления в IIS6 и выше доступен Win32 API. Это можно вызвать из C # через P / Invoke (сложнее) или путем помещения вызова в управляемую DLL-оболочку C ++. Подробнее см. HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK в MSDN.

Я попытался ввести требуемый код (прилагается ниже). Предупреждение: это уродливо и непроверено - это не приводит к сбою моего IIS, но (см. Выше) я не могу понять, как заставить работать перечисление кеша, поэтому я не могу на самом деле вызвать его с действительным URL-адресом для извлечения из кеша. Если вы можете заставить работать перечисление, то подключение действительного URL (и, следовательно, тестирование этого кода) должно быть простым.

Плохая новость:

  • как вы можете догадаться из примера кода, он не будет работать в режиме интегрированного конвейера IIS7, только в классическом режиме (или IIS6, конечно), где ASP.NET работает как ISAPI и имеет доступ к функциям ISAPI
  • возиться с частными полями - это серьезный взлом, и он может сломаться в новой версии
  • P / Invoke трудно справиться и требует (я считаю) полного доверия

Вот код:

using System;
using System.Web;
using System.Reflection;
using System.Runtime.InteropServices;

public partial class Test : System.Web.UI.Page
{
    /// Return Type: BOOL->int
    public delegate int GetServerVariable();

    /// Return Type: BOOL->int
    public delegate int WriteClient();

    /// Return Type: BOOL->int
    public delegate int ReadClient();

    /// Return Type: BOOL->int
    public delegate int ServerSupportFunction();

    /// Return Type: BOOL->int
    public delegate int EXTENSION_CONTROL_BLOCK_GetServerVariable();

    /// Return Type: BOOL->int
    public delegate int EXTENSION_CONTROL_BLOCK_WriteClient();

    /// Return Type: BOOL->int
    public delegate int EXTENSION_CONTROL_BLOCK_ReadClient();

    /// Return Type: BOOL->int
    public delegate int EXTENSION_CONTROL_BLOCK_ServerSupportFunction();

    public static readonly int HSE_LOG_BUFFER_LEN = 80;

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
    public struct EXTENSION_CONTROL_BLOCK
    {
        /// DWORD->unsigned int
        public uint cbSize;

        /// DWORD->unsigned int
        public uint dwVersion;

        /// DWORD->unsigned int
        public uint connID;

        /// DWORD->unsigned int
        public uint dwHttpStatusCode;

        /// CHAR[HSE_LOG_BUFFER_LEN]
        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 80 /*HSE_LOG_BUFFER_LEN*/)]
        public string lpszLogData;

        /// LPSTR->CHAR*
        public System.IntPtr lpszMethod;

        /// LPSTR->CHAR*
        public System.IntPtr lpszQueryString;

        /// LPSTR->CHAR*
        public System.IntPtr lpszPathInfo;

        /// LPSTR->CHAR*
        public System.IntPtr lpszPathTranslated;

        /// DWORD->unsigned int
        public uint cbTotalBytes;

        /// DWORD->unsigned int
        public uint cbAvailable;

        /// LPBYTE->BYTE*
        public System.IntPtr lpbData;

        /// LPSTR->CHAR*
        public System.IntPtr lpszContentType;

        /// EXTENSION_CONTROL_BLOCK_GetServerVariable
        public EXTENSION_CONTROL_BLOCK_GetServerVariable GetServerVariable;

        /// EXTENSION_CONTROL_BLOCK_WriteClient
        public EXTENSION_CONTROL_BLOCK_WriteClient WriteClient;

        /// EXTENSION_CONTROL_BLOCK_ReadClient
        public EXTENSION_CONTROL_BLOCK_ReadClient ReadClient;

        /// EXTENSION_CONTROL_BLOCK_ServerSupportFunction
        // changed to specific signiature for invalidation callback
        public ServerSupportFunction_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK ServerSupportFunction;
    }
    /// Return Type: BOOL->int
    ///ConnID: DWORD->unsigned int
    ///dwServerSupportFunction: DWORD->unsigned int
    ///lpvBuffer: LPVOID->void*
    ///lpdwSize: LPDWORD->DWORD*
    ///lpdwDataType: LPDWORD->DWORD*
    [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
    public delegate bool ServerSupportFunction_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK(
        uint ConnID, 
        uint dwServerSupportFunction, // must be HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK
        out Callback_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK lpvBuffer, 
        out uint lpdwSize, 
        out uint lpdwDataType);

    public readonly uint HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK = 1040;

    // typedef HRESULT (WINAPI * PFN_HSE_CACHE_INVALIDATION_CALLBACK)(WCHAR *pszUrl);
    [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
    public delegate bool Callback_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK(
        [MarshalAs(UnmanagedType.LPWStr)]string url);

    object GetField (Type t, object o, string fieldName)
    {
        FieldInfo fld = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
        return fld == null ? null : fld.GetValue(o);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        // first, get the ECB from the ISAPIWorkerRequest
        var ctx = HttpContext.Current;
        HttpWorkerRequest wr = (HttpWorkerRequest) GetField(typeof(HttpContext), ctx, "_wr");
        IntPtr ecbPtr = IntPtr.Zero;
        for (var t = wr.GetType(); t != null && t != typeof(object); t = t.BaseType)
        {
            object o = GetField(t, wr, "_ecb");
            if (o != null)
            {
                ecbPtr = (IntPtr)o;
                break;
            }
        }

        // now call the ECB callback function to remove the item from cache
        if (ecbPtr != IntPtr.Zero)
        {
            EXTENSION_CONTROL_BLOCK ecb = (EXTENSION_CONTROL_BLOCK)Marshal.PtrToStructure(
                ecbPtr, typeof(EXTENSION_CONTROL_BLOCK));
            uint dummy1, dummy2;

            Callback_HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK invalidationCallback;
            ecb.ServerSupportFunction(ecb.connID,
                    HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK,
                    out invalidationCallback,
                    out dummy1,
                    out dummy2);

            bool success = invalidationCallback("/this/is/a/test");
        }
    }
}
11
ответ дан 9 December 2019 в 22:37
поделиться

Из предоставленной вами ссылки на обсуждение видно, что метод или свойство кеша существует, но является защищенным или частным, поэтому вы не можете получить к нему доступ.

Обычно вам следует избегать использования методов, которые не являются частью общедоступного API, но если вы хотите получить к ним доступ, используйте Reflection. С помощью отражения вы можете вызывать частные методы и получать или устанавливать частные свойства и поля.

0
ответ дан 9 December 2019 в 22:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: