Virtual Developer Workshop: Containerized Development with Docker
I've always been intrigued by the Control Panel; what are those items in the Control Panel? Are they programs? What makes them appear? I'm not talking about what the various objects inside the Control Panel do or mean; I'm speaking about what make those objects tick, how I can make things easier for myself by running those objects directly from my programs. With this article, I will show you how to run all the various Control Panel applets from your own program.
Control Panel Applets Explained
Control Panel Applets are special purpose Dynamic Link Libraries (DLLs) that let users configure the environment of Microsoft® Windows®.
The primary responsibility of any Control Panel Applet is to display a window (typically a dialog box or property sheet) and to carry out any tasks the user specifies. Despite this responsibility, Control Panel Applets do not provide menus or other direct means for users to access their dialog boxes. Instead, these applications operate under the control of another application and launch their subprograms only when requested by the controlling application. Control Panel Applets, such as the Mouse applet, are usually controlled by a Windows system utility specifically designed to give users access to these applications.
Most Control Panel Applets display and manage a single subprogram, giving the user control of the settings and operational modes of a single system component. However, any given Control Panel Applet can provide any number of subprograms to control any number of system components. To distinguish among subprograms, a Control Panel Applet typically supplies the controlling application with a unique icon for each subprogram. The controlling application displays these icons, and the user can choose a subprogram by choosing the corresponding icon.
Behind the Scenes in Executing These Applets
To open or run these applets, you could use a Windows utility named RunDll32. RunDll32 enables you to call functions exported from a 32-bit DLL. These functions must have the following syntax:
void CALLBACK EntryPoint( HWND hwnd, // handle to owner window HINSTANCE hinst, // instance handle for the DLL LPTSTR lpCmdLine, // string the DLL will parse int nCmdShow // show state );
Now, I'm not going to go into the details of the physical contents these files need to have, but I'm just quickly going to explain how the RunDll32 utility works. Rundll32 loads the specified DLL using LoadLibrary, obtains the address of the function using the GetProcAddress function, and calls the function with the specified arguments, if any. When the function returns, Rundll32 unloads the DLL and exits.
It is possible to create a Unicode version of the function. Rundll32 first tries to find a function named EntryPointW. If it cannot find this function, it tries EntryPointA, and then EntryPoint.
Executing the Control Panel Applets
To use the RunDll32 utility in your program, you need to have a look at the Process class. This class provides access to local and remote processes and enables you to start and stop local system processes.
A Process object provides access to a process that is running on a computer. A process, in the simplest terms, is a running application. A thread is the basic unit to which the operating system allocates processor time.
To start a Process, you can use the Start method from the Process class; you also can include the StartInfo parameter that members can use to duplicate the functionality of the Run dialog box of the Windows Start menu. Anything that can be typed into a command line can be started by setting the appropriate values in the StartInfo property. The only StartInfo property that must be set is the FileName property. The FileName property does not have to be an executable file. It can be of any file type for which the extension has been associated with an application that is installed on the system. For example, the FileName property can have a .txt extension if you have associated text files with an editor, such as Notepad; or it can have a .doc extension if you have associated .doc files with a word processing tool, such as Microsoft Word.
On the command line, you can specify actions to take for certain types of files. For example, you can print documents or edit text files. Specify these actions by using the Verb member of the StartInfo property. For other types of files, you can specify command-line arguments when you start the file from the Run dialog box. For example, you can pass a URL as an argument if you specify your browser as the FileName. These arguments can be specified in the StartInfo property's Arguments member.
Putting Everything Together
Running Accessibility Options
'Open first tabpage of the Accessibility Options applet Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL access.cpl,,1") 'Open second tabpage of the Accessibility Options applet Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL access.cpl,,2") 'Open third tabpage of the Accessibility Options applet Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL access.cpl,,3")
As you can see, it is very easy running this applet with the use of the Process class. Here, you use Control_RunDLL as your Entrypoint for the shell32.dll. If you read closely, you would notice the last part of each statement. The numbers I've used are the numbers of the tabpages I wanted to show within the dialog box. Easy? Yes! I thought so too.
Running Add or Remove Programs
Static AddRemoveCount As Integer 'add & remove programs Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL appwiz.cpl,," & AddRemoveCount) AddRemoveCount += 1 'go to next option If AddRemoveCount > 3 Then AddRemoveCount = 0
The same rule of thumb applies here, except that with the Add or Remove Programs dialog, you are not dealing with tabs, but with four options, namely:
- Change or Remove Programs
- Add New Programs
- Add/Remove Windows Components
- Set Program Access and Defaults
This time, however, I made use of a Static variable counter named AddRemoveCount that keeps track of how many times the button is clicked; then, based on that, concatenates its value to the command string you are running. If the static variable equals the value of the last option, you just reset it to 0 to step through the options again.
Running Date & Time Settings
Static DateTimeCount As Integer 'date & time Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL timedate.cpl,," & DateTimeCount) DateTimeCount += 1 'go to next tab If DateTimeCount > 2 Then DateTimeCount = 0
Static DisplayCount As Integer DisplayCount += 1 If DisplayCount > 5 Then DisplayCount = 0 'display Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL desk.cpl,," & DisplayCount)
Running Game Controls
'game controllers Process.Start("rundll32.exe", "shell32.dll,Control_RunDLL joy.cpl")
With this applet, there aren't any additional tabs.
Running Internet Options
Static InternetCount As Integer InternetCount += 1 If InternetCount > 7 Then InternetCount = 0 'Internet options Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL inetcpl.cpl,," & InternetCount)
Static KeyboardCount As Integer KeyboardCount += 1 If KeyboardCount > 2 Then KeyboardCount = 0 'keyboard Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL main.cpl,@1," & KeyboardCount)
Static MouseCount As Integer MouseCount += 1 If MouseCount > 5 Then MouseCount = 0 'mouse Process.Start("rundll32.exe", "shell32.dll, _ Control_RunDLL main.cpl,@0," & MouseCount)