I have created an application that has an update system, something unconventional:
this app is installed and run from:
C:\Program Files (x86)\Application test
the executable is called:
searchdata.exe
but at some point I had the great idea to make an update system that executes the following steps:
- Click the update button: check if the executable exists
update.exe
.
- if it exists, run it immediately and close
searchdata.exe
. - does not exist - download
update.dat
from a URL and rename it to update.exe.
- This is the download and progress bar script:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
DownloadFileWithProgress("http://test.pro/installer/update.dat", AppDomain.CurrentDomain.BaseDirectory + "update.exe", ProgressBar1, Label4);
}
private void DownloadFileWithProgress(string DownloadLink, string TargetPath, ProgressBar Progress, Label LabelProgress)
{
int bytesProcessed = 0;
Stream remoteStream = null;
Stream localStream = null;
HttpWebResponse response = null;
try
{
WebRequest request = WebRequest.Create(DownloadLink);
double TotalBytesToReceive = 0;
var SizewebRequest = WebRequest.Create(new Uri(DownloadLink));
SizewebRequest.Method = "HEAD";
using (var WebResponse = SizewebRequest.GetResponse())
{
var fileSize = WebResponse.Headers.Get("Content-Length");
TotalBytesToReceive = Convert.ToDouble(fileSize);
}
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
remoteStream = response.GetResponseStream();
string filePath = TargetPath;
localStream = File.Create(filePath); // Aquí mero es el error
byte[] buffer = new byte[1024];
int bytesRead = 0;
do
{
bytesRead = remoteStream.Read(buffer, 0, buffer.Length);
localStream.Write(buffer, 0, bytesRead);
bytesProcessed += bytesRead;
double bytesIn = double.Parse(bytesProcessed.ToString());
double percentage = bytesIn / TotalBytesToReceive * 100;
percentage = Math.Round(percentage, 0);
if (Progress.InvokeRequired)
{
Progress.Invoke(new MethodInvoker(() =>
{
Progress.Value = int.Parse(Math.Truncate(percentage).ToString());
}));
}
else
{
Progress.Value = int.Parse(Math.Truncate(percentage).ToString());
}
if (LabelProgress.InvokeRequired)
{
LabelProgress.Invoke(new MethodInvoker(() =>
{
LabelProgress.Text = int.Parse(Math.Truncate(percentage).ToString()) + "%";
}));
}
else
{
LabelProgress.Text = int.Parse(Math.Truncate(percentage).ToString()).ToString() + "%";
}
}
while (bytesRead > 0);
}
else
{
throw new ArgumentException(response.StatusDescription, "Respuesta del Servidor");
}
}
catch (Exception ex)
{
MessageBox.Show("Error en DownloadFileWithProgress" + ex.Message);
}
finally
{
if (response != null)
response.Close();
if (remoteStream != null)
remoteStream.Close();
if (localStream != null)
localStream.Close();
}
}
- the problem is that I'm running with normal privileges, I don't want to have to use administrative privileges , but running gives me an access denied error when trying to write the file to the application directory.
There is no solution, specify until today 04/14/2021. For Windows Operating Systems the folders
they are blocked and only the installers and the execution of software with elevated privileges have access, for security reasons there is no way and it is preferable not to try to avoid this parameterization of the OS
The Alternate solution has to do with the use of
ClickOnce
Microsoft for update support or the use ofAppData
in the architecture and design of the software where the main program is oneLauncher
that points to the data and executables inAppData
.Related documentation:
https://docs.microsoft.com/en-us/windows/uwp/design/app-settings/store-and-retrieve-app-data
https://www.genbeta.com/desarrollo/variables-entorno-que-serven-como-podemos-editlas-windows-linux
https://stackoverflow.com/a/7946155/4717133
Since I'm not an expert, I'm looking for a tutorial or official documentation to support me in refactoring the application.