windows service (C#) dll (c++)
От: mrjeka Россия  
Дата: 24.09.09 09:43
Оценка:
Привет всем.
Такая вот проблема.

Есть кусок кода(C#), который работает с dll(C++)
в dll передается массив объектов для инициализации.

Если все это дело работает в консольном приложении, то все норм, но если через win-service,то массивы не инициализируются в dll. Такое ощущение что метод из dll(c++) просто не вызывается.
Вызов сделан через DllImport

Кто-нибудь может разъяснить, в чем косяк?

ps пробовал запускать службу под разными аккаунтами, в том числе и под админом.
Re: windows service (C#) dll (c++)
От: x64 Россия http://x64blog.name
Дата: 24.09.09 12:28
Оценка:
M>Если все это дело работает в консольном приложении, то все норм, но если через win-service,то массивы не инициализируются в dll. Такое ощущение что метод из dll(c++) просто не вызывается.

Ну чудес-то не бывает, может быть, действительно не вызывается?

M>Кто-нибудь может разъяснить, в чем косяк?


Код DLL показывай.
JID: x64j@jabber.ru
Re[2]: windows service (C#) dll (c++)
От: Аноним  
Дата: 24.09.09 13:43
Оценка:
Здравствуйте, x64, Вы писали:
x64>Ну чудес-то не бывает, может быть, действительно не вызывается?
x64>Код DLL показывай.


BOOL Ptks::ObjectRead(InfoObjectStruct *pInfoObjectStruct, int dObjectStart, int dObjectNum)
{
    int i;
    InfoObjectStruct m_InfoObjectStruct;//Это и есть структура, она воспроизведена в C# для передачи сюда.
    //Открываю файл в памяти
    if( FileOpen() ) 
    {
//        memcpy(pInfoObjectStruct, (LPSTR)lpFileMap[0] + sizeof(PtksFileStruct), sizeof(InfoObjectStruct) * dObjectNum);
        for( i = dObjectStart; i < (dObjectStart+dObjectNum); i++ )
        {
            //Считываю данные из отображенного файла
            memcpy(&m_InfoObjectStruct, (LPSTR)lpFileMap[dServerNum] + sizeof(PtksFileStruct) + sizeof(InfoObjectStruct)*i,               sizeof(InfoObjectStruct));
            //Записываю данные в объект
            memcpy((LPSTR)pInfoObjectStruct + sizeof(InfoObjectStruct)*i, &m_InfoObjectStruct, sizeof(InfoObjectStruct) );
        }        
        //Освобождаю идентификаторы
        FileClose();
        return TRUE;
    }
    return FALSE;
}


Ну в принципе вот метод из dll на С++. Это вообще не наша библиотека (стороннего разработчика).
Вообще не понятно, почему из консоли работает а из службы нет?
Re[3]: windows service (C#) dll (c++)
От: x64 Россия http://x64blog.name
Дата: 24.09.09 14:50
Оценка: +1
А>Ну в принципе вот метод из dll на С++.

Есть подозрения на тему функции FileOpen(). Её код тоже давай.
JID: x64j@jabber.ru
Re[3]: windows service (C#) dll (c++)
От: Slider_spb Россия  
Дата: 24.09.09 15:06
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Вообще не понятно, почему из консоли работает а из службы нет?
Попробуйте службу запустить из под того же аккаунта, под которым работает из консоли...
Re[3]: windows service (C#) dll (c++)
От: Pavel Dvorkin Россия  
Дата: 25.09.09 04:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вообще не понятно, почему из консоли работает а из службы нет?


Проверь права доступа к файлу. Разрешен ли он для той учетной записи, под которой выполняется сервис ?
With best regards
Pavel Dvorkin
Re[4]: windows service (C#) dll (c++)
От: mrjeka Россия  
Дата: 25.09.09 06:44
Оценка:
Здравствуйте, x64, Вы писали:

x64>Есть подозрения на тему функции FileOpen(). Её код тоже давай.



BOOL Ptks::FileOpen()
{
    hEventTermination[dServerNum] = OpenEvent(EVENT_ALL_ACCESS, FALSE, lpEventTerminationName[dServerNum]);
     if(hEventTermination[dServerNum] == NULL) 
    {
        dLastErrorCode = 1;
        return FALSE;
    }
    //
    hEventConfig[dServerNum] = OpenEvent(EVENT_ALL_ACCESS, FALSE, lpEventConfigName[dServerNum]);
    // Если открыть не удалось, выводим код ошибки
    if(hEventConfig[dServerNum] == NULL)
    {
        CloseHandle(hEventTermination[dServerNum]);
        dLastErrorCode = 2;
        return FALSE;
    }
    hEventReceive[dServerNum] = OpenEvent(EVENT_ALL_ACCESS, FALSE, lpEventReceiveName[dServerNum]);
    // Если открыть не удалось, выводим код ошибки
    if(hEventReceive[dServerNum] == NULL)
    {
        CloseHandle(hEventTermination[dServerNum]);
        CloseHandle(hEventConfig[dServerNum]);
        dLastErrorCode = 2;
        return FALSE;
    }
    //
    hEventTransmite[dServerNum] = OpenEvent(EVENT_ALL_ACCESS, FALSE, lpEventTransmiteName[dServerNum]);
    // Если открыть не удалось, выводим код ошибки
    if(hEventTransmite[dServerNum] == NULL)
    {
        CloseHandle(hEventTermination[dServerNum]);
        CloseHandle(hEventConfig[dServerNum]);
        CloseHandle(hEventReceive[dServerNum]);
        dLastErrorCode = 2;
        return FALSE;
    }
    // Открываю объект-отображение
    hFileMapping[dServerNum] = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, lpFileShareName[dServerNum]);
    // Если открыть не удалось, выводим код ошибки
    if(hFileMapping[dServerNum] == NULL)
    {
        CloseHandle(hEventTermination[dServerNum]);
        CloseHandle(hEventConfig[dServerNum]);
        CloseHandle(hEventReceive[dServerNum]);
        CloseHandle(hEventTransmite[dServerNum]);
        dLastErrorCode = 2;
        return FALSE;
    }
    // Выполняю отображение файла на память.
    // В переменную lpFileMap будет записан указатель на отображаемую область памяти
    lpFileMap[dServerNum] = MapViewOfFile(hFileMapping[dServerNum], FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    // Если выполнить отображение не удалось, выводим код ошибки
    if(lpFileMap[dServerNum] == 0)
    {
        CloseHandle(hEventTermination[dServerNum]);
        CloseHandle(hEventConfig[dServerNum]);
        CloseHandle(hEventReceive[dServerNum]);
        CloseHandle(hEventTransmite[dServerNum]);
        CloseHandle(hFileMapping[dServerNum]);
        dLastErrorCode = 2;
        return FALSE;
    }
    dLastErrorCode = 0;
    return TRUE;
}


Вообще файл открывается только в памяти. Никакого физического файла на диске не существует.

Просто объясните плиз, почему из консоли пашет, а из службы нет. Если это права доступа, то служба же запускается под админом
Re[4]: windows service (C#) dll (c++)
От: mrjeka Россия  
Дата: 25.09.09 06:45
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>Проверь права доступа к файлу. Разрешен ли он для той учетной записи, под которой выполняется сервис ?


Файл существует только в памяти. Физически на диске его нет. Служба запускается под тем же аком что и консоль (ну т.е. под админом)
Re[3]: windows service (C#) dll (c++)
От: pumpurumer  
Дата: 25.09.09 07:26
Оценка:
логи чтоли какиенибуть в сервис встройте, коли есть код dll тожет туда логи. смотрите что происходит... ну или поставить в onStart(не помню как он называется по научному) в самое начало thread.sleep(10000); и за это времся подцепится отладчиком студии к сервису и посмотреть что происходит.
Re[5]: windows service (C#) dll (c++)
От: Pavel Dvorkin Россия  
Дата: 25.09.09 07:53
Оценка:
Здравствуйте, mrjeka, Вы писали:

M>Здравствуйте, Pavel Dvorkin, Вы писали:



PD>>Проверь права доступа к файлу. Разрешен ли он для той учетной записи, под которой выполняется сервис ?


M>Файл существует только в памяти. Физически на диске его нет.


А это что ? Ну не файл, так мэппинг, все равно права доступа.

hFileMapping[dServerNum] = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, lpFileShareName[dServerNum]);
// Если открыть не удалось, выводим код ошибки

>Служба запускается под тем же аком что и консоль (ну т.е. под админом)


Уверен ? А не под SYSTEM ?

В общем, совет простой. Вставь в FileOpen вывод в лог и посмотри, что не сработало.
With best regards
Pavel Dvorkin
Re[6]: P.S.
От: Pavel Dvorkin Россия  
Дата: 25.09.09 07:55
Оценка:
и при выводе в лог выводи результат вызова функции GetLastError().
With best regards
Pavel Dvorkin
Re[5]: windows service (C#) dll (c++)
От: x64 Россия http://x64blog.name
Дата: 25.09.09 10:22
Оценка:
M>Просто объясните плиз, почему из консоли пашет, а из службы нет. Если это права доступа, то служба же запускается под админом

Спокойно давай, без паники. Теперь напиши чему равны вот эти переменные:

lpEventTerminationName
lpEventConfigName
lpEventReceiveName
lpEventTransmiteName
lpFileShareName

И напиши ещё какая ОС. И кроме того, раз уж у тебя есть доступ к исходникам этого всего, ну так напихай туда ещё вызовов OutputDebugString(_T("hello")) где ошибка может быть, и смотри результат в DebugView, — сразу всё понятно станет.
JID: x64j@jabber.ru
Re[5]: windows service (C#) dll (c++)
От: Мизантроп  
Дата: 25.09.09 13:50
Оценка:
Здравствуйте, mrjeka, Вы писали:

Ну а сами эвенты и MMF конечно-же создаются с защитой по умолчанию, то есть с NULL вместо дескриптора защиты. И как результат — ERROR_ACCESS_DENIED. И зачем Вам EVENT_ALL_ACCESS при откратии эвента? Возьмите за правило никогда не запрашивать лишних прав, и не назначать, кстати, тоже.

А это dLastErrorCode = 1; вместо GetLastError называется "Сам себе злобный буратино". Вы же сами от себя спрятали причину сбоя, потому и локализовать проблему не смогли.
"Нормальные герои всегда идут в обход!"
Re[4]: windows service (C#) dll (c++)
От: Аноним  
Дата: 25.09.09 13:54
Оценка:
Здравствуйте, pumpurumer, Вы писали:

P>логи чтоли какиенибуть в сервис встройте, коли есть код dll тожет туда логи. смотрите что происходит... ну или поставить в onStart(не помню как он называется по научному) в самое начало thread.sleep(10000); и за это времся подцепится отладчиком студии к сервису и посмотреть что происходит.


Ну вобще то для этого есть программные брикпоинты
Debugger.Break();
Re[6]: windows service (C#) dll (c++)
От: x64 Россия http://x64blog.name
Дата: 25.09.09 14:57
Оценка:
М>Ну а сами эвенты и MMF конечно-же создаются с защитой по умолчанию, то есть с NULL вместо дескриптора защиты. И как результат — ERROR_ACCESS_DENIED.

Полагаю всё же, что проблема у автора не в нехватке прав, ведь он же сам написал, что пробовал запускать службу от имени разных учётных записей. Подозреваю, проблема в том, что та сторонняя библиотека просто изначально не была спроектирована для использоваться в многосеансовой среде (multisession environment). Хотя точно сейчас не могу сказать, зависит от ответов автора на эти
Автор: x64
Дата: 25.09.09
вопросы.

М>И зачем Вам EVENT_ALL_ACCESS при откратии эвента? Возьмите за правило никогда не запрашивать лишних прав, и не назначать, кстати, тоже.


А вот это +500, ибо это важнейшее правило в Windows NT, его несоблюдение может иметь весьма плачевные последствия.
JID: x64j@jabber.ru
Re[7]: windows service (C#) dll (c++)
От: Мизантроп  
Дата: 25.09.09 15:33
Оценка:
Здравствуйте, x64, Вы писали:

x64>Полагаю всё же, что проблема у автора не в нехватке прав, ведь он же сам написал, что пробовал запускать службу от имени разных учётных записей. Подозреваю, проблема в том, что та сторонняя библиотека просто изначально не была спроектирована для использоваться в многосеансовой среде (multisession environment). Хотя точно сейчас не могу сказать, зависит от ответов автора на эти
Автор: x64
Дата: 25.09.09
вопросы.


Честно говоря, я этот момент пропустил Ну тогда скорее всего Вы правы, объекты созданы в локальном каталоге, то бишь префикс Global указан не был.
"Нормальные герои всегда идут в обход!"
Re[8]: windows service (C#) dll (c++)
От: Мизантроп  
Дата: 25.09.09 15:41
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>Ну тогда скорее всего Вы правы, объекты созданы в локальном каталоге, то бишь префикс Global указан не был.


Впрочем, одно другому не мешает, вполне возможно, что имеют место обе ошибки Ну а главное зло — отсутствие проверки last error.
"Нормальные герои всегда идут в обход!"
Re[9]: windows service (C#) dll (c++)
От: Мизантроп  
Дата: 25.09.09 16:09
Оценка:
Здравствуйте, Мизантроп, Вы писали:

А вообще в подобных случаях лучше объекты создавать из сервиса, дабы не было проблем с правами доступа к глобальному каталогу, а из пользовательской сессии их открывать. А так ещё придётся как-то определять, в какой сессии работает процесс, создавший объекты, или перебирать все каталоги, так как эвенты без нужной привилегии в глобальном каталоге создать не получится, а она по умолчанию отсутствует, насколько помню. И даже если дело в данном случае не в этом, и сессия на машине только одна, нулевая, этот момент всё равно надо учитывать. На висте уже сессия сервисов отделена от интерактивной, и обратного хода уже не будет.
"Нормальные герои всегда идут в обход!"
Re[7]: windows service (C#) dll (c++)
От: mrjeka Россия  
Дата: 25.09.09 17:32
Оценка:
Здравствуйте, x64, Вы писали:

Дело в том, что dll является не нашей, а сторонней. Исходники есть, но не все. По большому счету нужно было выяснить причину неработоспособности. Т.е. уточнить, у нас косяк или в dll. Выяснилось, что метод ReadObject (метод из dll) возвращает код ошибки 2. Судя по коду, там почти половина случаев когда возвращается этот код. Поэтому эта проблема передана разработчикам этой dll'ки.

Вообще массив объектов создается на нашей стороне (C#). в dll передается указатель на массив и длина массива. Структура объектов была создана в соответствии со структурой в плюсах. (т.е. в типах полей ошибки нет).

OC Vista x64. Но приложения C# собраны под x86 (и консоль и служба).

Что касается аккаунта, под которым запускается все дело: это АДМИН(100%) — для тех кто переспрашивает не перепутал ли я его с System.
Re[8]: windows service (C#) dll (c++)
От: x64 Россия http://x64blog.name
Дата: 25.09.09 18:16
Оценка:
M>Выяснилось, что метод ReadObject (метод из dll) возвращает код ошибки 2.
M>OC Vista x64.

Ну в таком случае, всё банально, и мои опасения
Автор: x64
Дата: 25.09.09
подтверждаются. 99% за то, что имена объектов не содержат префикса "Global\", что означает создание объекта в локальном сеансе (local session), т.е. в том же сеансе, что и вызывающий (caller). Дело в том, что начиная с Vista службы всегда выполняются в сеансе (код 0), отличном от сеансов приложений (код не 0). Этим объясняется работоспособность библиотеки в консольном приложении, и ошибка при использовании её в службе. Ну, в общем, с некоторыми доработками оно будет работать и в службах.
JID: x64j@jabber.ru
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.