How to find the path to the executable of a program - vb.net

In a VB.NET application I need to set a button to start a program - specifically, Steam. But I need to allow for the user having installed the program somewhere other than the default location "C:\Program Files (x86)\Steam". So all I know is the executable name: "steam.exe".
In searching for an answer it looks like I should be able to get the path using Microsoft.Win32.Registry somehow, but the examples I'm seeing aren't helping me (I guess I'm just not getting how to apply those examples to my situation).
This tutorial gives the example of finding the path to the excel executable:
Dim regKey As RegistryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\MICROSOFT\Windows\CurrentVersion\AppPaths\excel.exe")
Dim path As String = regKey.GetValue("Path").ToString
But I'm getting a value of "Nothing" for regKey. Not only that, even if it did get a value for regKey, how would I know the registry path for another program (Steam, in my case)?
And how much will the version of Windows change the possible registry location of a program - if at all?

Related

creating a folder and verifying that the path is ok

I want to create a folder in my VB .NET app but I can't get to verify that the path is correct. For example, if I enter
My.Computer.FileSystem.CreateDirectory("lol it will work")
It works... While it doesn't look like a folder path at all... How can I verify that the path entered is correct ? And since it doesn't throw any exception, the folder must be created somewhere, but where ? I can't find it...
Thank you
Your Directory name "lol it will work" is a valid name.
When you don't provide an explicit path, My.Computer.FileSystem.CreateDirectory() (as well as some other methods/functions) will assume the string you provided is the path to a directory which relative path is your Application's current directory.
So it doesn't matter whether you're passing a complete path (that looks like a valid folder path) or a partial path/folder name that will be associated with the application's Directory as long as :
the resolved Path is a valid path (that doesn't contains invalid chars or missing folder name separator)
you (your application) have access to that path
the resulting path doesn't exceed the max allowed number of characters.
you don't encounter some specific Exceptions...
So, how do you know your application current working path ?
Since you used My.Application.FileSystem :
My.Computer.FileSystem.CurrentDirectory ' Read/Write Property As String
You can use System.IO :
System.IO.Directory.GetCurrentDirectory() ' Get a String
System.IO.Directory.SetCurrentDirectory(NewPath) ' Set
You can also use System.Environment.Directory
Environment.CurrentDirectory ' Read/Write Property As String
Both three (My.Computer.FileSystem, System.IO.Directory and Environment) are writable, and returns the current directory to be resolved in case you're providing relative paths in your application.
So, to answer your question : "How can I verify that the path entered is correct ?"
If you just created the Directory and you get no exception, then the name of your (relative) directory is valid, and the directory has been created :
My.Computer.FileSystem.CreateDirectory("lol it will work")
' Verification :
If System.IO.Directory.Exists("lol it will work") Then
MessageBox.Show("The Directory has been created !")
Else
MessageBox.Show("The Directory has'n been created !")
End If
' Shows "The Directory has been created !"
So you know that even other Functions/Methods can resolve relative path (not all though) by fallbacking to the defined Relative Working Path of your Application.
The test above is the same as :
System.IO.Directory.Exists( _
Path.Combine(Environment.CurrentDirectory, "lol it will work"))
CAUTION :
Due to the writable nature of those objects, your application
may change the Current Directory any time.
Consider :
the use of alternative objects/variables to get your working directory or similar
working with only explicit paths
using a global/static variable that stores the CurrentDirectory upon startup (can fail very easily)
restoring the CurrentDirectory whenever you're changing it (though you will use at a time or another an object that changes the CurrentDirectory without warning - read the documentation of that object whenever it involves a directory manipulation; OpenFileDialog for example which has different behaviours on XP and Win7/8) - This move is the least recommended.
Alternates :
AppDomain.CurrentDomain
AppDomain.CurrentDomain.BaseDirectory
This is a ReadOnly Property. It returns the path to the directory your assembly (application) were loaded from. Caution ! This path has a trailing "\" like :
G:\Tools\...\Sources\bin\Debug\ ' <- !!!
Assembly.GetExecutingAssembly().Location
System.IO.Directory.GetParent(Assembly.GetExecutingAssembly().Location)
This will also return the path to the directory the assembly were loaded from, but without the trailing "\" due to the use of GetParent()
Using Assembly to retrieve a path is useful when you're dealing with dependencies where not all Assemblies are loaded from the same directory. Codes that uses relative paths should use this approach instead of the classic ones.
I assume the same applies for Thread Domain if you want to get deep in multithreads (while I'm not really sure of the relevant aspect of this assumption - Never used this one !) :
Thread.GetDomain().BaseDirectory ' ReadOnly
And the good old Application.StartupPath
Application.StartupPath ' ReadOnly
...which also has a trailing "\". You can't access StartupPath until the application has actually started ! However, I've never checked whether it's working well when you start another process from your application and using that through the other process... (if it's possible... just imagining though)

Unpack a rar file

Okay, so I have searched for dll files that will allow me to unrar files and I was able to find quite a few such as unrar.dll, chilkat, sharpcompress and some more but I wanted to use the one provided by Rar themselves.
So I referenced the DLL file in my project and imported it. I was using unrar.dll.
But I wasn't able to find any up to date code to allow me to test and try things out. All the examples I found were either not up to date or not for Vb.net.
I also tried the official example, which came in the installation but that didn't work even after I fixed it and when I tried to use the code I always got an error for
object reference not set to an instance of an object
I just want to unrar a rar file from a specific location to the root directory of my program so if my program was on the desktop I want it to unrar a file in My documents and extract the files to my desktop.
If you just want to unrar files, I Was able to do that with SharpCompress
First I created a new VB.Net App and added a reference to SharpCompress.dll before using this code to extract all the files from a Rar file.
'Imports
Imports SharpCompress.Archives
Imports SharpCompress.Common
'Unrar code
Dim archive As IArchive = ArchiveFactory.Open("C:\file.rar")
For Each entry In archive.Entries
If Not entry.IsDirectory Then
Console.WriteLine(entry.Key)
entry.WriteToDirectory("C:\unrar", New ExtractionOptions With
{.ExtractFullPath = True, .Overwrite = True})
End If
Next
More code samples
for those who will try in vb.net the extract options are renamed and used as
Dim options As New ExtractionOptions With {
.ExtractFullPath = True,
.Overwrite = True
}
entry.WriteToDirectory(Application.StartupPath, options)

How do i download a file with CA-VO

I'd like to download a file using HTTP. How do I do it?
I have investigated this further and have re-ordered my suggestions from last week as a result:
The class 'CHttp' in VO's 'Internet' library has a method GetFile (the VO 2.5 "what's new" has a brief description on page 10). I've not tried it, though. You'll probably want something like this:
local oSession as CHttp
local lSuccess as logic
oSession := CHttp{}
oSession:ConnectRemote("foo.example.com") // Server domain name
lSuccess := oSession:GetFile("bar/baz.pdf",; // Remote filename
"c:\temp\baz.pdf",; // Local filename
lFailIfAlreadyExists)
oSession:CloseRemote()
// If lSuccess, the file should be downloaded to cLocalFileName.
// I don't know whether the filename arguments should use / or \ for directory separators.
I think another way is to use the Windows ShellExecute function to invoke an external program which downloads the file. I found an example of ShellExecute here. I haven't tried this as I don't have a VO compiler (or help file!) available to me at the moment. I'm not sure whether this is a good way or not, and I don't know whether it's safe from people trying to run a malicious command by supplying a sneaky filename. But I think the following might work. It assumes you have the program curl.exe (see: curl) on your path, which is used for downloading the file. You may need the fully path of curl.exe instead. I'm not sure where the file will be saved by default (I think you can specify a working directory in the parameter labelled lpDirectory)
local cParameters as string
local cURL:="http://www.example.com/interesting.htm" as string
local cLocalFile:="savefile.html" as string
cParameters := "-o "+cLocalFile+" "+cURL
ShellExecute(NULL /*Window handle*/,;
String2PSZ("open"),;
String2PSZ("curl.exe"),;
String2PSZ(cParameters),;
NULL_PTR /* lpDirectory */,;
SW_SHOWNORMAL)
See also the MSDN page for ShellExecute.
There appears to be a method App:Run(cCommand) which can be used to start external applications

Executable directory where application is running from?

I need to get the path (not the executable) where my application is running from:
System.AppDomain.CurrentDomain.BaseDirectory()
When I run the above statement with & "/images/image.jpg" on my local machine it works fine but when I install the application on another machine it says it cannot find the file and there is a lot of extra path information some.
I just need the directory of where the app is running. I am coding in VB.NET with Visual Studio 2008.
Thanks!
This is the first post on google so I thought I'd post different ways that are available and how they compare. Unfortunately I can't figure out how to create a table here, so it's an image. The code for each is below the image using fully qualified names.
My.Application.Info.DirectoryPath
Environment.CurrentDirectory
System.Windows.Forms.Application.StartupPath
AppDomain.CurrentDomain.BaseDirectory
System.Reflection.Assembly.GetExecutingAssembly.Location
System.Reflection.Assembly.GetExecutingAssembly.CodeBase
New System.UriBuilder(System.Reflection.Assembly.GetExecutingAssembly.CodeBase)
Path.GetDirectoryName(Uri.UnescapeDataString((New System.UriBuilder(System.Reflection.Assembly.GetExecutingAssembly.CodeBase).Path)))
Uri.UnescapeDataString((New System.UriBuilder(System.Reflection.Assembly.GetExecutingAssembly.CodeBase).Path))
---
Edit October 18, 2021:
Sigh... None of the above work if using net5.0 or net6.0 and publishing app as single-file bundle. Best I got now is:
// This will give you the directory but not the assembly
string basedir = AppContext.BaseDirectory;
// Before you package the app as a single file bundle, you will get the dll.
// But after you publish it, you'll get the exe.
string pathToExecutable = Environment.GetCommandLineArgs()[0].Replace(".dll", ".exe");
Dim strPath As String = System.IO.Path.GetDirectoryName( _
System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
Taken from HOW TO: Determine the Executing Application's Path (MSDN)
I needed to know this and came here, before I remembered the Environment class.
In case anyone else had this issue, just use this: Environment.CurrentDirectory.
Example:
Dim dataDirectory As String = String.Format("{0}\Data\", Environment.CurrentDirectory)
When run from Visual Studio in debug mode yeilds:
C:\Development\solution folder\application folder\bin\debug
This is the exact behaviour I needed, and its simple and straightforward enough.
Dim P As String = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
P = New Uri(P).LocalPath
You could use the static StartupPath property of the Application class.
You can write the following:
Path.Combine(Path.GetParentDirectory(GetType(MyClass).Assembly.Location), "Images\image.jpg")

"The directory name is invalid" error on Process.Start?

I am writing a launcher program, and when I go to start the process I get the "The directory name is invalid" error. Here is the code that is launching the process:
Const DEBUG_ROOT = _
"Z:\Kiosk_JC\KioskSignIn.root\KioskSignIn\KioskSignIn\KioskSignIn\bin\Debug"
Dim oKiosk As New System.Diagnostics.Process
oKiosk.StartInfo.UserName = oEnc.Decrypt(Username)
oKiosk.StartInfo.Password = oEnc.DecryptSecure(Password)
oKiosk.StartInfo.Domain = oEnc.Decrypt(Domain)
''// The AddBS function appends a '\' to the passed string if it is not present
oKiosk.StartInfo.WorkingDirectory = AddBS(DEBUG_ROOT)
oKiosk.StartInfo.FileName = "KioskSignIn.exe"
oKiosk.StartInfo.UseShellExecute = False
Dim proc As Process = Nothing
proc = System.Diagnostics.Process.Start(oKiosk.StartInfo)
I saw on another question here that I needed to set the WorkingDirectory (before I started searching I was getting the error). Even though I have this property set, I am still getting the error. Any thoughts?
More info
I should also note that my Z:\ is a on my network. I have a function that resolves a path to UNC. When I ran this function on DEBUG_ROOT, I get the same error.
I tried moving the application to c:\kiosk. Same result. I am logged in as the user I am impersonating, so I have access to all shares and files.
Here is the link, for some reason the URL formating wants to consume all the text after the link is designated:
Referred Post
Mapped drives are per-user. You are likely starting the process with a different user.
Sounds like the process can't see the Z: drive or doesn't have security access. What user context does the app run under? Perhaps the Z: drive is not available in that context.
I got the same error as you do. most likely the user you use to run the process does not have access to specified resource (exe file)
try to move your exe to some other location and/or give your user access rights to the file.