master
cpp 92 lines 2.55 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 HandleConsoleProgressBar.cpp
8
9 Abstract:
10
11 This file contains the HandleConsoleProgressBar class implementation.
12
13 --*/
14
15 #include "precomp.h"
16
17 #include "HandleConsoleProgressBar.h"
18
19 using wsl::windows::common::HandleConsoleProgressBar;
20
21 HandleConsoleProgressBar::HandleConsoleProgressBar(HANDLE handle, std::wstring&& message, Format format)
22 {
23 // If this file isn't a disk file, we can't show actual progress. Just show an indicator in that case
24 LARGE_INTEGER fileSize{};
25 if (GetFileType(handle) != FILE_TYPE_DISK || !GetFileSizeEx(handle, &fileSize))
26 {
27 m_progressBar.emplace<ConsoleProgressIndicator>(std::move(message));
28 }
29 else if (format == FileSize)
30 {
31 auto& progressBar = m_progressBar.emplace<ConsoleProgressIndicator>(std::move(message), false);
32
33 m_thread = std::thread([handle, &progressBar, this]() {
34 UpdateFileSize(handle, progressBar);
35 progressBar.End();
36 });
37 }
38 else
39 {
40 WI_ASSERT(format == FilePointer);
41
42 auto& progressBar = m_progressBar.emplace<ConsoleProgressBar>();
43
44 m_thread = std::thread([handle, fileSize, &progressBar, this]() {
45 UpdateProgress(handle, fileSize, progressBar);
46 progressBar.Clear();
47 });
48 }
49 }
50
51 void HandleConsoleProgressBar::UpdateProgress(HANDLE handle, LARGE_INTEGER fileSize, ConsoleProgressBar& progressBar) const
52 try
53 {
54 while (!m_event.is_signaled())
55 {
56 LARGE_INTEGER position{};
57 THROW_IF_WIN32_BOOL_FALSE(SetFilePointerEx(handle, LARGE_INTEGER{}, &position, FILE_CURRENT));
58
59 constexpr auto progressResolution = 1000;
60 const auto progressRatio = (position.QuadPart / (double)fileSize.QuadPart) * progressResolution;
61
62 progressBar.Print(static_cast<UINT>(progressRatio), progressResolution);
63 std::this_thread::sleep_for(std::chrono::milliseconds(100));
64 }
65 }
66 CATCH_LOG();
67
68 void HandleConsoleProgressBar::UpdateFileSize(HANDLE handle, ConsoleProgressIndicator& progressBar) const
69 {
70 try
71 {
72 while (!m_event.is_signaled())
73 {
74 LARGE_INTEGER size{};
75 THROW_IF_WIN32_BOOL_FALSE(GetFileSizeEx(handle, &size));
76
77 progressBar.UpdateProgress(std::format(L" ({} MB)", size.QuadPart / _1MB));
78
79 std::this_thread::sleep_for(std::chrono::milliseconds(100));
80 }
81 }
82 CATCH_LOG();
83 }
84
85 HandleConsoleProgressBar::~HandleConsoleProgressBar()
86 {
87 if (m_thread.joinable())
88 {
89 m_event.SetEvent();
90 m_thread.join();
91 }
92 }