Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.12.16;
Скачать: [xml.tar.bz2];

Вниз

Получение названий продуктов запущенных приложений   Найти похожие ветки 

 
Hint   (2007-11-17 11:14) [0]

Использую вот такой код:
function GetVersionString(pData: pointer; nDataSize: DWORD; sKey: string): string;
type
 V_LIST = record
   w1: DWORD;
   w2: DWORD;
   w3: PCHAR;
 end;
 LANGANDCODEPAGE = record
   wLang, wCodePage: word;
 end;
 PLANGANDCODEPAGE = ^LANGANDCODEPAGE;
var
 buf: PCHAR;
 dwDummy: DWORD;
 p: PLANGANDCODEPAGE;
 c: array[0..1024] of char;
 vl: V_LIST;
begin
 VerQueryValue(pData, "\VarFileInfo\Translation", pointer(p), dwDummy);
 vl.w1 := p^.wLang;
 vl.w2 := p^.wCodePage;
 vl.w3 := @sKey[1];
 wvsprintf(c, "\StringFileInfo\%.4x%.4x\%s", PCHAR(@vl));
 if VerQueryValue(pData, c, pointer(buf), dwDummy) then result := buf else result := "";
end;

function GetProductName(sFilename: string): string;
var
 nDataSize, dwDummy: DWORD;
 pData: pointer;
begin
 result:="";
 if sFilename="" then exit;
 nDataSize := GetFileVersionInfoSize(@sFilename[1], dwDummy);
 if nDataSize <= 0 then exit;
 GetMem(pData, nDataSize);
 GetFileVersionInfo(@sFilename[1], 0, nDataSize, pData);
 result := GetVersionString(pData, nDataSize, "ProductName");
 FreeMem(pData);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
var
 i,j:integer;
 ph: THandle;
 mh: hmodule;
 procs: array[0..$FFF] of dword;
 count, cm: cardinal;
 ModName: array[0..max_path] of char;
 s1,s2: string;
begin
 if EnumProcesses(@procs, sizeof(procs), count) then
    begin
     j:=count div 4 - 1;
     for i:=0 to j do
        begin
         ph:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, procs[i]);
         if ph > 0 then
             begin
              EnumProcessModules(ph, @mh, 4, cm);
              GetModuleFileNameEx(ph, mh, ModName, sizeof(ModName));
              s1:=string(ModName);
              s2:=GetProductName(s1); //!!!
              m.Lines.Add(ExtractFileName(s1)+" - "+s2);
              CloseHandle(ph);
             end;
        end;
    end;
end;

И почему-то у некоторых пользователей при вызове GetProductName происходит ошибка. Код находится в DLL, ошибка возникает у 1 человека из 50. Как найти причину - не знаю. Вроде все правильно, но что-то не так...


 
Kolan ©   (2007-11-17 11:15) [1]

> И почему-то у некоторых пользователей при вызове GetProductName
> происходит ошибка

Так и написано &laquo;Ошибка&raquo;?


 
Hint   (2007-11-17 11:24) [2]

Поток, содержащий вызов GetProductName завершает свою работу


 
Leonid Troyanovsky ©   (2007-11-17 12:08) [3]


> Hint   (17.11.07 11:24) [2]

Боже мой, потоки, формы - и все свалено в dll.
Странно, что у 49 что-то работало.

--
Regards, LVT.


 
Hint   (2007-11-17 13:23) [4]

Формы там нет. Код скопирован из DLL в пустой проект с формой, чтобы было проще искать ошибку.
А DLL и поток - почему бы и нет? DLL при инициализации создает один служебный поток.


 
Leonid Troyanovsky ©   (2007-11-17 13:31) [5]


> Hint   (17.11.07 13:23) [4]

> А DLL и поток - почему бы и нет? DLL при инициализации создает
> один служебный поток.

Показывай, как. И где завершается.

Впрочем, можно и почитать
http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-11-17 13:34) [6]


> Hint   (17.11.07 13:23) [4]

> Формы там нет. Код скопирован из DLL в пустой проект с формой,
>  чтобы было проще искать ошибку.

Какой код работал в dll?

--
Regards, LVT.


 
Hint   (2007-11-17 13:45) [7]

В DLL:
begin
createthread(nil, 0, @MyThread, nil, 0, mt);
end;


procedure MyThread;
begin
while true do
 begin
  sleep(10000);
  search;
 end;
end;


Где search - тоже самое, что и FormCreate, только вместо m.Lines.Add:
if s2="xxx" then ...


 
Leonid Troyanovsky ©   (2007-11-17 13:59) [8]


> Hint   (17.11.07 13:45) [7]

Во-первых, BeginThread.
Во-вторых, while true do - в печь.
В-третьих, тема then .. - не раскрыта.
В-четвертых, как осуществлялась инициализация,
не показано.

--
Regards, LVT.


 
Hint   (2007-11-17 14:09) [9]

Спасибо, от CreateThread уже избавился (почитал справку в чем разница).
---
Мне нужно, чтобы код выполнялся пока приложение не будет закрыто, поэтому и использую "while true do". Есть какие-то другие варианты?
---
If then - не важно. Что-то вроде:
if s2="xxx" then MessageBox(0,"xxx","xxx",0);
В любом случае этот код уже не выполняется, т.к. на GetProductName все прерывается.
---
Какая инициализация?


 
Leonid Troyanovsky ©   (2007-11-17 14:20) [10]


> Hint   (17.11.07 14:09) [9]

> Мне нужно, чтобы код выполнялся пока приложение не будет
> закрыто, поэтому и использую "while true do". Есть какие-
> то другие варианты?

Например,
while (WaitForSingleObject(hEventStop, 10000) <> WAIT_OBJECT_0) do
Но, это лишь как пример, т.к. у WFSO есть и другие возвращаемые значения.

> If then - не важно.

Отнюдь.

> В любом случае этот код уже не выполняется, т.к. на GetProductName
> все прерывается.

Что значит "все прерывается"?

> Какая инициализация?


> DLL при инициализации создает один служебный поток.

--
Regards, LVT.


 
Hint   (2007-11-17 14:29) [11]

Под инициализацией я ивел ввиду код между begin и end (BeginThread).


while true do
begin
sleep(x);
if EnumProcesses(@procs, sizeof(procs), count) then
   begin
    j:=count div 4 - 1;
    for i:=0 to j do
       begin
        ph:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, procs[i]);
        if ph > 0 then
            begin
             EnumProcessModules(ph, @mh, 4, cm);
             GetModuleFileNameEx(ph, mh, ModName, sizeof(ModName));
             s1:=string(ModName);
             ATL("before");
             s2:=GetProductName(s1); //!!!
             ATL("after");
             m.Lines.Add(ExtractFileName(s1)+" - "+s2);
             CloseHandle(ph);
            end;
       end;
   end;
ATL("done");
end;


Если добавить в код вызов функции ATL, которая записывает передаваемую ей строку в текстовый файл, то у большинства пользователей в файле будут каждые N секунд появляться строки:

> before
> after
> ...
> before
> after
> done
> ...


А у одного человека из 50ти:

> before
> after
> ...
> before

Приложение будет работать дальше, а записи в файл уже не произойдет. При чем "done" не появится ни разу.


 
Leonid Troyanovsky ©   (2007-11-17 14:45) [12]


> Hint   (17.11.07 14:29) [11]

> Под инициализацией я ивел ввиду код между begin и end (BeginThread).

Это место весьма проблемное, я ж ссылку приводил.
Лучше взять за правило делать экспортируемые процедуры Init/Fin

> Приложение будет работать дальше, а записи в файл уже не
> произойдет.

Например, в том самом потоке возникло исключение, убившее поток
(немного странно, что не процесс). Т.е., то, что в then .. - важно,
скорее всего, неправильная/отсутствующая синхронизация.

--
Regards, LVT.


 
Hint   (2007-11-17 15:15) [13]

Дело в том, что исключение происходит в GetProductName, т.к. "after" в логе уже не появляется.
ATL("before");
s2:=GetProductName(s1); //!!!
ATL("after");
if s2="xxx" then ...

В принципе я об этом написал в первом сообщении, только код упростил, чтобы не было лишних вопросов про поток и DLL =) Т.к. думаю в данном случае это не важно (есть before, нет after, значит ошибка в GetProductName). Но эта функция у меня, как и у многих других, работает нормально в данном контексте (совместно с EnumProcesses). Получается при запросе информации о каком-то приложении происходит ошибка. Что это может быть за приложение? Функция GetProductName написана не корректна или я что-то не принимаю в учет?


 
Leonid Troyanovsky ©   (2007-11-17 15:27) [14]


> Hint   (17.11.07 15:15) [13]

> это может быть за приложение? Функция GetProductName написана
> не корректна или я что-то не принимаю в учет?

Мне многое не нравится в оном написании, начиная со String,
который, видимо, попадает куда-то в exe.

А так - MSDN - в зубы, Win32Check - в руки - и вперед.
И никаких 1024.

--
Regards, LVT.


 
Hint   (2007-11-17 15:33) [15]

Вот нашел сообщение с похожей проблемой:
http://t3stament01.name/08/visnet-getfileversioninfosize/


 
Leonid Troyanovsky ©   (2007-11-17 15:35) [16]


> Hint   (17.11.07 15:15) [13]

> чтобы не было лишних вопросов про поток и DLL

Зря думаешь, что лишние.
Хотя, с другой стороны, как еще было узнать о
некорректности GetProductName :)

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-11-17 16:03) [17]


> Hint   (17.11.07 15:33) [15]

> Вот нашел сообщение с похожей проблемой:

Вот, это понятней.
Т.е., исключения нет, а есть бесконечное ожидание.
Вполне возможно, что некоторые файлы локированы,
а GetFileVersionInfo требуется мапить файл для
определения размера ресурса.

Хотя, не очень понятно, почему это exe, а не длл.
Может, на той машине какой-нить терминальный сервис?

Ну, и для того, чтобы избежать подобного, нужно
перед GetFileVersionInfo убедится можно ли файл читать.
Неохота лезть в MSDN, но, кажется, что там д.б. об этом.

--
Regards, LVT.


 
Hint   (2007-11-17 16:08) [18]

Кстати, может быть проблема из-за запущенного RAdmin?


 
Leonid Troyanovsky ©   (2007-11-17 16:13) [19]


> Hint   (17.11.07 16:08) [18]

> Кстати, может быть проблема из-за запущенного RAdmin?

Не знаю, у меня его нет.
Надо логировать имена процессов и смотреть.

Да и какая разница? Если файл локирован на чтение,
то никакой GetFileVersionInfo не получить.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-11-17 16:26) [20]


> Leonid Troyanovsky ©   (17.11.07 16:03) [17]

> Ну, и для того, чтобы избежать подобного, нужно
> перед GetFileVersionInfo убедится можно ли файл читать.

Не, не так.
Нужно открыть на чтение, а после GFVI - закрыть(хендл).
Если на открытие - отлуп, то ресурсы не прочитать.

--
Regards, LVT.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.12.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.041 c
2-1195666443
navichok
2007-11-21 20:34
2007.12.16
BDE error $000F


15-1194987690
DVM
2007-11-14 00:01
2007.12.16
В догонку про загрузку CPU.


2-1195649367
{ент
2007-11-21 15:49
2007.12.16
List box


2-1195822761
Maker
2007-11-23 15:59
2007.12.16
Перебор компонентов по имени


2-1195557465
LikefNik
2007-11-20 14:17
2007.12.16
TRichEdit +BMP





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский