Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[C#] Pobranie postępu wypakowania z programu 7z.exe

mikmas 10 Lis 2017 17:35 384 6
  • #1 10 Lis 2017 17:35
    mikmas
    Poziom 18  

    Wypakowuję moim programem pewien plik z użyciem odpalenia zewnętrznego programu 7z.exe. Gdy zrobię to cmd widzę ładnie procentowo postęp, natomiast gdy przekieruję StandardOutput do swojej zmiennej to dostaję jakieś tam tylko zdawkowe nic ciekawego nie mówiące informacje. Gdzie on strzela te rozszerzone informacje?

    0 6
  • #2 10 Lis 2017 20:11
    JacekCz
    Poziom 36  

    na wyjście stdout (nazwa chyba powszechnie znana ??? - a to da się przekierować) rzadko sie robi zaawansowanie procentowe. Wtedy gdy się robi, polega to na kombinacjach z BS, CR,LF itd... parę razy trafiłem na takie programy, zarówno linux jak i DOS/Win. Ale rzadko.

    Wyście bezpośrednio na okno konsoli za "dawnych czasów" robiło się BIOS-em, konsolowe aplikacje windowsowe też mają podobne API. Dlatego tego nie przechwytujesz.
    Bezpośrednio, czyli z możliwością czyszczenia jakieś pozycji, cofania kursora i inne - wtedy zrobienie procentu jest łatwe.


    Jak ma bić ambitnie: .NET wrapper dla biblioteki 7-Zip, arytmetyka procentu po jakimś bloku danych. Tak mam zrobiony procent zipowania w Javie.

    0
  • #3 12 Lis 2017 12:26
    kaamil1984
    Poziom 11  

    Hmmm wydaje mi się że to jest wysyłane na standardowe wyjście. Podejrzewam ze używasz metody ReadLine() i dlatego masz z tym problem.

    7zip wyswietlając postęp rozpakowywania pliku nie wysyła na konsolę znaku przejścia do nastepnej linii (LF - line feed) tylko robi powrót do poczatku wiersza (CR - carriage return), po czym nadpisuje aktualną linię konsoli nowym tekstem.

    Warunkiem koniecznym do pomyślnego ukończenia działania metody SerialPort.ReadLine() jest odczytanie znaku line feed (LF) w czasie krótszym niż SerialPort.ReadTimeout. Dopóki ten znak sie nie pojawi - program bedzie czekał.

    Znak LF pojawia sie dopiero po zakonczeniu pracy, i dlatego ReadLine Ci nie działa tak, jakbyś chciał.

    Musisz użyć metody Read() lub ReadExisting(), otrzymany strumień tekstu ciąć w miejscach gdzie występuje znak CR.

    0
  • #4 18 Lis 2017 13:21
    mikmas
    Poziom 18  

    Wybaczcie, że dopiero teraz odpisuję. Nie widziałem powiadomienia o odpowiedzi.
    Nie, nie odczytuję via readline. Robię to tak:

    Kod: csharp
    Zaloguj się, aby zobaczyć kod

    Po otrzymaniu pierwszych bloków informacji stdout aplikacji milczy. Żadnych CR czy jakichkolwiek innych danych.
    To jest do użytku wew. firmy, więc procent to bardziej bajer niż rzeczywiście kluczowa funkcjonalność, stąd też nie ma sensu babrać się we wrappery. Czyli nie jest to w prosty sposób możliwe?

    0
  • #5 19 Lis 2017 18:45
    kaamil1984
    Poziom 11  

    Milczy, bo Twoja pętla

    Code:
    while ((readed = read.Read(data, 0, 8192)) > 0)
    


    skończyła się.

    Read() zakończyło się jeden raz (nastąpił moment kiedy bufor był na chwilę pusty bo na tą chwilę wszystko było odczytane).

    Powinieneś inaczej zbudować tą pętlę while. Może coś w tym rodzaju:

    Code:
    while ((readed = read.Read(data, 0, 8192).contains("\n"))


    I do tego musisz dorobić jakieś wyjście z pętli na wypadek problemu z komunikacją. Ewentualnie ustaw ReadTimeout i "łap" wyjątek
    Code:
    System.TimeoutException
    .

    0
  • #6 20 Lis 2017 15:28
    mikmas
    Poziom 18  

    Read nie wyjdzie, jak nic nie będzie na wyjściu. Tak działają wszystkie streamy. Jak nic nie ma do odczytania to "wisi" (blocking mode). Twoje rozwiązanie jest bardzo łopatologiczne. Nie ma obowiązku, aby znajdował się znak nowej linii w wysłanym komunikacie. Program wyśle mi np. tylko spację i pętla się skończy doprowadzając do katastrofy (później ja robię z wypakowanymi plikami kilka operacji).

    W ogóle takie rozwiązanie jest nie do przyjęcia, bo streamy - teoretycznie - nie mają obowiązku dać ci tyle, ile wysłał program. Program mógł wypluć "Ala ma kota\n", ale nic nie ma obowiązku zapewnić, żebyś nie dostał to w dwóch wywołaniach w postaci "Ala ", "ma kota\n".

    Moja konstrukcja jest jak najbardziej poprawna i działa (inaczej by nie wisiał)

    0