Abdul Saleem
Abdul Saleem

Reputation: 10612

Making my application to be the default one to open all .txt files

After publishing my application, i can assign my app exe file to be the default one to open .txt files. Here how can i get the filePath for the file which have invoked the application?

    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();
    }

Here how can i get the filePath when user double click on to some txt file from explorer..?

Upvotes: 5

Views: 1760

Answers (5)

Shell
Shell

Reputation: 6849

There are several way to make your application as default application for particular file type.

  1. You can change the registry value manually and give the application path for the .txt extension. HKEY_CURRENT_USER\Software\Classes
  2. Assign the properties in your Setup Project: Project Properties->Publish->Options->File Assosiations->[Add your extensions]
  3. You can write some code to change the registry and associate the default application for particular extension.

[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");

You can also read this article and download the example for the same from here

Upvotes: 2

Joe White
Joe White

Reputation: 97696

There are two ways to get the command-line arguments in .NET. You can put a parameter list on your Main method, or you can use the Environment.GetCommandLineArgs method.

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);

Since you're using WPF (and therefore don't control the Main method), your best bet would be to go with GetCommandLineArgs.

Upvotes: 3

Abdul Saleem
Abdul Saleem

Reputation: 10612

Here's the solution for WPF

Matthew showed me how to do this in windows forms application, and i researched a bit and found solution for wpf.

Here's step by step i did..

First I added a void Main function in App.Xaml.cs

 public partial class App : Application
{
    [STAThread]

    public static void Main()
    {

    }
}

While compiling it showed an error Saying multiple entry points for the application. When double clicked, it navigated to the App.g.cs file where the actual entry point exists..

   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();
    }
}

.

Now i removed all lines here and copied the entry point to App.xaml.cs And also removed the startupURI from App.xaml

<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>

Now the App.g.cs

public partial class App : System.Windows.Application {

    /// <summary>
    /// Application Entry Point.

}

And the 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();
    }
}

And the MainWindow

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();
    }
}

Upvotes: 0

Abdul Saleem
Abdul Saleem

Reputation: 10612

With the help of Matthew Haugen i've done this and its working for Forms Application

Program.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] : ""));
    }
}

And the form

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();
    }
}

I've put this assuming it might help some for Forms Application. But i'm still looking for an answer for doing the same in WPF..

Upvotes: 0

Matthew Haugen
Matthew Haugen

Reputation: 13286

File args are passed via command-line arguments. Thus, you need to check in your Program.cs file (probably) to look at the string[] args parameter.

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.
}

In essence, the call that explorer.exe (Windows Explorer, the desktop, the start menu, what have you) makes when you double-click test.txt when Notepad is your default text editor, looks something like this:

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

It's the same kind of syntax as you'd use in a command line to call robocopy (although you'd probably need more arguments than this):

robocopy source.txt destination.txt

By consequence of this workflow, you can also override default file association behavior in order to start a program of your choosing to read a file, similar to a programmatic Open With.... The following will always open Notepad, regardless of whatever other application might be associated with the .jpg extension (which probably isn't Notepad).

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

Upvotes: 2

Related Questions