views:

229

answers:

4

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.

A: 

My guess is that if you can't find it anywhere on the system, it is stored in the assembly as some kind of meta data. Open the file up with a binary editor and search for the name you are looking for.

Nick Berardi
What's wrong with that answer?
Nathan Taylor
Was wondering the same thing myself. :)
Nick Berardi
+2  A: 

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,

Ron Klein
A: 

I searched all over the system... checked the registry, searched the contents of every file for the names, opened the .scr files in a hex viewer, but never could find the names anywhere... I also then tried installing other screen savers and noticed that the always showed up in the settings as the file name. Whatever I changed the file name to, showed up there. So for the non-standard screen savers it's not looking for any special names... this lead me to believe that the names of the built in screen savers were somehow hard coded into the settings dialog as special cases.

So I did the same thing in my app...just made an array of all the special cases and handled accordingly. Seems to be the only option.

Adam Haile
+2  A: 

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.

Thomas Levesque
Awesome..I totally didn't realize that was possible.
Adam Haile