C# 刷新资源管理器

发布于 2024-08-09 10:22:15 字数 267 浏览 8 评论 0原文

在我的程序中,我切换隐藏文件的注册表值以告诉资源管理器是否隐藏或显示它们。但是,由于资源管理器不会自行刷新,因此我发送事件

 SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);

来刷新所有内容。然而,不幸的是,它似乎并没有带来任何令人耳目一新的东西。我看到桌面上的屏幕有点闪烁,但为了看到更改,我必须手动刷新文件夹。 SHChangeNotify 似乎不适合我。任何帮助将不胜感激。

In my program I toggle the registry value of hidden files to tell explorer whether to hide or show them. However, since explorer doesn't refresh on it's own, I send the event

 SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);

to refresh everything. However, it doesn't seem to be refreshing anything unfortunately. I see the screen on the desktop flicker a bit, but in order to see the changes, I have to manually refresh the folder. SHChangeNotify doesn't seem to be working for me. Any help would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风情万种。 2024-08-16 10:22:15

执行此操作的一种方法是更新注册表设置,然后将 F5 键发送到当前窗口。它只需要很少的代码,但使用 SendKeys 从来都不是理想的选择,它只会更新当前窗口的视图。

static void ShowHide()
{
    string AdvKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
    bool Hidden = (int)Registry.GetValue(AdvKey, "Hidden", 0) == 1;
    int h1 = 1; int h2 = 1;
    if (Hidden) { h1 = 2; h2 = 0; }
    Registry.SetValue(AdvKey, "Hidden", h1, RegistryValueKind.DWord);
    Registry.SetValue(AdvKey, "ShowSuperHidden", h2, RegistryValueKind.DWord);
    Thread.Sleep(100); //A small wait is needed here to ensure the registry is updated
    SendKeys.SendWait("{F5}"); //This updates the current window
    SHChangeNotify(0x08000000, 0x1000, IntPtr.Zero, IntPtr.Zero); //This may update the other windows
}

[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);

更好的方法是使用 SHGetSetSettings API。这将可靠地更新所有资源管理器窗口中的视图,并更新注册表中的设置。下面的代码基于此处发布的答案。

using Microsoft.Win32;
using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("shell32.dll")]
    public extern static void SHGetSetSettings(ref Structures.SHELLSTATE lpss, Structures.SSF dwMask, bool bSet);

    internal static class Structures
    {
        [Flags]
        public enum SSF : int
        {
            SSF_SHOWALLOBJECTS = 0x00000001,
            SSF_SHOWSUPERHIDDEN = 0x00040000,
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct SHELLSTATE
        {
            public uint bitvector;

            public uint FShowAllObjects
            {
                get => this.bitvector & 1;
                set => this.bitvector = value | this.bitvector;
            }

            public uint FShowSuperHidden
            {
                get => (this.bitvector & 0x8000) / 0x8000;
                set => this.bitvector = (value * 0x8000) | this.bitvector;
            }
        }
    }

    public static void ToggleHiddenFiles(bool bShow)
    {
        Structures.SHELLSTATE state = new Structures.SHELLSTATE();

        state.FShowAllObjects = (uint)(bShow ? 1 : 2);
        state.FShowSuperHidden = (uint)(bShow ? 1 : 0);

        SHGetSetSettings(ref state, Structures.SSF.SSF_SHOWALLOBJECTS | Structures.SSF.SSF_SHOWSUPERHIDDEN, true);
    }

    static void Main()
    {
        string AdvKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
        bool Hidden = (int)Registry.GetValue(AdvKey, "Hidden", 0) == 1;
        ToggleHiddenFiles(!Hidden);
    }
}

One way to do this is to update the registry settings and then send an F5 key to the current window. It takes very little code, but it's never ideal to use SendKeys and it only updates the view for the current window.

static void ShowHide()
{
    string AdvKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
    bool Hidden = (int)Registry.GetValue(AdvKey, "Hidden", 0) == 1;
    int h1 = 1; int h2 = 1;
    if (Hidden) { h1 = 2; h2 = 0; }
    Registry.SetValue(AdvKey, "Hidden", h1, RegistryValueKind.DWord);
    Registry.SetValue(AdvKey, "ShowSuperHidden", h2, RegistryValueKind.DWord);
    Thread.Sleep(100); //A small wait is needed here to ensure the registry is updated
    SendKeys.SendWait("{F5}"); //This updates the current window
    SHChangeNotify(0x08000000, 0x1000, IntPtr.Zero, IntPtr.Zero); //This may update the other windows
}

[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);

A better method is to use the SHGetSetSettings API. This will reliably update the view in all Explorer Windows and updates the settings in the registry as well. The code below is based on an answer posted here.

using Microsoft.Win32;
using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("shell32.dll")]
    public extern static void SHGetSetSettings(ref Structures.SHELLSTATE lpss, Structures.SSF dwMask, bool bSet);

    internal static class Structures
    {
        [Flags]
        public enum SSF : int
        {
            SSF_SHOWALLOBJECTS = 0x00000001,
            SSF_SHOWSUPERHIDDEN = 0x00040000,
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct SHELLSTATE
        {
            public uint bitvector;

            public uint FShowAllObjects
            {
                get => this.bitvector & 1;
                set => this.bitvector = value | this.bitvector;
            }

            public uint FShowSuperHidden
            {
                get => (this.bitvector & 0x8000) / 0x8000;
                set => this.bitvector = (value * 0x8000) | this.bitvector;
            }
        }
    }

    public static void ToggleHiddenFiles(bool bShow)
    {
        Structures.SHELLSTATE state = new Structures.SHELLSTATE();

        state.FShowAllObjects = (uint)(bShow ? 1 : 2);
        state.FShowSuperHidden = (uint)(bShow ? 1 : 0);

        SHGetSetSettings(ref state, Structures.SSF.SSF_SHOWALLOBJECTS | Structures.SSF.SSF_SHOWSUPERHIDDEN, true);
    }

    static void Main()
    {
        string AdvKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
        bool Hidden = (int)Registry.GetValue(AdvKey, "Hidden", 0) == 1;
        ToggleHiddenFiles(!Hidden);
    }
}
情归归情 2024-08-16 10:22:15

尝试使用 SHGetSetSettings 更改 fShowAllObjects

但使用 SHGetSetSettings 进行简单的获取和设置将不起作用。

它足够智能,可以将当前设置与您发送的设置进行比较,并且只有在两者不同时才会通知其他窗口更改。

要刷新桌面,请使用 IShellWindows 枚举 shell 窗口,请检查 IWebBrowser2.FullName 属性以跳过 IE 窗口,然后调用 IWebBrowser2::Refresh。

Try SHGetSetSettings with your change to fShowAllObjects

A simple Get and Set with SHGetSetSettings won't work though.

It's smart enough to compare it's current settings to what your sending it and will only notify other windows of the change if the two are different.

To refresh the desktop use IShellWindows to enumerate shell windows, check the IWebBrowser2.FullName property to skip IE windows and then call IWebBrowser2::Refresh.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文