Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Retrieve Names of Installed Screen Savers

I want to be able to show basically the same list that the Windows Screen Saver dialog shows, with the name of each screen saver. The problem I've run into however is that the names that show up in the drop down list on the dialog don't seem to correspond to the filename, embedded file information, anything in the registry, etc.

For example, the 3D FlowerBox screen saver has a file description of Direct3D FlowerBox. And I can't find just "3D FlowerBox" anywhere.

Where is this information stored? And How can I retrieve it.

like image 343
Adam Haile Avatar asked Aug 27 '09 14:08

Adam Haile


2 Answers

This question is a bit old, but I just had to solve the same problem and came up with the following solution:

public class ScreenSaverInfo
{
    public string FileName { get; set; }
    public string Name { get; set; }
}

public IEnumerable<ScreenSaverInfo> GetScreenSavers()
{
    string currentSSPath = null;
    using (RegistryKey desktopKey = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop"))
    {
        if (desktopKey != null)
        {
            string screenSaverExe = desktopKey.GetValue("SCRNSAVE.EXE") as string;
            if (!string.IsNullOrEmpty(screenSaverExe))
            {
                currentSSPath = Path.GetDirectoryName(screenSaverExe);
            }
        }
    }

    HashSet<string> directories = new HashSet<string>();
    directories.Add(Environment.GetFolderPath(Environment.SpecialFolder.System));
    directories.Add(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86));
    if (currentSSPath != null)
        directories.Add(currentSSPath);

    foreach (string dir in directories)
    {
        foreach (string file in Directory.EnumerateFiles(dir, "*.scr", SearchOption.TopDirectoryOnly))
        {
            yield return GetScreenSaverInfo(file);
        }
    }
}

public ScreenSaverInfo GetScreenSaverInfo(string filename)
{
    IntPtr hLibrary = IntPtr.Zero;
    try
    {
        hLibrary = LoadLibrary(filename);
        StringBuilder sb = new StringBuilder(1024);
        LoadString(hLibrary, 1, sb, sb.Capacity);
        return new ScreenSaverInfo
        {
            FileName = filename,
            Name = sb.ToString()
        };
    }
    finally
    {
        if (hLibrary != IntPtr.Zero)
            FreeLibrary(hLibrary);
    }
}

[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);

[DllImport("kernel32.dll")]
static extern bool FreeLibrary(IntPtr hLibrary);

[DllImport("user32")]
static extern int LoadString(IntPtr hInstance, int wID, [Out] StringBuilder lpBuffer, int nBufferMax);

Basically, the display name of the screensaver is the first resource string in the .scr file. Note that for some screensavers (e.g. Windows built-in screensavers), the localized resources are not in the main .scr file but in a .scr.mui file in a culture-specific subdirectory. You don't have to worry about it, because LoadString knows where to find the adequate resource.

like image 51
Thomas Levesque Avatar answered Sep 20 '22 18:09

Thomas Levesque


Take a look at a question I once asked here about screen saver. It's a direction to the solution. In addition, it seems that there's no such thing exists in the framework itself.

HTH,

like image 20
Ron Klein Avatar answered Sep 18 '22 18:09

Ron Klein