【问题标题】:Making my application to be the default one to open all .txt files使我的应用程序成为打开所有 .txt 文件的默认应用程序
【发布时间】:2014-09-16 02:12:07
【问题描述】:

发布我的应用程序后,我可以将我的应用程序 exe 文件指定为默认打开 .txt 文件的文件。在这里如何获取调用应用程序的文件的文件路径?

    public MainWindow()
    {
        InitializeComponent();
        string filePath = "";
        FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        StreamReader sr = new StreamReader(fs);
        txt.Text = sr.ReadToEnd();
        sr.Close();
        fs.Close();
    }

当用户从资源管理器中双击某个 txt 文件时,我如何获取文件路径..?

【问题讨论】:

  • 顺便说一句,您可能想要使用using 块而不是手动关闭FileStreamStreamReader。这没什么大不了的,但要养成一个好习惯。
  • 设置为默认应用需要调整注册表,这可能需要提升权限。
  • 我通常使用积木马修豪根。但这样做可能会在我说不清楚或不恰当的时候对我投反对票。
  • 没有人会因为使用using 块而投反对票。这被认为是一种很好的做法。

标签: c# wpf winforms


【解决方案1】:

文件参数通过命令行参数传递。因此,您需要检查您的Program.cs 文件(可能)以查看string[] args 参数。

void Main(string[] args)
{
    string filename;

    if(args != null && args.Length > 0)
        filename = args[0];
    else
        filename = null;

    // use filename as appropriate, perhaps via passing it to your entry Form.
}

本质上,当您在记事本是默认文本编辑器时双击test.txt 时,explorer.exe(Windows 资源管理器、桌面、开始菜单,您有什么)的调用看起来像这样:

notepad.exe C:\users\name\desktop\test.txt

这与您在命令行中调用robocopy 使用的语法相同(尽管您可能需要比这更多的参数):

robocopy source.txt destination.txt

通过此工作流程,您还可以覆盖默认文件关联行为,以启动您选择的程序来读取文件,类似于程序化 Open With...。以下将始终打开记事本,无论其他任何应用程序可能与.jpg 扩展名(可能不是记事本)相关联。

notepad.exe C:\users\name\desktop\test.jpg

【讨论】:

  • 感谢您的回答,我将使用 Windows 窗体应用程序检查它并告诉您。但是wpf中没有void main。有什么解决办法吗?
  • @Sayka 啊,你已经标记了你的问题winforms。我不确定。我可以四处逛逛,看看我能找到什么,我并不立即熟悉 WPF 的工作流程。但它应该是应用程序的入口点所在的任何地方。
  • 谢谢你,马修。从您的详细解释中,我了解了如何将参数传递给应用程序..
【解决方案2】:

有几种方法可以使您的应用程序成为特定文件类型的默认应用程序。

  1. 您可以手动更改注册表值并提供 .txt 扩展名的应用程序路径。 HKEY_CURRENT_USER\Software\Classes
  2. 在您的安装项目中分配属性:项目属性->发布->选项->文件关联->[添加您的扩展]
  3. 您可以编写一些代码来更改注册表并为特定扩展关联默认应用程序。

[DllImport("Kernel32.dll")]
private static extern uint GetShortPathName(string lpszLongPath, 
    [Out] StringBuilder lpszShortPath, uint cchBuffer);

// Return short path format of a file name
private static string ToShortPathName(string longName)
{
    StringBuilder s = new StringBuilder(1000);
    uint iSize = (uint)s.Capacity;
    uint iRet = GetShortPathName(longName, s, iSize);
    return s.ToString();
}

// Associate file extension with progID, description, icon and application
public static void Associate(string extension, 
       string progID, string description, string icon, string application)
{
    Registry.ClassesRoot.CreateSubKey(extension).SetValue("", progID);
    if (progID != null && progID.Length > 0)
        using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(progID))
        {
            if (description != null)
                key.SetValue("", description);
            if (icon != null)
                key.CreateSubKey("DefaultIcon").SetValue("", ToShortPathName(icon));
            if (application != null)
                key.CreateSubKey(@"Shell\Open\Command").SetValue("", 
                            ToShortPathName(application) + " \"%1\"");
        }
}

// Return true if extension already associated in registry
public static bool IsAssociated(string extension)
{
    return (Registry.ClassesRoot.OpenSubKey(extension, false) != null);
}

///How to Associate
///.ext: give the extension here ie. .txt
///ClassID.ProgID: Give the unique id for your application. ie. MyFirstApplication1001
///ext File:Description of your application
///YourIcon.ico:Icon file
///YourApplication.exe:Your application name
Associate(".ext", "ClassID.ProgID", "ext File", "YourIcon.ico", "YourApplication.exe");

您也可以阅读这篇文章并从here下载相同的示例

【讨论】:

    【解决方案3】:

    有两种方法可以在 .NET 中获取命令行参数。您可以在Main 方法上放置参数列表,也可以使用Environment.GetCommandLineArgs 方法。

    var allArgs = Environment.GetCommandLineArgs();
    // The first element is the path to the EXE. Skip over it to get the actual arguments.
    var userSpecifiedArguments = allArgs.Skip(1);
    

    由于您使用的是 WPF(因此不要控制 Main 方法),因此最好的选择是使用 GetCommandLineArgs

    【讨论】:

    • 您可以(并且通常应该)在任何类型的程序中控制Main 方法,即使它碰巧使用了 WPF。WPF 与该问题完全无关。
    【解决方案4】:

    在 Matthew Haugen 的帮助下,我完成了这项工作,并为 Forms Application 工作

    程序.cs

    static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1(args != null && args.Length > 0 ? args[0] : ""));
        }
    }
    

    还有形式

    public partial class Form1 : Form
    {
        public Form1(string fileName)
        {
            InitializeComponent();
            if (fileName != "")
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                using (var sr = new StreamReader(fs)) textBox1.Text = sr.ReadToEnd();
        }
    }
    

    我假设它可能对表单应用程序有所帮​​助。但我仍在寻找在 WPF 中做同样事情的答案..

    【讨论】:

      【解决方案5】:

      这是 WPF 的解决方案

      Matthew 向我展示了如何在 Windows 窗体应用程序中执行此操作,我进行了一些研究并找到了 wpf 的解决方案。

      这是我一步一步做的..

      首先我在 App.Xaml.cs 中添加了一个 void Main 函数

       public partial class App : Application
      {
          [STAThread]
      
          public static void Main()
          {
      
          }
      }
      

      编译时显示错误说应用程序有多个入口点。双击时,它导航到实际入口点所在的 App.g.cs 文件..

         public partial class App : System.Windows.Application {
      
          /// <summary>
          /// InitializeComponent
          /// </summary>
          [System.Diagnostics.DebuggerNonUserCodeAttribute()]
          [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
          public void InitializeComponent() {
      
              #line 4 "..\..\App.xaml"
              this.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative);
      
              #line default
              #line hidden
          }
      
          /// <summary>
          /// Application Entry Point.
          /// </summary>
          [System.STAThreadAttribute()]
          [System.Diagnostics.DebuggerNonUserCodeAttribute()]
          [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
          public static void Main() {
              FileOpen.App app = new FileOpen.App();
              app.InitializeComponent();
              app.Run();
          }
      }
      

      .

      现在我删除了这里的所有行并将入口点复制到 App.xaml.cs 并且还从 App.xaml 中删除了 startupURI

      <Application x:Class="FileOpen.App"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               >
      <Application.Resources>
      
      </Application.Resources>
      

      现在是 App.g.cs

      public partial class App : System.Windows.Application {
      
          /// <summary>
          /// Application Entry Point.
      
      }
      

      还有 App.xaml.cs

      public partial class App : Application
      {
          [System.STAThreadAttribute()]
          [System.Diagnostics.DebuggerNonUserCodeAttribute()]
          [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
          public static void Main(string[] args)
          {
              MainWindow window = new MainWindow(args != null && args.Length > 0 ? args[0] : "");
              window.ShowDialog();
          }
      }
      

      还有主窗口

      public partial class MainWindow : Window
      {
          public MainWindow(string filePath)
          {
              InitializeComponent();
              if (filePath != "")
                  using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                  using (var sr = new StreamReader(fs)) txt.Text = sr.ReadToEnd();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-06
        • 2014-01-31
        • 2019-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多