The OP was running Visual Studio in administrator mode, therefore the program being run was run in administrator mode as well. According to this question, due to desktop and the application running at different privilege levels, you should not be able to drag and drop between the desktop and the application.
I am not sure on why the OP was able to drop files in from what I assume was a normal Windows File Explorer as technically that should suffer from the same issue.
For simplicity I just used an empty Form with the property AllowDrop
equal to true
and the events, DragDrop
linked to the method DnDExample_DragDrop
and DragOver
linked to the method DnDExample_DragOver
. I also imported Windows Script Host Object Model
into the project by right clicking on the project, clicking add reference, going to the COM tab, finding the reference on there and then importing it.
Enough about the set up.
A simple way would be to use the DragOver and Drop events on your list. For simplicity, I just used a form.
In the drag over, you want to check the file types of the files being dragged on to the area you are meant to drop it. If all the files are the correct type, the shortcut type, then you want to allow the drop.
On the drop, you can then handle the logic of what you want to happen. For my example, I just print the shortcut file paths out and their target.
using System;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using IWshRuntimeLibrary;
namespace DragAndDropShortcut
{
public partial class DnDExample : Form
{
private readonly WshShell shell = new WshShell();
public DnDExample()
{
InitializeComponent();
}
private void DnDExample_DragOver(object sender, DragEventArgs e)
{
// This checks that each file being dragged over is a .lnk file.
// If it is not, it will show the invalid cursor thanks to some
// e.Effect being set to none by default.
bool dropEnabled = true;
if (e.Data.GetDataPresent(DataFormats.FileDrop, true))
{
if (e.Data.GetDataPresent(DataFormats.FileDrop, true) &&
e.Data.GetData(DataFormats.FileDrop, true) is string[] filePaths &&
filePaths.Any(filePath => Path.GetExtension(filePath)?.ToLowerInvariant() != ".lnk"))
{
dropEnabled = false;
}
}
else
{
dropEnabled = false;
}
if (dropEnabled)
{
// Set the effect to copy so we can drop the item
e.Effect = DragDropEffects.Copy;
}
}
private void DnDExample_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop) &&
e.Data.GetData(DataFormats.FileDrop, true) is string[] filePaths)
{
// Print out the path and target of each shortcut file dropped on
foreach (string filePath in filePaths)
{
IWshShortcut link = (IWshShortcut)shell.CreateShortcut(filePath); //Link the interface to our shortcut
Console.WriteLine(filePath);
Console.WriteLine(link.TargetPath); //Show the target in a MessageBox using IWshShortcut
Console.WriteLine();
}
}
}
}
}
AllowDrop
and, inListView_DragEnter
,if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
. Then handle the file drop inListView_DragDrop
. The icon's path is referenced in Shell link properties. If could be a file or the icon index contained in an executable. The executable can be a different file than the target one. For example, it could the program that opens the file or an icon in shell32.dll etc. – Jimistring link = e.Data.GetData(DataFormats.FileDrop).First();
you can get more info like so – TaWAssocQueryString
to get the associated app's executable and get the icon from there. It could also be a pointer to anItemIdList
. – Jimiicon
stuck. Probably, just the file name is needed -- Which post? The one that castsShellLinkObject
or the one that usesType.GetTypeFromProgID("Shell.Application");
(I actually use the Shell interfaces directly, not aShell32
reference, which brings upMicrosoft Shell Controls and Automation
. There are many posts stating the former doesn't work on Windows 8+). – Jimi