C
C#3mo ago
Noah

Downloading and extracting a .7z file from within a WinUI application

I'm currently developing an application installer using WinUI3, and I'm stuck at the part where the installer actually downloads the .7z file for the application and extracts it. This is the first time I've dealt with something like this. Further context: I'm trying to download the 7z file to a path determined by an input on the page previous, and I have passed through the variable on my Frame.Navigate() so I can access it.
No description
124 Replies
Stefanidze
Stefanidze3mo ago
Give some more info? I can't see the code that's actually doing the unpacking, and the image is not informative
Noah
Noah3mo ago
Yeah hold on, you'll have to forgive my nightmare mess of code to try and do this
Noah
Noah3mo ago
This is what it tries to do in the background, but nothing ever downloads / happens
No description
Stefanidze
Stefanidze3mo ago
ummm, post the code (use a pastebin)? Please don't use screenshots, they make it much harder to help you
Noah
Noah3mo ago
oh my bad
Noah
Noah3mo ago
Pastebin
DownloadingPage.xaml.cs - Pastebin.com
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Stefanidze
Stefanidze3mo ago
Ok, so i would consider this a strange approach. A: You will need to install a copy of 7zip with your program, might not be the best option for the user, especially if they already have 7zip installed. B: Why use processes and raw binaries in the first place? There are nuget libraries that provide much better level of responsiveness than Process, so you can actually see what and where went wrong. Also shouldn't it be
string argument1 = "-e " + selectedFolder + "\\update.7z"; // Arguments


ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = exePath,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
Arguments = $"{argument1}"
};
string argument1 = "-e " + selectedFolder + "\\update.7z"; // Arguments


ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = exePath,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
Arguments = $"{argument1}"
};
When passing arguments?
Noah
Noah3mo ago
Is there any other method of extratcting a 7z without having to include a copy? I can change to a normal .zip file instead if that means it doesn't need any extras to be downloaded. Also, is the code for actually downloading correct? I don't see anything being downloaded 7zr.exe syntax is just the letter e without any hyphens
Stefanidze
Stefanidze3mo ago
Well, that's very important, i assumed you've checked for the existence of the file...
Noah
Noah3mo ago
The file downloads when I pass a pre-written directory, but not any of my variable ones
Stefanidze
Stefanidze3mo ago
I don't think that's the issue, but use async/await with http not: HttpResponseMessage response = client.GetAsync(fileUrl).Result; better: HttpResponseMessage response = await client.GetAsync(fileUrl); Also, i would recommend using RestSharp, for the sake of convenience
Noah
Noah3mo ago
I'll take a look at RestSharp, but the await thing won't work since it's not in an async method
Stefanidze
Stefanidze3mo ago
Make it async method? I'm pretty sure there is an async override option
Noah
Noah3mo ago
This might go down as one of the most obvious things I've ever missed in my life lmao
Stefanidze
Stefanidze3mo ago
So, did you find an async method? Did it fix the problem?
Noah
Noah3mo ago
It didn't fix the file not appearing, but it did fix another issue I was having where the app would lock up while executing the code in that method But I'm changing to RestSharp to see if it works
c#
var request = new RestRequest(Method.GET);
c#
var request = new RestRequest(Method.GET);
For some reason, VS tells me that GET does not exist in Method But that is the right syntax according to the documentation
Stefanidze
Stefanidze3mo ago
Here, made RestSharp code working for you (using insomnia):
var client = new RestClient();
var request = new RestRequest("https://gitlab.com/suyu-emu/suyu-releases/-/raw/master/v0.0.2-master/Suyu-Windows_x64.7z?ref_type=heads&inline=false", method: Method.Get);
request.AddHeader("User-Agent", "insomnia/2023.5.8");
var response = await client.ExecuteAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK){
//File.WriteAllBytes("path", Encoding.UTF8.GetBytes(response.Content));
}
var client = new RestClient();
var request = new RestRequest("https://gitlab.com/suyu-emu/suyu-releases/-/raw/master/v0.0.2-master/Suyu-Windows_x64.7z?ref_type=heads&inline=false", method: Method.Get);
request.AddHeader("User-Agent", "insomnia/2023.5.8");
var response = await client.ExecuteAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK){
//File.WriteAllBytes("path", Encoding.UTF8.GetBytes(response.Content));
}
Documentation is a bit outdated...
Noah
Noah3mo ago
thank you so much! I must have been reading some out of date documentation because it all looks different That explains it then, slightly thought I was going crazy :)
Stefanidze
Stefanidze3mo ago
It's pretty easy to figure out on your own, using just intellisense, but here are the up-to-date docs: https://restsharp.dev/v107/
RestSharp Next (v107+) | RestSharp
Simple .NET client for HTTP REST APIs
Noah
Noah3mo ago
Intellisense is handy I have to say. Another thng though, this doesn't seem to be downloading anything either, is there a way for me to see the progress of the download?
Stefanidze
Stefanidze3mo ago
Put a breakpoint after you await the request, inspect the values this won't show you the progress in real time, but will alert you when the file is downloaded
Noah
Noah3mo ago
So I should add "Debugger.Break();" below that line, and set my debugger onto the Breakpoint screen? This is the first time I've had to use one I ran the code and now it's highlighted yellow
Stefanidze
Stefanidze3mo ago
What ide are you using?
Noah
Noah3mo ago
Visual Studio
Stefanidze
Stefanidze3mo ago
Breakpoints look like this:
Stefanidze
Stefanidze3mo ago
No description
Stefanidze
Stefanidze3mo ago
No description
Stefanidze
Stefanidze3mo ago
red dot - the line the execution will stop at
Stefanidze
Stefanidze3mo ago
You can inspect the values of variables in the "locals" tab
No description
Noah
Noah3mo ago
Could this maybe have something to do with it?
No description
Stefanidze
Stefanidze3mo ago
Yep, that's an exception
Noah
Noah3mo ago
I don't know how the direcotry isn't found
Stefanidze
Stefanidze3mo ago
Can you show me the code once again (i think it has changed significantly since the last time) and the values of any variables you're supplying?
Noah
Noah3mo ago
hold on it's doing something
No description
Noah
Noah3mo ago
I had to do File.Create before writing to the file another obvious thing that I ovelrooked however it's still 0b
Stefanidze
Stefanidze3mo ago
No? It depends, but the method File.WriteAllBytes creates the file automatically
Noah
Noah3mo ago
Pastebin
Download.xaml.cs - Pastebin.com
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Noah
Noah3mo ago
That's weird then The directory on File.WriteAllBytes is real and it's the only other time a directory is mentioned in the file and I have manually set it to my downloads folder
Noah
Noah3mo ago
lol what
No description
Stefanidze
Stefanidze3mo ago
As far as i remember file paths use / not \
Noah
Noah3mo ago
Oh? All my other paths have used \ but those were in XAML actually
Noah
Noah3mo ago
Still getting an IO exception
No description
Stefanidze
Stefanidze3mo ago
Can you send the stack trace?
Noah
Noah3mo ago
My call stack is empty
Noah
Noah3mo ago
No description
Stefanidze
Stefanidze3mo ago
Well, that's strange
Noah
Noah3mo ago
am I looking in the wrong place probably am
Stefanidze
Stefanidze3mo ago
debug tab:
No description
Stefanidze
Stefanidze3mo ago
This is how it looks for me (very old project)
Noah
Noah3mo ago
No description
Noah
Noah3mo ago
Maybe my debugger settings aren’t right
Noah
Noah3mo ago
I got something! But I have no clue what has opened this file
No description
Noah
Noah3mo ago
Honestly it might be the File.Create()
Stefanidze
Stefanidze3mo ago
Well, just delete the file (manually) for now I suspect it's Process.Start you're doing to unzip it Are you sure your logic waits for the file to get downloaded before processing it?
Noah
Noah3mo ago
I removed that part of the code until I could get the downloaading functional
Noah
Noah3mo ago
File.Create removed fixed it
No description
Noah
Noah3mo ago
my own fix is what broke it in the end lol
Stefanidze
Stefanidze3mo ago
ok, great
Noah
Noah3mo ago
do I need to close the connection or anything afterwards?
No description
Noah
Noah3mo ago
a few exceptions are thrown after it's idle for a few minuites client.Dispose() fixed it 🎉 now I've seen online that something called 7zSharp exists so it might be handy to use so hopefully I can take it from here 🤞
Stefanidze
Stefanidze3mo ago
Returning to the path not found issue, this works for me: File.WriteAllBytes(Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads/", "test.7z")), Encoding.UTF8.GetBytes(response.Content)); In general you would want to use Path class for safe path handling Good luck to you, hope you can get it working!
Noah
Noah3mo ago
Thanks! :) Oops back again, if I want the installer to be able to write to program files, I need to run it as adminstrator, but this then breaks the FolderPicker on the previous page meaning it can't install anywhere @Stefanidze I don't like pinging because people have lives outside of helping people on Discord, but you've been so helpful and clearly know what you're talking about so hopefully this is a quick fix
Stefanidze
Stefanidze3mo ago
Hi, i'm ok with pinging I will need to see the code, i'm not familiar with any universal "Folder Picker" pattern
Noah
Noah3mo ago
The FolderPicker is a part of WinUI
c#
public async void PickFolderButton_Click(object sender, RoutedEventArgs e)
{
// Clear previous returned file name, if it exists, between iterations of this scenario
PickFolderOutputTextBlock.Text = "";

// Create a folder picker
FolderPicker openPicker = new Windows.Storage.Pickers.FolderPicker();

// See the sample code below for how to make the window accessible from the App class.
var window = App.CurrentWindow;

// Retrieve the window handle (HWND) of the current WinUI 3 window.
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);

// Initialize the folder picker with the window handle (HWND).
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);

// Set options for your folder picker
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add("*");

// Open the picker for the user to pick a folder
StorageFolder folder = await openPicker.PickSingleFolderAsync();
if (folder != null)
{
PickFolderOutputTextBlock.Text = folder.Path + @"\suyu";
}
else
{
PickFolderOutputTextBlock.Text = "No folder selected.";
}
}
c#
public async void PickFolderButton_Click(object sender, RoutedEventArgs e)
{
// Clear previous returned file name, if it exists, between iterations of this scenario
PickFolderOutputTextBlock.Text = "";

// Create a folder picker
FolderPicker openPicker = new Windows.Storage.Pickers.FolderPicker();

// See the sample code below for how to make the window accessible from the App class.
var window = App.CurrentWindow;

// Retrieve the window handle (HWND) of the current WinUI 3 window.
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);

// Initialize the folder picker with the window handle (HWND).
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);

// Set options for your folder picker
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add("*");

// Open the picker for the user to pick a folder
StorageFolder folder = await openPicker.PickSingleFolderAsync();
if (folder != null)
{
PickFolderOutputTextBlock.Text = folder.Path + @"\suyu";
}
else
{
PickFolderOutputTextBlock.Text = "No folder selected.";
}
}
Stefanidze
Stefanidze3mo ago
Well, nothing i can do
Stefanidze
Stefanidze3mo ago
GitHub
Trying to use a FileOpenPicker while running the app as Administrat...
Describe the bug I am trying to open a File Picker but it works only if I am not using the app in elevation mode. I'm getting the following error: System.Runtime.InteropServices.COMException: &...
Stefanidze
Stefanidze3mo ago
this is a winui bug, try finding solution in the issue?
Noah
Noah3mo ago
common microsoft L
Stefanidze
Stefanidze3mo ago
yep Also, if you want to dig into this, try creating an issue for FolderPicker on winui github, i don't think it exists
Noah
Noah3mo ago
none of the fixes even work wtf is this I've got 2 options then: - Don't allow install to program files - Only install to program files
Stefanidze
Stefanidze3mo ago
Well, how about writing two apps, one the installer, and other one is the picker, and pass the location via command line arguments? I'm trying to think of a lossless workaround...
Noah
Noah3mo ago
so am I it would be nice to just launch the file picker as unelevated while the rest of the program is
leowest
leowest3mo ago
I dont use WinUI so I promise nothing, what is the issue with picking a file?
Noah
Noah3mo ago
The FilePicker/FolderPicker function doesn’t work when the app is opened as admin and neither do any of the alternatives for some reason
leowest
leowest3mo ago
why do u need admin?
Noah
Noah3mo ago
To write to program files
leowest
leowest3mo ago
why do u need to write to a folder that is not normally written to?
Noah
Noah3mo ago
For an installer
leowest
leowest3mo ago
I might be missing some more context here because a installer will normally go to a temp folder and install to a location, sure it could be program files
Noah
Noah3mo ago
It needs to copy the files to the users selected folder, which could end up being a protected folder such as program files unless I use an elevated command line etc to move the files AFTER extraction to the temp folder
leowest
leowest3mo ago
ok but why can't you have your users pick a non protected folder to install so they dont need to rely on protected locations
Noah
Noah3mo ago
because some people like using program files, i don’t want to just make some folders off limits because of an arbitrary limitation that microsoft can’t be bothered fixing
leowest
leowest3mo ago
AFAIK filepicker have something to get permissions to write to other folder then the regular ones have u tried that?
Noah
Noah3mo ago
FilePicker doesn’t have that because filepicker can pick the protected folders, the problem comes in the next step when the application tries to write to it and can’t as it doesn’t have privileges
Stefanidze
Stefanidze3mo ago
Well, using some workaround maintained by someone other than microsoft may be an option...
leowest
leowest3mo ago
https://learn.microsoft.com/en-us/windows/uwp/files/file-access-permissions#example its the same as uwp as far as I remember so let me try to understand u have a winui3 app on programs file already and u want to have it move files to its install dir? or u are writing an installer and want it to install things to a folder of the user choice
Stefanidze
Stefanidze3mo ago
This is not the problem, the problem is that built-in FolderPicker class doesn't work (in an unspecified way) when application has elevated permissions
leowest
leowest3mo ago
that's great, I already understood that and I want to see if the uwp solution would work for it, thus im trying to understand what he is doing
Noah
Noah3mo ago
Writing an installer (will be built unpacked obviously) and I want it to do this
leowest
leowest3mo ago
k, I will give it a go here and see if it works.
sibber
sibber3mo ago
thats only if its packaged
leowest
leowest3mo ago
I see, so unlike uwp it have a unpackaged version? @Noah this solution works https://github.com/PavlikBender/Pickers unhappily beyond selecting the folder u will have other issues moving the files(so my suggestion is, try to create the folder first if it fails just tell the user to choose a different folder) its the simplest to implement since all u need is to reference the project or library if u build it
sibber
sibber3mo ago
yeah you can use the uwp file pickers but you dont need to request any permissions if its unpackaged you dont need a lib
leowest
leowest3mo ago
yeah very interesting I just made a simple app to try it out a bit confusing the templates naming but found the unpackaged one
sibber
sibber3mo ago
yeah last i checked they still didnt have an unpackaged template you just need to change the csproj yourself
leowest
leowest3mo ago
the thing is, it doesn't open the folderpicker with winui3 default api, so the library is the workaround
sibber
sibber3mo ago
wdym?
leowest
leowest3mo ago
what are u referring to here
sibber
sibber3mo ago
to use the pickers from Windows.Storage.Pickers
leowest
leowest3mo ago
then yes, u do need that library
sibber
sibber3mo ago
why?
leowest
leowest3mo ago
the reason is because for whatever finik reason winui3 under admin right does not open the folder picker
sibber
sibber3mo ago
i didnt use any lib when i used them
leowest
leowest3mo ago
it works perfectly fine without admin rights
sibber
sibber3mo ago
huh
leowest
leowest3mo ago
which is the issue the OP is having
sibber
sibber3mo ago
i thought they fixed that a while ago what version of winui are they using?
leowest
leowest3mo ago
apparently not, I tried it myself, and under the thread about that issue that was one of the solutions
sibber
sibber3mo ago
you initialized it with the main window handle?
leowest
leowest3mo ago
this is what the template gave me as default net7.0-windows10.0.19041.0 var handle = WindowNative.GetWindowHandle(App.MainWindow);
sibber
sibber3mo ago
does op use packaged or unpackaged?
leowest
leowest3mo ago
I believe unpackaged as he said above in some messages
sibber
sibber3mo ago
did they send the csproj? wait is there a github issue?
leowest
leowest3mo ago
no, but I tried it myself just now yes there is
sibber
sibber3mo ago
ah can you link it?
sibber
sibber3mo ago
thanks
leowest
leowest3mo ago
as you can see still open, so this https://github.com/PavlikBender/Pickers library was the simplest way to go around the issue but its not the only issue the OP will have since he also wants to move files into a protected folder
sibber
sibber3mo ago
its 2 years old oof
leowest
leowest3mo ago
welcome to WinUi3 😛 glad im a wpf fanboy MAUI is also full of holes u have to patch things
sibber
sibber3mo ago
yeah im not interested in touching maui
leowest
leowest3mo ago
wish I had that privilege. anyway to not burry the thread
MODiX
MODiX3mo ago
leowest
<@295671854104969216> this solution works https://github.com/PavlikBender/Pickers unhappily beyond selecting the folder u will have other issues moving the files(so my suggestion is, try to create the folder first if it fails just tell the user to choose a different folder)
React with ❌ to remove this embed.
leowest
leowest3mo ago
because u can test for the authorization failure.