<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; AutoHotkey: проверка возможности запуска файла]]></title>
	<link rel="self" href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=511&amp;type=atom" />
	<updated>2007-06-20T00:57:01Z</updated>
	<generator>PunBB</generator>
	<id>https://forum.script-coding.com/viewtopic.php?id=511</id>
		<entry>
			<title type="html"><![CDATA[AutoHotkey: проверка возможности запуска файла]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=3246#p3246" />
			<content type="html"><![CDATA[<p>Чтобы было понятно, что и зачем я здесь предлагаю, я начну &quot;пораньше&quot;. А именно со <a href="http://www.script-coding.com/AutoHotkey/Run.html">справки</a> к командам <strong><span style="color: blue">Run</span></strong> и <strong><span style="color: blue">RunWait</span></strong> из которой следует, что запускать можно:</p><div class="quotebox"><cite>Справка в переводе YMP&#039;а пишет:</cite><blockquote><p>документ, URL, исполняемый файл (.exe, .com, .bat, и т.п.), ярлык (.lnk) или &quot;системный глагол&quot;. Если задаётся имя локального файла без указания пути, вначале производится поиск в папке, определяемой встроенной переменной A_WorkingDir. Если файл там не найден, система будет искать его в папках, включённых в системный путь (переменная окружения Path).</p></blockquote></div><p>(Спасибо <strong>YMP</strong>&#039;у за то огромное количество качественных переводов, которые он сделал).</p><p>Справка немногословна, поэтому я опишу чуть подробнее, как именно происходит запуск файла, если не указан путь к нему. Итак:</p><p>	1. Сначала запускаемый файл ищется в рабочей папке скрипта и если там не найден, то дальнейший поиск перепоручается системе<br />	2. Сначала система ищет одноимённый псевдоним в реестре по адресу <strong>HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths</strong> (см. детали по ссылке ниже)<br />	3. Затем она ищет нужный файл в папке <strong>Windows\system32</strong><br />	4. Затем ищет его в папке <strong>Windows</strong> (без подпапок)<br />	5. И наконец, файл ищется в папках, указанных в переменной окружения <strong>Path</strong></p><p>Если файл в итоге найден - он запускается, нет - облом. Естественно.</p><p><strong>Примечание 1</strong>: В <a href="http://msdn2.microsoft.com/en-us/library/aa969373.aspx">MSDN</a> указан немного иной порядок, но:<br />	во-первых, именно в таком порядке запускает файлы моя система WinXP SP2 (а, скажем, в Win98 порядок другой)<br />	во-вторых, для рассматриваемых целей не важно где именно будет найден файл, главное - может он быть запущен или нет</p><p>К чему все эти подробности? А к тому, что иногда нужно знать существует ли запускаемый файл и, соответственно, будет ли он запущен командой <strong><span style="color: blue">Run</span></strong>. Особенно это полезно при запуске консольных утилит через comspec, когда ErrorLevel не информативен. Вот посмотрите:</p><div class="codebox"><pre><code>RunWait, %comspec% /c bootcfg.exe /? &gt; c:\bootcfg.txt,, Hide ; запрос и сохранение справки по утилите bootcfg
MsgBox, ErrorLevel = %ErrorLevel% ; ErrorLevel = 0, всё нормально

RunWait, %comspec% /c bootcfg.exe /help &gt; c:\bootcfg.txt,, Hide ; несуществующий параметр help
MsgBox, ErrorLevel = %ErrorLevel% ; ErrorLevel = 1

RunWait, %comspec% /c bootcfg1.exe /? &gt; c:\bootcfg.txt,, Hide ; несуществующий файл bootcfg1.exe
MsgBox, ErrorLevel = %ErrorLevel% ; ErrorLevel = 1

RunWait, %comspec% /c &quot;bootcfg.exe /? &gt; z:\bootcfg.txt&quot;,, Hide ; несуществующий файл z:\bootcfg.txt
MsgBox, ErrorLevel = %ErrorLevel% ; ErrorLevel = 1

RunWait, %comspec% /c bootcfg.exe /? &gt; c:\bootcfg.txt,, Hide ; файл bootcfg.txt с атрибутом только для чтения
MsgBox, ErrorLevel = %ErrorLevel% ; ErrorLevel = 1</code></pre></div><p>Т.е. неясно таки был запущен файл или всё же нет. Проблема особенно актуальна, если вы хотите запустить некий стандартный файл (ну, скажем, ftp.exe), а его на этой системе нет (ох, ручки мои шаловливые).<br />Для проверки существования файла в AutoHotkey есть команда <strong><span style="color: blue">IfExist</span></strong> и функция <strong><span style="color: blue">FileExist</span></strong>, но они не годятся, т.к.<br />- во-первых, неизвестно где лежит проверяемый файл<br />- во-вторых, в реестре то они не ищут</p><p>Поэтому я написал незатейливую функцию, которая ищет указанный файл примерно так же, как будет его искать сама система. И если находит, то возвращает путь к найденному файлу. (Почему &quot;примерно&quot; - см. выше Примечание 1).<br />На самом деле система ищет и запускает исполнимые файлы даже без явного указания расширения, но явное указание даже удобнее в том смысле, что можно проверять не только исполнимые файлы.</p><p>Вот функция:<br /></p><div class="codebox"><pre><code>; ============================================================================================================
FileExistInShell( Target_File ) ; функция проверки возможности запуска файла
{
    ; В качестве параметра функция принимает имя файла (с расширением!)
    ; Если файл найден, то функция возвращает путь к нему.
    ; Обычно имеет смысл проверять исполнимые файлы, но это не обязательно :)

    ; Сначала ищем в App Paths
    Loop, HKEY_LOCAL_MACHINE, SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths, 2, 1 ; ищем путь в реестре
    {
        If ( A_LoopRegName != Target_File ) ; если текущий раздел не тот, что ищем
            Continue

        RegRead, Target_Path, %A_LoopRegKey%, %A_LoopRegSubKey%\%A_LoopRegName% ; читаем парам. &quot;по умолчанию&quot;
        IfExist, %Target_Path% ; если файл, указанный в реестре существует
            Return, %Target_Path% ; возвращаем путь к файлу
        Else ; если вдруг файл по указанному пути не существует
            Break ; больше в реестре не ищем
    }

    ; В App Paths не нашли, ищем в системных папках
    IfExist, %A_WinDir%\System32\%Target_File% ; если нашли файл
        Return, A_WinDir &quot;\System32\&quot; Target_File ; возвращаем путь к файлу

    IfExist, %A_WinDir%\%Target_File% ; если нашли файл
        Return, A_WinDir &quot;\&quot; Target_File ; возвращаем путь к файлу

    ; Напоследок ищем в переменной окружения Path
    EnvGet, EnvPath, Path ; получаем переменную окружения Path
    StringSplit, EnvPathArray, EnvPath, `; ; разбиваем на части в массив
    Loop, %EnvPathArray0% ; проверяем полученные пути
    {
        Target_Path := % EnvPathArray%A_Index% &quot;\&quot; Target_File ; составляем путь
        IfExist, %Target_Path% ; если нашли файл
            Return, %Target_Path% ; возвращаем путь к файлу
    }
    Return ; выходим из функции (не нашли файл)
}
; ============================================================================================================</code></pre></div><p><strong><span style="color: purple">Несколько примеров применения:</span></strong></p><p>Показываем путь, по которому будет запущен WinRAR.exe<br /></p><div class="codebox"><pre><code>MsgBox, % FileExistInShell( &quot;WinRAR.exe&quot; )</code></pre></div><p>Показываем путь, по которому будет запущен win.ini<br /></p><div class="codebox"><pre><code>MsgBox, % FileExistInShell( &quot;win.ini&quot; )</code></pre></div><p>Показываем путь, по которому будет запущен notepad.exe<br /></p><div class="codebox"><pre><code>fTest = notepad.exe
If FileExistInShell( fTest )
    MsgBox, % &quot;Файл будет запущен из:`n&quot;  FileExistInShell( fTest )</code></pre></div>]]></content>
			<author>
				<name><![CDATA[Androgen]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=4</uri>
			</author>
			<updated>2007-06-20T00:57:01Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=3246#p3246</id>
		</entry>
</feed>
