Launch a file using a wildcard?

Hi there, folks. Hope you’re all safe & healthy.
I’m trying to have my app launch an .exe file in a given folder without needing to specify the full file name (something akin to *.exe), but I can’t find any info on how to do that. Seems like it should be a simple thing. I’d like to be able to have a button that just targets a folder and runs whatever .exe is in that folder.
The reason for doing this is that my app is a suite of tools for windows PC tweaking/repair/diagnostics, etc. It contains other apps that sometimes need to be re-downloaded, replacing older versions.
I am using Xojo 2019r1. Updating is not a possibility at this time. I appreciate any help I can get.

I’d like to be able to have a button that just targets a folder and runs whatever .exe is in that folder.

What, all possibly 32 of them?

You need to poll the folder’s children, examine the filenames for .EXE on the end, and decide for yourself whether to launch them.

And what if there are multiple *.exe files in the folder? Launch the first you come across? Launch each? Launch the latest modified timestamp?

I am not sure if 2019R1 lets you use For Each … on a folder, but untested you could use something like this:

// Setup reference to path containing executable(s)
dim path as FolderItem = SpecialFolder.Desktop

// Launch first file ending in .exe
if path <> nil and path.Exists and path.Directory then
  for i as integer = 1 to path.Count
    dim f as FolderItem = path.Child(i)
    if f.Name.right(4).Lowercase = ".exe" then
      f.Launch
      exit for
    end if
  next
end if

Overly simplistic but gives you one general idea.

My apologies, guys. I thought I had mentioned that there is only one exe per folder. Sorry to have wasted your time & effort.
Would I still have to use a loop to launch that single file? Is there no available wildcard?

And what is wrong with a loop? Just make yourself a little method, or better yet an extension, that takes a wildcard. Untested, here is sample code that gives the general idea:

Function LaunchWildcard(extends path as FolderItem, pattern as string)

  // Create regular expression to test filenames
  dim re As new RegEx
  re.SearchPattern = pattern

  // Launch first file matching pattern requested
  if path <> nil and path.Exists and path.Directory then
    for i as integer = 1 to path.Count
      dim f as FolderItem = path.Child(i)
      // When filename matches pattern, launch it
      if re.Search(f.Name) then
        f.Launch
        exit for
      end if
    next
  end if

End Function

Then just call with something like:

  dim path as FolderItem = SpecialFolder.Desktop
  path.LaunchWildcard("^abc.*\.exe")

Note that this uses a regular expression, not the same wildcards as you may think of for filenames. So you have to format the search pattern according to regex rules – which are vastly more powerful than traditional filename wildcards. So the ^ above means the abc has to be the start of the string so it does not match MyAbcVxyz.exe or whatever. The . is needed to force it to match a period so the . ahead of exe is not itself treated as a single character wildcard. Some people prefer “^abc.*[.]exe” type syntax instead.

Probably better would be to have it return a boolean so you can tell when it fails to find a match but the point here was just to show how to make an extension to simply launch a file in a given path with a single line of code.

Also note that be default the RegEx search is not case-sensitive, which is likely what you will want for testing filenames under Windows.

1 Like

If there is only one FILE in the folder, you can probably just use

var f as folderitem = parentfolder.child(0)
if f.name.right(4) = ".exe' then f.open

IIRC there may be some invisibles in the folder … eg ‘.’
so you may need to fiddle with which child index you launch

if there are more files and one of them is an exe, you absolutely have to loop

I quickly put this together:

Public Function findSingleFile(path as FolderItem, extension as String) As FolderItem
  for each f as FolderItem in path.Children
    if f.Name.LastField( "." ) = extension then
      Return f
    end if
  next
End Function

Example usage:

var dlg as new SelectFolderDialog
var path as FolderItem = dlg.ShowModal
if path <> nil then
  var file as FolderItem = findSingleFile( path, "png" )
  MessageBox( file.NativePath )
end if

@Douglas_Handy has the best approach if you have a pattern to match, but if you always have only a single file with that extension in the directory, then my version will get you there.

Anthony,

While I like your function, he did say he is at 2019r1 and not planning on an upgrade. Which is why I did not use For Each or LastField() etc. But it could be easily switched to syntax that is 2019r1 friendly without using RegEx like my sample.

Ah. I missed that. My bad. Thanks for pointing it out.

Great googly-moogly! You guys are so awesome. Thank you all so much for all the help. I’ll play around with what you’ve given me and let you know how it goes.
BTW: I never said there was anything wrong with a loop, just asked if that would still need to be used. :wink:

I’m having an issue with all examples given above, all in the same line:
dim f as FolderItem = path.Child(i) (or similar)
This throws a type mismatch error saying that “Parameter Name expects string, but this is type integer”.
I do understand why it’s throwing the error.
I feel like I’m staring at the solution to that but just don’t see it. Any suggestions?

My bad; told you it was untested. Child() is for getting a given child when you know the name of it. Item() is for getting a given index element when iterating over the parent folder. Replace Child() with Item() and see if it works.

This is partly why the For Each syntax in newer versions is so nice…

1 Like

EUREKA! (no, I’m not saying you stink)
.Item(1)
That did the trick. Thank you all so much for your help!

1 Like