Jump to content

Recommended Posts

Posted (edited)

I hope this is bullet proof. It search for the executable also in the CLSID, keys if the FLTP does not give answers.

Tested with Paint shop pro (it executable have space) with a filename with spaces...

MsgBox(0, '', _ShellExecute('"wabmig.exe"', '', ''))

Func _ShellExecute($LINE, $FOLDER, $VERB)
   
  ; -1 Badly formatted line
  ; -2 File not found
   Local $LINE, $I, $I2, $FILE, $ARGUMENTS, $FLTP = '', $EXT = '', $CMD, $PATH, $PATHEXT, $HANDLE, _
         $DEFVERB, $ENV, $ENVX, $WILDCARDS = 0, $FOLDER, $CLSID
   
   $LINE = StringStripWS($LINE, 3)
   $LINE = _SplitArguments($LINE)
   If $line = -1 Then Return -1
   $line = StringSplit($line,@lf)
   $FILE = $LINE[1]
   $ARGUMENTS = $LINE[2]
   $LINE = ''

  ;Now we separed $File and $Arguments
   If StringInStr($FILE, '*') Or StringInStr($FILE, '?') Then $WILDCARDS = 1
   
   Select
      Case StringInStr(FileGetAttrib($FILE), 'd');It is a folder
         $FLTP = 'Folder'
         $LINE = '"' & $FILE & '" ' & $ARGUMENTS
      Case Not FileExists($FILE)    ;It seems the file does not exist
         Select
            Case _Any(StringLeft($FILE, StringInStr($FILE, ':')), 'http:|https:');It is a internet address
               $EXT = 'html'
               $LINE = $FILE & ' ' & $ARGUMENTS
            Case StringLeft($FILE, 4) = 'www.';It is technically badly formatted internet address.
               $EXT = 'html'
               $LINE = $FILE & ' ' & $ARGUMENTS
            Case StringLeft($FILE, StringInStr($FILE, ':')) = 'mailto:';It is email link
               $FLTP = 'mailto'
               $LINE = $FILE & ' ' & $ARGUMENTS
            Case Not StringInStr($FILE, '\') And StringInStr($FILE, '.', 0, -1);It is a file name with extension, but it isn't in the current folder.
               Select
                  Case RegRead('HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\' & $FILE, '') <> '';It have its HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths key
                     $LINE = _RunRegShortCut($FILE, $ARGUMENTS)
                  Case Else;We need to look for this file in the whole %path%
                     $PATH = StringSplit(EnvGet('path'), ';')
                     For $I = 1 To $PATH[0]
                        $HANDLE = FileFindFirstFile($PATH[$I] & '\' & $FILE)
                        If $HANDLE = -1 Then ContinueLoop
                        $LINE = '"' & $PATH[$I] & '\' & FileFindNextFile($HANDLE) & '" ' & $ARGUMENTS
                        FileClose($HANDLE)
                        ExitLoop
                     Next
                     If $LINE = '' Then Return -2
               EndSelect
            Case StringInStr($FILE, '\', 0, -1) < StringInStr($FILE, '.', 0, -1);It is full path with extension, but it does not exist.
              ;So we can assume that is badly typed.
               Return -2
            Case StringInStr($FILE, '\', 0, -1) > StringInStr($FILE, '.', 0, -1);It is path without extension. The file still may exists.
              ;We have to check all %pathext% in the given folder
               $PATH = StringLeft($FILE, StringInStr($FILE, '\', 0, -1))
               $FILE = StringTrimLeft($FILE, StringInStr($FILE, '\', 0, -1))
               $PATHEXT = StringSplit(EnvGet('pathext'), ';')
               For $I = 1 To $PATHEXT[0]
                  $HANDLE = FileFindFirstFile($PATH & $FILE & $PATHEXT[$I])
                  If $HANDLE = -1 Then ContinueLoop
                  $LINE = '"' & $PATH & FileFindNextFile($HANDLE) & '" ' & $ARGUMENTS
                  FileClose($HANDLE)
                  ExitLoop
               Next
               If $LINE = '' Then Return -2
            Case Not StringInStr($FILE, '\', 0, -1) And Not StringInStr($FILE, '.', 0, -1);It is just a word, with no extension and no path. Good hunt.
              ;We have to check all %pathext% in the HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths and in all %path%
               $PATHEXT = StringSplit(EnvGet('pathext'), ';')
               For $I = 1 To $PATHEXT[0]
                  RegRead('HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\' & $FILE & $PATHEXT[$I], '')
                  If @error Then ContinueLoop
                  $FILE = $FILE & $PATHEXT[$I]
                  $LINE = _RunRegShortCut($FILE, $ARGUMENTS)
                  ExitLoop
               Next
               If $LINE = '' Then
                  $PATH = StringSplit(EnvGet('path'), ';')
                  For $I = 1 To $PATH[0]
                     For $I2 = 1 To $PATHEXT[0]
                        $HANDLE = FileFindFirstFile($PATH[$I] & '\' & $FILE & $PATHEXT[$I2])
                        If $HANDLE = -1 Then ContinueLoop
                        $LINE = '"' & $PATH[$I] & '\' & FileFindNextFile($HANDLE) & '" ' & $ARGUMENTS
                        ExitLoop 2
                     Next
                  Next
                  If $LINE = '' Then Return -2
               EndIf
            Case Else;I do not know when it may happen, but...
               Return -1
         EndSelect
      Case Else;The file clearly exists
         If $WILDCARDS = 0 Then
            $LINE = '"' & $FILE & '" ' & $ARGUMENTS
         Else
            $PATH = StringLeft($FILE, StringInStr($FILE, '\', 0, -1))
            $HANDLE = FileFindFirstFile($FILE)
            $LINE = '"' & $PATH & FileFindNextFile($HANDLE) & '" ' & $ARGUMENTS
            FileClose($HANDLE)
         EndIf
   EndSelect
   
   $LINE = StringSplit(_SplitArguments($LINE), @LF)
   $FILE = FileGetShortName($LINE[1]);ok, it is not the best, but it a pain othewise.
   $ARGUMENTS = $LINE[2]
   
   If $EXT = '' Then $EXT = StringTrimLeft($FILE, StringInStr($FILE, ".", 0, -1))
   If $EXT = 'lnk' Then;Beasts of .lnk files...
      $FLTP = FileGetShortcut($FILE)
      If FileExists($FLTP[0]) Then Run($FLTP[0] & ' ' & $FLTP[2] & $ARGUMENTS, $FLTP[1], $FLTP[6])
      $CMD = $FILE & ' ' & $ARGUMENTS
      $FLTP = ''
   Else
      If $FLTP = '' Then
         $FLTP = RegRead("HKEY_CLASSES_ROOT\." & $EXT, "")
         If @error Then $FLTP = $EXT & "file"
      EndIf
      $DEFVERB = RegRead("HKEY_CLASSES_ROOT\" & $FLTP & "\shell", "")
      If $DEFVERB = "" Then $DEFVERB = "Open"
      If $VERB = "" Then
         $CMD = RegRead("HKEY_CLASSES_ROOT\" & $FLTP & "\shell\" & $DEFVERB & "\command", "")
      Else
         $CMD = RegRead("HKEY_CLASSES_ROOT\" & $FLTP & "\shell\" & $VERB & "\command", "")
      EndIf
      If @error Then
         $CMD = RegEnumKey("HKEY_CLASSES_ROOT\" & $FLTP & "\shell", 1)
      EndIf
      If @error Then
         $CLSID = RegRead("HKEY_CLASSES_ROOT\" & $FLTP & "\CLSID", '')
         If $CLSID = '' Then Return 2
         Select
            Case RegRead("HKEY_CLASSES_ROOT\CLSID\" & $CLSID & '\LocalServer32', '') <> ''
               $CMD = RegRead("HKEY_CLASSES_ROOT\CLSID\" & $CLSID & '\LocalServer32', '')
               $cmd = $cmd & ' "' & $file & '" ' & $ARGUMENTS
            Case RegRead("HKEY_CLASSES_ROOT\CLSID\" & $CLSID & '\LocalServer', '') <> ''
               $CMD = RegRead("HKEY_CLASSES_ROOT\CLSID\" & $CLSID & '\LocalServer', '')
               $cmd = $cmd & ' ' & $file & ' ' & $ARGUMENTS
            Case Else
               Return -2
         EndSelect
      Else
         $CMD = StringReplace($CMD, "%l", $FILE)
         $CMD = StringReplace($CMD, "%1", $FILE)
         $CMD = StringReplace($CMD, "%*", $ARGUMENTS)
         $CMD = StringReplace($CMD, "%2", $ARGUMENTS)
         For $I = 2 To 9
            $CMD = StringReplace($CMD, "%" & $I, "")
         Next
         
         $ENV = StringInStr($CMD, "%", 0, 1)
         If Not @error Then
            For $I = 1 To 5 Step 2
               If Not StringInStr($CMD, "%", 0, $I) Then ExitLoop
               $ENVX = StringMid($CMD, StringInStr($CMD, "%", 0, $I) + 1, StringInStr($CMD, "%", 0, $I + 1) - 2)
               $CMD = StringReplace($CMD, "%" & $ENVX & "%", EnvGet($ENVX))
            Next
         EndIf
         If StringInStr($CMD, '/idlist,%I') Then
            $CMD = StringReplace($CMD, ',/idlist,%I', '');needed for opening folders with explorer.
            $CMD = StringReplace($CMD, '/idlist,%I', '')
         EndIf
         
         While StringInStr($CMD, '""')
            $CMD = StringReplace($CMD, '""', '')
         Wend
      EndIf
      Run($CMD, $FOLDER)
      If @error = 1 Then Return -2
   EndIf
   
   Return $CMD
EndFunc  ;==>_ShellExecute

Func _SplitArguments($LINE)
   Local $LINE, $FILE, $I, $ARGUMENTS
   
   If StringLeft($LINE, 1) = '"' Then;If the line begins with a " the text between the two " is $file and the other is $arguments.
      $I = StringInStr($LINE, '"', 0, 2)
      If $I = 0 Then Return -1      ;If there is not a second " the line is badly formatted
      $FILE = StringMid($LINE, 2, $I - 2)
      $ARGUMENTS = StringTrimLeft($LINE, $I)
   Else
      If StringInStr($LINE, ' ') Then;If there are no ", so is the first space that divide $file and $arg.
         $FILE = StringLeft($LINE, StringInStr($LINE, ' ') - 1)
         $ARGUMENTS = StringTrimLeft($LINE, StringInStr($LINE, ' ') - 1)
      Else                          ;If there are no " and no spaces, there are no arguments.
         $FILE = $LINE
      EndIf
   EndIf
   Return $FILE & @LF & $ARGUMENTS
EndFunc  ;==>_SplitArguments

Func _RunRegShortCut($FILE, $ARGUMENTS)
   Local $FILE, $CMD, $ARGUMENTS
   $CMD = RegRead('HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\' & $FILE, '')
   If StringLeft($cmd,1) <> '"' And StringInStr($cmd,' ') And Not StringInStr($cmd,'%') Then $cmd = '"' & $cmd & '"'
   $CMD = StringReplace($CMD, '%SystemRoot%', @WindowsDir)
   $CMD = StringReplace($CMD, '%ProgramFiles%', @ProgramFilesDir)
   $CMD = _SplitArguments($CMD)
   
   Select
      Case StringInStr($CMD, '%*')
         $CMD = StringReplace($CMD, '%*', $ARGUMENTS)
      Case StringInStr($CMD, '%1')
         $CMD = StringReplace($CMD, '%1', $ARGUMENTS)
      Case StringInStr($CMD, '%l')
         $CMD = StringReplace($CMD, '%l', $ARGUMENTS)
   EndSelect
   
   While StringInStr($CMD, '%')
      $CMD = StringReplace($CMD, StringMid($CMD, StringInStr($CMD, '%'), 2), '')
   Wend
   $CMD = StringSplit($CMD, @LF)
   $CMD = '"' & $CMD[1] & '" ' & $CMD[2]
   Return $CMD
EndFunc  ;==>_RunRegShortCut

Func _Any($ITEM, $LIST)
   Local $LIST
   $LIST = StringSplit($LIST, '|')
   For $C = 1 To $LIST[0]
      If $LIST[$C] = $ITEM Then
         Return 1
      EndIf
   Next
   Return 0
EndFunc  ;==>_Any
Edited by ezzetabi
Posted (edited)

Still not happening.

Still opens with the open/new/blank dialogue.

When I type "filemaker pro.exe" at a command prompt it opens to a blank screen, with no dialogue.

When I type "filemaker pro.exe" c:\file.fp5 it opens the file, so I assume it is possible.

BTW the path to my file is

C:\Documents and Settings\Monster\Desktop\Clones\file.fp5

Edited by m0n5ter
Posted

OK

It has something to do with the path.

When I do this:

_ShellExecute('"C:\Documents and Settings\Monster\Desktop\Clones\dentists.fp5"','','')

It works

When I do this:

_ShellExecute('dentists.fp5','','')

It does not :ph34r:

Posted

No. I just noticed it. The file path "bug" you reported is not actually a "bug" per se. It is a windows limitation. Until windows searches every directory on your computer for a filename, Autoit will not do it either.

Who else would I be?
Posted

No. I just noticed it. The file path "bug" you reported is not actually a "bug" per se. It is a windows limitation. Until windows searches every directory on your computer for a filename, Autoit will not do it either.

<{POST_SNAPBACK}>

How did you notice it? :ph34r:

Was it from my screenshot?

Posted (edited)

No, this-is-me. If the problem were a path problem the udf should return -2, not start the program... There is somethig strange.

Probably a Return -2 is missing somewhere.

Edited by ezzetabi
Posted

... I do not know. A string like dentist.fp5 should activate this part of code...

Case Not StringInStr($FILE, '\') And StringInStr($FILE, '.', 0, -1);It is a file name with extension, but it isn't in the current folder.
               Select
                  Case RegRead('HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\' & $FILE, '') <> '';It have its HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths key
                     $LINE = _RunRegShortCut($FILE, $ARGUMENTS)
                  Case Else;We need to look for this file in the whole %path%
                     $PATH = StringSplit(EnvGet('path'), ';')
                     For $I = 1 To $PATH[0]
                        $HANDLE = FileFindFirstFile($PATH[$I] & '\' & $FILE)
                        If $HANDLE = -1 Then ContinueLoop
                        $LINE = '"' & $PATH[$I] & '\' & FileFindNextFile($HANDLE) & '" ' & $ARGUMENTS
                        FileClose($HANDLE)
                        ExitLoop
                     Next
                     If $LINE = '' Then Return -2

...And of course finding nothing in the Registry should look for the file in the path, and since the file will be not found the $line should be still empty and activate the Return...

m0n5ter, can you please put a msgbox(0,'',$line) just before If $line = '' Then Return -2 ?

Is it empty, if it is not what is wrote?

Posted

I hope that this indeed solves something. When the script have the full path it converts it to its short version. So with no spaces there should be no problems... Those " are indeed a pain...

Posted

I hope that this indeed solves something. When the script have the full path it converts it to its short version. So with no spaces there should be no problems... Those " are indeed a pain...

<{POST_SNAPBACK}>

OK I figured it out, but have not solved it. Basically $line when it first gets into the UDF is correct. But when it passes $line to your UDF Func _SplitArguments($LINE)

and passes the results back, $file did not equal what $line did. I fixed it for my solution by just making $file = $line since I am only using it in this one solution, with no arguments.

For your information, $file on it's return was "C:\Documents" and $arguments was " and Settings\Monster\Desktop\Clones\Dentists.fp5"

So it would appear as though Func _SplitArguments($LINE) is making a mess of the splint because of the presence of the space. But I didn't have time to check it out any further, but as I said I got it working for me by missing out the Func _SplitArguments($LINE) and making $file = $line.

Cheers

Monster

  • 2 weeks later...
Posted

Guys, I need some help.

I need to use _ShellExecute to open IE and load a URL , but it doesn´t work on Windows NT.

Can anyone help me?

Thanks.

Posted (edited)

ezzetabi, Nice Job

I let windows explorer do all the work.

Note: needs improvements, but is good enough for me because it does exactly what I need.

Opt("WinTitleMatchMode",4)
Opt("TrayIconDebug",1)

_LaunchSomeThing(@ProgramFilesDir & "\AutoIt3\AutoIt.chm")

Func _LaunchSomeThing($Path)
   $PathArray = StringSplit($Path,"\")
   $FileName = $PathArray[$PathArray[0]]
   $Dir = StringTrimRight($Path,StringLen($PathArray[$PathArray[0]]) + 1)   
   If StringRight($Dir,1) = "\" Then $Dir = StringTrimRight($Dir,1)
   Run("explorer " & $Dir,"",@SW_MINIMIZE)
   $ExpClass = "classname=CabinetWClass|classname=ExploreWClass"
   $ExpClassArray = StringSplit($ExpClass,"|")
   For $i = 1 To $ExpClassArray[0]
      While 1
         If WinExists($ExpClassArray[$i]) Then ExitLoop(2)
         Sleep(10)
      Wend
   Next
   WinWait($ExpClassArray[$i],$Dir)
   $ExpHandle = WinGetHandle($ExpClassArray[$i],$Dir)
   ControlFocus($ExpClassArray[$i],$Dir,"SysListView321")
   ControlSend($ExpClassArray[$i],$Dir,"SysListView321",$Filename)
   ControlSend($ExpClassArray[$i],$Dir,"SysListView321","{ENTER}")
   WinClose($ExpHandle,$Path)
EndFunc
Edited by bshoenhair
  • 4 months later...
Posted

Man! I must have started something. :lmao: It's amazing that a simple idea made by one person (me) can be changed and improved by another (ezzetabi) and eventually updated and improved by yet another person (slimshady). This is something that has gone much farther than I ever expected. One thing I did notice Slim is that you cannot select a "verb" to execute on a file using the DllCall version. Therefore, one cannot (for example) launch the Print verb on a txt file or similar situations.

Who else would I be?
Posted (edited)

I made an alternative to the Run function.

I was bored that's why I made it functional.

Edit:

I just read the thread completely and I realise that ezzetabi didn't even use ShellExecute.

I used ezzetabi's function which he posted here.

Edited by SlimShady

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...