MFC project without exe file [duplicate] - visual-studio-2010

I am creating a program in c++, which I want to be able to have the option to have users let it auto start in windows. So when a user starts his computer, windows will auto start this program. I have read stuff about modifying the registry or putting it in the startup folder, but what would be the best "clean" way to do this?

Startup folder is clean enough.
Gives the user the possibility to remove it if needed.

There are many ways to autostart an application, but the easiest, most common and IMO best are:
Put a shortcut in the autostart folder
Add an autostart entry to the registry (Software\Microsoft\Windows\CurrentVersion\Run)
The end result is the same for both. I believe the registry way is executed earlier in the logon process than the startup way, but I am not certain. It does not make any difference for most cases anyway. I prefer the registry, but that is personal taste. You can create and delete the registry key or the shortcut programatically in your app.
With both options you can use either one setting for all users (All User startup folder, or under HKLM key in the registry) or user specific (user startup folder or under HKCR key).
In general it is better to use the per user options, because you can be certain to have writing privileges in those areas; and every user on the computer can have his/her own setting.

Depending on whether you're executing an all-user or per-user install, put it in the Startup folder for All Users or the per-user Startup folder. The Startup folder you see in the menu is the merger of both, but non-admin users cannot remove the entries coming from the All-user part.
You actually don't have to do anything for this, though. Users can copy your normal shortcut to the Startup menu themselves. Hence, any program can be an auto-startup program. Doesn't need to be C++ at all.

You can register it as a windows service.You can use "Qt Solutions" for easily making an application as windows service.

With this code you can do it
procedure TForm1.Button1Click(Sender: TObject);
var
Reg:TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',True);
Reg.WriteString('Program name',ParamStr(0));
finally
Reg.Free;
end;
end;
or this:
using Microsoft.Win32;
private void AddStartUpKey(string _name, string _path) {
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Software\Micros oft\Windows\CurrentVersion\Run", true);
key.SetValue(_name, _path);
}
private void RemoveStartUpKey(string _name) {
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Software\Micros oft\Windows\CurrentVersion\Run", true);
key.DeleteValue(_name, false);
}

Related

How do programs that don't appear in the startup folder auto-execute on startup?

Just out of curiosity I was wondering how this is done. I know you can probably manually make a program startup using windows scheduler, but for something download from the interwebs, such as Discord, how does it autonomously give itself the ability to run on startup without actually being in the startup folder?
I found the answer elsewhere on this site, here is the link and a quote
https://stackoverflow.com/a/20781275/9546874
Add a new startup application Open your registry and find the key [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run].
For each program you want to start automatically create a new string value using a descriptive name, and set the value of the string to the program executable.
For example, to automatically start Notepad, add a new entry of "Notepad"="c:\windows\notepad.exe".
Some applications do not appear in the startup folder but start up automatically anyway. Programmers have the ability to disable their application showing up in the startup folder. To answer your question, it's a decision made by the dev team behind the application.
Here is a link to disable those applications using the shell: Disable items not in the Startup folder
This article goes into depth about how windows uses registry keys to open applications upon startup.
If you would like to disable discord's auto startup, this is how.

Create startup folder - 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.

Add explorer context menu item for PDF files from delphi

I have my application written in Delphi XE that works with PDF files. Applicaiton is Win32. On start I would like to ensure that there is my item in explorer context menu for PDF files. I would like to be able to specify whether it should be added for active user only or for all users (with UAC I will need to restart with Admin privileges but thats ok).
I started with How to associate a Delphi program with a file type, but only for the current user? and How to add item to windows explorer content menu in delphi? . I tested it with manual registry editing via regedit and it worked fine for "new" extensions. But for .pdf it is more complicated as it will be most probably already present in the registry.
On my PC the .pdf key is referencing AcroExch.Document . But adding shell/something subkey to the AcroExch.Document key is not working because it has CurVer subkey referencing to AcroExch.Document.7. However another PC with another verison of Acrobat had this names a little different. It is no problem for me to follow the CurVer reference but is that a correct approach? And what about situation where no PDF reader is installed, how should I name my keys so Acrobat won't overwrite them when installed?
But more pressing matter is in which root should I put my keys? How to associate a Delphi program with a file type, but only for the current user? is mentioning HKLM (Local Machine) and HKCU (Current user). Its seems rather straightforward but I am unable to set values in HKLM from Delphi. Strangely I can create keys:
var reg:TRegistry;
key := '\Software\Classes\'+keyname+'\shell\'+name+'\command';
reg.CreateKey(key);
but I am getting Access Denied when trying to write the actual value:
reg.OpenKey(key,false);
reg.WriteString('',command);
I am getting the same Access Denied exception even on WinXP, no matter if the applicaiton is running as Admin (Win7), I even tried to set permissions (Everyone full control) for the key via regedit (I can edit the value via regedit without problems). I tried creating the registry with different access modes, all with no luck:
reg := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY);
reg := TRegistry.Create(KEY_ALL_ACCESS or KEY_WOW64_64KEY);
reg.Access := KEY_ALL_ACCESS;
reg.Access := KEY_WRITE or KEY_WOW64_64KEY;
reg.Access := KEY_ALL_ACCESS or KEY_WOW64_64KEY;
With HKCU everything works fine.
So I tried writing into HKEY_CLASSES_ROOT and it works and actually puts the keys exactly where I want (into HKLM) if running as Admin. But according to http://msdn.microsoft.com/en-us/library/windows/desktop/ms724475.aspx
The HKEY_CLASSES_ROOT (HKCR) key contains file name extension associations and COM class registration information such as ProgIDs, CLSIDs, and IIDs. It is primarily intended for compatibility with the registry in 16-bit Windows.
I do not like the note about the primary purpose being compatibile with 16-bit Windows. And the actual conditions where the changes will be written is more complicated than I would like.
So basically I have these questions:
What is the advantage of using AcroExch.Document and CurVer instead of pointing directly to AcroExch.Document.7? And what are the "best manners" when adding my keys into this structure? What about the case when the .pdf is not yet associated with anything?
Where should I put my keys and why I am not able to write into HKLM?
Edit:
The problem with Access Denied when writing to HKLM was caused by my error. I did use in previous code openKeyReadOnly and I did not notice that it will swtich the Access property to readonly for all subsequent calls.
To answer your other question, if Adobe is not installed yet then obviously the PDF keys will likely not exist in the Registry yet so you would have to create your own .pdf and ProgID keys so that you can attach your Shell command on it. If Adobe is installed afterwards, it is likely going to wipe out your keys and replace them with its own, so you would have to recreate your Shell command within Adobe's key structure. Your app can query the Registry to check for that condition periodically, such as at startup.
You have asked two separate questions. Since I know the answer to one and not the other, I'm going to answer just one. For future reference, I do recommend that you ask a single question at a time.
Where should I put my keys?
You are correct in discerning that you should not use HKCR. The documentation for HKCR says:
Class registration and file name extension information is stored under
both the HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER keys. The
HKEY_LOCAL_MACHINE\Software\Classes key contains default settings that
can apply to all users on the local computer. The
HKEY_CURRENT_USER\Software\Classes key contains settings that apply
only to the interactive user. The HKEY_CLASSES_ROOT key provides a
view of the registry that merges the information from these two
sources. HKEY_CLASSES_ROOT also provides this merged view for
applications designed for previous versions of Windows.
....
If you write keys to a key under HKEY_CLASSES_ROOT, the system stores
the information under HKEY_LOCAL_MACHINE\Software\Classes. If you
write values to a key under HKEY_CLASSES_ROOT, and the key already
exists under HKEY_CURRENT_USER\Software\Classes, the system will store
the information there instead of under
HKEY_LOCAL_MACHINE\Software\Classes.
So, it is reasonable to use HKCR for reading, but for writing you typically need to exert control over whether to write to HKLM or HKCU. And that means that you cannot write to HKCR.
So, write to HKLM\Software\Classes for machine-wide settings, and HKCU\Software\Classes for user-specific settings.
Note that in Windows 7 and later neither of these keys is redirected and so you do not need to worry about using KEY_WOW64_64KEY. However, in Vista and XP64, and the equivalent server editions, these keys are redirected and reflected. Which means that it might be prudent to use KEY_WOW64_64KEY.

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.

Launch app on startup for all users, but also allow per-user setting (Windows)

I need my application installer set the program to auto-startup for all users.
Then each individual user should be able to modify this option without affecting others.
Currently I write to HKLM/../Run with installer, which acomplishes the first task.
But then I can't disable autorun for current user, because deleting th HKLM/../Run entry would disable it for everybody.
Is there a way to do that, without using shortcuts in Autostart folder?
start it for all users always but check a configuration variable in HKLU to see if it should exit immediately
Any reason not to use the HKCU Run key in the first place?
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]

Resources