UrlDownloadFoFile z biblioteki dll - nie działa

0
library download;
uses
  Windows,
  Urlmon;

procedure DllMain(reason: integer) ;
begin
   case reason of
   DLL_PROCESS_ATTACH:
     begin
       MessageBox(0, 'Downloading started!', 'DLL_PROCESS_ATTACH', MB_OK);
       UrlDownloadToFile(nil, 'http://www.google.pl/images/srpr/logo4w.png', 'C:\logo.png', 0, nil);
       MessageBox(0, 'Downloading finished!', 'DLL_PROCESS_ATTACH', MB_OK);
     end;
   DLL_PROCESS_DETACH:
     begin
       MessageBox(0, 'Unloading DLL!', 'DLL_PROCESS_DETACH', MB_OK);
     end;
   end;
end; (*DllMain*)

begin
   MessageBox(0, 'begin... ', ' DLL! ', MB_OK);
   DllProc := @DllMain;
   DllProc(DLL_PROCESS_ATTACH);
   //more DLL code here...
end.

Dlaczego mi to nie działa? Tzn. w momencie załadowania biblioteki przez program biblioteka nie pobiera pliku z Internetu?

Kod kompiluje się. W momencie załadowania biblioteki przez program pojawia się pierwszy MessageBox(0, 'begin... '..., nastepnie pojawia się drugi MessageBox(0, 'Downloading started!'... i cisza, nic się nie dzieje. Próbowałem też z UrlDownloadToFileA i to samo - czyli nic. Próbowałem też inną metodę pobierania pliku - z pomocą klasy WinInet i też nie pobiera pliku. Wspomniane sposoby działają z pliku exe ale z biblioteki dll nie chcą działać.

Ewentualnie, jak w inny sposób "zmusić" bibliotekę dll żeby pobrała plik?

Myślę, że nie w tym problem. Jak dam URLDownloadToFile w główntm bloku 'begin end' dll'ki to też nie pobiera pliku.

dodanie znacznika <code class="delphi"> - fp

0

A masz prawo zapisywać na C:\ ? Funkcja zwraca jakiś błąd (jaki) ?

0

Nie zwraca żadnych błędów. Mam prawo zapisywać na każdym dysku. Z exe'ka ta funkcja działa a z dll'a nie chce. Podobnie, nie działa downloader oparty o klasę WinInet. Natomiast downloader oparty bezpośrednio na Winsock działa odpalony z boblioteki dll.

A jak sprawdzić czy program ma prawo zapisywać na dysku?

0

Spróbować utworzyć jakiś plik jak zwróci odmowa dostępu to nie masz ale w takich lokalizacjach jak C:\ (o ile C: jest dyskiem systemowym) gdzie jak wiadomo mogą zapisywać tylko aplikacje uruchomione na prawach admina lepiej sprawdzić właśnie czy aplikacja ma prawa admina np. taką znalezioną w sieci funkcją:

uses
  WinSvc;

function IsAdmin(Host : string = '') : Boolean;
var
  H: SC_HANDLE;
begin
  if Win32Platform <> VER_PLATFORM_WIN32_NT then
    Result := True
  else begin
    H := OpenSCManager(PChar(Host), nil, GENERIC_READ or GENERIC_WRITE or GENERIC_EXECUTE);
    Result := H <> 0;
    if Result then
      CloseServiceHandle(H);
  end;
end;

albo lepsza funkcja jeżeli proces ma prawa admina powinna zwrócić eiFull:

unit ElevationInfo;

interface

type
  TElevationInfo = (eiUnknown, eiDefault, eiFull, eiLimited);
(*
      eiFull: current process is already elevated
      eiLimited: current process is not elevated, but can be by showing the elevation request dialog
      eiDefault: current process is not elevated, and not running under an administrator account
*)
  function GetElevationInfo: TElevationInfo;

implementation
uses
  Windows, SysUtils;

function GetElevationInfo: TElevationInfo;
const
  TokenElevationType = 18;
  TokenElevation     = 20;
  TokenElevationTypeDefault = 1;
  TokenElevationTypeFull    = 2;
  TokenElevationTypeLimited = 3;
var
  token: Cardinal;
  ElevationType: Integer;
  Elevation: DWord;
  dwSize: Cardinal;
begin
  Result := eiUnknown;
  if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, token) then
    try
      if GetTokenInformation(token, TTokenInformationClass(TokenElevationType), @ElevationType, SizeOf(ElevationType), dwSize) then
        case ElevationType of
          TokenElevationTypeDefault:  Result := eiDefault;
          TokenElevationTypeFull:     Result := eiFull;
          TokenElevationTypeLimited:  Result := eiLimited;
        else
          Result := eiUnknown;
        end
      else
        RaiseLastOSError;

      if Result = eiDefault then begin
        if GetTokenInformation(token, TTokenInformationClass(TokenElevation), @Elevation, SizeOf(Elevation), dwSize) then begin
          if Elevation <> 0 then
            Result := eiFull;
        end else
          RaiseLastOSError;
      end;

    finally
      CloseHandle(token);
    end
  else
    RaiseLastOSError;
end;

end.

Tak poza tym ten Twój kod z funkcją UrlDownloadToFile na 100% działa sprawdziłem tyle że tak jak pisałem musisz mieć prawa do zapisu na C:\ (i rzeczywiście funkcja nie zwraca błędu jeżeli nie masz takich praw tylko zwraca S_OK tak jakby się wszystko powiodło).

0

Więc dałem ten pierwszy kodzik do DLL i okazuje się że są prawa admina. Natomiast drugi kodzik wywala błędy i nie można się dowiedzieć co zwraca. A nie wiem jak debugować biblioteke dll. Ja zmieniam jej rozszerzenie na cpl (panel sterowania) i dwukrotnie klikam w nią - wtedy ona wykonuje to co ma w głównej pętli , uruchamia się proces rundll32.exe Ale tak jak już pisałem ten kodzik http://4programmers.net/Forum/Delphi_Pascal/147141-problem_z_algorytmem_do_pobierania_pliku pobiera plik więc prawa do zapisu muszą być.

Dałem też do biblioteki kodzik który wypakowuje z zasobów biblioteki plik i zapisuje go na dysku i wszystko działa. Także prawa do zapisu są.

0

Jak masz prawa do zapisu to musi działać nie ma powodu dlaczego miało by nie działać skoro u mnie na Windows 7 x64 działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1