Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.12.16;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.027 c
4-1180351823
Lex_!
2007-05-28 15:30
2007.12.16
Список оборудования в системе


2-1195379062
Новичек
2007-11-18 12:44
2007.12.16
Передача параметров другой программе.


15-1195238324
homm
2007-11-16 21:38
2007.12.16
Повпрос по RAID


2-1195311260
Dru095
2007-11-17 17:54
2007.12.16
как удалить файл с определенной датой создания


2-1195630538
Neket
2007-11-21 10:35
2007.12.16
Округление