Create startup folder - Windows - windows

I script a lot of things to manage the computers in my company. I often need to add shortcuts into the personnal startup folder of users (without a GPO).
Windows 8/8.1 doesn't have a personnal startup folder by default.
Its location is C:\Users\<username>\AppData\Roaming\Microsoft\Windows\Start Menu\
It is easy to create this folder, but it needs a desktop.ini file into it, with the correct content, for the name to be localised (else it is displayed "Startup" whatever the language).
What is the "official" way to create this folder?
Or what is the official way to add something into it?
I'd prefer a PowerShell or batch command, but whatever reliable mean is okay.

I guess you can do something with the ComObject for this special folder:
$startup = (New-Object -ComObject Shell.Application).NameSpace(0x07)
By the way, if I enter shell:startup in a run box (Win+R) on my Win 8.1 system, it directs me to my personal startup folder (C:\Users\User\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup).

As far as I know, there is no reliable way to do this.
You can get the path with [environment]::getfolderpath("Startup") but the returned string is empty if the folder was neve created. And I don't know any API entry to create it.
So you have to manually create it:
check if the former command return anything (if yes, just create you shortcut)
create yourself the startup folder. Use [environment]::getfolderpath("StartMenu") and add \startup to the path
then create the desktop.ini file and populate it yourself
and update the registry HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders (I didn't check if this is the right place. [environment]::getfolderpath("Startup") must return the right value)
UPDATE: I just found SHGetKnownFolderPath API which allow to create the required folder if needed (with dwFlags). I'm not good at PowerShell, so I don't know how to call this. Maybe Someone can give a better answer.

Related

Create generic shortcuts in Windows 10 using extended shell path

I want to create generic shortcuts in Windows 10 using a target path
extension of the shell path, something like
%windir%\explorer.exe shell:AppData ..\Local\Temp
%windir%\explorer.exe shell:AppData works by itself, takes me to roaming userfiles.
I could use
%windir%\explorer.exe shell:UsersFilesFolder
which would take me to %UserProfile% and append from there (if I could find out how) only it would be handy to be able to go up a level if possible as well.
I can't work out
How to append a further couple directories into the shortcut target path
How to go up one directory first (..?)
What is the syntax to make this work?
First of all, %Temp% might not be the same as %LOCALAPPDATA%\Temp!
The way to create a perfect shortcut to %Temp% is not that easy, ideally the .lnk should only contain a EXP_SZ_LINK:EXP_SZ_LINK_SIG block with the %Temp% string. You have to manually delete the ItemIdList block to get a .lnk file like that. %Temp% is extra complicated because it does not have a special folder canonical name you can use with the shell: protocol.
I don't believe the shell: protocol supports .. nor . path components.
shell:AppData ..\Local is also wrong because the local appdata folder might be somewhere else (< Windows Vista used different names) and a better command would be %windir%\explorer.exe "shell:LocalAppData" (and in turn %windir%\explorer.exe "shell:Local AppData\Temp") but all of those commands have other issues.
First of all, Explorer might not be the users shell and you risk not obeying the users preferences.
Another problem is that a .lnk file contains the attributes of its target and because the link actually points to a .exe file your .lnk file will not have the FILE_ATTRIBUTE_DIRECTORY bit set for its target attribute and the shell will not understand that it points to a folder. A .lnk that points to a folder will sometimes open in the same window when navigating the shell instead of opening a new file browser window.
The .lnk binary format is documented and by breaking the rules a little bit I have been able to create a link that points to a file/folder inside a special shell folder by combining a EXP_SPECIAL_FOLDER block with a manipulated ItemIdList but for whatever reason this trick does not work for deeper paths.
A EXP_SPECIAL_FOLDER block and a empty ItemIdList is the only way to create shortcuts to special folders that is guaranteed to work on all systems but you have to create it manually, the IShellLink implementation adds system specific blocks that might break things if you try to use the link on another system.
The .lnk format has not changed much since Windows 95 and there is simply no easy way to create shortcuts relative to special folders that also work when they are copied to other systems. The relative path string in a .lnk is relative to the .lnk file itself and is not helpful in this case.
I would recommend that you simply create the .lnk on the target system in your installer/application and let IShellLink fill in as much information as possible behind your back.

Going over all user profiles during installation

I'm creating a Windows application that needs to add an entry to the Send-To explorer context menu, and needs to do so for all users. Since the Send-To folder is specific for each user, with no common folder for all users, I'm left with two choices:
I can go over all user profiles, as well as the default user profile, find the SendTo folder and add the shortcut to it. This will ensure the shortcut is deleted during uninstall.
Or, I can make sure the shortcut is in the SendTo folder each time a user logs in (by adding my application to the start-up folder of all users). This will make my life a lot easier during installation, but when the application is uninstalled, all those shortcuts will not be removed.
So either way, I need a way to find the SendTo folder of all users. I can scan HKEY_USERS and find the SendTo folder of each user (it might not be in the default location, the user can move it), but how do I find out the user profile's root folder? The registry has something like %USERPROFILE\AppData\Roaming... for the SendTo folder. How can I figure out what %USERPROFILE% is for another user?
Thanks.
Easier approach: use the launch sequence of the exe itself to check whether the shortcut it present on launch, and create it if not.
Uninstall for all users is best handled using ActiveSetup which will run "something runnable" once for each user logging onto the machine. In your case a simple batch command could do the job.
If you do chose this uninstall approach, you must make sure that your msi installer checks for this uninstall key and deletes it on install - otherwise you have a delete operation scheduled for the shortcut the next time a user logs on.
Also keep in mind that each install should use a different entry in ActiveSetup to ensure that the shortcut creation is re-run for a user who has had it uninstalled already. This last part might be slightly incomprehensible before you read more about ActiveSetup: http://www.etlengineering.com/installer/activesetup.txt
You can create a custom action inside MSI, which will go through all user profiles and remove your shortcuts from SendTo folder. All users profile you can find, just scan all folders in %systemdrive%\Users folders in Windows7 (Vista), or Documents and Settings in Windows XP.
Or you can use ActiveSetup mechanism for this purpose, create some script (application) which remove your shortcut from SendTo folder, when user will log in to system next time.

Windows 7 - Can't update my program's files in C:\Program Files

I have an addin program that works with MS Word (version 2007). It is located in the C:\Program Files location. I installed Windows 7 and then went to make a routine change to my files in this location and it would only bring up a read only file. How can I grant myself permission to write to my own program? I cannot change this location or use any other workaround. I have this product out to 25 different companies and I can't change the programming to work from any other location. Thanks
You could also embed a manifest in your EXE that makes your program require adminrights on Windows 7 / Vista.
On Windows Vista, UAC means that users run without admin rights and don't have write access to the program files directories.
The correct solution is to write to a folder for which standard users do have write permissions.
The solution you are looking for is to make your app's folder within program files writeable to all users. You can do this by adding a DACL when installing. It is extremely bad practice to allow standard users to write inside the program files directory and I urge you instead to re-code your app so that it does not need to write there.
Assuming you're doing this as part of modifying the config (and not when your application is running for regular users)...
Your user account probably doesn't have the correct permissions to write/modify the file. Assuming your account is an administrator account, right-click the file, select "Properties". Click the "Security" tab. Click edit and give your user account Full Control.
If you can't do this, it's probably because the ownership of the file doesn't allow you. If this is the case, click on "Advanced", go to the "Owner" tab, and click "Edit".
However, if it needs these permissions when it's running, you should instead be using the %AppData% folder.

Rename a directory in installer

I am working on a Windows application which needs to be able to update itself. When a button is pressed it starts the installer and then the parent application exits. At some point during the installer, the installer attempts to rename the directory that the parent application was running from and fails with "Access Denied" If you run the installer from the desktop it works.
I am using CreateProcess to start the installer, is there some way of using this or another API to create the installer completely independantly from the parent application so that it doesn't retain some attachment to the directory.
I'm not convinced that launching the installer separately will solve your issue. It sounds more like a permissions problem that you might be able to solve using ACL manipulation. If the app doesn't already have permissions to mess with that folder, you might be able to write a custom action to remedy the problem by adding the necessary permissions to your process.
Another way of doing this is to make sure that the directory deletion is happening within a custom action that you control (as in, you own/maintain the code that performs the deletion, rather than rely on MsiExec to do it for you). Then, set that custom action to run in the System context so that it will have the same permissions as a service. That should provide your installer with sufficient rights to remove the folder.
You should use the normal update system within the windows installer.
your access denied message appears because file/directory is in use.
renaming directories isn't also not a good idea.
what happened if the user clicks "repair" or "uninstall" ?
you can start the msi with shellexec. after that terminate you app immediately.
you should check that in the msi that your app is NOT running anymore.
do the update. if a file is in use the installer automatically wants to reboot to replace the stuff.
CreateProcess should work if you are passing it the right parameters. Don't reference the parent process in any way and set most things to NULL. If that doesn't work, then you can try WinExec().

How to get the actual path of a file in Vista with UAC?

I am calling CreateFile() to create a file in the Program Data directory. I'm using SHGetSpecialFolderPath() to get the dir name.
I have a user with Vista for whom CreateFile() is returning error 5 (Access Denied). It would help if I knew where CreateFile() was actually attempting to create the file so we can check his folder permissions. The problem with Vista (UAC) is, it's not attempting to create the file in the directory I passed in. It could also be in a VirtualStore directory. An added source of confusion is this user is German and although SHGetSpecialFolderPath() is returning "C:\Program Data\blah blah" as the path, I don't think that's actually where the path is. I think German Vista uses the German word for "Program Data". I would like to be able to tell the user "This is the exact path where we are trying to create the file. Check your permissions on this folder."
I know you can get the a path from an open file handle, but in this case the CreateFile() is failing so I don't have an open handle. How can I get Vista to tell me the actual path where it's attempting to create the file?
Fire up Process Monitor and watch what it does:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
If with UAC the paths used are not the ones you want, then the redirection is in effect.
To make sure that redirection does not occur, add a manifest to your application which indicates to Vista that your application is properly coded and aware of access restrictions (i.e., you don't write to e.g., HKLM or the programs folder if your app doesn't need admin privileges to run).
But your application should be able to write to the APPDATA folder (if that's what you really use).
Make sure you're using CSIDL_APPDATA and not CSIDL_COMMON_APPDATA (the latter one being accessible only with admin privileges).
To find the real path (the one you would expect) tell the user to type %APPDATA% into the explorer bar (or hit Windows+R, then type %APPDATA%, enter). This will open the explorer on that folder.
My understanding is that ProgramData is used by Vista to write files that were attempting to be written inside C:\Program Files, but failed, since unless you are running the app as Admin you can't write inside program files. Maybe you should try saving your files to the AppData folder under the current user.

Resources