Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Вопрос по dll


Автор: Verus 7.6.2009, 19:41
Суть такая что есть функции в дллке:
Код

extern "C" BOOL __stdcall DllMain ( HINSTANCE instance, DWORD reason, LPVOID reserved )
{
    MessageBoxA(0,"DllMain","!!!!!",MB_ICONINFORMATION);
    return true;
}


и

Код

extern "C" HRESULT __stdcall DllRegisterServer()
{    
    MessageBoxA(0,"DllRegisterServer","!!!!!",MB_ICONINFORMATION);
    while(true)
    {
        
    }
    return S_OK;
}


Когда произвожу дебаг с помощью привязки в regsvr32.exe в студии, то все проходит хорошо. А когда например установлю dll'ку в систему и после перезагрузки она должна запускаться автоматически, ничего не происходит. Пытаюсь ее удалить - нельзя, значит всетаки она загрузилась в память, но не работает. В чем может быть проблема?

Автор: Cheloveck 7.6.2009, 22:14
def файл с кодом примерно такого содержания я обычно прикомпилирую. 

Код

LIBRARY    "Server"

EXPORTS

    DllGetClassObject   PRIVATE
    DllCanUnloadNow     PRIVATE
    DllRegisterServer   PRIVATE
    DllUnregisterServer PRIVATE

Посмотри на свою таблицу импорта. Может там и нету этих функций...

Автор: jonie 8.6.2009, 08:17
Цитата

А когда например установлю dll'ку в систему и после перезагрузки она должна запускаться автоматически, ничего не происходит.
чего это она должна загружаться?? И вообще если ты не залогинен то и мессадж бокса не увидишь

Автор: Verus 8.6.2009, 09:23
Cheloveck, да у меня точно такой же файлsmile

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

Автор: Verus 8.6.2009, 15:06
В общем сейчас ситуация такая: dll загружается и работает, но не вызывается функция DllRegisterServer() где мне необходимо было вызвать:
Код

CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, 
        IID_IWebBrowser2, (void**)&pBrowser2);


тогда другой вопрос - как мне вызвать CoCreateInstance() из dll или это невозможно?

Автор: xvr 8.6.2009, 17:23
А с чего DllRegisterServer должна вызываться в автомате? Ее зовет только regsvr32

Автор: Cheloveck 8.6.2009, 17:26
Ты не путай CoCreateInstance создаёт объект, а DllRegisterServer()  - просто регит классы в системном реестре, один раз

Автор: Verus 8.6.2009, 22:06
Цитата(Cheloveck @ 8.6.2009,  17:26)
Ты не путай CoCreateInstance создаёт объект, а DllRegisterServer()  - просто регит классы в системном реестре, один раз

Да я не путаю, просто мне необходимо вызвать CoCreateInstance как-то.

Автор: xvr 8.6.2009, 23:33
Цитата(Verus @ 8.6.2009,  22:06)
Цитата(Cheloveck @ 8.6.2009,  17:26)
Ты не путай CoCreateInstance создаёт объект, а DllRegisterServer()  - просто регит классы в системном реестре, один раз

Да я не путаю, просто мне необходимо вызвать CoCreateInstance как-то.

Ну так и вызывай из DllMain, какие проблемы ?
Только не забудь CoInitialize позвать.
Хотя нет, проблемы будут (MSDN):
Цитата

Because there is no way to control the order in which in-process servers are loaded or unloaded, do not call CoInitialize, CoInitializeEx, or CoUninitialize from the DllMain function.
Видимо надо что нибудь взвести в DllMain (например создать поток), и потом оттуда звать и CoInitialize и CoCreateInstance

Автор: Verus 9.6.2009, 08:51
Пытаюсь создать поток, но надо ограничить чтобы был поток только один:
Код

int count = (int) pvParam;
    count++;
    ofstream outfile("D:\\log.txt", ofstream::binary|ofstream::app);
    outfile <<"threadStart count:" << count << "\n";
    outfile.close();
    if(count > 1) return 0;

    for(int i=0;;i++)
    {
        ofstream outfile("D:\\log.txt", ofstream::binary|ofstream::app);
        outfile <<"threadStart:" << i << "\n";
        outfile.close();
    }


Но почему-то тут поток не впадает в бесконечный цикл. Точнее впадает, но потоков создается куча, хотя так не должно быть. Т.к. в поток передаю глобальную переменную.

Автор: Andrey44 9.6.2009, 09:02
Извините, не проснулся. smile 

Автор: GremlinProg 9.6.2009, 09:11
запускай поток при fdwReason == DLL_PROCESS_ATTACH

раз он должен быть бесконечный, то на DLL_PROCESS_DETACH все равно придется завершиться в данном процессе и начать по-новой в другом (на следующий DLL_PROCESS_ATTACH), если таковые будут

а для нескольких одновременно запущенных процессов создавай простой именованый мьютекс
и распространяй владение им между DLL_PROCESS_ATTACH и DLL_PROCESS_DETACH,
работать в таком случае всегда будет только один поток

Автор: xvr 9.6.2009, 09:30
Цитата(Verus @ 9.6.2009,  08:51)
Пытаюсь создать поток, но надо ограничить чтобы был поток только один:
Код

int count = (int) pvParam;
    count++;
    ofstream outfile("D:\\log.txt", ofstream::binary|ofstream::app);
    outfile <<"threadStart count:" << count << "\n";
    outfile.close();
    if(count > 1) return 0;

    for(int i=0;;i++)
    {
        ofstream outfile("D:\\log.txt", ofstream::binary|ofstream::app);
        outfile <<"threadStart:" << i << "\n";
        outfile.close();
    }


Но почему-то тут поток не впадает в бесконечный цикл. Точнее впадает, но потоков создается куча, хотя так не должно быть. Т.к. в поток передаю глобальную переменную.

Код делает непонятно что  smile 
Во первых он явно не считает количество своих вызовов, т.к. счетчик count у него локальный
Во вторых, он зацикливается и фигачит в бедный 'D:\log.txt' до переполнения диска
В третьих вообще не ясно как он создается (да и терминировать его тоже желательно, GremlinProg абсолютно правильно заметил)
В четвертых, а нельзя ли вообще обойтись без dll? Автозапуск обычно все же на .exe делают, автозапустить .dll без извратов (типа rundll32) вообще невозможно

Добавлено через 2 минуты и 41 секунду
Кстати, вопрос вдогонку - зачем создавать IE при запуске? Он скорее всего не заработает, ему нужно много чего для работы, что появится только после ПОЛНОЙ раскрутки залогиненного пользователя.

Автор: Verus 9.6.2009, 12:04
Цитата(GremlinProg @  9.6.2009,  09:11 Найти цитируемый пост)
запускай поток при fdwReason == DLL_PROCESS_ATTACH

раз он должен быть бесконечный, то на DLL_PROCESS_DETACH все равно придется завершиться в данном процессе и начать по-новой в другом (на следующий DLL_PROCESS_ATTACH), если таковые будут

а для нескольких одновременно запущенных процессов создавай простой именованый мьютекс
и распространяй владение им между DLL_PROCESS_ATTACH и DLL_PROCESS_DETACH,
работать в таком случае всегда будет только один поток 


А можно чуток поподробней как это сделать?
Я делаю примерно так:
Код

extern "C" BOOL __stdcall DllMain ( HINSTANCE instance, DWORD reason, LPVOID reserved )
{
    switch(reason)
    {
    case DLL_PROCESS_ATTACH:
        {
            ofstream outfile("D:\\log.txt", ofstream::binary|ofstream::app);
            outfile <<"DllMain" << "\n";
            outfile.close();
            unsigned ThreadID;
            HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &threadStart, (PVOID) 0, 0, &ThreadID);
            break;
        }
    case DLL_PROCESS_DETACH:
        {
            break;
        }
    }
    return true;
}

Код

unsigned WINAPI threadStart(PVOID pvParam)
{
    _threadCount++;
    ofstream outfile("D:\\log1.txt", ofstream::binary|ofstream::app);
    outfile <<"threadStart count:" << _threadCount << "\n";
    outfile.close();
    if(_threadCount > 1) return 0;

    for(int i=0;;i++)
    {
        ofstream outfile("D:\\log2.txt", ofstream::binary|ofstream::app);
        outfile <<"threadStart:" << i << "\n";
        outfile.close();
        Sleep(5000);
    }

}

Но так в бесконечный цикл не впадает. Чего-то я не понял как сделать с мьютексами :(

Добавлено через 8 минут и 17 секунд
Цитата(xvr @  9.6.2009,  09:30 Найти цитируемый пост)
Кстати, вопрос вдогонку - зачем создавать IE при запуске? Он скорее всего не заработает, ему нужно много чего для работы, что появится только после ПОЛНОЙ раскрутки залогиненного пользователя.

Ну тут можно ведь поставить какой нить Sleep() и подождать пока нормально загрузится все.
А вообще нужно именно длл, с ехе все получается без проблем и работает.

Автор: GremlinProg 9.6.2009, 12:32
Код

case DLL_PROCESS_ATTACH:
  ImOwner = FALSE;
  hMutex = ::CreateMutex(NULL,FALSE,_T("MyMutex"));
  if( ::WaitForSingleObject(hMutex,0) == WAIT_OBJECT_0 ){
    ImOwner = TRUE;
    // создать поток
  }
  break;
case DLL_PROCESS_DETACH:
  if( ImOwner ){
    ::ReleaseMutex( hMutex );
  }
  ::CloseHandle( hMutex );
  break;

тогда счетчики в потоке не нужны,
но данные, которые поток генерирует (если он это делает), должны быть переданы в другой процесс на DLL_PROCESS_DETACH, чтобы поток всякий раз не начинал работу с нуля

хотя это и не так интересно, перекидывать свою работу из процесса в процесс,
гораздо проще все таки все это делать в своем собственном процессе (без длл)

xvr, верно подметил,
длл все таки обычно используют пассивно, слейвом, т.е. без ее собственной инициативы,
к чему такие навороты, Verus?

Автор: Verus 9.6.2009, 14:45
Да, гиблая идея была...
Спасибо за помощь, узнал хоть что-то новое smile
Буду делать через ехе.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)