diff --git a/README.md b/README.md
index babca27..79aa1db 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,86 @@
# winrun
+
Simple Windows Executable to run commands from a file.
## About
-The current [Base Camp™](https://mountain.gg/base-camp/) release does not support running commands or launching programs with custom launch options,
-while at the same time only allowing you to select .exe files to be launched.
-This program is a quick and dirty workaround for this usecase.
-I can't think of any other usecase, because usually you could just write a .bat file or something similar.
+The current [Base Camp™](https://mountain.gg/base-camp/) release does not support running commands or launching programs with custom launch options, while at the same time only allowing you to select .exe files to be launched.
+
+This program is a quick and dirty workaround for this usecase.
+
+Sometimes it may be desired to launch applications in the background, without giving focus to them. ***winrun*** allows for this.
## Installation and Usage
+
- Download the [latest version](https://github.com/schnotzler/winrun/releases) (winrun.exe)
- Move the downloaded executable to any directory you like. I prefer to use same location as the program i want to run is in.
-- Create a simple file named `winrun.cfg` in the ***same directory as winrun.exe***
-- Add you command(s) to `winrun.cfg`. See [this example](https://github.com/schnotzler/winrun/blob/main/winrun.cfg) which would run the windows calculator app
+- Create a simple file named `winrun.cfg` in the ***same directory as winrun.exe***
+- Add the process(es) you wish to run `winrun.cfg`. See [this example](https://github.com/schnotzler/winrun/blob/main/winrun.cfg) which would run the windows editor (notepad.exe). Have a look at section [Advanced Usage](#detailed-usage-of-cfg) for more information
- Now select `winrun.exe` from your directory in `Base Camp™`»`Device`»`Key Binding`»`Key`»`Function`»`Run Program`»`Link`
-Note: Of course you can have multiple configuration of `winrun` in use, just make sure to use a different directory with a different `winrun.cfg`
+Note: Of course you can have multiple configurations of `winrun` in use, just make sure to use a different directory with a different `winrun.cfg`
+
+## Detailed usage of `.cfg`
+
+### General
+
+The winrun.cfg file is parsed line by line.
+Each line is executed one after another.
+Empty lines are skipped.
+It is therefore possible to open multiple programs in one go.
+
+### Leading whitespaces
+Leading spaces or tabs are ignored.
+So each one of the lines below is valid in a `winrun.cfg` and is going to give the same result.
+
+```cfg
+notepad.exe winrun.cfg
+ notepad.exe winrun.cfg
+ notepad.exe winrun.cfg
+ notepad.exe winrun.cfg
+```
+
+### Running in background
+
+The default behaviour if not specified is, that the newly launched Program will receive focus.
+
+But it is possible to start programs in the background, without giving focus to them, as well.
+However some applications give focus to themselves on launch, so your mileage may vary here.
+
+To mark program, to be run without focus, just add `#NOFOCUS` before the command.
+
+Whitespace handling is quite lenient here as well.
+
+So each one of the lines below is valid in a `winrun.cfg` and is going to give the same result, that is opening notepad without giving focus to the new window.
+
+
+```cfg
+#NOFOCUSnotepad.exe winrun.cfg
+#NOFOCUS notepad.exe winrun.cfg
+ #NOFOCUS notepad.exe winrun.cfg
+ #NOFOCUSnotepad.exe winrun.cfg
+#NOFOCUS notepad.exe winrun.cfg
+ #NOFOCUS notepad.exe winrun.cfg
+ #NOFOCUSnotepad.exe winrun.cfg
+```
+
+Analog to `#NOFOCUS` there is also support for `#FOCUS`, which as you may have guessed gives focus to the new window.
+`#FOCUS` may be omitted, since it is the default behaviour anyway.
+
+You can mix and match `#NOFOCUS`, `#FOCUS`, and no explicit specification in the same `winrun.cfg` to your liking on a per-line-basis.
+
+Example for a mixed `winrun.cfg`, that would start 2 instances of notepad in the background and 2 in the foreground (only the last one will retain focus obviously). 2 of the editors will be empty, while 2 opened winrun.cfg. With the empty notepad launched by line 3 having focus.
+
+```cfg
+#NOFOCUSnotepad.exe winrun.cfg
+#FOCUS notepad.exe winrun.cfg
+notepad.exe
+#NOFOCUS notepad.exe
+```
+
+## Troubleshooting
+
+- If you have problems running your program, try using the absolute file path of your program `C:\WINDOWS\system32\notepad.exe` for example
+- Open an Issue only **after** you have read this `Readme.md` entirely
This is provided as-is. Use this program at you own risk, i am not responsible for any problems or damages you might have due to using this program
diff --git a/main.c b/main.c
index 0bda2cd..a3af1d9 100644
--- a/main.c
+++ b/main.c
@@ -2,6 +2,13 @@
#include
#include
+void ShowErrorBox( char* msg, char* windowtitle ) {
+ HWND hwnd = NULL; // Use NULL to display the message box as a standalone window
+ LPCSTR text = msg; // The text to display in the message box
+ LPCSTR title = windowtitle; // The title of the message box
+ MessageBox( hwnd, text, title, MB_OK | MB_ICONERROR );
+}
+
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int nCmdShow ) {
FILE* fp;
char linebuf[256 + 1] = { 0 };
@@ -25,8 +32,10 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdPara
return -2;
}
+ int retVal = 0;
+
// read and execute from file line by line
- while ( 0 < fscanf( fp, "%256[A-Za-z0-9 -\\:]\n", linebuf ) ) {
+ while ( EOF != fscanf( fp, "%256[A-Za-z0-9 -\\:]\n", linebuf ) ) {
STARTUPINFOA startupInfo = { 0 };
PROCESS_INFORMATION processInfo = { 0 };
@@ -37,25 +46,56 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdPara
startupInfo.cb = sizeof( STARTUPINFO );
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
- // Focus new Window
- // startupInfo.wShowWindow = SW_SHOWNORMAL;
+ // Trim leading whitespace(s)
+ while ( *commandLineArgs == ' ' || *commandLineArgs == '\t' ) {
+ commandLineArgs++;
+ }
- // Don't Focus new Window
- startupInfo.wShowWindow = SW_SHOWNOACTIVATE;
+ // Check for specified focus state and handle accordingly
+ if ( strncmp( "#NOFOCUS", commandLineArgs, 8 ) == 0 ) {
+ // Don't Focus new Window
+ startupInfo.wShowWindow = SW_SHOWNOACTIVATE;
+ commandLineArgs += 8;
+ } else { // Focus new Window
+ if ( strncmp( "#FOCUS", commandLineArgs, 6 ) == 0 ) {
+ commandLineArgs += 6;
+ }
+ startupInfo.wShowWindow = SW_SHOWNORMAL;
+ }
+
+ // Trim leading whitespace(s)
+ while ( *commandLineArgs == ' ' || *commandLineArgs == '\t' ) {
+ commandLineArgs++;
+ }
+
+ // Skip empty lines
+ if ( strlen( commandLineArgs ) == 0 ) {
+ // move fp by 1
+ fgetc( fp );
+ continue;
+ }
// Launch the process
if ( CreateProcessA( NULL, commandLineArgs, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo ) ) {
- printf( "Process started with process ID %lu\n", processInfo.dwProcessId );
+ // printf( "Process started with process ID %lu\n", processInfo.dwProcessId );
CloseHandle( processInfo.hProcess );
CloseHandle( processInfo.hThread );
} else {
- printf( "Error launching process: %lu\n", GetLastError() );
- fclose( fp );
- return ( -3 );
+ char* errortext = calloc( sizeof( char ), 512 + 1 /* \0 */ );
+ // char errortext[512];
+ snprintf( errortext,
+ 512,
+ "Error launching process: %lu\nFailed command: >%s<\nLine in file: %s",
+ GetLastError(),
+ commandLineArgs,
+ linebuf );
+ ShowErrorBox( errortext, "CreateProcess Error" );
+ free( errortext );
+ retVal = -3;
}
}
// cleanup and close
fclose( fp );
- return ( 0 );
+ return ( retVal );
}
diff --git a/winrun.cbp b/winrun.cbp
index ac40024..67b6e8a 100644
--- a/winrun.cbp
+++ b/winrun.cbp
@@ -3,6 +3,7 @@
+
@@ -17,11 +18,16 @@
+
-
+
+
+
+
+
@@ -37,9 +43,6 @@
-
-
-
diff --git a/winrun.cfg b/winrun.cfg
index f8e3807..3d25181 100644
--- a/winrun.cfg
+++ b/winrun.cfg
@@ -1 +1 @@
-start calc
+notepad.exe winrun.cfg
\ No newline at end of file