I need to execute another application and I'm wondering if there's a reason why I should use WinExec instead of ShellExecute or vice versa.
Which are differences between two methods? Is there one that should be preferred?
WinExec is long deprecated and retained only for backwards compatibility reasons. It is used to start executables. Don't use it, due to its deprecation. As stated in the documentation:
This function is provided only for compatibility with 16-bit Windows. Applications should use the CreateProcess function.
ShellExecute is not deprecated, but also should not be used since it cannot report errors properly.
Use ShellExecuteEx to execute shell verbs.
If you wish to create a process, and you know the executable file name, use CreateProcess. Unless you need to execute elevated in which case you need ShellExecuteEx with the runas verb.
Related
How do I know in a windows program if a process is running if I only know the exe file name ?
The process in question is TeamSpeak3 ts3client_win64.exe for 64 bit and ts3client_win32.exe for 32 bit.
I am using C++
Use the CreateToolhelp32Snapshot function to create a snapshot of the current process table, then use the Process32First and Process32Next functions to iterate the snapshot. You can get the name for each executable file by looking at the szExeName field of the PROCESSENTRY32 structure.
See the MSDN example for a sample of how to use these functions.
The advantage of this approach is that, unlike any EnumProcesses-based solution, it doesn't suffer from race conditions: with EnumProcesses it can happen that a process gets destroyed after you finished enumerating the processes but before you got around to opening the process (or reading our the process executable name).
You can use a combination of EnumProcesses, OpenProcess, and GetModuleFileNameEx (or alternatively, QueryFullProcessImageName for Vista or later). MSDN even has an example.
Windows NT has several APIs for enumerating processes.
EnumProcesses
ToolHelp
NtQuerySystemInformation (discouraged)
WMI's Win32_Process (works remotely)
If you use CreateProcess, it only works on .exe's, apparently. What's the best way to make this work with other executable file types?
The best we have so far is to prepend cmd /c to such cases. Is that really the correct approach?
Batch files aren't technically executable files, they are just registered to open with cmd. As you mention that you need the ability to manipulate I/O handles, your best bet is indeed to use CreateProcess with cmd /c.
In POSIX, there is the fork() function to create a sub-process. How can I achieve fork()'s functionality in Windows?
There is no direct equivalent of fork() on Windows.
CreateProcess() is the native function that can be used to create a new process (but, again, the semantics are rather different to fork()'s).
To put this another way, on Unix it is possible for a process to cheaply create a clone of itself. There is no inexpensive way to do this on Windows.
If you don't care about the cloning aspect of fork(), then CreateProcess() should do just fine.
Folks,
Is it possible to create a bat file that launches an executable and waits for a pre-determined string in the standard output. When that string is found, the batch file will exit (the exe can continue running). How could this be accomplished?
In short, no.
Note that originally MS-DOS was an operating system in which Windows ran. Now it is an application that simulates the earlier OS. The way to solve your would possibly involve using an application called from within MS-DOS, that will perform this kind of logic (i.e. IF(file_is_present_with_string)THEN {...}) in the MS-DOS command library.
Powershell is a powerful scripting language allowing you to perform many operations previously unavailable in MS-DOS, such as take the output from one MS-DOS command (e.g. ipconfig /all) and reformat it into a different layout, possibly using it as another command's input parameters (e.g. select a value from ipconfig and use it in another command). Although it supports MS-DOS command execution, it does so through the use of CMDLETs (pronouned command-let) which is a self-contained application designed to run inside Powershell. There are many other CMDLETs out there that might be able to help solve your problem.
In Windows -- and probably Unix for that matter -- using the chdir() function in a (32-bit) program doesn't change the directory when the program exits. (It does in a 16-bit Windows program.)
Does anybody know how to do that in a Windows 32-bit program?
Uhm... IMHO it's exactly one of the things that the OS must guarantee not to happen. The current dir is a per-process property, a child process usually inherits it from the parent process, but the reverse should not happen (and it doesn't).
To obtain what you want, the parent could actively watch some information (message, file, shared memory...) in which the child process stores the new directory, and then call chdir() with the new value.
As far as I know, Windows' cmd.exe doesn't have any mechanism like that.
Actually, by using code injection techniques (e.g. CreateRemoteThread) on the parent process it could be possible to force it to do something unexpected, but it's a very dirty trick, not at all good neither general.
Win16 was different: there was a single "msdos" state for all the programs, but it was a limitation, not a feature.
It sounds like you're asking one process (your Win32 program) to change the CWD of another process (your shell). As far as I know, this is impossible without the latter process providing an API for such a purpose. The nearest I can come to any sort of reference for this assertion, however, is the following quote from MSDN:
A parent process can directly alter the environment variables of a child process during process creation. This is the only situation when a process can directly change the environment settings of another process.
Well yeah it's true the popular API calls to change directory change it for the process. ... BUT ...
(1.) 16-bit windows programs can change the global directory; probably because they run in the same process as the command.com thing. That's what I've been happily using for years; I assume XP somehow emulates this? ... But now Windows 7 64-bit won't run 16-bit programs anymore! (?)
(2.) Both Windows and Unix "cd" commands can of course change directories for the calling process -- presumably because they are built-in commands of the command shell. But successor Windows shells manage to accomplish this, or at least I hope PowerShell can do that. All built-ins?
(3.) The way I've wound-up doing it is modifying my programs that used to call the API to simply emit "cd \dst\directory" to stdout, then in a procedure do
chdirprogram >t~.bat
call T~.bat
Which works great. And of course the usual point of a change-directory program is to provide the functionality in a batch procedure with a computed destination. Which of course you can do in Unix with Bash etc. variables, but not in Windows batch files, although maybe (?) in the numerous successor Windows procedure things, which I don't want to use. ... Since this functionality is obviously useful, I was hoping someone knew of a sneaky Windows call what'd do it. The explanation that it's somehow wrong for a process to change the directory for a calling process is one of those bogus, "you're not supposed to do that and I won't tell you why" excuses. ... But I guess I'll just stick to my pitiful little batch files.
Are you talking about the SetCurrentDirectory function of Windows API? The article says that the function "changes the current directory for the current process". In for instance Delphi, there is a function ChDir that actually calls this API function.