13

Does anyone know how to programmatically access the "All Users" Startup Menu?

In XP, located here:

C:\Documents and Settings\All Users\Start Menu\Programs\Startup

And in Windows 7, located here:

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup

Specifically, I've got a Setup and Deployment project, and I'd like to put a shortcut to the application in the Startup menu for all users so that the application is start whenever anyone logs in.

EDIT: I'm pretty sure this is where Brian got his answer from.

fre0n
  • 1,885
  • 1
  • 20
  • 26
  • Credit goes to Brian R. Bondy; he answered the question as I phrased it. I ended up creating a folder named "Startup" under "User's Programs Menu" (View > File System). And I relied on the user installing the program with "Install ... for yourself, or for anyone who uses this computer" set to "Everyone". If the user selected "Just me", then it would have only been placed in the Startup menu for that user. And I suppose I'm OK with that. I suppose I *could* have copied a shortcut in a Custom Action using Brian's method... – fre0n Feb 24 '10 at 22:02

6 Answers6

22

In .NET 4 CommonStartMenu was added to the Environment.SpecialFolder enum, so you can use:

Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu)
Nick T
  • 25,754
  • 12
  • 83
  • 121
Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
  • This is awesome, however, attempting to access that folder programmatically will give you "Access to the path 'C:\Documents and Settings\All Users\Start Menu' is denied." so doesn't seem very useful. – Logicsaurus Rex Dec 21 '17 at 17:08
  • @LogicsaurusRex By "access" you mean modify items in the folder? That will definitely require admin permissions and applies to all answers to this question not just this one. – Mike Zboray Dec 21 '17 at 17:22
  • In my case, I was simply trying to remove a shortcut to an app, and calling IO.Directory.GetFiles on that start menu path blew up with an Access Denied. It would seem that in about half the cases, people would want modify access. Read Only seems very limited usefulness. So it's one thing to have a path to something, but another to be able to use it for anything. I realize "using" the path wasn't really the question, but the next logical inference would include using it, and perhaps for modify. – Logicsaurus Rex Dec 21 '17 at 18:05
20

There is no constant defined for the normal way of Environment.GetFolderPath for the all users start menu, but you can do it this way by using the Win32 API SHGetSpecialFolderPath:

class Program
{
    [DllImport("shell32.dll")]
    static extern bool SHGetSpecialFolderPath(IntPtr hwndOwner,
       [Out] StringBuilder lpszPath, int nFolder, bool fCreate);
    const int CSIDL_COMMON_STARTMENU = 0x16;  // All Users\Start Menu

    static void Main(string[] args)
    {
        StringBuilder path = new StringBuilder(260);
        SHGetSpecialFolderPath(IntPtr.Zero, path, CSIDL_COMMON_STARTMENU, false);
        string s = path.ToString();
    }
}
Mengdi Gao
  • 780
  • 8
  • 23
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
4

"All Users" resides in the ALLUSERSPROFILE environment variable:

C:\>dir "%ALLUSERSPROFILE%\Start Menu"
 Volume in drive C is awesome
 Volume Serial Number is 8C57-DB1A

 Directory of C:\Documents and Settings\All Users\Start Menu

12/28/2009  10:27 PM    <DIR>          .
12/28/2009  10:27 PM    <DIR>          ..
12/28/2009  10:01 PM             1,566 Microsoft Update.lnk
02/23/2010  09:57 PM    <DIR>          Programs
12/28/2009  10:27 PM             1,563 Set Program Access and Defaults.lnk
12/28/2009  08:51 PM               398 Windows Catalog.lnk
12/28/2009  08:51 PM             1,507 Windows Update.lnk
               4 File(s)          5,034 bytes
               3 Dir(s)  64,214,460,416 bytes free
Seth
  • 45,033
  • 10
  • 85
  • 120
4

You can also try!

string allUsers=Environment.GetEnvironmentVariable("ALLUSERSPROFILE")+ "\\Start Menu\\Programs";
Zain Ali
  • 15,535
  • 14
  • 95
  • 108
2

You can access the startup folder using the appropriate MSI property (see here for more details): [StartupFolder]

However, as typical for user-dependent MSI variables, this property points either to the user's startup folder or the all users' startup folder, depending on the value of the ALLUSERS property.

This means that when you install for "Everyone" (per-machine) you will get the folder

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\

otherwise you will the per-user folder within the user's profile. This is by design and also makes sense, as a per-user installation will not have permission to write to the all users folder.

In your Setup and Deployment project, do the following to place files into the startup folder:

  • open the File System view,
  • right-click the folder tree and add a custom folder.
  • under the properties of this folder, set DefaultLocation to [StartupFolder]
  • add the content to the custom folder
Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
0

From C++, as for moment of writing this, Microsoft encourages to use SHGetKnownFolderPath with desired value of KNOWNFOLDERID enum. The value you need to use is FOLDERID_CommonStartMenu. In your case, the code would look like:

wchar_t * path = nullptr;
const auto result = SHGetKnownFolderPath(FOLDERID_CommonStartMenu, 0, NULL, &path);
if (S_OK == result)
{
    // do what you want with path, f.ex. create string from it
    std::wstring pathAsString(path);
    // according to documentation, calling process is responsible for freeing this resource
    CoTaskMemFree(path);
}

Reference of SHGetKnownFolderPath is there:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx

Reference of all available values of enum KNOWNFOLDERID is there:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx

Info, that calling process is responsible for freeing resource, can be found in documentation of SHGetKnownFolderPath in part documenting ppszPath parameter.

Please note, that when it is executed from service, some values are not available (for example related to data of user, f.ex. FOLDERID_Documents). Moreover, if some values are not available if you are using different architecture (f.ex. value related to FOLDERID_ProgramFilesX64 is not available on 32-bit operating system).

If somebody is willing to know where Microsoft encourages to use SHGetKnownFolderPath instead of other available functions, please read top of documentation of deprecated SHGetFolderPath.

apanas
  • 11
  • 1