Pergunta

I have a program that works when, a file is opened with it using the right click menu in explorer. But if I select multiple files and then right click and open with my program then it opens multiple instances of my program, instead of just passing the multiple files as arguments to a single instance. The program is written in vb.net but is not a windows form, it is just a module, so I can to tick the Single instance option in the properties in Visual Studio.

So how do I open multiple files from explorer context menu in a single instance.

Foi útil?

Solução

No happy answers here, Windows Explorer doesn't provide an easy way to start your program passing all selected files. That requires a shell context menu handler, they are very difficult to write in managed code. And up to .NET 4.0 could not be safely written.

It is nevertheless easy to simulate it with the application framework available in VB.NET, make your app a singleton and implement the StartupNextInstance event. The only issue is that this is not particularly fast. And that it doesn't work in console mode apps.

Outras dicas

this link helped me to get paths of selected files in explorer by clicking on a context-menu item: .NET Shell Extensions - Shell Context Menus

it's in C# language but as that article poster said it can be used in vb.net too.

real easy :)

Hope this help you too! :)

Here's The Steps:

1) Download thee SharpShell library>>

Download the 'SharpShell Library' zip file at the top of the article and add a reference to the downloaded SharpShell.dll file.

or you can download it via Nuget:

If you have Nuget installed, just do a quick search for SharpShell and install it directly - or get the package details at https://www.nuget.org/packages/SharpShell.

Add the following references:

System.Windows.Forms
System.Drawing

Use these at top of your code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpShell;
using SharpShell.SharpContextMenu;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using SharpShell.Attributes;

Derive your Class From SharpContextMenu Right click on the SharpContextMenu part of the line and choose Implement Abstract Class.

CanShowMenu

This function is called to determine whether we should show the Context Menu Extension for a given set of files. The files the user has selected are in the property SelectedItemPaths. We can check these file paths to see whether we actually want to show the menu. If the menu should be shown, return true. If not, return false.

CreateMenu

This function is called to actually create the Context Menu. A standard WinForms ContextMenuStrip is all we need to return.

Here's the whole namespace SourceCode:

namespace CountLinesExtension
{
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class Class1 : SharpContextMenu
{
protected override bool CanShowMenu()
{
        //  We will always show the menu.
        return true;
        //throw new NotImplementedException();
    }

    protected override ContextMenuStrip CreateMenu()
    {
        //  Create the menu strip.
        var menu = new ContextMenuStrip();

        //  Create a 'count lines' item.
        var itemCountLines = new ToolStripMenuItem
        {
            Text = "Count Lines"
        };

        //  When we click, we'll call the 'CountLines' function.
        itemCountLines.Click += (sender, args) => CountLines();

        //  Add the item to the context menu.
        menu.Items.Add(itemCountLines);

        //  Return the menu.
        return menu;
        //throw new NotImplementedException();
    }
    private void CountLines()
    {
        //  Builder for the output.
        var builder = new StringBuilder();

        //  Go through each file.
        foreach (var filePath in SelectedItemPaths)
        {
            //  Count the lines.
            builder.AppendLine(string.Format("{0} - {1} Lines",
              Path.GetFileName(filePath), File.ReadAllLines(filePath).Length));
        }

        //  Show the ouput.
        MessageBox.Show(builder.ToString());
    } 

}
}

Next, we must give the assembly a strong name. There are ways around this requirement, but generally this is the best approach to take. To do this, right click on the project and choose 'Properties'. Then go to 'Signing'. Choose 'Sign the Assembly', specify 'New' for the key and choose a key name. You can password protect the key if you want to, but it is not required

Now Install and register Shell Extension: The regasm Tool

You can use the tool 'regasm' to install and register a shell extension. When using regasm, the shell extension will be installed into the registry (i.e. the Class ID of the COM Server will be put in the COM Server Classes section and associated with the path to the actual server file), it will also register the associations.

The Server Manager Tool

The Server Manager Tool is my preferred approach for installing/uninstalling and registering/unregistering, at least during development, because it lets you install and register as separate steps. It will also let you specify whether you're installing/uninstalling etc in 32 bit or 64 bit mode.

It was the whole Sample sourceCode. we can add any number of context-menu items, any function,any fileExtension,etc.

While I know this was for vb.net, I am sure you can use this c# code with just a few modifications, this worked for me. Maybe it isn't the best way to do it, but for me, it was the simplest way. It checks to see if the application title is currently running before running a second copy.

This is in the Program.cs

 static frmMain Form;

    [STAThread]
    static void Main(string[] args)
    {
        bool blnCurrentlyRunning = false;

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Process[] processes = Process.GetProcesses();
        foreach (var item in processes)
        {
            if (item.MainWindowTitle.IndexOf("Application Title") != -1)
                blnCurrentlyRunning = true;
        }

        if (!blnCurrentlyRunning)
        {
            Form = new frmMain();
            Application.Run(Form);
        }
        else
        {
            Application.Exit();
        }
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top