<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; WSH: пункт «Найти объект» в контекстном меню ярлыков в Проводнике]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=2253</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=2253&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «WSH: пункт «Найти объект» в контекстном меню ярлыков в Проводнике».]]></description>
		<lastBuildDate>Sun, 21 Sep 2008 17:26:32 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[WSH: пункт «Найти объект» в контекстном меню ярлыков в Проводнике]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=14170#p14170</link>
			<description><![CDATA[<p>По-моему, было бы удобнее, если бы вместо или кроме кнопки «Найти объект...» в окне свойств ярлыков (файлов .lnk) был бы такой же пункт в их контекстном меню. (Как я слышал, в Windows Vista в меню ярлыков есть пункт «Открыть место хранения файла».) Поэтому я написал сценарий для обработки такого пункта:<br /></p><div class="codebox"><pre><code>// FindTarget.js
// аргумент - путь к lnk-ярлыку
try {
  OpenParentFolderAndSelectItem(
    GetFolderItemByFilePath(WScript.Arguments.Item(0)).GetLink.Target,
    1|4|8|16
  );
} catch (Err) {};

function GetFolderItemByFilePath(Path) {
  var FSO=new ActiveXObject(&quot;Scripting.FileSystemObject&quot;);
  return (
    new ActiveXObject(&quot;Shell.Application&quot;)).
      NameSpace(FSO.GetParentFolderName(Path)).ParseName(FSO.GetFileName(Path));
}

function OpenParentFolderAndSelectItem(FolderItem, Flags) {
  var
    Shell=FolderItem.Application,
    ShellWindows=Shell.Windows(),
    ParentFolder=FolderItem.Parent,
    Err;
  Shell.Open(ParentFolder);
  for (var t=50; --t&gt;=0; WScript.Sleep(50))
    try {
      var FolderView=ShellWindows.Item().Document;
      if (FoldersAreEqual(ParentFolder, FolderView.Folder)) {
        FolderView.SelectItem(FolderItem, Flags);
        return;
      }
    } catch (Err) {}
}

function FoldersAreEqual(Folder1, Folder2) {
  while (Folder1!=Folder2) {
    if (Folder1==null || Folder2==null || Folder1.Self.Path!=Folder2.Self.Path)
      return false;
    Folder1=Folder1.ParentFolder; Folder2=Folder2.ParentFolder;
  }
  return true;
}</code></pre></div><p>Для появления его в меню, создайте ключ реестра<br />HKEY_CLASSES_ROOT\lnkfile\shell\FindTarget<br />со значением по умолчанию<br />«&amp;Найти объект»<br />и подкюч<br />HKEY_CLASSES_ROOT\lnkfile\shell\FindTarget\command<br />со значением по умолчанию вида:<br />«&quot;путь_к_WScript.exe&quot; &quot;путь_к_файлу_сценария&quot; &quot;%1&quot;».</p><p>Например, если сценарий у вас находится по адресу<br />D:\My Works\My Scripts\FindTarget.js,<br />то можно воспользоваться таким reg-файлом:<br /></p><div class="codebox"><pre><code>REGEDIT4

[HKEY_CLASSES_ROOT\lnkfile\shell\FindTarget]
@=&quot;&amp;Найти объект&quot;
[HKEY_CLASSES_ROOT\lnkfile\shell\FindTarget\command]
@=&quot;C:\\WINDOWS\\System32\\WScript.exe \&quot;D:\\My Works\\My Scripts\\FindTarget.js\&quot; \&quot;%1\&quot;&quot;</code></pre></div><p><span class="bbu">Описание работы сценария</span>:<br />1) сценарий в качестве аргумента получает путь к файлу-ярлыку;<br />2) получаем объект FolderItem конечного объекта ярлыка;<br />3) открываем (или активируем, если оно уже открыто) окно Проводника с родительской папкой конечного объекта ярлыка с помощью команды<br /></p><div class="codebox"><pre><code>  Shell.Open(ParentFolder);</code></pre></div><p>— замечено, что метод <em>Shell.Open()</em> (а также <em>Shell.NameSpace()</em>) может принимать в качестве аргумента не только путь папки или целочисленный идентификатор специальной папки, но и объекты <em>Folder</em> и <em>FolderItem</em>. Если это у вас не работает, то можете взамен воспользоваться командой<br /></p><div class="codebox"><pre><code>  ParentFolder.Self.InvokeVerb(&quot;Open&quot;);</code></pre></div><p>4)&nbsp; получаем доступ к только что открытому окну папки, вызвав метод&nbsp; <em>ShellWindows.Item()</em> без параметров, — замечено, что вызов этого метода без параметров возвращает последнее активное окно в коллекции <em>ShellWindows</em>, а не то же самое, что <em>ShellWindows.Item(0)</em>, как утверждается в документации;<br />5)&nbsp; получаем объект <em><a href="http://msdn2.microsoft.com/en-us/library/bb774049.aspx">FolderView</a></em> окна папки и вызываем его метод <em><a href="http://msdn2.microsoft.com/en-us/library/bb774047.aspx">SelectItem()</a></em>.</p><p><span class="bbu">Рассмотрим переход от п.2 к п.3 и п.4</span>:<br />Т.к. открытие окна происходит асинхронно выполнению сценария, то без соответствующей проверки <em>ShellWindows.Item()</em> может возвратить ссылку на предыдущее активное окно (или <em>null</em>, если открытых окон не было) или окно может быть ещё не готово предоставить свой объект <em>FolderView</em>.<br />Поэтому в сценарии добавлено ожидание совпадения родительской папки конечного объекта ярлыка (<em>ParentFolder</em>) и папки в активном окне (<em>FolderView.Folder</em>).<br />При сравнении папок (объектов <em>Folder</em>) нужно учитывать, что некоторые папки (Рабочий стол, Мои документы, Общие документы…) могут рассматриваться и как обычные папки файловой системы, и как специальные системные папки; причём информация об этом может сохранятся в ярлыках. При сравнении путей таких папок (получаемых при помощи <em>.Self.Path</em>) получаются одинаковые значения; но при открытии окна такой папки, если открыто окно её «двойника», всё равно открывается новое окно. Более того, это происходит не только для самих папок-двойников, но и для их подпапок любого уровня. Поэтому при сравнении папок нужно сравнивать и их родительские папки, родительские папки родительских папок и т.д. Такое сравнение осуществляет пользовательская функция <em>FoldersAreEqual(Folder1, Folder2)</em>, где <em>Folder1</em>, <em>Folder2</em> — объекты <em>Folder</em>.</p><p><span class="bbu">Дополнительные замечания</span>:<br />• У меня сложилось впечатление, что мне удалось полностью воспроизвести поведение кнопки «Найти объект...» за исключением исправления ярлыков на более несуществующие объекты.<br />• Функция <em>OpenParentFolderAndSelectItem(FolderItem, Flags)</em> (в паре с используемой ею функцией <em>FoldersAreEqual()</em>) может без изменений использоваться в других сценариях решающих похожие задачи.<br />• В <a href="http://support.microsoft.com/kb/299776/">статье базы знаний Microsoft</a> говорится, что, если существует ключ реестра<br />HKEY_CLASSES_ROOT\lnkfile\shell,<br />то могут возникнуть трудности с запуском ярлыков с панели ярлыков MS Office 2000 (? — Microsoft Office Shortcut Bar). Подробнее в этом вопросе я не разбирался.</p><p><a href="http://forum.script-coding.com/viewtopic.php?id=2228">Тема форума</a></p>]]></description>
			<author><![CDATA[null@example.com (wisgest)]]></author>
			<pubDate>Sun, 21 Sep 2008 17:26:32 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=14170#p14170</guid>
		</item>
	</channel>
</rss>
