473,703 Members | 2,438 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Command Line Interface (CLI): your recommendations

Hello, All!

I'm implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:

1) get whole string of input line
2) preset table of strings matching <command>
3) preset table of function calls
4) scan <command> table for string, if match - call matching function (I
declare ALL callback functions as having the same format)

Here is code implementing part of this algorithm. The problem I came across
is if pressing 'Enter' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it's printed repeatedly in a line.

Before I went too far, I would like to ask your opinion about concept I'm
using and recommendations if possible:

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define COUNT(a) (sizeof(a) / sizeof(a[0]))

const char *PROMPT = "CLI>";

enum errCodes { RC_SUCCESS = 0, RC_ERROR = -1 };

/* table of <commands> */
const char *commands[] = {
"show",
"version",
"help",
"port",
"exit"
};

/* callback function */
typedef int (*handler_ptr_t )(int, char**);

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20
char command[MAX_NAME];
#define MAX_ARGS 4
char params[MAX_ARGS];
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

int cliShow(int argc, char *argv[])
{
puts("cliShow() stub");
return 0;
}

int cliVersion(int argc, char *argv[])
{
puts("cliVersio n() stub");
return 0;
}

int cliHelp(int argc, char *argv[])
{
puts("cliHelp() stub");
return 0;
}

int cliPort(int argc, char *argv[])
{
puts("cliPort() stub");
return 0;
}

int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCE SS);
}

/* define table functions pointers */
handler_ptr_t ftable[] = { cliShow, cliVersion, cliHelp, cliPort, cliExit };

/* parse command line and fill structure */
static int
cliParseCommand Line(char *buf, cmdLineEntry_t *cli)
{
const char delim[] = " \t\n";
unsigned int i;
char *token;

memset(cli, 0, sizeof *cli);

token = strtok(buf, delim);
for (i = 0; i < COUNT(commands) ; i++) {
if (!strcmp(token, commands[i])) {
strcpy(cli->command, token);
cli->cmd_handler = ftable[i];
i = 0;
for (token = strtok(NULL, delim); token != NULL; ) {
cli->params[i++] = token;
token = strtok(NULL, delim);
}
cli->params_num = i;
return 0;
}
}
return -1;
}

int main(void)
{
char buf[BUFSIZ] = {0};
cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };

while (1) {
printf("%s", PROMPT);
if ( fgets(buf, BUFSIZ, stdin) ) {
/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' || buf[0]
== '\t')
continue;

/* parse stream */
if ( cliParseCommand Line(buf, &cli) < 0 ) {
printf("Error : invalid command!\n");
continue;
}
else {
cli.cmd_handler (cli.params_num , cli.params);
}
}
else continue; /* EOL */
} /* while */

return 0;
}

TIA!
With best regards, Roman Mashak. E-mail: mr*@tusur.ru
Feb 11 '06
34 6856

"Roman Mashak" <mr*@tusur.ru > wrote in message
news:ds******** ***@relay.tomsk .ru...
Hello, Rod!
Sorry I made typo in first post, right definition of "cmdLineEntry_t " is:

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20
char command[MAX_NAME];
#define MAX_ARGS 10
char *params[MAX_ARGS];
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

i.e. params is array of pointers to char.

Some suggestions:

I would change this line, extra spaces deleted: if (buf[0]=='\n'||buf[0]==' '||buf[0]=='\r'||buf[0]=='\t')
To this, to specifically catch an ASCII carriage return and newline:
if buf[0]==0x0A||buf[0]==0x0D||buf[0]==' '||buf[0]=='\t')

Or, to this:
if (strtok(buf,"\x 0D\x0A\t ")==NULL)

For this section, certain compilers will complain about a missing return:
int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCE SS);
}
You'll need to add a fake return:
int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCE SS);
return 0; /* fake return */
}

You are using 'puts' in your stubs. If you remove them, this else section
in main() will need to output a "\n":
else {
cli.cmd_handler (cli.params_num , cli.params); printf("\n"); }


Since you are using fgets(), forget about the setbuf(stdin,NU LL).
If you are writing this for DOS, consider using cgets() and
setbuf(stdin,NU LL).
Good Luck,

Rod Pemberton
Feb 12 '06 #11
On Sun, 12 Feb 2006 01:14:51 +0700, "Roman Mashak" <mr*@tusur.ru >
wrote:
Hello, All!

I'm implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:

1) get whole string of input line
2) preset table of strings matching <command>
3) preset table of function calls
4) scan <command> table for string, if match - call matching function (I
declare ALL callback functions as having the same format)

Here is code implementing part of this algorithm. The problem I came across
is if pressing 'Enter' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it's printed repeatedly in a line.
How could you execute the code with all the syntax errors?

Before I went too far, I would like to ask your opinion about concept I'm
using and recommendations if possible:
You really should compile your code and correct the errors before
asking for help.

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define COUNT(a) (sizeof(a) / sizeof(a[0]))

const char *PROMPT = "CLI>";

enum errCodes { RC_SUCCESS = 0, RC_ERROR = -1 };

/* table of <commands> */
If this comment were not here, would your code be any less clear? If
the comment does not add something to what is immediately obvious in
the code, it actually reduces readability.
const char *commands[] = {
"show",
"version",
"help",
"port",
"exit"
};

/* callback function */
typedef int (*handler_ptr_t )(int, char**);

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20
Move these defines to either before the typedef or to the start of
your source (your choice before or after the includes). Never disrupt
the flow of a struct declaration like this.
char command[MAX_NAME];
#define MAX_ARGS 4
char params[MAX_ARGS];
What you have here is an array of four char. Not enough space to hold
even one argument let alone four. Based on how you use it later, I am
pretty certain that you wanted
char *params[...]
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

int cliShow(int argc, char *argv[])
{
puts("cliShow() stub");
return 0;
}

int cliVersion(int argc, char *argv[])
{
puts("cliVersio n() stub");
return 0;
}

int cliHelp(int argc, char *argv[])
{
puts("cliHelp() stub");
return 0;
}

int cliPort(int argc, char *argv[])
{
puts("cliPort() stub");
return 0;
}

int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCE SS);
}

/* define table functions pointers */
handler_ptr_ t ftable[] = { cliShow, cliVersion, cliHelp, cliPort, cliExit };
You intend for this to be a global table. You have defines, typedefs,
enum declarations, global definitions, and function definitions
interspersed with each other. When you fill in the stub functions,
you will have a hellacious time finding anything. While it is "only"
a matter of style, it will make debugging much easier if your organize
things better. My recommendation:

Put all your defines, typedefs, and declarations in a header
file. Include prototypes for all your functions. Group like
directives (all defines, then all typedefs, etc). I even include my
#include<...> directives in this header but others prefer to leave
those in their function source files.

Put each function in its own source file. If you really want
to keep them all together (such as for posting here), the order them
in some way that makes it easy for others to find. I prefer main
first and the others following alphabetically. That way, I can tell
if I have scrolled to far when looking for a function.

/* parse command line and fill structure */
static int
cliParseComman dLine(char *buf, cmdLineEntry_t *cli)
{
const char delim[] = " \t\n";
unsigned int i;
char *token;

memset(cli, 0, sizeof *cli);
Not a problem but also of no value. Just so you know, forcing a
pointer to have all bits zero is not the same as setting it to NULL.
For integers and characters all bits zero is 0 but that may not be
true for floats and doubles.

token = strtok(buf, delim);
for (i = 0; i < COUNT(commands) ; i++) {
if (!strcmp(token, commands[i])) {
strcpy(cli->command, token);
cli->cmd_handler = ftable[i];
i = 0;
You have a logical breakdown here. Either initialize and increment i
in your for statement or do it in individual statements in the loop,
BUT NOT BOTH.
for (token = strtok(NULL, delim); token != NULL; ) {
cli->params[i++] = token;
This is a syntax error since params[i] is a char and token is a char*.

When you fix params, it will hold the (up to) four addresses of the
arguments in buf. This makes it obvious that you want to completely
process each input line before obtaining the next (which is consistent
with your code in main).

But you are inconsistent. You actually copy the command but only
store the argument addresses. What about the command is so special
that you need to store the actual characters in cli->command rather
than simply the address of the command in buf?
token = strtok(NULL, delim);
}
cli->params_num = i;
return 0;
}
}
return -1;
}

int main(void)
{
char buf[BUFSIZ] = {0};
cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };
Another syntax error due to the bad declaration or params. That first
NULL is not a suitable value for an array of four char.
while (1) {
printf("%s", PROMPT);
Use fflush here to force the output to your screen.
if ( fgets(buf, BUFSIZ, stdin) ) {
/* skip LF/CR/TAB/SP */
if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' || buf[0]
== '\t')
Look up the isspace() function if you really want to do this. Are you
sure you want to do this since the strtoken call in
cliParseCommand Line() will very happily skip over leading white space
for you?
continue;

/* parse stream */
if ( cliParseCommand Line(buf, &cli) < 0 ) {
printf("Error : invalid command!\n");
continue;
}
else {
cli.cmd_handler (cli.params_num , cli.params);
Another syntax error due to params.
}
}
else continue; /* EOL */
A continue at the end of a loop is somewhat superfluous.
} /* while */

return 0;
}

Remove del for email
Feb 12 '06 #12
On Sun, 12 Feb 2006 12:33:22 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

; nasmw -f obj this_file.asm
; bcc32 file.c this.obj

section _DATA public align=4 class=DATA use32

extern _isspace
global _popola

; global _main

section _TEXT public align=1 class=CODE use32

; int popola(char** v, char* buf, int limit)
; s=0j, 4i, 8b, 12ra, 16@v, 20@buf, 24@limit
_popola:
push ebx
push esi
push edi
%define @v esp+16
%define @buf esp+20
%define @limit esp+24
xor edi, edi
cmp dword[@v], 0
je .fn
cmp dword[@buf], 0
je .fn
cmp dword[@limit], 0
jle .fn
mov esi, [@buf]
xor ebx, ebx
..a0:
mov bl, [esi]
push ebx
call _isspace
add esp, 4
cmp eax, 0
je .a1
inc esi
jmp short .a0
..a1:
cmp ebx, 0
je .fn
cmp edi, [@limit]
jne .a2
inc edi
jmp short .fn
..a2:
mov eax, [@v]
mov dword[eax+4*edi], esi
inc edi
..a3:
mov bl, [esi]
cmp ebx, 0
je .a4
push ebx
call _isspace
add esp, 4
cmp eax, 0
jne .a4
inc esi
jmp short .a3
..a4:
cmp ebx, 0
je .fn
mov byte[esi], 0
inc esi
jmp short .a0

..fn:
mov eax, edi
%undef @v
%undef @buf
%undef @limit
pop edi
pop esi
pop ebx
ret

---------------------------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define UC unsigned char
#define U unsigned

static const char *pc = "CLI[\"vexit\" to end]> ";

struct you{
char* name;
char* pointer;
unsigned npar;
struct you* prev;
};

struct you *last=0;

int popola(char** v, char* buf, int limit);
int
inserisci(const char* name, char* pointer, U par)
{struct you *tm;
char *tmp;
unsigned sz;
///////////////////
if( name==0 || (sz=strlen(name ))==0 )
return 0;
if( (tm =malloc(sizeof( struct you)))==0 )
return 0;
if( (tmp=malloc(siz eof(sz+2)))==0 )
{free(tm); return 0;}
tm->name=tmp; strcpy(tm->name, name);
tm->pointer= pointer; tm->npar=par;
tm->prev=last; last=tm;
return 1;
}

void free_list(void)
{struct you *p=last, *v;
while(1) {if(p==0) break;
v=p; p=p->prev;
free(v->name); free(v);
}
}
int show(void){puts ("cliShow() stub");return 0;}
int version(void){p uts("cliVersion () stub");return 0;}
int help(void){puts ("cliHelp() stub");return 0;}
int port(void){puts ("cliPort() stub"); return 0;}
void vexit(void)
{puts("cliExit( ) stub");
free_list();
exit(0);
}

void add(char* a1, char* a2)
{int aa1, aa2;
sscanf(a1, "%d", &aa1);
sscanf(a2, "%d", &aa2);
printf("%d\n", aa1+aa2);
}

void sub(char* a1, char* a2)
{int aa1, aa2;
sscanf(a1, "%d", &aa1);
sscanf(a2, "%d", &aa2);
printf("%d\n", aa1-aa2);
}
int main(void)
{char buf[BUFSIZ] = {0}, *a[32];
struct you *p;
int cv;
/////////////////////////////////
inserisci("show ",(char*) show, 0);
inserisci("vers ion", (char*) version, 0);
inserisci("help ", (char*) help, 0);
inserisci("port ", (char*) port, 0);
inserisci("vexi t",(char*) vexit, 0);
inserisci("add" ,(char*) add, 2);
inserisci("sub" ,(char*) sub, 2);

la:;
while (1)
{printf("%s", pc); fflush(stdout);
if( fgets(buf, BUFSIZ, stdin)!=0 )
{cv=popola(a, buf, 7);
if(cv<=0) goto la;
else --cv;
for(p=last; p ;p=p->prev)
if(strcmp(p->name, a[0])==0)
{if(p->npar!=(U)cv) goto la;
switch(p->npar)
{case 0:
( (void (*)(void))(p->pointer) )( );
break;
case 1:
( (void (*)(char*))(p->pointer) )(a[1]);
break;
case 2:
( (void (*)(char*, char*))(p->pointer) )
(a[1], a[2]);
break;
case 3:
( (void (*)(char*, char*, char*))(p->pointer) )
(a[1], a[2], a[3]);
break;
case 4:
( (void (*)(char*, char*, char*, char*) )
(p->pointer) ) (a[1], a[2], a[3], a[4]);
break;
case 5:
( (void (*)(char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5]);
break;
case 6:
( (void (*)(char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6]);
break;
case 7:
( (void (*)(char*, char*, char*, char*, char*, char*, char*))
(p->pointer) )( a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
break;
default:
goto la;
}
}
}
}
return 0;
}

Feb 12 '06 #13
On Mon, 13 Feb 2006 00:16:32 +0100, in comp.lang.c , RSoIsCaIrLiIoA
<zz@zz.z> wrote:
On Sun, 12 Feb 2006 12:33:22 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

; nasmw -f obj this_file.asm


You've alreadyt been asked several times not to post asm here.

You were looking a bit like a redeemed troll. You're not, it seems.

*plonk*
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Feb 13 '06 #14
In article <h3************ *************** *****@4ax.com>,
Mark McIntyre <ma**********@s pamcop.net> wrote:
On Mon, 13 Feb 2006 00:16:32 +0100, in comp.lang.c , RSoIsCaIrLiIoA
<zz@zz.z> wrote:
On Sun, 12 Feb 2006 12:33:22 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

; nasmw -f obj this_file.asm
You've alreadyt been asked several times not to post asm here.


Be careful, you might hurt his feelings.
You were looking a bit like a redeemed troll. You're not, it seems.
Be careful, you might hurt his feelings.
*plonk*


Oh, look! Now, you've gone and done it. His wittle feewings have been
crushed.

Feb 13 '06 #15
Hello, Keith!
You wrote on Sun, 12 Feb 2006 10:17:54 GMT:

KT> <unistd.h> isn't a standard C header, and _GNU_SOURCE isn't standard C
KT> either, but your program doesn't seem to depend on either of them.
Yes, you're absolutely right, I forgot to remove those for this minimal
example from original code.
KT> I don't know what you mean by "same effect remained". Is there a
KT> problem?
By "same effect remained" I meant that if 'Enter' is pressed and not
released for a few seconds it ends up in 'CLI>' prompt is skipped sometimes
and printed twice in a same line. Seems like what Walter Roberson explained
here, but 'fflush(sydout) ' didn't help.

What did I forget else?

With best regards, Roman Mashak. E-mail: mr*@tusur.ru
Feb 13 '06 #16
"Roman Mashak" <mr*@tusur.ru > writes:
Hello, Keith!
You wrote on Sun, 12 Feb 2006 10:17:54 GMT:

KT> <unistd.h> isn't a standard C header, and _GNU_SOURCE isn't standard C
KT> either, but your program doesn't seem to depend on either of them.
Yes, you're absolutely right, I forgot to remove those for this minimal
example from original code.
KT> I don't know what you mean by "same effect remained". Is there a
KT> problem?
By "same effect remained" I meant that if 'Enter' is pressed and not
released for a few seconds it ends up in 'CLI>' prompt is skipped sometimes
and printed twice in a same line. Seems like what Walter Roberson explained
here, but 'fflush(sydout) ' didn't help.


If you hold the Enter down for a few seconds, it probably goes into
auto-repeat mode; I've seen that kind of thing cause input and output
to get out of sync.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 13 '06 #17
Hello, Keith!
You wrote on Mon, 13 Feb 2006 04:02:34 GMT:

KT> If you hold the Enter down for a few seconds, it probably goes into
KT> auto-repeat mode; I've seen that kind of thing cause input and output
KT> to get out of sync.
[OT]
It happens only in telnet/ssh sessions, via serial cable all works fine
[/OT]

With best regards, Roman Mashak. E-mail: mr*@tusur.ru
Feb 13 '06 #18
Hello, RSoIsCaIrLiIoA!
You wrote on Sun, 12 Feb 2006 12:33:22 +0100:

??>> matching function (I declare ALL callback functions as having the same
??>> format) Here is code implementing part of this algorithm. The problem
??>> I came across is if pressing 'Enter' continuously then sometimes
??>> output of PROMPT turnes out clumsy, i.e. it's printed repeatedly in a
??>> line.

R> i don't see where the problem is

R> #include <stdio.h>
R> #include <string.h>
R> #include <stdlib.h>
R> #include <ctype.h>

R> #define UC unsigned char
[skip]

Thank you for code, but I didn't ask for it :) I have my own to fix and
maintain.

With best regards, Roman Mashak. E-mail: mr*@tusur.ru
Feb 13 '06 #19
"Roman Mashak" <mr*@tusur.ru > writes:
Hello, Keith!
You wrote on Mon, 13 Feb 2006 04:02:34 GMT:

KT> If you hold the Enter down for a few seconds, it probably goes into
KT> auto-repeat mode; I've seen that kind of thing cause input and output
KT> to get out of sync.
[OT]
It happens only in telnet/ssh sessions, via serial cable all works fine
[/OT]


<OT>
Not surprising; there are probably more layers of buffering between
the keyboard and the program.
</OT>

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 13 '06 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
1867
by: djc | last post by:
I'm new to this and was wondering what the options are for interpreting the command line using a CLI program. Specifically methods for interpreting the parameters passed to the program on the command line. I noticed that visual studio adds the following for you when creating a new CLI program: void main(string args) { }
51
4135
by: Ojas | last post by:
Hi!, I just out of curiosity want to know how top detect the client side application under which the script is getting run. I mean to ask the how to know whether the script is running under Command Prompt or Browser or some other application? Ojas.
0
8750
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9244
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9004
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8961
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7853
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5922
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4679
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3114
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2439
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.