Jump to content

ertank

Members
  • Content Count

    233
  • Joined

  • Last visited

Posts posted by ertank


  1. 2 hours ago, Dave Nottage said:

    You don't have Read Call Log and Read Phone Numbers permissions set in the Project Options for Android 64-bit.

    That's it. I should have spotted that. I guess I am still not used to different settings on 32Bit and 64Bit of same OS.

    Thanks.


  2. Hello,

     

    I am using Delphi 10.3.3, targeting Android 64Bit and 32Bit. Attached is a test project I used.

     

    If that same project is compiled for Android 32Bit it gets two permission request as can be seen in below pictures

    image.thumb.png.f08dbdad660fab9ad7595a82c7e6a302.pngimage.thumb.png.6e8fc8c736eb491dadb2da6498d320c7.png

     

    However, if same code without changing anything is compiled for Android 64Bit it only asks for a single permission as can be seen in below picture

    image.thumb.png.573bae3cce20b07a6a589eb9a13c605c.png

     

    Both bitness apk files are tested on same physical phone running Android 9.

     

    I have tried to change order of permissions in request to see if this is related with request order. I always get same above permission asked on 64bit version.

     

    Let me know if you think this is a bug in Delphi, please.

     

    Thanks & regards,

    Ertan

     

    Android64Bit_Permisions.7z


  3. On 1/16/2020 at 12:28 AM, Remy Lebeau said:

    Do you have the same error if you manually deactivate the TIdUDPServer BEFORE exiting your app? That would allow Indy to clean up everything in a more deterministic manner.  The TIdUDPServer destructor will normally deactivate the server and clean up, but there is no call to that destructor in your stack trace.  The stack trace suggests the RTL is freeing a UDP listener thread that is still actively running, but crashes when the TIdThread destructor tries to decrement the global IdThread.GThreadCount counter, which has probably already been finalized and freed by the RTL before the listener thread is freed.  So you should deactivate the server beforehand to ensure there are no threads running when the RTL does its own cleanup.

    So far I have tried following on a fresh project using one TIdTCPServer and one TIdIPMCastServer:

    - Set Active property to False any Indy component on form manually way before closing app: Failed

    - Set Active property to False any Indy component on form manually. Free them way before closing app: Failed

    - Remove all auto-create components. Create them using code without owner. Set Active property of them to False way before closing app: Failed

    - Remove all auto-create components. Create them using code without owner. Set Active property of them to False. Free them at run-time way before closing app: Failed

    - Remove all auto-create components. Create them using code without owner. Set Active property of them to False. *Do not* Free them at run-time and close app: Failed (this one was just for my curiosity)

     

    I get very similar call stack for all tests above.

     

    Then I tried to do some tests using just a single component:

    - Using run-time created TIdTCPServer with no owner. Active property set to False at run-time. *Did not* free and closing app: No exception (just some memory leak obviously)

    - Using run-time created TIdTCPServer with no owner. Active property set to False at run-time. Freed before closing app: No exception

    - Using run-time created TIdTCPServer with no owner. Active property *not* set to False at run-time. Freed before closing app: No exception

    - Using design-time placed TIdTCPServer with no owner. Active property set to False at run-time way before closing app: Failed 

    - Using run-time created TIdIPMCastServer with no owner. Active property set to True, used TIdIPMCastServer.Send() and property set to False. Freed at run-time way before closing app: No exception

     

    It is interesting that using either component alone created at run-time is not failing at all. Mixing them both seems to be having a problem. Using TIdUDPClient for sending broadcast messages with TIdTCPServer also failing.

     

    In anyway, it seems to be best creating components at run-time as putting them on form at design time is always failing.


  4. On 1/15/2020 at 10:13 PM, Stéphane Wierzbicki said:

    What disturbs me the most is the lack of available documentation and examples. 

     

    I really don't know how to properly handle this... I've also tried to use Indy and send an pre-formatted XML file (thanks to SOAPUI) but it failed (504 Connection reset by peer). Maybe @Remy Lebeau can helps on this? 

    I was more suggesting alternative way to use your web service. Something like semi-manual Delphi SOAP web service use.

     

    It is sometimes easier to explain in code. Please check attached demo. Especially file "ISrvConsultaCartera.WS.pas".

     

    I could not test everything as your URL was missing in the first place. I do hope that will help you out.

    SOAP_before_execute.7z


  5. 23 hours ago, Remy Lebeau said:

    I can't really comment on the multicast issue, especially on Android.  But if you are really doing multicasting, why are you using TIdUDPServer?  That is not a multicast-enabled component.  Indy has separate TIdIPMCastClient and TIdIPMCastServer components specifically for multicast.

    I did not know until I read your reply that there are dedicated components. I am going to try them.

    23 hours ago, Remy Lebeau said:

    For UDP, assuming a plain vanilla network broadcast is in fact, being used, are you setting up the TIdUDPServer.Bindings collection at all prior to activating the server?

    Below is all I set on TIdUDPServer. Actually, I set these at design time and activate component at run-time as in my initial post.

    TIdUDPServer.Active := False;
    TIdUDPServer.BroadcastEnable := True;
    TIdUDPServer.DefaultPort := 8080;

     

    23 hours ago, Remy Lebeau said:

    One problem I do see is your use of TThread.Queue() captures the ABinding object, which is no longer valid once the TIdUDPServer is freed.  Delphi anonymous procedures capture variables, not values.  You should use TThread.Queue() more like this instead:

    Using suggested code, I still get segmentation fault (11) when app exists. However, call stack changed a little this time as in attached screen shot.

    image.thumb.png.cdf3695dd5f1738991ed7e10072b6837.png


  6. There is also a difference of missing empty soap header in Delphi version

    <soapenv:Header/>

    You can try creating a soap header and see if it helps.

     

    What I do under similar cases is manually creating XML using THTTPRIO.OnBeforeExecute() event.

     

    SOAP was using Indy components before. Now it is using THTTPClient in recent versions. Changes presented some bugs like Delphi 10.3.3 version have problem of not reading error message in returned XML if it exists (https://quality.embarcadero.com/browse/RSP-27194). BTW, I do not see any clue about having namespace support for SOAP anywhere.


  7. Hello,

     

    I am using Delphi 10.3.3, Indy 10.6.2.5366 (stock Indy version)

     

    I am trying to listen broadcast UDP messages on Android (exact version I am testing is 4.4.2, I need to support latest versions, too) connected to a local WiFi. Broadcast messages will be sent in same network.

     

    I have found this page https://stackoverflow.com/questions/19040674/delphi-xe5-tidudpserver-does-not-receive-anything-on-android and tried to do it as to my understanding.

     

    Project has CHANGE_WIFI_MULTICAST_STATE permission set.

     

    UDP server parameters are as following at design time and everything else is left as default:

    TIdUDPServer.Active = False

    TIdUDPServer.BroadcastEnable = True

    TIdUDPServer.DefaultPort = 8080

     

    I have following code where timer is activated as last line in OnFormCreate() event and has 0.5 seconds delay:

    procedure TForm3.tmrCheckPhoneServiceTimer(Sender: TObject);
    var
      WifiManagerObj: JObject;
    begin
      // Run just once
      tmrCheckPhoneService.Enabled := False;
    
      // Get necessary OS settings to receive broadcast messages
      Log('Getting multicast lock...');
      WifiManagerObj := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.WIFI_SERVICE);
      FWifiManager := TJWifiManager.Wrap((WifiManagerObj as ILocalObject).GetObjectID);
      FMulticastLock := FWifiManager.createMulticastLock(StringToJString('LightFactory Remote'));
      FMulticastLock.setReferenceCounted(True);
      FMulticastLock.acquire();
      // Try to open a port on Android by sending a broadcast message
      Log('Sending a broadcast message...');
      IdUDPServer1.Broadcast('test', IdUDPServer1.DefaultPort);
      // Now we can start to listen
      Log('Activating UDP listener...');
      IdUDPServer1.Active := True;
    
      if FPhoneDialerService = nil then
      begin
        TDialogService.ShowMessage('PhoneDialer service not supported');
        Exit();
      end;
    
      PermissionsService.RequestPermissions([FCallPhonePermission], MakePhoneCallPermissionRequestResult, DisplayRationale);
    end;

    I have following code in my OnDestroy() event:

    procedure TForm3.FormDestroy(Sender: TObject);
    begin
      // Stop listenning.
      IdUDPServer1.Active := False;
      // Release multicast lock
      FMulticastLock.release();
    end;

     

    My broadcast listening code is as following:

    procedure TForm3.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
      const AData: TIdBytes; ABinding: TIdSocketHandle);
    var
      Data: string;
    begin
      Data := TEncoding.Default.GetString(AData);
      TThread.Queue(nil, procedure begin Log('Incoming broadcast message from: ' + ABinding.PeerIP) end);
    
      if SameText(Data, 'mytriggerphrase') then
      begin
        TThread.Queue(nil, procedure begin TestConnection(ABinding.PeerIP) end);
      end;
    end;

     

    After I run the app, I have following in my log:

    2020-01-14 00:59:33.697 Getting multicast lock...
    2020-01-14 00:59:33.736 Sending a broadcast message...
    2020-01-14 00:59:33.740 Activating UDP listener...
    2020-01-14 00:59:33.804 Incoming broadcast message from: 192.168.1.186
    

    That IP number in above log belongs to Android device itself.

     

    I have following problems that I could not figure a solution:

    1- I do not get any other broadcast message from my PC application which is sending one broadcast message each second. Is there anything I am doing wrong for that to happen?

    2- I get segmentation fault (11) when closing my app. Detailed call stack and exact line is in attached picture. This happens each and every close. I did not understand why.

     

    Lastly, I am not sure if my code is doing it correct to keep multicast lock thru all run-time. I read a suggestion to release a multicast lock once finished with it in order to save battery life. So, I wonder if I can release multicast lock right after enabling my TIdUDPServer?

     

    Any help is appreciated.

     

    Thanks & regards,

    Ertan

     

    image.png

    • Like 1

  8. That was it. My same registry key was as below:

    image.thumb.png.e1fe77258b3596b812c56e368651aa11.png

     

    After making it look like same with your settings Android Service compilation works fine.

     

    I am not sure how that registry setting value removed in there.

     

    BTW, I did also fix 64bit sdk value, too.

     

    Thanks.

    • Like 1

  9. Here is complete output of messages

    Build
      Checking project dependencies...
      Building Project2.dproj (Debug, Android)
      brcc32 command line for "Project2.vrc"
        c:\program files (x86)\embarcadero\studio\20.0\bin\cgrc.exe -c65001 Project2.vrc -foProject2.res 
      [Exec Error] The command ""\bin\javac" -d "C:\Users\Ertan\Documents\Embarcadero\Studio\Projects\JavaClasses\Project2" -Xlint:deprecation -classpath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\android-support-v4.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\fmx.jar" -bootclasspath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar" -encoding UTF-8 -target 1.6 -g -source 1.6  .\Android\Debug\Project2.java .\Android\Debug\Project2ProxyInterface.java" exited with code 3.
      Failed
      Elapsed time: 00:00:00.8
    Output
      Build started 12.01.2020 12:06:25.
      __________________________________________________
      Project "C:\Users\Ertan\Documents\Embarcadero\Studio\Projects\Project2.dproj" (Build target(s)):
      Target BuildVersionResource:
          c:\program files (x86)\embarcadero\studio\20.0\bin\cgrc.exe -c65001 Project2.vrc -foProject2.res 
          CodeGear Resource Compiler/Binder
          Version 1.2.2 Copyright (c) 2008-2012 Embarcadero Technologies Inc.
          
          Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
          
          Copyright (C) Microsoft Corporation.  All rights reserved.
          
          
          Deleting file "Project2.vrc".
      Target BuildAndroidServiceJarFile:
          "\bin\javac" -d "C:\Users\Ertan\Documents\Embarcadero\Studio\Projects\JavaClasses\Project2" -Xlint:deprecation -classpath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\android-support-v4.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\fmx.jar" -bootclasspath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar" -encoding UTF-8 -target 1.6 -g -source 1.6  .\Android\Debug\Project2.java .\Android\Debug\Project2ProxyInterface.java
          The system cannot find the path specified.
          c:\program files (x86)\embarcadero\studio\20.0\bin\CodeGear.Common.Targets(871,5): error MSB3073: The command ""\bin\javac" -d "C:\Users\Ertan\Documents\Embarcadero\Studio\Projects\JavaClasses\Project2" -Xlint:deprecation -classpath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\android-support-v4.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\fmx.jar" -bootclasspath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar" -encoding UTF-8 -target 1.6 -g -source 1.6  .\Android\Debug\Project2.java .\Android\Debug\Project2ProxyInterface.java" exited with code 3.
      Done building target "BuildAndroidServiceJarFile" in project "Project2.dproj" -- FAILED.
      Done building project "Project2.dproj" -- FAILED.
      Build FAILED.
      c:\program files (x86)\embarcadero\studio\20.0\bin\CodeGear.Common.Targets(871,5): error MSB3073: The command ""\bin\javac" -d "C:\Users\Ertan\Documents\Embarcadero\Studio\Projects\JavaClasses\Project2" -Xlint:deprecation -classpath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\android-support-v4.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\fmx.jar" -bootclasspath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar" -encoding UTF-8 -target 1.6 -g -source 1.6  .\Android\Debug\Project2.java .\Android\Debug\Project2ProxyInterface.java" exited with code 3.
          0 Warning(s)
          1 Error(s)
      Time Elapsed 00:00:00.63
    

    I read "The system cannot find the path specified." along the lines. That I presume goes for "\bin\javac" as every other file/directory listed do exist in my system.

     

    I am uncertain why. Registry search did not find me anything that I think is relevant. There is no "javac" location setting in SDK settings. I am clueless.


  10. Hello,

     

    Using Delphi 10.3.3. I have no problem compiling Android apps. I just needed to use a service to test something and I failed to compile. Below is error message I receive on a new Android Service project:

    [Exec Error] The command ""\bin\javac" -d "C:\Users\Ertan\Documents\Embarcadero\Studio\Projects\JavaClasses\Project2" -Xlint:deprecation -classpath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\android-support-v4.jar";"c:\program files (x86)\embarcadero\studio\20.0\lib\Android\Debug\fmx.jar" -bootclasspath "C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.36039.7899\platforms\android-26\android.jar" -encoding UTF-8 -target 1.6 -g -source 1.6  .\Android\Debug\Project2.java .\Android\Debug\Project2ProxyInterface.java" exited with code 3.

    I have no problem running javac on command prompt

    C:\Users\Ertan>javac
    Usage: javac <options> <source files>
    where possible options include:
      -g                         Generate all debugging info
      -g:none                    Generate no debugging info
      -g:{lines,vars,source}     Generate only some debugging info
      -nowarn                    Generate no warnings
      -verbose                   Output messages about what the compiler is doing
      -deprecation               Output source locations where deprecated APIs are used
      -classpath <path>          Specify where to find user class files and annotation processors
      -cp <path>                 Specify where to find user class files and annotation processors
      -sourcepath <path>         Specify where to find input source files
      -bootclasspath <path>      Override location of bootstrap class files
      -extdirs <dirs>            Override location of installed extensions
      -endorseddirs <dirs>       Override location of endorsed standards path
      -proc:{none,only}          Control whether annotation processing and/or compilation is done.
      -processor <class1>[,<class2>,<class3>...] Names of the annotation processors to run; bypasses default discovery process
      -processorpath <path>      Specify where to find annotation processors
      -parameters                Generate metadata for reflection on method parameters
      -d <directory>             Specify where to place generated class files
      -s <directory>             Specify where to place generated source files
      -h <directory>             Specify where to place generated native header files
      -implicit:{none,class}     Specify whether or not to generate class files for implicitly referenced files
      -encoding <encoding>       Specify character encoding used by source files
      -source <release>          Provide source compatibility with specified release
      -target <release>          Generate class files for specific VM version
      -profile <profile>         Check that API used is available in the specified profile
      -version                   Version information
      -help                      Print a synopsis of standard options
      -Akey[=value]              Options to pass to annotation processors
      -X                         Print a synopsis of nonstandard options
      -J<flag>                   Pass <flag> directly to the runtime system
      -Werror                    Terminate compilation if warnings occur
      @<filename>                Read options and filenames from file
    
    
    C:\Users\Ertan>

    My version of "javac.exe" is located at

    C:\Program Files\Java\jdk1.8.0_60\bin\javac.exe

     

    I have seen some people having exact same error on my searches. No solution that I could find so far.

     

    I am planning to setup a virtual machine to install fresh copy of Delphi 10.3.3 and test if working on it. Before I do that I wonder if there is something I need to check.

     

    Thanks & regards,

    Ertan


  11. Hello,

     

    I am using Delphi 10.3.3. I would like to read caller number right at the time phone is ringing.

     

    Edit: I am looking for a solution for Android platform only.

     

    Using google, I have found a lot of samples from past about reading call logs, placing calls, etc. I could not find how I should be reading caller number right at the time of a call.

     

    Any help is appreciated.

     

    Thanks & regards,

    Ertan


  12. Hello,

     

    I am using Delphi 10.3.3. For certain reasons I need to use WinInet directly. It has to run on Windows XP and higher versions. I have found below code (slightly changed to compile under my Delphi version) on Stackoverflow by @Remy Lebeau which works good on Windows 7 and higher.

    procedure WebPostData(const UserAgent: string; const Server: string; const Resource: string; const Data: Pointer; DataSize: UInt32; const ContentType: string; Response: TStream);
    var
      hInet: HINTERNET;
      hHTTP: HINTERNET;
      hReq: HINTERNET;
      Heade: string;
      Buffer: array[0..1023] of Byte;
      BytesRead: DWORD;
    const
      accept: packed array[0..1] of PChar = (PChar('*/*'), nil);
    begin
      hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
      if not Assigned(hInet) then RaiseLastOSError;
      try
        hHTTP := InternetConnect(hInet, PChar(Server), INTERNET_DEFAULT_HTTPS_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 1);
        if not Assigned(hHTTP) then RaiseLastOSError;
        try
          hReq := HttpOpenRequest(hHTTP, PChar('POST'), PChar(Resource), nil, nil, @accept, INTERNET_FLAG_SECURE or INTERNET_FLAG_KEEP_CONNECTION, 1);
          if not Assigned(hReq) then RaiseLastOSError;
          try
            Heade := 'User-Agent: ' + UserAgent + #13#10 +
                     'Accept-Language: en-us,en;q=0.5'#13#10 +
                     'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7'#13#10 +
                     'Content-Type: ' + ContentType + #13#10 +
                     'Keep-Alive: 300'#13#10;
    
            if not HttpAddRequestHeaders(hReq, PChar(Heade), Length(Heade), HTTP_ADDREQ_FLAG_ADD) then RaiseLastOSError;
    
            if not HTTPSendRequest(hReq, nil, 0, Data, DataSize) then RaiseLastOSError;
    
            repeat
              if not InternetReadFile(hReq, @Buffer, SizeOf(Buffer), BytesRead) then RaiseLastOSError;
              if (BytesRead = 0) then Break;
              if Response <> nil then
                Response.WriteBuffer(Buffer, BytesRead);
            until False;
          finally
            InternetCloseHandle(hReq);
          end;
        finally
          InternetCloseHandle(hHTTP);
        end;
      finally
        InternetCloseHandle(hInet);
      end;
    end;

     

    When I try that code on Windows XP I get below error.

    System Error. Code: 12157.

     

    I do not know if that is possible what I would like to do, but I appreciate any help.

     

    Thanks & regards,

    Ertan


  13. Add a TMemo on your form.

    When showing a message, add a line on memo.

    You will see that order of messages displayed will be same as your code order.

    You will see messages displayed will be reversed.

    This is because each message dialog displayed on top of existing one

    11 minutes ago, limelect said:

    What you say that if i have 3 or 4  ShowMessage in the same procedure the last will show first ?

    Yes, just test it.


  14. 2 hours ago, limelect said:

    first information then result. But i get first result then information.

    If application is running on Android, message dialog on that OS is asynchronous. Meaning, they do not block code execution.

     

    What happens at run-time, I think is;

    First dialog displayed first, code continue to execute, second dialog displayed second.

    However, as second is displayed as the last message, it appeared on top of all others.


  15. Latest clone as of several minutes ago and IdStackUnix.pas cannot be compiled for Lazarus under Linux x86_64

    /fpcupdeluxe/ccr/indy/Lib/./System/IdStackUnix.pas(701,21) Error: (5000) Identifier not found "FIONBIO"
    /fpcupdeluxe/ccr/indy/Lib/./System/IdStackUnix.pas(1053,40) Error: (5000) Identifier not found "FIONBIO"
    /fpcupdeluxe/ccr/indy/Lib/./System/IdStackUnix.pas(1058,26) Error: (5000) Identifier not found "EAGAIN"
    /fpcupdeluxe/ccr/indy/Lib/./System/IdStackUnix.pas(1058,34) Error: (5000) Identifier not found "EWOULDBLOCK"
    /fpcupdeluxe/ccr/indy/Lib/./System/IdStackUnix.pas(1058,47) Error: (5000) Identifier not found "EINPROGRESS"

     


  16. I just used fpcupdeluxe and it seems to be broken on somewhere else now:

    /fpcupdeluxe/ccr/indy/Lib/./System/IdStack.pas(247,57) Error: (4001) Incompatible types: got "LongInt" expected "LongWord"

    BTW, this is Linux x86_64 I am trying to build Indy on.


  17. Hello,

     

    I am trying to install Indy on a Linux x86_64 using fpcupdeluxe and following line seems broken.

    /fpcupdeluxe/ccr/indy/Lib/./System/IdGlobal.pas(7536,11) Error: (2021) ENDIF without IF(N)DEF

    /fpcupdeluxe/ccr/indy/Lib/./System/IdGlobal.pas(7536,11) Error: (2021) ENDIF without IF(N)DEF

    It is simply missing a $ sign.


  18. I did not have any problem using web installer for several versions now. My 10.3.2 was a web installer installed. I choose not to remove all registry settings when asked. Installer first uninstalled 10.3.2 and after installed 10.3.3 just fine. I did not have to re-install any of my components except Ide FixPack.

     

    You better have a fast internet connection for web installer, let it install over night or something similar though.

×