views:

240

answers:

5

I need to store files into the common desktop on Windows. The application is a very special application for exactly one special PC (device preparation), so it had to be easy for non-techie users to find and modify the configuration file. Now we switched to a domain, and because different people (with different accounts) should use the software, it has to be in a common place, seen by every user. So please don't ask why it's on the desktop ;)

Previously, I just used Environment.GetFolderPath(Environment.SpecialFolder.Desktop). There are several of the common folders in the SpecialFolder enumeration, but the common desktop seems not to be there. Am I missing something, or do I have to p/invoke SHGetSpecialFolderPath with CSIDL_COMMON_DESKTOPDIRECTORY?

+2  A: 

I think you have to use the SHGetSpecialFolderPath API, since there is no enum value for "CommonDesktopDirectory". You can't explicitly use the value of CSIDL_COMMON_DESKTOPDIRECTORY and cast it to Environment.SpecialFolder, because the GetFolderPath method checks that the value is defined in the enum. Here's the code of the GetFolderPath method (from Reflector) :

public static string GetFolderPath(SpecialFolder folder)
{
    if (!Enum.IsDefined(typeof(SpecialFolder), folder))
    {
        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, GetResourceString("Arg_EnumIllegalVal"), new object[] { (int) folder }));
    }
    StringBuilder lpszPath = new StringBuilder(260);
    Win32Native.SHGetFolderPath(IntPtr.Zero, (int) folder, IntPtr.Zero, 0, lpszPath);
    string path = lpszPath.ToString();
    new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
    return path;
}

So you can easily copy and adapt the part that you need...

Thomas Levesque
OK, I just wanted to be sure. Now that I had a look at the MSDN docs, there is a note that in Vista and later, you should use KNOWNFOLDERID instead of CLSID values. Does that also apply if my app must run on XP?
OregonGhost
No, I think it's for Vista only
Thomas Levesque
I'll likely go with another folder (see my comments to the question), but this is the best answer to the question, so I accepted it. Thanks for your prompt reply.
OregonGhost
+1  A: 

For clarification - By common desktop do you mean C:\Documents and Settings\All Users\Desktop?

If yes, this is an ugly hack -

Dim c As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
Dim comDesktop As String = c.Substring(0, c.LastIndexOf("\")) + "\Desktop"
Yes, I mean that. But it's really to ugly.
OregonGhost
A: 

You can use Windows Script Host - WshShell.SpecialFolders

http://msdn.microsoft.com/en-us/library/0ea7b5xe(VS.85).aspx

Bogdan_Ch
Thanks for the idea, but I'd rather p/invoke than introduce such a dependency :)
OregonGhost
A: 

First, add a reference to "Windows Script Host Object Model". You'll find this in the COM tab of the "Add References" dialog.

using IWshRuntimeLibrary;

object commonUserDesktop = "AllUsersDesktop";
WshShell shell = new WshShellClass();
string commonPath = shell.SpecialFolders.Item(ref commonUserDesktop).ToString();
Jim
Like I wrote at Bogdan_Ch's answer, I'd rather not use WSH for such a task. P/Invoke is fine with me.
OregonGhost
A: 

Another way (yes it is also ugly and will work probably only on Windows XP, not on Vista) is to read a value from registry

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders , Common Desktop

Bogdan_Ch
This is not only ugly, but a compatibility nightmare. If I remember correctly, it even was only in some CTP version of Windows, but since applications relied on it, it has to be in Windows for decades.
OregonGhost