vb.net Can an executable replace itself and how? - vb.net

I want to make a simple updater for my program, but I do not want a separate executable. Is this possible?
So I check a location (ftp,http) for lets say version.txt, I compare versions. Now what? Can I overwrite my running executable and how. My program is like 4 MB ...
If it is not posible just tell me please :)
Update:
My.Computer.FileSystem.RenameFile("Test.exe", "SecondTest.exe")
My.Computer.FileSystem.CopyFile("12.exe", "Test.exe")
This seems to work. So I rename my current executable, then put the other on its place ... Am I looking for trouble here?

Ok so this works like a charm:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
My.Computer.FileSystem.RenameFile("Test.exe", "oldversion.exe")
My.Computer.FileSystem.CopyFile("newversion.exe", "Test.exe")
Process.Start("test.exe")
End
End Sub
End Class
So when test.exe runs, it renames itself to oldversion.exe then copies newversion to test.exe and starts it, then shuts down.
Now all I have to add is check for oldversion at every start and delete it if it exists.
The trick was to rename itself ...

Related

Why does my subroutine, which handles a double-click event on a listbox, not work?

I have declared a Sub that is meant to trigger when the listbox 'lstStudents' is double-clicked. However, it does not trigger when this happened. There can't be an error in the code itself as it is auto-generated. Why does the code not function as expected? The code is below:
Private Sub lstStudents_DoubleClick(sender As Object, e As EventArgs) Handles lstStudents.DoubleClick
Msgbox("test")
End Sub
The message box is only present for testing purposes.
Could You try to delete that previous "lstStudents" and add new one then apply the "ListBox1_DoubleClick" on it again to make sure it works.
Otherwise let us know what is going there because I think your code is normally and it should be working 100%.

How do you launch an .exe in a VB.net application who's directory varies amongst users?

I am creating an application for an Arma 3 server that directly launches the game and connects the user to a specific server. The problem that I am encountering, being the relatively new VB coder that I am, is that the Arma3battleye.exe directory (the .exe used to launch the game) may be installed in different directories depending on where the user originally installed it. I've developed the code to connect the user to the server if they've installed Arma in the normal location:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Process.Start("C:\Program Files (x86)\Steam\steamapps\common\Arma 3\arma3battleye.exe", "2 1 -noSplash -skipIntro -useBE -noPause -world=empty -connect=192.99.36.80 -port=2505 -mod=#Exile;#AlRayak;#AllInArmaTerrainPack;#CUP Units;#CUP Vehicles;#CUP Weapons;#CBA_A3;#TRYK's Multi-Play Unifrom's pack")
End Sub
However, after researching for many hours, I cannot determine how to have the program automatically determine the install directory of the arma3batteye.exe and then execute it with all of the correct start parameters included. Any solutions or pointers to help solve this problem would be greatly appreciate.
TLDR: What is the easiest way to program an application to automatically find the install directory of a given .exe and then execute it with the given parameters as I've done above?
Edit: Another thread similar to mine asks a similar question (how to view/get to the steam folder without hard coding it. They arrive at the conclusion that if you do (for winx32):
Dim strSteamInstallPath as String = My.Computer.Registry.GetValue(
"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", Nothing)
Or using this registry location for winx64:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Valve\Steam
and then were to create a button using Process.Start that it would allow you to ultimately view the directory. At this point I haven't discovered a way for that to translate into being able to execute the battleyearma3.exe from within that steam directory with the proper parameters. While it seems this code may be useful in arriving at the solution I'm looking for, I can only get the program to view the general steam directory at this time.
edit: Solution posted at bottom. Thanks to #VisualVincent who was really the one that allowed me to complete this. It really should be you having posted the correct answer, not me.
I would use the registry...
You add a key like HKEY_LOCAL_MACHINE\Software\Arma3\ServerPath = "..." when you install the server.
And whenever you need to start the client, you check up the path from that registry key.
So with the comments and tips you gave me (especially #VisualVincent) I managed to piece enough stuff together to solve my issue. Thanks to everyone for the help:
First I declared 2 variables. The first one (BattleyePath) goes into the registry as far as I can get it to dig. Executing this variable on its own will open the users steam directory. I then declared a second variable (BattleyePath2) which uses IO.Path.Combine get to the directory the users Arma3.exe is installed in:
Dim BattleyePath As String = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Valve\Steam", "InstallPath", Nothing)
Dim BattleyePath2 As String = IO.Path.Combine(BattleyePath, "SteamApps", "common", "Arma 3", "arma3battleye.exe")
I added a couple buttons to close the program and mute the sound:
`Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Close()
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
My.Computer.Audio.Stop()
End Sub`
Finally I created the button that actually launches the game:
`Private Sub Button4_Click_1(sender As Object, e As EventArgs) Handles Button4.Click
Process.Start(BattleyePath2, "2 1 -noSplash -skipIntro -useBE -noPause -world=empty -connect=192.99.36.80 -port=2505 -mod=#Exile;#AlRayak;#AllInArmaTerrainPack;#CUP Units;#CUP Vehicles;#CUP Weapons;#CBA_A3;#TRYK's Multi-Play Unifrom's pack")
End Sub`

How to save a changed label when you exit

In my program I have a preview, and edit side.
When you edit using the text boxes on the edit side(right side) and click "save", It should change the label on the right side (preview side). Although when you exit the program and re-open, all the data you entered has disappeared!,
I have tried the below code and had no luck as my result.
Public Class Form1
Private Shared NameBasic As Integer
Public Sub New()
InitializeComponent()
lblNameBasic.Text = Convert.ToString(NameBasic)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
NameBasic = txtFirstBasic.Text
lblNameBasic.Text = Convert.ToString(NameBasic)
End Sub
End Class
Also my goal is to have it be able to take it on a flashdrive onto any computer and have that data still saved within the exe. Is this even manageable? (I am more of a web based programmer so I am a bit new to this)
You need to write values to a text file at the same location of the exe. and read it. you will need both exe and the textfile.
OR
You will need to write a dll on run-time and write some values while closing the application. this will be more secure then the text file. here you will need both exe and dll to be copied into flash drive
OR
the application setting as spoken by others..

How do I use My.Computer.FileSystem.CurrentDirectory with My.Computer.Network.DownloadFile?

I am trying to use it like this:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
My.Computer.Network.DownloadFile(
"http://magicalexample.com/multi.zip", "My.Computer.FileSystem.CurrentDirectory\multi.zip")
Process.Start("cmd", "/k jar xf multi.zip")
MsgBox("Done.")
End Sub
End Class
(note: I screwed up the formatting, it's right in VB, don't worry lol)
When I try to use the update button, it tells me that destinationFileName needs to include a file name. Do they not play well together or what?
My.Computer.FileSystem.CourrentDirectory is a variable and isn't going to be magically parsed into your string. You need to concatenate the variable with the file location:
My.Computer.Network.DownloadFile("http://magicalexample.com/multi.zip", My.Computer.FileSystem.CurrentDirectory & "\multi.zip")
Or use the Path.Combine() method to merge the directory plus filename:
My.Computer.Network.DownloadFile("http://magicalexample.com/multi.zip", Path.Combine(My.Computer.FileSystem.CurrentDirectory, "multi.zip"))
Note that your examples aren't working for various reasons. They need the http:// in front of them AND the file must exist at the source (cannot be a 404 Not Found Error). Also, the extra semi colon in the comments you posted seems to indicate that it wouldn't even be compiling so you might be running a prior version. I created a new project and as an example ran this code which worked to download the google logo from the main page.
My.Computer.Network.DownloadFile("https://www.google.com/images/srpr/logo11w.png", Path.Combine(My.Computer.FileSystem.CurrentDirectory, "logo.png"))

Closing multiple programs with the same name

One part of my program is to close another program or the same program with the same name... I looked up how to do this and got this code:
Dim myprocesses() As Process
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each p As Process In myprocesses
If p.MainWindowTitle.Contains("notepad") Then
p.CloseMainWindow()
End If
Next
End Sub
It should work, however when I run it I'm getting an error message on the Next statement saying:
{"Object reference not set to an instance of an object."}
Does anyone know what's wrong with the above code?
UPDATE: Some of these answers seem to work :) Thanks. However there is a slight problem because sometimes the program doesn't load up until about 30 seconds (notepad was just put there for simplicity) so I need the code to close the PROCESS and not the actual program when it loads.
Hope you can understand that xD ^^^^
Obviously you declared the myprocesses() but null, so to achieve your task you must use GetProcessesByName
For Each process1 As Object In Process.GetProcessesByName("Notepad")
process1.Kill()
Next
But here's the proper way to manage the .exe process.
Try below code in your button click event:
Dim myProc As System.Diagnostics.Process
For Each myProc In System.Diagnostics.Process.GetProcesses
Console.WriteLine(myProc.MainWindowTitle)
If myProc.MainWindowTitle.ToUpper.Contains("NOTEPAD") Then
myProc.CloseMainWindow()
End If
Next