首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Windows代码包在ShellFile/ShellFile/ShellObject对象上调用谓词?

如何使用Windows代码包在ShellFile/ShellFile/ShellObject对象上调用谓词?
EN

Stack Overflow用户
提问于 2014-01-17 14:13:57
回答 4查看 3K关注 0票数 0

我正在寻找一个C#Vb.NET解决方案,以了解如何在存储在回收站中的ShellObject (ShellFileShellFolder)上调用undelete谓词。

我写过的回收站部分,我只需要知道如何在删除的项目上调用一个动词。

为了更好地理解我,我将演示如何使用Shell32接口调用一个动词的示例,但是在我感兴趣使用的Windows API Code Pack库的ShellObject/ShellFile/ShellFolder项上找不到任何类似的方法:

代码语言:javascript
复制
Private SH As New Shell
Private RecycleBin As Folder = 
        SH.NameSpace(ShellSpecialFolderConstants.ssfBITBUCKET)

Dim RandomDeletedItem As FolderItem = RecycleBin.Items.Cast(Of FolderItem)(1)

RandomDeletedItem.InvokeVerb("undelete")

这应该是Windows API Code Pack不完整的等价物(VB.NET中)

代码语言:javascript
复制
Private Shared RecycleBin As IKnownFolder = KnownFolders.RecycleBin

Dim RandomDeletedItem As ShellObject = RecycleBin(1)
Dim RandomDeletedFile As ShellFile = RecycleBin(1)
Dim RandomDeletedFolder As ShellFolder = RecycleBin(1)

' Here I need to know how to invoke the "undelete" verb on each object above...
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-01-19 18:17:58

如何使用ShellExecuteEx取消删除“回收斌”中的文件,给出它的解析名称:

代码语言:javascript
复制
    ' some file we got from the recycle bin iterating through the IShellItems:
    Dim sParsing As String = _
      "E:\$RECYCLE.BIN\S-1-5-21-2546332361-822210090-45395533-1001\$RTD2G1Z.PNG"
    Dim shex As New SHELLEXECUTEINFO
    shex.cbSize = Marshal.SizeOf(shex)

    ' Here we want ONLY the file name.
    shex.lpFile = Path.GetFileName(sParsing)

    ' Here we want the exact directory from the parsing name
    shex.lpDirectory = Path.GetDirectoryName(sParsing)
    shex.nShow = SW_SHOW  ' = 5
    '' here the verb is undelete, not restore.
    shex.lpVerb = "undelete"

    ShellExecuteEx(shex)
票数 1
EN

Stack Overflow用户

发布于 2014-01-18 19:54:55

下面是一些实用程序代码,它允许您在任何shell项上调用任何谓词。这是关于Recycle Bin文件夹和undelete规范动词的一个小示例:

代码语言:javascript
复制
IKnownFolder folder = KnownFolders.RecycleBin;
foreach (ShellObject deleted in folder)
{
    if (...) // whatever
    {
        CallShellItemVerb(deleted.Properties.System.ParsingPath.Value, "undelete");
    }
}

public static void CallShellItemVerb(string parsingPath, string verb)
{
    if (parsingPath == null)
        throw new ArgumentNullException("parsingPath");

    if (verb == null)
    {
        verb = "open";
    }

    // get an item from the path
    IShellItem item;
    int hr = SHCreateItemFromParsingName(parsingPath, IntPtr.Zero, typeof(IShellItem).GUID, out item);
    if (hr < 0)
        throw new Win32Exception(hr);

    // get the context menu from the item
    IContextMenu menu;
    Guid BHID_SFUIObject = new Guid("{3981e225-f559-11d3-8e3a-00c04f6837d5}");
    hr = item.BindToHandler(IntPtr.Zero, BHID_SFUIObject, typeof(IContextMenu).GUID, out menu);
    if (hr < 0)
        throw new Win32Exception(hr);

    // build a fake context menu so we can scan it for the verb's menu id
    ContextMenu cm = new ContextMenu();
    hr = menu.QueryContextMenu(cm.Handle, 0, 0, -1, CMF_NORMAL);
    if (hr < 0)
        throw new Win32Exception(hr);

    int count = GetMenuItemCount(cm.Handle);
    int verbId = -1;
    for (int i = 0; i < count; i++)
    {
        int id = GetMenuItemID(cm.Handle, i);
        if (id < 0)
            continue;

        StringBuilder sb = new StringBuilder(256);
        hr = menu.GetCommandString(id, GCS_VERBW, IntPtr.Zero, sb, sb.Capacity);
        if (sb.ToString() == verb)
        {
            verbId = id;
            break;
        }
    }

    if (verbId < 0)
        throw new Win32Exception("Verb '" + verb + "' is not supported by the item");

    // call that verb
    CMINVOKECOMMANDINFO ci = new CMINVOKECOMMANDINFO();
    ci.cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO));
    ci.lpVerb  = (IntPtr)verbId;
    hr = menu.InvokeCommand(ref ci);
    if (hr < 0)
        throw new Win32Exception(hr);
}

[ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellItem
{
    // NOTE: only partially defined, don't use in other contexts
    [PreserveSig]
    int BindToHandler(IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IContextMenu ppv);
}

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214e4-0000-0000-c000-000000000046")]
private interface IContextMenu
{
    [PreserveSig]
    int QueryContextMenu(IntPtr hmenu, int iMenu, int idCmdFirst, int idCmdLast, int uFlags); 

    [PreserveSig]
    int InvokeCommand(ref CMINVOKECOMMANDINFO pici);

    [PreserveSig]
    int GetCommandString(int idCmd, int uFlags, IntPtr pwReserved, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMax);
}

[DllImport("user32.dll")]
private static extern int GetMenuItemCount(IntPtr hMenu);

[DllImport("user32.dll")]
private static extern int GetMenuItemID(IntPtr hMenu, int nPos);

[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int SHCreateItemFromParsingName(string path, IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem item);

private const int CMF_NORMAL = 0x00000000;
private const int GCS_VERBW = 4;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct CMINVOKECOMMANDINFO
{
    public int cbSize;
    public int fMask;
    public IntPtr hwnd;
    public IntPtr lpVerb;
    public string lpParameters;
    public string lpDirectory;
    public int nShow;
    public int dwHotKey;
    public IntPtr hIcon;
}
票数 6
EN

Stack Overflow用户

发布于 2014-01-19 19:50:43

这只是@Nathan解决方案的改编,以便正确地处理ShellObject对象(可以是ShellItemShellFolder或其他对象)。

WindowsAPICodePack库提供了在ShellExecuteInfo结构中使用的WindowShowCommand枚举,因此不需要为其编写文档。

以下是:

代码语言:javascript
复制
''' <summary>
''' Performs an operation on a specified file..
''' </summary>
''' <param name="lpExecInfo">
''' A pointer to a 'ShellExecuteInfo' structure that contains and receives information about
''' the application being executed.
''' </param>
''' <returns><c>true</c> if successful, <c>false</c> otherwise.</returns>
<DllImport("Shell32", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function ShellExecuteEx(
              ByRef lpExecInfo As ShellExecuteInfo
) As Boolean
End Function

''' <summary>
''' Contains information used by 'ShellExecuteEx' function.
''' </summary>
<Description("'lpExecInfo' parameter used in 'ShellExecuteEx' function")>
Public Structure ShellExecuteInfo

    ''' <summary>
    ''' Required. 
    ''' The size of this structure, in bytes.
    ''' </summary>
    Public cbSize As Integer

    ''' <summary>
    ''' Flags that indicate the content and validity of the other structure members.
    ''' </summary>
    Public fMask As Integer

    ''' <summary>
    ''' Optional. 
    ''' A handle to the parent window, 
    ''' used to display any message boxes that the system might produce while executing this function. 
    ''' This value can be NULL.
    ''' </summary>
    Public hwnd As IntPtr

    ''' <summary>
    ''' A string, referred to as a verb, that specifies the action to be performed. 
    ''' The set of available verbs depends on the particular file or folder. 
    ''' Generally, the actions available from an object's shortcut menu are available verbs. 
    ''' This parameter can be NULL, in which case the default verb is used if available. 
    ''' If not, the "open" verb is used. 
    ''' If neither verb is available, the system uses the first verb listed in the registry. 
    ''' </summary>
    <MarshalAs(UnmanagedType.LPTStr)> Public lpVerb As String

    ''' <summary>
    ''' The address of a null-terminated string that specifies the name of the file 
    ''' or object on which ShellExecuteEx will perform the action specified by the lpVerb parameter. 
    ''' The system registry verbs that are supported by the ShellExecuteEx function include "open" 
    ''' for executable files and document files and "print" for document files 
    ''' for which a print handler has been registered. 
    ''' Other applications might have added Shell verbs through the system registry, 
    ''' such as "play" for .avi and .wav files.
    ''' To specify a Shell namespace object, pass the fully qualified parse name 
    ''' and set the SEE_MASK_INVOKEIDLIST flag in the fMask parameter.
    ''' </summary>
    <MarshalAs(UnmanagedType.LPTStr)> Public lpFile As String

    ''' <summary>
    ''' Optional. 
    ''' The address of a null-terminated string that contains the application parameters. 
    ''' The parameters must be separated by spaces. 
    ''' If the lpFile member specifies a document file, lpParameters should be NULL.
    ''' </summary>
    <MarshalAs(UnmanagedType.LPTStr)> Public lpParameters As String

    ''' <summary>
    ''' Optional. 
    ''' The address of a null-terminated string that specifies the name of the working directory. 
    ''' If this member is NULL, the current directory is used as the working directory.
    ''' </summary>
    <MarshalAs(UnmanagedType.LPTStr)> Public lpDirectory As String

    ''' <summary>
    ''' Required. 
    ''' Flags that specify how an application is to be shown when it is opened; 
    ''' one of the SW_ values listed for the ShellExecute function. 
    ''' If lpFile specifies a document file, the flag is simply passed to the associated application. 
    ''' It is up to the application to decide how to handle it.
    ''' </summary>
    Dim nShow As WindowShowCommand

    ''' <summary>
    ''' If SEE_MASK_NOCLOSEPROCESS is set and the ShellExecuteEx call succeeds, 
    ''' it sets this member to a value greater than 32. 
    ''' If the function fails, it is set to an SE_ERR_XXX error value that indicates the cause of the failure. 
    ''' Although hInstApp is declared as an HINSTANCE for compatibility with 16-bit Windows applications, 
    ''' it is not a true HINSTANCE. 
    ''' It can be cast only to an int and compared to either 32 or the following SE_ERR_XXX error codes.
    ''' </summary>
    Dim hInstApp As IntPtr

    ''' <summary>
    ''' The address of an absolute ITEMIDLIST structure (PCIDLIST_ABSOLUTE) 
    ''' to contain an item identifier list that uniquely identifies the file to execute. 
    ''' This member is ignored if the fMask member does not include SEE_MASK_IDLIST or SEE_MASK_INVOKEIDLIST.
    ''' </summary>
    Dim lpIDList As IntPtr

    ''' <summary>
    ''' The address of a null-terminated string that specifies one of the following
    ''' A ProgId. For example, "Paint.Picture".
    ''' A URI protocol scheme. For example, "http".
    ''' A file extension. For example, ".txt".
    ''' A registry path under HKEY_CLASSES_ROOT that names a subkey that contains one or more Shell verbs. 
    ''' This key will have a subkey that conforms to the Shell verb registry schema, such as shell\verb name.
    ''' </summary>
    <MarshalAs(UnmanagedType.LPTStr)> Public lpClass As String

    ''' <summary>
    ''' A handle to the registry key for the file type. 
    ''' The access rights for this registry key should be set to KEY_READ. 
    ''' This member is ignored if fMask does not include SEE_MASK_CLASSKEY.
    ''' </summary>
    Public hkeyClass As IntPtr

    ''' <summary>
    ''' A keyboard shortcut to associate with the application. 
    ''' The low-order word is the virtual key code, and the high-order word is a modifier flag (HOTKEYF_).
    ''' For a list of modifier flags, see the description of the WM_SETHOTKEY message. 
    ''' This member is ignored if fMask does not include SEE_MASK_HOTKEY.
    ''' </summary>
    Public dwHotKey As Integer

    ''' <summary>
    ''' A handle to the icon for the file type. 
    ''' This member is ignored if fMask does not include SEE_MASK_ICON. 
    ''' This value is used only in Windows XP and earlier. 
    ''' It is ignored as of Windows Vista.
    ''' </summary>
    Public hIcon As IntPtr

    ''' <summary>
    ''' A handle to the monitor upon which the document is to be displayed. 
    ''' This member is ignored if fMask does not include SEE_MASK_HMONITOR.
    ''' </summary>
    Public hProcess As IntPtr

End Structure

''' <summary>
''' Invokes a verb on a ShellObject item.
''' </summary>
''' <param name="ShellObject">
''' Indicates the item.
''' </param>
''' <param name="Verb">
''' Indicates the verb to invoke on the item.
''' </param>
Public Shared Sub InvokeItemVerb(ByVal [ShellObject] As ShellObject,
                                 ByVal Verb As String)

    Dim FileName As String = [ShellObject].ParsingName.Split("\").Last
    Dim FileDir As String = IO.Path.GetDirectoryName([ShellObject].ParsingName)

    Dim sei As New ShellExecuteInfo

    With sei

        .cbSize = Marshal.SizeOf(sei)

        ' Here we want ONLY the filename (without the path).
        .lpFile = FileName

        ' Here we want the exact directory from the parsing name.
        .lpDirectory = FileDir

        ' Here the show command.
        .nShow = WindowShowCommand.Show

        ' Here the verb to invoke.
        .lpVerb = Verb

    End With

    ' Invoke the verb.
    ShellExecuteEx(sei)

End Sub
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21187912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档