65.9K
CodeProject 正在变化。 阅读更多。
Home

快速应用程序启动实用程序

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (8投票s)

2007 年 3 月 3 日

CPOL

5分钟阅读

viewsIcon

48013

downloadIcon

812

这款 Windows 工具能让你通过输入应用程序名称或部分名称来简单地启动应用程序。它省去了你在层级式的“开始->所有程序”菜单中搜索的麻烦,或者在任务栏创建一个庞大的“快速启动”文件夹的需要。

引言

如果你的电脑上安装了大量应用程序,“开始->所有程序->..”文件夹可能塞满了各种各样的链接。当你记不清应用程序的路径,或者文件夹里有太多链接时,寻找一个特定的应用程序来启动可能不是一件愉快的事情。

如果你能只需输入应用程序的名称(或部分名称),然后让电脑为你提供所有匹配的应用程序,并通过按一次按键来启动它们,那岂不是太棒了?

这个小巧的“启动器”应用程序就能做到这一点。它适用于 Windows XP,并使用了 .NET 2.0 框架。

输入应用程序名称或部分名称,然后按回车键

Screenshot - image001.jpg

现在,使用向上/向下箭头键从过滤后的匹配列表中选择要运行的应用程序,然后按一次回车键即可启动它

Screenshot - image002.jpg

请注意,Windows Vista 在其核心操作系统开始菜单中提供了类似的功能。现在我们也可以在 Windows XP 中做到这一点了。

配置选项

右键单击组合框左侧的图标以打开上下文菜单。然后选择“高级设置”以查看设置窗体。
可以在此处进行其他自定义设置,例如指定搜索快捷方式文件的文件夹。

Screenshot - image004.jpg

建议:将启动器配置为始终通过 Alt+Ctrl+L 弹出

“启动器”是一个单实例应用程序。如果有人尝试启动一个新实例的启动器应用程序,而另一个实例已存在,则焦点将转移到已有的“启动器”应用程序,而不会创建新的实例。
为启动器应用程序创建快捷方式并为其分配一个键盘快捷键(我使用了 Alt+Ctrl+L)非常有帮助,这样无论你在电脑上做什么,都可以随时输入 Alt+Ctrl+L,并将焦点切换到启动器应用程序。

Screenshot - image003.jpg

在此应用程序出现之前,我大量使用“快速启动”工具栏,但自从有了这个程序,我移除了“快速启动”快捷方式,并且只使用这个工具来启动我的应用程序。它更快,而且我的任务栏区域也更整洁,利用得更好。

它是如何工作的?

启动时,应用程序会扫描“开始 -> 所有程序”菜单下的所有快捷方式(*.lnk)文件名和属性。它还会查找自定义配置部分(如配置选项部分所述)中其他文件夹里的快捷方式文件。快捷方式文件名和属性存储在一个 DataTable 对象中。一个 DataView 对象用于根据用户输入过滤内容。

当用户在组合框中输入一个字符串并按 Enter 键时,组合框将填充所有包含该字符串的程序文件。如果用户在选中一个应用程序时按 Enter 键,该应用程序就会启动。所以只需输入应用程序的名称(或部分名称),按 Enter 键获取匹配应用程序的列表,然后再次按 Enter 键即可启动您想要的应用程序。非常简单。

该应用程序是一个非常小的窗体,没有边框,并且默认配置为“最顶层”显示在右上角(位于潜在的最大化窗口标题栏下方)。您可以通过拖动左侧的图标来移动该应用程序。要查看更多选项,请右键单击左侧的图标,会出现一个弹出菜单。

用于查找和存储快捷方式文件名的代码段如下:

private void ProcessFolder(string folderName) {
   if (!System.IO.Directory.Exists(folderName))
      return;
   DirectoryInfo d = new DirectoryInfo(folderName);
   foreach (FileInfo f in d.GetFiles()) {
      if (f.Extension.ToLower() == ".lnk")
         ProcessShortcutFile(f);
   }
   foreach (DirectoryInfo di in d.GetDirectories())
      ProcessFolder(di.FullName);
}

private void ProcessShortcutFile(FileInfo f) {
   FileInfo fi;
   
   if (System.IO.File.Exists(f.FullName)) {
      WshShortcut theShortcut = (WshShortcut)theShell.CreateShortcut(f.FullName); 
      if (System.IO.File.Exists(theShortcut.TargetPath)) {
         fi = new FileInfo(theShortcut.TargetPath);
         if (mExtentions.Contains(fi.Extension.ToLower())) {
            string name;
            name = f.Name.Substring(0, f.Name.Length - 4);
            if (name.Contains("Shortcut to ")) {
               if (name.IndexOf("Shortcut to ") == 0) {
                  name = name.Replace("Shortcut to ", "");
               }
            }

            mRowArgs[0] = name;
            mRowArgs[1] = ReplaceEnvVar(theShortcut.TargetPath);
            mRowArgs[2] = ReplaceEnvVar(theShortcut.WorkingDirectory);
            mRowArgs[3] = theShortcut.Arguments;
            mRowArgs[4] = ReplaceEnvVar(theShortcut.IconLocation);
            mRowArgs[5] = ReplaceEnvVar(f.FullName);

            if (mRowArgs[4].Split(',')[0] == "") {
               mRowArgs[4] = mRowArgs[1] + mRowArgs[4];
            }

            if (Properties.Settings.Default.SelectDistinctShortcutFiles) {
               if (!mAllTargetFilesAndArguments.Contains(mRowArgs[1] + 
		" " + mRowArgs[3])) {
                  mAllTargetFilesAndArguments.Add(mRowArgs[1] + " " + mRowArgs[3]);
                  mDataTable.Rows.Add(mRowArgs);
               }
            } else {
               mDataTable.Rows.Add(mRowArgs);
            }
         }
      }
   }
}

扫描快捷方式文件

我使用 System.IO 命名空间中的 DirectoryInfo FileInfo 类来遍历指定文件夹内的所有快捷方式文件。然后,我使用 WshShortcut COM 对象来获取快捷方式文件的 TargetPathArgumentsWorkingDirectoryIconLocation 属性。如果您知道任何纯 .NET 对象可以用来收集快捷方式文件中的信息,请告诉我。

从应用程序中提取图标

启动的应用程序使用一个所有者绘制的组合框,该组合框显示应用程序的图标及其快捷方式文件名。为了从应用程序中提取图标,我使用了 IconExtractor 类,该类又使用了 Shell32.dll 中的 ExtractIconExW 函数。

填充列表框

当用户输入一个 string (至少 3 个字符长)然后按 Enter 键时,将调用 PopulateComboItems() 方法。然后 DataView 被过滤并返回给 MainForm

这里是相关的代码片段。cmb ComboBox 对象。dvComboDataSource DataView 对象。

private void PopulateComboItems() {
   dvComboDataSource = sStartApps.GetMatchingLinks(cmb.Text);
   cmb.DataSource = dvComboDataSource;
   cmb.DisplayMember = "ShortcutName";
}

这是检索过滤后的 DataView 的方法

public DataView GetMatchingLinks(string s) {
   s = s.Trim();
   if (s.Length > 2) {
      mDataView.RowFilter = @"ShortcutName like '%" + s + @"%'";
      return mDataView;
   } else {
      return null;
   }
}

启动应用程序

当用户在列表框选定项上按 Enter 键时,cmb_KeyDown 事件负责检测 Enter 键,并根据 dvComboDataSource 对象启动相应的应用程序。

void cmb_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) {
   switch (e.KeyCode) {
      case Keys.Enter:
         if (cmb.SelectedIndex >= 0) {
            //Start the application
            cmb.Cursor = System.Windows.Forms.Cursors.AppStarting;
            e.SuppressKeyPress = true;
            p.BackColor = Color.LightGreen;
            p.Invalidate();

            System.Diagnostics.Process.Start(SelectedItem("ShortcutFullName"));

            cmb.Cursor = System.Windows.Forms.Cursors.Default;
         } else {
            //Search for matching applications and 
            //show them in the combo box
            . . . 
            . . . 
            . . . 
}

private string SelectedItem(string itemName) {
   return ((DataRowView)cmb.SelectedItem)[itemName].ToString();
}

启动器是一个单实例应用程序

下面的代码在启动器应用程序启动时检查所有系统进程。如果启动器应用程序的另一个实例已在运行,则它会切换到该实例。我们使用 WshShellClass COM 对象的 AppActivate() 方法。

[STAThread]
static void Main() {
   System.Diagnostics.Process p;
   if (OtherInstanceExists(out p)) {
      //Switching to a running instance of the application... 
      IWshRuntimeLibrary.WshShellClass shell = 
         new IWshRuntimeLibrary.WshShellClass();
      object p1 = (object)p.Id;
      object p2 = (object)null;
      shell.AppActivate(ref p1, ref p2);
   } else {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new MainForm());
   }
}

static bool OtherInstanceExists(out Process proc) {
   Process[] p = Process.GetProcessesByName(
      Process.GetCurrentProcess().ProcessName);
   proc = null;
   if (p.Length > 0) {
      //first check this is not the current process
      if (p.Length == 1) {
         if (p[0].Id==Process.GetCurrentProcess().Id) {
            return false;
         } else {
            proc = p[0];
            return true;
         }
      } else {
         foreach (Process pr in p) {
            if (pr.Id != Process.GetCurrentProcess().Id) {
               proc = pr;
            }
         }
         return true;
      }
   } else {
      return false;
   }
}

备注

  • 指向 URL 的快捷方式文件(*.url)不会添加到 DataTable。如果您想包含 URL,只需为 Internet Explorer 创建一个快捷方式,并将其参数设置为您感兴趣的 URL。
  • 该应用程序使用 COM 互操作进行三种类型的操作:
    1. 评估快捷方式文件的内容(目标文件、工作目录、参数等) 
    2. 使启动器成为单实例应用程序 
    3. 从目标文件中提取图标。
      如果您知道任何一种纯 .NET 方法可以完成这些任务中的任何一项,请告诉我。
  • 搜索 string 的长度必须至少为 3 个字符,否则将不会返回任何搜索结果。

历史

  • 2007 年 3 月 3 日:首次发布
© . All rights reserved.