On Windows it opens a console window that I'd like to get rid of. I want another function that is capable, without exception, of all the same things system() can do, but without that nasty command prompt comng up. I'm making an extension for GameMaker: Studio that does everything I need it to on Linux and Mac as they don't append opening a terminal window with system(). But since Windows works a bit differently with that function, I'm really stuck.
I've tried googling all over for solutions like ShellExecute or CreateProcess but neither of those are what I'm looking for. I want to be able to do DOS/Run Commands. A couple small examples
md c:\new_folder\
or
start notepad.exe
Stuff like that while also supporting multiple arguments. I've seen one possibilty is exec() but it replaces the current process, which on Windows there is no fork() function so I'm not sure how to use exec() how I'd like it to work without a fork() equivalent handy. I'd like to also give the user the ability to choose whether to wait for finishing. For example
// waits for notepad to close before going back to initial application.
SomeCustomFunction("notepad.exe", true);
// does not wait for notepad to close before resume.
SomeCustomFunction("notepad.exe", false);
On Linux, I wrote an *.SO library that looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
extern "C"
{
double SomeCustomFunction(char *fname,double wait)
{
if (wait < 1)
{
if (fork() == 0)
{
system(fname);
exit(0);
}
}
else
{
system(fname);
}
return 0;
}
}
It throws two warnings in Code::Blocks, but it compiles fine and works exactly how I want it to when I call the library from my GameMaker: Studio game / program.
Here's my attempt at the "Windows equivalent" (*.DLL):
#include "main.h"
#define DLL extern "C" _declspec(dllexport)
DLL double SomeCustomFunction(char *fname,double wait)
{
PROCESS_INFORMATION ProcessInfo;
STARTUPINFO StartupInfo;
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof StartupInfo;
if (CreateProcess(NULL, fname,
NULL,NULL,FALSE,0,NULL,
NULL,&StartupInfo,&ProcessInfo))
{
if (wait >=1)
{
WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
}
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
}
return 0;
}
The problem is, on Windows, with the way I have it set up, it doesn't accept the same kind of stuff I'd like it to do, as mentioned earlier in this post.
I would use something like spawn() instead of CreateProcess(), but spawn() requires a separate string and argument for the filename and arguments, which I'd prefer to be all in one string / argument like in my Linux library function.
Thanks
Related
I have a compiled program (task.exe). The result of this program is a new cmd window with specific commands there. I need to execute commands just in that cmd window, that is, I need to send keyboard input to that window. I tried to make something like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Start task.exe");
system("task.exe && command ");
return 0;
}
Guys, could you please help me with this problem. I think maybe I should somehow get the created process, and then work from there.
You can send keyboard input using the function SendInput.
A better, but more complex approach would be using Microsoft UI Automation.
I am packaging a program on Windows that expects to be able to externally call OpenSSH. So, I need to package ssh.exe with it and I need to force ssh.exe to always be called with a custom command line parameter (specifically -F to specify a config file it should use). There is no way to force the calling program to do this, and there are no simple ways to do this otherwise in Windows (that I can think of anyway - symlinks or cmd scripts won't work) so I was just going to write a simple wrapper in C to do it.
This is the code I put together:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int ret;
char **newv = malloc((argc + 2) * sizeof(*newv));
memmove(newv, argv, sizeof(*newv) * argc);
newv[argc] = "-F ssh.conf";
newv[argc+1] = 0;
ret = execv("ssh.orig.exe", newv);
printf("execv failed with return value of %i", ret);
return ret;
}
I then compile this code using GCC 4.6.3 in Cygwin and it runs without error; however, there is a strange behavior with regards to input and output. When you go to type at the console (confirming the authenticity of the host and entering in a password, etc) only part of the input appears on the console. For example, if I type in the word 'yes' and press enter, only the 'e' will appear on the console and SSH will display an error about needing to type 'yes' or 'no'. Doing this from the Windows command prompt will result in your input going back to the command propmt, so when you type 'yes' and press enter, you get the ''yes' is not recognized as an internal or external command...' message as if the input were being typed at the command prompt. Eventually SSH will time out after that.
So, I'm obviously missing something here, and I'm assuming it has something to do with the way execv works (at least the POSIX Cygwin version of it).
Is there something I'm missing here or are there any alternatives? I was wondering if maybe I need to fork it and redirect the I/O to the fork (although fork() doesn't seem to work - but there are other issues there on Windows). I tried using _execv from process.h but I was having issues getting the code right for that (also could have been related to trying to use gcc).
It's also possible that there may be a non-programming way to do this that I haven't thought of, but all of the possibilities I've tried don't seem to work.
Thoughts?
I ended up finding a solution to this problem. I'm sure there were other ways to do this, but this seems to fix the issue and works well. I've replaced the execv line with the following code:
ret = spawnv(P_WAIT, "ssh.orig.exe", newv);
You have to use 'P_WAIT' otherwise the parent process completes and exits and you still have the same problem as before. This causes the parent process to wait, but still transfers input and output to the child process.
Using system() or exec(), I can get any command to execute but they display the result into the Console. I want to execute the command and extract the output and process it, and then display it. How can I achieve this on Windows/DOS Platform?
There's nothing like that in standard C, but usually, for compatibility with POSIX, compilers implement popen (_popen in VC++), which starts a command (as it would do with system) and returns a FILE * to the stream you asked for (you can ask for stdout if you want to read the output or stdin if you want to give some input to the program).
Once you have the FILE *, you can read it with the usual fread/fscanf/..., like you would do on a regular file.
If you want to have both input and output redirection things start to get a bit more complicated, since Windows compilers usually do have something like POSIX pipe, but it isn't perfectly compatible (mostly because the Windows process creation model is different).
In this case (and in any case where you need more control on the started process than the plain popen gives you) I would simply go with the "real" way to perform IO redirection on Windows, i.e. with CreateProcess and the appropriate options; see e.g. here.
Matteo Italia's answer is awesome. But some compilers (especially older ones) don't support popen().
If popen() is not supported, here's a possible solution.
In DOS we can redirect the output to a temporary file using >.
Ex:
C:\> ipconfig > temp.txt
I can then open temp.txt in my C-code and then reprocess its content.
My C code for this will be something like:
system("ipconfig > temp.txt");
FILE *fp;
fp = fopen("temp.txt","r");
// //
//... Code for reprocessing can go here ...//
// //
Here's an alternative answer for those without popen that should work on most system. This code is not thread safe. I expect that this is not a significant limitation for most situation.
#include <stdio.h>
#include <process.h>
#include <io.h>
#include <sys\stat.h>
#include <assert.h>
int main()
{
int so = dup(1);
close(1);
int i = creat("output.txt", S_IWRITE);
assert(i == 1); // i should be 1...
system("dir");
close(i);
dup2(so, 1);
close(so);
}
I want to start a simple program when windows start but I don't want to show the console output window associated with that program. Just to test, the program can be as simple as:
int main (int argc, char** argv)
{
while (1)
{
printf ("hello world...\n");
Sleep (10000);
}
return 0;
}
compiling it as: cl foo.c
I know how to start the program when windows is starting (putting in startup folder, creating registry etc), but I don't know how to hide the console output window that comes when the program is started.
While searching for this, I found that I can use start /B foo.exe. Is there any other method for doing this? some thing like "&" we use on unix.
My actual program is big and is written in C, so I can not use some other alternatives i found for c# (like WinMain) and java (like explained here).
This should work.
#include <windows.h>
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdParam, int iCmdShow)
{
for (;;) {
//action here
}
return 0;
}
WinMain is not a C# entry point. C# uses a method of a static class; it is called Main by default, but can be configured to any static-class method.
In Windows, non-console C programs should define a WinMain. You can then link them using the linker's /subsystem:windows command-line option, invokable either directly or from CL.
One method is calling FreeConsole() as first thing in main. It will hide the console window, if any.
Unfortunately simply setting FreeConsole() as the first function in main allows the window to appear momentarily anyway. And FreeConsole removes the window so that if you wish to use it later( as in killing the process ) you have to make it appear on screen in a mode out of your control.
Windows allows Win32 programs to have only one of four contexts under Visual Studio: Window program with initial GUI window, Console program with initial Console window, DLL or Lib. Changing the subsystem to a non-Console choice from the project->Properties->System view only results in linking issues that block the build.
Here is what worked for me with only a little effort. Use Mike's approach above and choose Win32 Project with Window Application. Then delete everything in WinMain after the "Place code here" direction and delete all the called functions. Return true or 1, as you wish from WinMain. No window of any type will appear on launch.
And when you are ready to deal with a Console Window call AllocConsole() in your code and deal with its positioning and size as you see fit. The Console can be positioned off screen and slid into view if you wish; it only takes a few minutes to get the handle on the configuring functions. Start with Microsoft's 'Console Functions' in MSDN documents. Unfortunately, there is no book on how to use all the functions properly as there is for NCurses in Linux.
When you're creating your project create one with WinMain instead ( Win32 Project ). If you still want the console later use AllocConsole() and FreeConsole().
If the program would be eg procexp.exe you can do this out of the box :
cmd /c "start C:\Users\denni\OneDrive\_bin\_tools\ProcessExplorer\procexp.exe"
WinMain isn't unique to C#. It's possible to write GUI applications in C too. The WinMain function is the entry point, but nothing says you have to actually create a window. You could have WinMain do nothing more than call the first function of your program to get it started. Then you'd have your program running with no GUI window and no console window.
Of course, this also means no easy way to stop it, short of killing it from Task Manager.
My program loads several dlls and calls their functions. The dlls can use different versions of CRT.
When C runtime checks the validity of arguments and finds problems, it calls the invalid parameter handle, which in turn, closes the application, with or without the "Send-Don't send" dialog.
I tried calling *_set_invalid_parameter_handler* but it only works if it is called from within the bad dll. I tried SetErrorMode, but all I managed to do is get the process killed without the dialog.
Is there any way to handle those exceptions? I don't care if some resources are compromised. All I want is to allow users to save the configuration. If the dialog appears, they click on it and kill the process.
EDIT
It turns out the solution to load all versions of CRT or to enumerate all DLLs fails. To make all clear, here is a small example to play with:
This would be my main application (let's call the file application.c):
#include <windows.h>
void myInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) {
wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
}
void fixMyProblem() {
}
int main(int argc, char **argv) {
HMODULE hModule = LoadLibrary("extension.dll");
void (WINAPI *function)() = GetProcAddress(hModule, "function");
fixMyProblem();
function();
}
This application loads a dll that does bad things (it is not developed by me, so I will not accept any solution telling me to fix the bugs there). Lets' call that file extension.c.
#include <stdio.h>
__declspec(dllexport) void function() {
printf("do bad stuff");
fopen(NULL, "r");
}
To compile, do:
cl extension.c /link /OUT:extension.dll /DLL
cl application.c
The question is what do I do in function fixMyProblem(), so that I don't get the send/don't send dialog on XP or the application has stopped working dialog on 7.
According to David Gladfelter I should do
void fixMyProblem() {
_set_invalid_parameter_handler(myInvalidParameterHandler);
}
and also do this for each version CRT available. It turns out that even with one single version of CRT (I use the same for both exe and dll), it still does not work. They both use the same version of CRT, but is seems they do not use the same CRT.
If this is is the case, I assume that the stuff I have to change is inside the DLL. Of course, it does not export *_set_invalid_parameter_handler*.
But to be fair to David Heffernan, here is the implementation for his solution:
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
void fixMyProblem() {
HANDLE hProcess = GetCurrentProcess();
HMODULE *hModules;
DWORD requiredSize = 0;
DWORD secondRequiredSize = 0;
if (!EnumProcessModules(hProcess, NULL, 0, &requiredSize)) {
printf("oops\n");
return;
}
hModules = malloc(requiredSize);
if (EnumProcessModules(hProcess, hModules, requiredSize, &secondRequiredSize)) {
int i;
int loadedModules = min(requiredSize, secondRequiredSize) / sizeof(HMODULE);
for (i = 0; i < loadedModules; i++) {
void *(WINAPI *_set_invalid_parameter_handler_function)(void *) = (void *(WINAPI *)(void *)) GetProcAddress(hModules[i], "_set_invalid_parameter_handler");
if (_set_invalid_parameter_handler_function != NULL) {
_set_invalid_parameter_handler_function(myInvalidParameterHandler);
printf("fixed dll %d\n", i);
}
}
} else {
printf("oops\n");
}
free(hModules);
}
For my real application, not this test, I get 1 dll fixed (msvcp90.dll). It still does not fix my problem.
I would appreciate any help in solving this.
If the dll is built with a statically linked CRT, then the state and functions of the CRT will be local to that instance of the dll.
I am assuming the invalid parameter handler used by the CRT is calling the UnhandledExceptionFilter function, from the OS, to show that "nice" error dialog.
You could try to hook functions like UnhandledExceptionFilter or TerminateProcess, making the dll use your own functions instead. You can do this by parsing the Import Address Table of the loaded dll, search for the function name you are interested, and change the address to point to your function.
You could always enumerate the modules in your process and if it's a C runtime then get hold of the invalid parameter handler with a call to GetProcAddress.
But you'd be better off trying to fix the bugs at root. Trying to ignore such problems mostly just leads to further problems because memory gets corrupted and so on.
You could create another DLL that uses the same version of the CRT as the version used by the DLL that causes the invalid parameter handler to be called and register the invalid parameter handler it in that new DLL. The invalid parameter handler is global to the process/CRT-version combination.
If you don't know what version the DLL is using and you can't figure it out, worst-case is you create several DLL's, one for each CRT version:
VS 6 static/dynamic/multithreaded/single-threaded
VS.NET static/dynamic/multithreaded/single-threaded
VS 2003 static/dynamic/multithreaded/single-threaded
VS 2005 static/dynamic
VS 2008 static/dynamic
VS 2010 static/dynamic
You could probably create them as static .lib files and link them all into one (very confused) DLL.