Zurück   RR:Board > Computer > Programmierung & Entwicklung > Projekte / Codes

Software Anwendungen mit Source Code - Projekt Vorstellung und Entwicklung.
Antwort
 
Themen-Optionen Thema durchsuchen

[C/C++] - ApplicationService
Alt 26.04.2011, 16:14   # 1
terraNova
Ehrenmitglied
vip
Bewertung:
terraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 Punkte
terraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 Punkte
Registriert seit: Feb 2007
Beiträge: 1.333
Power: 24
Hey,

ich hab spontan ein Programm geschrieben, dass Programme wie einen Service behandelt.
D.h. es ist möglich normale Programme, die nicht als Service gedacht sind (z.B. Server wie Teamspeak3), zu starten und zu beenden. Es wird also nichts an Windows geändert und lässt sich einfach per CMD bedienen, was so manche Arbeit ersparen dürfte, wenn etwas schnell gehen soll.

Wie gesagt, das Programm ist spontan geschrieben, sollten euch also Fehler auffallen dürft ihr mir gerne verraten wie diese auftreten (Genauer Befehl), damit ich diese sobald wie möglich beheben kann.

Bedienung dürfte selbsterklärend sein, wenn nicht: Fragen!

Code:
#include <iostream> #include <string> #include <vector> #include <queue> #include <fstream> #include <cstdlib> #define WIN32_LEAN_AND_MEAN #include <windows.h> #define TAS_FILE_DEFAULT "tas.db" using namespace std; enum { SC_NONE = 0, SC_START = 0x01, SC_STOP = 0x10, SC_RESTART = 0x11, }; enum { SQ_NONE = 0, SQ_ADD, SQ_REMOVE, SQ_CONTROL, SQ_STATUS, }; enum { SDB_SKIP = -2, SDB_ADD = -1, SDB_FIRST = 0, }; struct tas_entry { char id[16]; char path[256]; char param[256]; unsigned pid; void set_id( char* _id ) { strncpy(id, _id, 16); } void set_path( char* _path ) { strncpy(path, _path, 256); } void set_param( char* _param ) { strncpy(param, _param, 256); } }; struct tas_task { int type; int action; tas_entry entry; tas_task(int _type = SQ_NONE) : type(_type), action(SC_NONE) { memset(&entry, 0, sizeof(tas_entry)); } }; struct tas_config { bool verbose; bool changes; char db[256]; queue< tas_task > tasks; vector< pair<tas_entry, long> > services; tas_config() : verbose(false), changes(false) { strncpy(db, TAS_FILE_DEFAULT, 16); } void set_db( char* _db ) { strncpy(db, _db, 256); } }; void tas_check_opt(tas_config& conf, char opt, int argc_left, char **argv); void tas_init(tas_config& conf); void tas_close(tas_config& conf); // writes db if tas_config::changes was set void tas_process_tasks(tas_config& conf); bool tas_process_task(tas_config& conf, tas_task& task); void tas_print_task(const tas_task& task, bool details = false); bool tas_service_exists(const tas_config& conf, const char* id, size_t& pos); bool tas_service_running(tas_entry& entry); int main( int argc, char *argv[] ) { tas_config conf; if(argc == 1) { tas_check_opt(conf, 'h', 0, 0); return EXIT_SUCCESS; } for(int i=1; i<argc; i++) { if(argv[i][0] == '-') { size_t len = strlen(argv[i]); for(size_t j=1; j<len; j++) { tas_check_opt(conf, argv[i][j], argc-i, argv+i); } } } tas_init(conf); tas_process_tasks(conf); tas_close(conf); return EXIT_SUCCESS; } void tas_check_opt(tas_config& conf, char opt, int argc_left, char **argv) { switch(opt) { case 'h': { cout << "tAppSvc <-hvarcds> [id|path] [[path|action] [param]]" << endl << endl << "OPTIONS: " << endl << "\t-h USAGE" << endl << "\t-v VERBOSE" << endl << "\t-a <id> <path> [param] ADD SERVICE" << endl << "\t-r <id> REMOVE SERVICE" << endl << "\t-c <id> <action> CONTROL SERVICE" << endl << "\t-d <path> ALT. DATABASE" << endl << "\t-s SHOW SERVICES" << endl << "\t-s <id> STATUS" << endl << endl << "ACTIONS: " << endl << "\tstart START SERVICE" << endl << "\tstop STOP SERVICE" << endl << "\trestart RESTART SERVICE" << endl << endl; exit(EXIT_SUCCESS); } break; case 'v': { conf.verbose = true; } break; case 'a': { tas_task task(SQ_ADD); if(argc_left < 2) { cout << "Too few parameter (-a)" << endl << endl; tas_check_opt(conf, 'h', 0, 0); exit(EXIT_FAILURE); } task.entry.set_id(argv[1]); task.entry.set_path(argv[2]); if(argc_left > 3 && argv[3][0] != '-') task.entry.set_param(argv[3]); conf.tasks.push(task); } break; case 'r': { tas_task task(SQ_REMOVE); if(argc_left < 1) { cout << "Too few parameter (-r)" << endl << endl; tas_check_opt(conf, 'h', 0, 0); exit(EXIT_FAILURE); } task.entry.set_id(argv[1]); conf.tasks.push(task); } break; case 'c': { tas_task task(SQ_CONTROL); if(argc_left < 3) { cout << "Too few parameter (-c)" << endl << endl; tas_check_opt(conf, 'h', 0, 0); exit(EXIT_FAILURE); } task.entry.set_id(argv[1]); if(!strcmp(argv[2], "start")) { task.action = SC_START; } else if(!strcmp(argv[2], "stop")) { task.action = SC_STOP; } else if(!strcmp(argv[2], "restart")) { task.action = SC_RESTART; } else { cout << "Unknown action '" << argv[2] << "' for '" << argv[1] << "'. Skipping" << endl << endl; break; } conf.tasks.push(task); } break; case 'd': { if(argc_left < 1) { cout << "Too few parameter (-d)" << endl << endl; tas_check_opt(conf, 'h', 0, 0); exit(EXIT_FAILURE); } conf.set_db(argv[1]); } break; case 's': { tas_task task(SQ_STATUS); if(argc_left > 1) task.entry.set_id(argv[1]); conf.tasks.push(task); } break; default: { cout << "Unknown parameter '" << opt << "'. Skipping" << endl << endl; } break; } } void tas_init(tas_config& conf) { fstream db(conf.db, ios::binary|ios::in); tas_entry ent; size_t pos = 0; if(db.is_open() == false) { cout << "Database does not exists (" << conf.db << "). Creating and Quitting." << endl << endl; db.open(conf.db, ios::binary|ios::app); db.close(); exit(EXIT_FAILURE); } if(db.rdbuf()->in_avail() > 1) { while(db.rdbuf()->in_avail() > 1) { // SURELY EOF db.read((char*)&ent, sizeof(tas_entry)); conf.services.push_back(pair<tas_entry, long>(ent, pos)); pos = db.tellg(); if(conf.verbose == true) { cout << "read service '" << ent.id << "'" << endl; } } } db.close(); } void tas_close(tas_config& conf) { if(conf.changes == false) return; fstream db(conf.db, ios::binary|ios::out); if(db.is_open() == false) { cout << "Fatal Error: Could not write Database. Quitting." << endl; exit(EXIT_FAILURE); } for(vector< pair<tas_entry, long> >::iterator ent=conf.services.begin(); ent != conf.services.end(); ent++) { if((*ent).second != SDB_SKIP) { db.write((char*)(&(*ent).first), sizeof(tas_entry)); } else if((*ent).second == SDB_SKIP && (ent+1) == conf.services.end()) { char eof = EOF; db.write(&eof, 1); } } db.close(); } void tas_process_tasks(tas_config& conf) { while(conf.tasks.empty() == false) { bool ret = tas_process_task(conf, conf.tasks.front()); if(ret == true) { cout << "Task succeeded: "; tas_print_task(conf.tasks.front()); } else { cout << "Task failed: "; tas_print_task(conf.tasks.front(), true); } conf.tasks.pop(); } } bool tas_process_task(tas_config& conf, tas_task& task) { size_t pos; switch(task.type) { case SQ_ADD: { if(tas_service_exists(conf, task.entry.id, pos) == true) { cout << "Service (" << task.entry.id << ") already exists. Skipping" << endl << endl; return false; } HANDLE hFile = CreateFileA(task.entry.path, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(FAILED(hFile)) { cout << "Path (" << task.entry.path << ") doesn\'t exist. Skipping" << endl << endl; return false; } CloseHandle(hFile); conf.services.push_back(pair<tas_entry, size_t>(task.entry, SDB_ADD)); conf.changes = true; } break; case SQ_REMOVE: { if(tas_service_exists(conf, task.entry.id, pos) == false) { cout << "Service (" << task.entry.id << ") doesn\'t exists. Skipping" << endl << endl; return false; } cout << (*(conf.services.begin()+pos)).first.id << endl; conf.services.at(pos).second = SDB_SKIP; conf.changes = true; } break; case SQ_CONTROL: { if(tas_service_exists(conf, task.entry.id, pos) == false) { cout << "Service (" << task.entry.id << ") doesn\'t exists. Skipping" << endl << endl; return false; } switch(task.action) { case SC_RESTART: { cout << "Restarting Service (" << task.entry.id << ")" << endl; } case SC_STOP: { cout << "Stopping Service (" << task.entry.id << ")" << endl; if(tas_service_running(conf.services.at(pos).first) == false) { cout << "Service (" << task.entry.id << ") already stopped" << endl; } else { HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, conf.services.at(pos).first.pid); if(SUCCEEDED(hProc)) { if(TerminateProcess(hProc, 0) == TRUE) { conf.services.at(pos).first.pid = 0; conf.changes = true; } CloseHandle(hProc); } else { cout << "Unable to stop Process." << endl; } } if(task.action != SC_RESTART) break; } case SC_START: { cout << "Starting Service (" << task.entry.id << ")" << endl; PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}; si.cb = sizeof(STARTUPINFO); string exec = string(conf.services.at(pos).first.path) + " " + string(conf.services.at(pos).first.param); if(CreateProcessA(0, (char*)exec.c_str(), 0, 0, FALSE, NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi) == TRUE) { conf.services.at(pos).first.pid = pi.dwProcessId; cout << "Service running under PID " << conf.services.at(pos).first.pid << endl; conf.changes = true; } else { cout << "Could not start Service " << conf.services.at(pos).first.id << endl; return false; } } break; case SQ_STATUS: { if(conf.services.empty() == true){ cout << "No Services in Database" << endl << endl; return false; } if(task.entry.id[0] == 0) { for(vector< pair<tas_entry, long> >::iterator ent=conf.services.begin(); ent != conf.services.end(); ent++, pos++) { cout << "SERVICE (" << (*ent).first.id << "): " << endl << "\tPath: " << (*ent).first.path << endl << "\tParam: " << (*ent).first.param << endl << "\tState: " << (tas_service_running((tas_entry&)conf.services.at(pos))?"Running":"Stopped") << endl << endl; } } else { if(tas_service_exists(conf, task.entry.id, pos) == false) { cout << "Service (" << task.entry.id << ") doesn\'t exists. Skipping" << endl << endl; return false; } vector< pair<tas_entry, long> >::iterator ent = conf.services.begin()+pos; cout << "SERVICE (" << (*ent).first.id << "): " << endl << "\tPath: " << (*ent).first.path << endl << "\tParam: " << (*ent).first.param << endl << "\tState: " << (tas_service_running((tas_entry&)conf.services.at(pos))?"Running":"Stopped") << endl << endl; } } break; } return true; } void tas_print_task(const tas_task& task, bool details) { switch(task.type) { case SQ_ADD: { cout << "SQ_ADD" << endl; cout << "\tID: " << task.entry.id << endl; if(details == true) { cout << "\tPath: " << task.entry.path << endl; cout << "\tParam: " << task.entry.param << endl; } } break; case SQ_REMOVE: { cout << "SQ_REMOVE" << endl; cout << "\tID: " << task.entry.id << endl; if(details == true) { cout << "\tPath: " << task.entry.path << endl; cout << "\tParam: " << task.entry.param << endl; } } break; case SQ_CONTROL: { cout << "SQ_CONTROL "; switch(task.action) { case SC_START: { cout << "(SC_START)" << endl; } break; case SC_STOP: { cout << "(SC_STOP)" << endl; } break; case SC_RESTART: { cout << "(SC_RESTART)" << endl; } break; } cout << "\tID: " << task.entry.id << endl; if(details == true) { cout << "\tPath: " << task.entry.path << endl; cout << "\tParam: " << task.entry.param << endl; } } break; case SQ_STATUS: { cout << "SQ_STATUS " << endl; } break; } cout << endl; } bool tas_service_exists(const tas_config& conf, const char* id, size_t& pos) { pos = 0; for(vector< pair<tas_entry, long> >::const_iterator ent=conf.services.begin(); ent != conf.services.end(); ent++, pos++) { if(!strcmp(id, (*ent).first.id) && (*ent).second >= SDB_FIRST) return true; } return false; } bool tas_service_running(tas_entry& entry) { if(entry.pid == 0) return false; HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, entry.pid); if(FAILED(hProc)) { return false; } CloseHandle(hProc); return true; }
Ein Beispiel:
Code:
tAppSvc -a ts3_sv1 C:\Teamspeak3\ts3server_win32.exe "Parameter1 Parameter2" tAppSvc -c ts3_sv1 start
Wie immer würde ich gerne - aus Anstand - voher informiert werden, bevor ihr etwas kopiert.

Grüße.

toilet @0.3 (graphics)
toilet - colour based alternative to figlet using libcaca

(23:28) alex2: man ist absolut machtlos gegen diese dummheit
  terraNova ist offline   Mit Zitat antworten

Alt 26.04.2011, 20:03   # 2
Alex²
Outlaw Legend
blau blau blau 
Bewertung:
Alex² 80k+ RR.Geekpoints
Registriert seit: Aug 2005
Beiträge: 3.047
Power: 52
Wie sollte ich das der guten alten sc.exe vorziehen? Ich meine das ist im Prinzip nicht anderes als eine rudimentäre Kopie der Windows Service Implementierung.
  Alex² ist offline   Mit Zitat antworten

AW: ApplicationService
Alt 26.04.2011, 20:11   # 3
terraNova
Ehrenmitglied
vip
Bewertung:
terraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 Punkte
terraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 PunkteterraNova hat mehr als 15.000 Punkte
Registriert seit: Feb 2007
Beiträge: 1.333
Power: 24
Themenstarter
Zitat:
Zitat von Alex² Beitrag anzeigen
Wie sollte ich das der guten alten sc.exe vorziehen? Ich meine das ist im Prinzip nicht anderes als eine rudimentäre Kopie der Windows Service Implementierung.
sc funktioniert bei simplen Anwendungen nicht, deswegen wurde dieses Programm geschrieben.

toilet @0.3 (graphics)
toilet - colour based alternative to figlet using libcaca

(23:28) alex2: man ist absolut machtlos gegen diese dummheit
  terraNova ist offline   Mit Zitat antworten
Antwort

RR:Board > Computer > Programmierung & Entwicklung > Projekte / Codes > [C/C++] - ApplicationService

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir erlaubt, Anhänge anzufügen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

vB Code ist An.
Smileys sind An.
[IMG] Code ist An.
HTML-Code ist Aus.



Alle Zeitangaben in WEZ +1. Es ist jetzt 15:26 Uhr.
vBulletin Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.