Обработка команды SERVICE_CONTROL_PRESHUTDOWN в .Net Windows сервисе

В Windows Vista и выше появилась новая управляющая команда для сервисов — SERVICE_CONTROL_PRESHUTDOWN (0x0F). Для её использования нужно задать флаг SERVICE_ACCEPT_PRESHUTDOWN (0x100) и обработать в обработчике HandlerEx.

В .Net Framework (если, конечно, вы наследуете свой класс от System.ServiceProcess.ServiceBase) команду SERVICE_CONTROL_PRESHUTDOWN обработать можно через переопределение виртуального метода OnCustomCommand, а вот задать флаг "легальными" способами не получится.

Но можно задать, прописав в конструкторе следующий код:

            Type type = typeof(ServiceBase);

            FieldInfo fi = type.GetField("acceptedCommands", BindingFlags.Instance | BindingFlags.NonPublic);

            int val = (int)fi.GetValue(this);

            fi.SetValue(this, val | 0x100);

 

Теперь нужно только переопределить обработчик и обрабатывать там команду

        protected override void OnCustomCommand(int command)

        {

            if (command == 15)

                EventLog.WriteEntry("OnCustomCommand" + command.ToString());

        }

 

PS. Конечно же так не рекомендуется делать, т.к. Microsoft в любой момент может поменять имя переменной/способ задания статуса/ещё что-нибудь Улыбка

 

Tags: Vista, Windows 2008 Server, SERVICE_ACCEPT_PRESHUTDOWN, SERVICE_CONTROL_PRESHUTDOWN, C#, .Net Framework, Windows Service

Вызов управляемого метода из нативного кода

На rsdn.ru возник вопрос, как вызвать управляемый метод с передачей параметров из неуправляемого кода.

Свой ответ дублирую здесь:


вот набросал на скорую руку (получает два параметра, возвращает 1)

ошибки не проверяются, память подтекает и завершается неправильно

// clrhosttest.cpp : Defines the entry point for the console application.

//

 

#include "stdafx.h"

#include <mscoree.h>

 

#pragma comment(lib, "mscoree.lib")

 

#import <mscorlib.tlb> raw_interfaces_only high_property_prefixes("_get","_put","_putref") rename("ReportEvent", "StdReportEvent") rename("_DSA", "_CLR_DSA")

 

using namespace mscorlib;

 

 

int _tmain(int argc, _TCHAR* argv[])

{

    ICorRuntimeHost *pCorRuntimeHost = NULL;

 

    HRESULT g_hLastError = CorBindToRuntimeEx(L"v2.0.50727", L"wks",

        STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC,

        CLSID_CorRuntimeHost, IID_ICorRuntimeHost,

        (void **)&pCorRuntimeHost);

 

    g_hLastError = pCorRuntimeHost->Start();

 

 

    IUnknown *pUnkDomain = NULL;

    _AppDomain *pAppDomain = NULL;

 

    g_hLastError = pCorRuntimeHost->GetDefaultDomain((IUnknown**)&pUnkDomain);

    g_hLastError = pUnkDomain->QueryInterface(__uuidof(_AppDomain), (void**) &pAppDomain);

 

    _Assembly *pAssembly = NULL;

    BSTR bstrAssemblyString = SysAllocString(L"ClassLibrary1");

   

    g_hLastError = pAppDomain->Load_2(bstrAssemblyString, &pAssembly);

   

    SysFreeString(bstrAssemblyString);

 

    _Type *pType = NULL;

 

    BSTR typeString = SysAllocString(L"ClassLibrary1.Class1");

    VARIANT obj;

    g_hLastError = pAssembly->GetType_2(typeString, &pType);

    g_hLastError = pAssembly->CreateInstance(typeString, &obj);

    SysFreeString(typeString);

 

    VARIANT retVal;

 

    SAFEARRAY* safeArgs = SafeArrayCreateVector(VT_VARIANT, 0, 2);

 

    VARIANT vt;

    VariantInit(&vt);

    vt.vt = VT_BSTR;

    LONG ind = 0;

    vt.bstrVal = SysAllocString(L"568");

    g_hLastError = SafeArrayPutElement(safeArgs, &ind, &vt);

 

    VariantInit(&vt);

    vt.vt = VT_INT;

    vt.intVal = 45;

    ind = 1;

    g_hLastError = SafeArrayPutElement(safeArgs, &ind, &vt);

 

    BSTR methodString = SysAllocString(L"Test");

    g_hLastError = pType->InvokeMember_3(methodString, (BindingFlags)(BindingFlags_InvokeMethod | BindingFlags_Public | BindingFlags_Instance), NULL, obj, safeArgs, &retVal);

    SysFreeString(methodString);

 

    printf("%d", retVal.intVal);

 

 

    return 0;

}

 

// Class1.cs

namespace ClassLibrary1

{

    public class Class1

    {

        public Class1()

        {

        }

 

        public int Test(string s, int k)

        {

            return int.Parse(s) + k;

        }

    }

}

PS. в своем проекте я делаю хост на базе ICLRRuntimeHost, IHostControl и AppDomainManager и вам того же советую


Tags: .Net Framework, Hosting CLR, CorBindToRuntimeEx

Cognitive Technologies открывает исходный код OCR CuneiForm

Сама новость здесь.

Сайт программы тут.

Сейчас они думают под какой лицензией публиковать. Выбирают из GPL/LGPL и MIT/BSD. Одна из основных проблем – подвести всё под наше авторское законодательство.

Скорее всего, отдельно будут лицензированы ядро и фронтенд.

Немного удивляет реакция народа, тут же вылезли красноглазики орущие, что Open Source forever и всё такое. Хотя, на мой взгляд, всё прозаичней: а) OCR уже давно не основной хлеб (если вообще был таковым) Cognitive Technologies; б) с ABBYY очень сложно тягаться.

В любом случае новость хорошая, вот только дипломов/диссератций по распознаванию прибавится…

Tags: Cognitive Technologies, OCR CuneiForm, Open Source

«Грязные хаки» в .Net

 

Отлаживая код (с включенной отладкой по исходникам .Net) наткнулся на следующий код в классе Encoding:

        private static Encoding CreateDefaultEncoding()
        {
            Encoding enc;
            int codePage = Win32Native.GetACP();
 
            // For US English, we can save some startup working set by not calling
            // GetEncoding(int codePage) since JITting GetEncoding will force us to load
            // all the Encoding classes for ASCII, UTF7 & UTF8, & UnicodeEncoding.
            if (codePage == 1252)
                enc = new SBCSCodePageEncoding(codePage);
            else
                enc = GetEncoding(codePage);
 
            return (enc);
        }

 

Tags: .Net Source Code

Исходный код .Net

Прочитав в блоге Scott Guthrie о возможности протестить получение исходного кода .Net не преминул этим воспользоваться.

Через несколько часов получив инструкцию к какому символьному серверу подключатся, попробовал и не получилось 😦

С сервера не то что исходники, но и сами отладочные символы не скачивались.

Попробовал на Win2k3 (до этого был Win2k8 RC0) и стали скачиваться отладочные символы, но не исходники. И VS стал спрашивать уже конкретные cs файлы. Но в целом тоже не получилось, о чём и отправил фидбек.

Tags: .Net Source Code

 

Update:

Разные версии сборок, поэтому я из под Win2k8 ничего и не могу скачать. Осталось только выяснить какая версия pdb и исходников выложена на тестовом сервере.

 

Update2:

Сегодня с утра из под Win2k3 получилось и исходники получить (видимо вчера ещё не выложили). А в Win2k8 проблема действительно оказалась в версиях, заменив свой RC0 mscorlib.dll на Win2k3 mscorlib.dll я таки получил доступ к исходникам mscorlib.dll и из под Win2k8. Shawn Burke подтвердил, что проблема именно в этом:

"Yes, symbols on the server are for the RTM (1433) version, so that was definitely the problem."