【问题标题】:show multiple file properties in c#在 C# 中显示多个文件属性
【发布时间】:2016-04-27 07:59:36
【问题描述】:

我使用了here 中提到的方法,像在 windows 中一样显示文件属性。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct SHELLEXECUTEINFO
{
        public int cbSize;
        public uint fMask;
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string lpVerb;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string lpFile;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string lpParameters;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string lpDirectory;
        public int nShow;
        public IntPtr hInstApp;
        public IntPtr lpIDList;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string lpClass;
        public IntPtr hkeyClass;
        public uint dwHotKey;
        public IntPtr hIcon;
        public IntPtr hProcess;
}
public static bool ShowFileProperties(string Filename)
{
       SHELLEXECUTEINFO info = new SHELLEXECUTEINFO();
       info.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(info);
       info.lpVerb = "properties";
       info.lpFile = Filename;
       info.nShow = SW_SHOW;
       info.fMask = SEE_MASK_INVOKEIDLIST;
       return ShellExecuteEx(ref info);
}

我想知道是否有办法在选择多个文件时显示属性。

显示“多个文件的属性”,我的意思是当用户按住 ctrl 并选择多个文件时,右键单击-> 属性。链接中提到的代码适用于单个文件。但我需要显示多个文件。知道怎么做吗?

【问题讨论】:

  • 因此,如果您为一个文件手动执行此操作,您将获得一个正确的属性窗口。. 对 2 个文件执行相同操作,您将获得一个属性窗口而不是两个.. 所以我认为您必须写你自己的..
  • @3not3 我更新了我原来的解决方案。请让我知道它是否适合您。
  • 正是我想要的,我接受它作为答案。荣誉:)

标签: c# interop


【解决方案1】:

我在 MSDN 上发现了一个类似于SHELLEXECUTEINFO 的方法,我觉得很有趣。根据文章...

SHMultiFileProperties 函数

显示一组文件的合并属性表。显示所有文件共有的属性值,而不同的则显示字符串(多个值)。

https://msdn.microsoft.com/en-us/library/windows/desktop/bb762230(v=vs.85).aspx

我不确定如何将其转换为可用的 C# 代码,但当我这样做时,我会再次更新我的答案。

解决方案

我找到了解决办法! :D

public class Properties
{
    #region Import Methods

    [DllImport("shell32.dll", SetLastError = true)]
    static extern int SHMultiFileProperties(IDataObject pdtobj, int flags);

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr ILCreateFromPath(string path);

    [DllImport("shell32.dll", CharSet = CharSet.None)]
    public static extern void ILFree(IntPtr pidl);

    [DllImport("shell32.dll", CharSet = CharSet.None)]
    public static extern int ILGetSize(IntPtr pidl);

    #endregion

    #region Static Methods

    #region Private

    private static MemoryStream CreateShellIDList(StringCollection filenames)
    {
        // first convert all files into pidls list
        int pos = 0;
        byte[][] pidls = new byte[filenames.Count][];
        foreach (var filename in filenames)
        {
            // Get pidl based on name
            IntPtr pidl = ILCreateFromPath(filename);
            int pidlSize = ILGetSize(pidl);
            // Copy over to our managed array
            pidls[pos] = new byte[pidlSize];
            Marshal.Copy(pidl, pidls[pos++], 0, pidlSize);
            ILFree(pidl);
        }

        // Determine where in CIDL we will start pumping PIDLs
        int pidlOffset = 4 * (filenames.Count + 2);
        // Start the CIDL stream
        var memStream = new MemoryStream();
        var sw = new BinaryWriter(memStream);
        // Initialize CIDL witha count of files
        sw.Write(filenames.Count);
        // Calcualte and write relative offsets of every pidl starting with root
        sw.Write(pidlOffset);
        pidlOffset += 4; // root is 4 bytes
        foreach (var pidl in pidls)
        {
            sw.Write(pidlOffset);
            pidlOffset += pidl.Length;
        }

        // Write the root pidl (0) followed by all pidls
        sw.Write(0);
        foreach (var pidl in pidls) sw.Write(pidl);
        // stream now contains the CIDL
        return memStream;
    }

    #endregion

    #region Public 

    public static int Show(IEnumerable<string> Filenames)
    {
        StringCollection Files = new StringCollection();
        foreach (string s in Filenames) Files.Add(s);
        var data = new DataObject();
        data.SetFileDropList(Files);
        data.SetData("Preferred DropEffect", new MemoryStream(new byte[] { 5, 0, 0, 0 }), true);
        data.SetData("Shell IDList Array", Properties.CreateShellIDList(Files), true);
        return SHMultiFileProperties(data, 0);
    }

    public static int Show(params string[] Filenames)
    {
        return Properties.Show(Filenames as IEnumerable<string>);
    }

    #endregion

    #endregion
}

这是在 Windows 10 上测试并运行的。实际上,我是根据另外两篇 SO 文章提出的,因为这两个代码本身都不起作用。

来源:

P/Invoke for shell32.dll's SHMultiFileProperties

SHMultiFileProperties doens't work on XP

【讨论】:

  • 非常感谢您的支持,请问我可以得到您的试用解决方案吗?
猜你喜欢
  • 2023-03-03
  • 1970-01-01
  • 2012-08-06
  • 2012-08-16
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多