|
I found some source code for a client programmed in C.
Dont understand much but maybe someone else does.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <rpc des_crypt.h="">
#include <sys socket.h="">
#include <netinet in.h="">
#include <netdb.h>
#define CWS_NETMSGSIZE 240
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long uint64;
#define CWS_FIRSTCMDNO 0xe0
typedef enum
{
MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO,
MSG_CLIENT_2_SERVER_LOGIN_ACK,
MSG_CLIENT_2_SERVER_LOGIN_NAK,
MSG_CARD_DATA_REQ,
MSG_CARD_DATA,
MSG_SERVER_2_CLIENT_NAME,
MSG_SERVER_2_CLIENT_NAME_ACK,
MSG_SERVER_2_CLIENT_NAME_NAK,
MSG_SERVER_2_CLIENT_LOGIN,
MSG_SERVER_2_CLIENT_LOGIN_ACK,
MSG_SERVER_2_CLIENT_LOGIN_NAK,
MSG_ADMIN,
MSG_ADMIN_ACK,
MSG_ADMIN_LOGIN,
MSG_ADMIN_LOGIN_ACK,
MSG_ADMIN_LOGIN_NAK,
MSG_ADMIN_COMMAND,
MSG_ADMIN_COMMAND_ACK,
MSG_ADMIN_COMMAND_NAK,
MSG_KEEPALIVE = CWS_FIRSTCMDNO + 0x1d
} net_msg_type_t;
typedef enum
{
COMMTYPE_CLIENT,
COMMTYPE_SERVER
} comm_type_t;
typedef struct customData_struct
{
uint16 sid;
} customData_t;
void des_key_parity_adjust(uint8 *key, uint8 len)
{
uint8 i, j, parity;
for (i = 0; i < len; i++)
{
parity = 1;
for (j = 1; j < 8; j++) if ((key[i] >> j) & 0x1) parity = ~parity & 0x01;
key[i] |= parity;
}
}
uint8 *des_key_spread(uint8 *normal)
{
static uint8 spread[16];
spread[ 0] = normal[ 0] & 0xfe;
spread[ 1] = ((normal[ 0] << 7) | (normal[ 1] >> 1)) & 0xfe;
spread[ 2] = ((normal[ 1] << 6) | (normal[ 2] >> 2)) & 0xfe;
spread[ 3] = ((normal[ 2] << 5) | (normal[ 3] >> 3)) & 0xfe;
spread[ 4] = ((normal[ 3] << 4) | (normal[ 4] >> 4)) & 0xfe;
spread[ 5] = ((normal[ 4] << 3) | (normal[ 5] >> 5)) & 0xfe;
spread[ 6] = ((normal[ 5] << 2) | (normal[ 6] >> 6)) & 0xfe;
spread[ 7] = normal[ 6] << 1;
spread[ 8] = normal[ 7] & 0xfe;
spread[ 9] = ((normal[ 7] << 7) | (normal[ 8] >> 1)) & 0xfe;
spread[10] = ((normal[ 8] << 6) | (normal[ 9] >> 2)) & 0xfe;
spread[11] = ((normal[ 9] << 5) | (normal[10] >> 3)) & 0xfe;
spread[12] = ((normal[10] << 4) | (normal[11] >> 4)) & 0xfe;
spread[13] = ((normal[11] << 3) | (normal[12] >> 5)) & 0xfe;
spread[14] = ((normal[12] << 2) | (normal[13] >> 6)) & 0xfe;
spread[15] = normal[13] << 1;
des_key_parity_adjust(spread, 16);
return spread;
}
void des_random_get(uint8 *buffer, uint8 len)
{
uint8 idx = 0;
int randomNo = 0;
for (idx = 0; idx < len; idx++)
{
if (!(idx % 3)) randomNo = rand();
buffer[idx] = (randomNo >> ((idx % 3) << 3)) & 0xff;
}
}
int des_encrypt(uint8 *buffer, int len, uint8 *deskey)
{
uint8 checksum = 0;
uint8 noPadBytes;
uint8 padBytes[7];
char ivec[8];
uint16 i;
if (!deskey) return len;
noPadBytes = (8 - ((len - 1) % 8)) % 8;
if (len + noPadBytes + 1 >= CWS_NETMSGSIZE-8) return -1;
des_random_get(padBytes, noPadBytes);
for (i = 0; i < noPadBytes; i++) buffer[len++] = padBytes[i];
for (i = 2; i < len; i++) checksum ^= buffer[i];
buffer[len++] = checksum;
des_random_get((uint8 *)ivec, 8);
memcpy(buffer+len, ivec, 8);
for (i = 2; i < len; i += 8)
{
cbc_crypt(deskey , (char *) buffer+i, 8, DES_ENCRYPT, ivec);
ecb_crypt(deskey+8, (char *) buffer+i, 8, DES_DECRYPT);
ecb_crypt(deskey , (char *) buffer+i, 8, DES_ENCRYPT);
memcpy(ivec, buffer+i, 8);
}
len += 8;
return len;
}
int des_decrypt(uint8 *buffer, int len, uint8 *deskey)
{
char ivec[8];
char nextIvec[8];
int i;
uint8 checksum = 0;
if (!deskey) return len;
if ((len-2) % 8 || (len-2) < 16) return -1;
len -= 8;
memcpy(nextIvec, buffer+len, 8);
for (i = 2; i < len; i += 8)
{
memcpy(ivec, nextIvec, 8);
memcpy(nextIvec, buffer+i, 8);
ecb_crypt(deskey , (char *) buffer+i, 8, DES_DECRYPT);
ecb_crypt(deskey+8, (char *) buffer+i, 8, DES_ENCRYPT);
cbc_crypt(deskey , (char *) buffer+i, 8, DES_DECRYPT, ivec);
}
for (i = 2; i < len; i++) checksum ^= buffer[i];
if (checksum) return -1;
return len;
}
uint8 *des_login_key_get(uint8 *key1, uint8 *key2)
{
uint8 des14[14];
static uint8 des16[16];
int i;
for (i = 0; i < 14; i++)
{
des14[i] = key1[i] ^ key2[i];
}
memcpy(des16, des_key_spread(des14), 16);
return des16;
}
int network_message_send(int handle, uint16 *netMsgId, customData_t *customData, uint8 *buffer, int len, uint8 *deskey, comm_type_t commType)
{
uint8 netbuf[CWS_NETMSGSIZE];
if (len < 3 || len + 12 > CWS_NETMSGSIZE || handle < 0) return -1;
buffer[1] = (buffer[1] & 0xf0) | (((len - 3) >> 8) & 0x0f);
buffer[2] = (len - 3) & 0xff;
memcpy(netbuf+12, buffer, len);
len += 12;
if (netMsgId) { if (commType == COMMTYPE_CLIENT) (*netMsgId)++; netbuf[2] = (*netMsgId) >> 8; netbuf[3] = (*netMsgId) & 0xff; }
else netbuf[2] = netbuf[3] = 0;
if (customData)
{
netbuf[4] = customData->sid >> 8;
netbuf[5] = customData->sid & 0xff;
memset(netbuf+6, 0, 6);
}
else memset(netbuf+4, 0, 8);
if ((len = des_encrypt(netbuf, len, deskey)) < 0) return -1;
netbuf[0] = (len - 2) >> 8;
netbuf[1] = (len - 2) & 0xff;
write(handle, netbuf, len);
return 0;
}
int network_message_receive(int handle, uint16 *netMsgId, customData_t *customData, uint8 *buffer, uint8 *deskey, comm_type_t commType)
{
int len;
uint8 netbuf[CWS_NETMSGSIZE];
int returnLen;
if (customData) memset(customData, 0, sizeof(customData_t));
if (!buffer || handle < 0) return -1;
len = read(handle, netbuf, 2);
if (!len) return 0;
if (len != 2) return -1;
if (((netbuf[0] << 8) | netbuf[1]) > CWS_NETMSGSIZE - 2) return -1;
len = read(handle, netbuf+2, (netbuf[0] << 8) | netbuf[1]);
if (!len) return 0;
if (len != ((netbuf[0] << 8) | netbuf[1])) return -1;
len += 2;
if ((len = des_decrypt(netbuf, len, deskey)) < 15) return -1;
if ((returnLen = (((netbuf[13] & 0x0f) << 8) | netbuf[14]) + 3) > len-12) return -1;
if (netMsgId)
{
switch (commType)
{
case COMMTYPE_SERVER:
*netMsgId = (netbuf[2] << 8) | netbuf[3];
break;
case COMMTYPE_CLIENT:
if (*netMsgId != ((netbuf[2] << 8) | netbuf[3])) return -1;
break;
default:
return -1;
break;
}
}
if (customData)
{
customData->sid = (netbuf[4] << 8) | netbuf[5];
}
memcpy(buffer, netbuf+12, returnLen);
return returnLen;
}
void network_cmd_no_data_send(int handle, uint16 *netMsgId, customData_t *customData, net_msg_type_t cmd, uint8 *deskey, comm_type_t commType)
{
uint8 buffer[CWS_NETMSGSIZE];
buffer[0] = cmd; buffer[1] = 0;
network_message_send(handle, netMsgId, customData, buffer, 3, deskey, commType);
}
int network_cmd_no_data_receive(int handle, uint16 *netMsgId, customData_t *customData, uint8 *deskey, comm_type_t commType)
{
uint8 buffer[CWS_NETMSGSIZE];
if (network_message_receive(handle, netMsgId, customData, buffer, deskey, commType) != 3) return -1;
return buffer[0];
}
int network_tcp_incoming_port_open(uint16 port)
{
struct sockaddr_in socketAddr;
int socketOptActive = 1;
int handle;
if (!port) return -1;
if ((handle = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "network port %u open: ", port);
perror("socket");
return -1;
}
if (setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &socketOptActive, sizeof(int)) < 0)
{
fprintf(stderr, "network port %u open: error setsockopt\n", port);
close(handle);
return -1;
}
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = htons(port);
socketAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(handle, (struct sockaddr *) &socketAddr, sizeof (socketAddr)) < 0)
{
fprintf(stderr, "network port %u open: ", port);
perror("bind");
close(handle);
return -1;
}
if (listen(handle, 5) < 0)
{
fprintf(stderr, "network port %u open: ", port);
perror("listen");
close(handle);
return -1;
}
return handle;
}
int network_tcp_connection_accept(int socketHandle)
{
int connHandle;
struct sockaddr_in peerAddr;
struct sockaddr_in myAddr;
socklen_t peerAddrLen;
socklen_t myAddrLen;
uint16 peerPort, myPort;
uint32 peerIp, myIp;
if (socketHandle < 0) return -1;
peerAddrLen = sizeof(peerAddr);
myAddrLen = sizeof(myAddr);
if ((connHandle = accept(socketHandle, (struct sockaddr *) &peerAddr, &peerAddrLen)) < 0) { fprintf(stderr, "error network accept connection\n"); return -1; }
peerPort = ntohs(peerAddr.sin_port);
peerIp = ntohl(peerAddr.sin_addr.s_addr);
myPort = ntohs(myAddr.sin_port);
myIp = ntohl(myAddr.sin_addr.s_addr);
/* optional: do checks on or log IP of incoming connections */
return connHandle;
}
int network_tcp_connection_open(uint8 *hostname, uint16 port)
{
int handle;
struct hostent *hostaddr;
struct sockaddr_in socketAddr;
if (!(hostaddr = gethostbyname(hostname))) { fprintf(stderr, "Host lookup of %s failed\n", hostname); return -1; }
if ((handle = socket(PF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "network make connection: couldn't create socket\n"); return -1; }
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = htons(port);
socketAddr.sin_addr.s_addr = ((struct in_addr *)hostaddr->h_addr)->s_addr;
if (connect(handle, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0) { fprintf(stderr, "network make connection: error connect\n"); close(handle); return -1; }
return handle;
}
|
|
|
|
|
Hi,
I am working on a project with a WebBrowser, the poblem is I am looping in a function, and then I want the function to wait until the Document finishes loading..
something like this is what I am doing,
HTMLSelectElementClass sEC2 = (HTMLSelectElementClass) myDoc.all.item( "sel", 0 );
for( int x=0; x
|
|
|
|
|
i nead a code that calculating fraction by using operatoroverloading and the LCM and GCD
|
|
|
|
|
Gee - that doesn't sound like homework at all. What have you written so far ?
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Hi, Christian Graus i`m realy apperciate your replay and i think that i found the code i need.
using System;
namespace Point_project
{
public class Fraction
{
private int up, down;
public Fraction()
{}
public Fraction( int m, int n)
{
Up = m;
Down = n;
}
public override string ToString()
{
return Up+""+" / "+Down;
}
public int Up
{
get
{
return up;
}
set
{
up = value;
}
}
public int Down
{
get
{
return down;
}
set
{
down = value;
}
}
public static Fraction operator + (Fraction x, Fraction y)
{
int r1 = (x.Down * y.Up) + (y.down * x.Up);
int r2 = x.Down * y.down;
return new Fraction( r1, r2);
}
public static Fraction Add( Fraction x, Fraction y)
{
return x + y;
}
public static Fraction operator - (Fraction x, Fraction y)
{
int r1 = (y.down * x.Up)-(x.Down * y.Up) ;
int r2 = x.Down * y.down;
return new Fraction( r1, r2);
}
public static Fraction Sub( Fraction x, Fraction y)
{
return x - y;
}
public static Fraction operator * (Fraction x, Fraction y)
{
return new Fraction( x.Up * y.Up, x.Down * y.Down);
}
public static Fraction Multiply( Fraction x, Fraction y)
{
return x * y;
}
public static Fraction operator / ( Fraction x, Fraction y)
{
int r1 = x.Up * y.Down;
int r2 = x.Down * y.Up;
return new Fraction( r1, r2);
}
public static Fraction Division ( Fraction x, Fraction y)
{
return x / y;
}
public static int GCD(int left, int right)
{
if (left < 0)
left = - left;
if (right < 0)
right = - right;
if (left < 2 || right < 2)
return 1;
if(left == right)return left;
do
{
if (left < right)
{
int temp = left;
left = right;
right = temp;
}
left %= right;
} while (left != 0);
return right;
}
public void simplify()
{
int g=GCD(down,up);
down/=g;
up/=g;
}
}
public class FractionTeast
{
static void Main()
{
Fraction w = new Fraction();
Fraction x = new Fraction();
Fraction y = new Fraction();
Fraction z = new Fraction();
Console.Write("Numerator1 =");
x.Up = Convert.ToInt32(Console.ReadLine());
Console.Write("denominator1 =");
x.Down = Convert.ToInt32(Console.ReadLine());
while(x.Down == 0)
{
Console.Write("Invalid value REENTER denominator1 =");
x.Down = Convert.ToInt32(Console.ReadLine());
}
Console.Write("\nNumerator2 =");
y.Up = Convert.ToInt32(Console.ReadLine());
Console.Write("denominator2 =");
y.Down = Convert.ToInt32(Console.ReadLine());
while(y.Down == 0)
{
Console.Write("Invalid value REENTER denominator1 =");
y.Down = Convert.ToInt32(Console.ReadLine());
}
Console.Write("\nSelect the calculation type (1:Addtion, 2:Subtraction, 3:Multiplication, 4:Division, Or 0:ToTerminate)==>");
sbyte e = Convert.ToSByte(Console.ReadLine());
while(e != 0)
{
if(e < 0 || e > 4)
{
Console.Write("\nInvalid number PLEASE Select the calculation type (1:Addtion, 2:Subtraction, 3:Multiplication, 4:Division, Or 0:ToTerminate)==>");
e = Convert.ToSByte(Console.ReadLine());
}
if( e == 1)
{
z = (x+y);
z.simplify();
if(z.Down == 1)
{
Console.WriteLine(x.Up+"/"+x.Down+" + "+y.Up+"/"+y.Down+" = "+z.Up);
}
else if(z.Up == 0)
{
Console.WriteLine(x.Up+"/"+x.Down+" + "+y.Up+"/"+y.Down+" = 0");
}
else
{
Console.WriteLine(x.Up+"/"+x.Down+" + "+y.Up+"/"+y.Down+" = "+z);
}
Console.Write("\nSelect the calculation type (1:Addtion, 2:Subtraction, 3:Multiplication, 4:Division, Or 0:ToTerminate)==>");
e = Convert.ToSByte(Console.ReadLine());
}
if( e == 2)
{
z = (x-y);
z.simplify();
if(z.Down == 1)
{
Console.WriteLine(x.Up+"/"+x.Down+" - "+y.Up+"/"+y.Down+" = "+z.Up);
}
else if(z.Up == 0)
{
Console.WriteLine(x.Up+"/"+x.Down+" - "+y.Up+"/"+y.Down+" = 0");
}
else
{
Console.WriteLine(x.Up+"/"+x.Down+" - "+y.Up+"/"+y.Down+" = "+z);
}
Console.Write("\nSelect the calculation type (1:Addtion, 2:Subtraction, 3:Multiplication, 4:Division, Or 0:ToTerminate)==>");
e = Convert.ToSByte(Console.ReadLine());
}
if( e == 3)
{
z = (x*y);
z.simplify();
if(z.Down == 1)
{
Console.WriteLine(x.Up+"/"+x.Down+" X "+y.Up+"/"+y.Down+" = "+z.Up);
}
else if(z.Up == 0)
{
Console.WriteLine(x.Up+"/"+x.Down+" X "+y.Up+"/"+y.Down+" = 0");
}
else
{
Console.WriteLine(x.Up+"/"+x.Down+" X "+y.Up+"/"+y.Down+" = "+z);
}
Console.Write("\nSelect the calculation type (1:Addtion, 2:Subtraction, 3:Multiplication, 4:Division, Or 0:ToTerminate)==>");
e = Convert.ToSByte(Console.ReadLine());
}
if( e == 4)
{
z = (x/y);
z.simplify();
if(z.Down == 1)
{
Console.WriteLine(x.Up+"/"+x.Down+" / "+y.Up+"/"+y.Down+" = "+z.Up);
}
else if(z.Up == 0)
{
Console.WriteLine(x.Up+"/"+x.Down+" / "+y.Up+"/"+y.Down+" = 0");
}
else
{
Console.WriteLine(x.Up+"/"+x.Down+" / "+y.Up+"/"+y.Down+" = "+z);
}
Console.Write("\nSelect the calculation type (1:Addtion, 2:Subtraction, 3:Multiplication, 4:Division, Or 0:ToTerminate)==>");
e = Convert.ToSByte(Console.ReadLine());
}
}
if( e == 0)
{
Console.WriteLine("\nPress ENTER toterminate");
Console.ReadLine();
}
}
}
}
casue i'm the man withno lose
|
|
|
|
|
Looks likely. If you 'found' this code, I recommend you learn what it does, because your professor will ask you and your next homework will assume you know how this one works.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
well, i mean i that found the simplifying methods and matched it together and with the rest of the code even it(simplifying methods) were containing many mistakes and i fix it
but the rest of the code me who made it.
so don`t be ware for me
i made the discussion with my Prof. about it and i was great
but anyway thanks a lot
casue i'm the man withno lose
|
|
|
|
|
Hi!
Currently I'm writing a very simple mail server using SMTP and POP3. My architecture is as follows:
Start Mailserver ->
-> create SMTP server thread
-> create thread for each client that connects
-> create POP3 server thread
-> create thread for each client that connects
Stop Mailserver ->
-> Shutdown SMTP and POP3 thread and their children threads
Is this a good architecture to use in a server?
If yes, how do I gracefully shut down the threads? Right now I have a method "Stop" that will set a static volatile bool stop to true which will cause some while-loops to terminate, but that doesn't work, the loops don't register that "stop" has changed to true
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
I can't advise you on the arhitecture, becouse I have never programed a server of any kind (but I supose I would go the same way as you went...).
Anyways for the killing threads part: create a collection of your threads objects (I'm a little bit rusty on this part, but I do know that every thread has an object) and then when you have to kill them, just loop trough that collection and shut the threads down...
Easy.
Q:What does the derived class in C# tell to it's parent?
A:All your base are belong to us!
|
|
|
|
|
CWIZO wrote: just loop trough that collection and shut the threads down...
Yeah that's okay, but what is the correct way to shut the threads down?
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
I think every thread has a stop thread function or something like that... so that is the correct way.
Or am I missing your point?
Q:What does the derived class in C# tell to it's parent?
A:All your base are belong to us!
|
|
|
|
|
Hi,
The cost of VS 2005 standard edition is almost double in the UK
compared to the US. Is there any legal reason why I can't order VS from
the US instead of buying it locally?
Regards
Pieter
|
|
|
|
|
I can't imagine that there would be. Stuff in the UK always seems to cost more. when the UK is my only option for music I know it costs a ton.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Thanks Christian. Yes, stuff are sometimes pretty expensive in the UK. I don't mind paying a few £££s more, but double - that's ridiculous!
Pieter
|
|
|
|
|
Subject: Try/Catch Variable Scoping
If I try to compile the following code in .NET 1.1, I get the error "Use of unassigned local variable 'rdr'" when I'm assigning a value to intSurveyQuestionOrdinal. I understand that the try block's brace is creating a separate scope. However, I tried to get around that by declaring rdr at the top of the method. Why doesn't this work?
Thanks.
protected int GetSurveyQuestion()
{
SqlDataReader rdr;
SqlConnection connection = new SqlConnection(AppConfig.GetDbConnectionString(Convert.ToString(Request.Url)));
connection.Open();
SqlCommand command = new SqlCommand("usp_SEL_SurveyQuestion", connection);
command.CommandType = CommandType.StoredProcedure;
try
{
rdr = command.ExecuteReader();
}
catch(Exception exc)
{
pnlQuestion.Visible = false;
pnlError.Visible = true;
lblAdminPageHeader1.Text = "Application Error";
lblAdminPrompt1.Text = "The SELECT database operation failed: " + exc.Message;
rdr.Close();
connection.Close();
}
int intSurveyQuestionOrdinal = rdr.GetOrdinal("SurveyQuestion"); // <--- ERROR HAPPENS HERE
int intSurveyIDOrdinal = rdr.GetOrdinal("SurveyID");
while (rdr.Read())
{
strSurveyQuestion = rdr.GetString(intSurveyQuestionOrdinal);
intSurveyID = rdr.GetInt32(intSurveyIDOrdinal);
}
rdr.Close();
connection.Close();
return intSurveyID;
}
|
|
|
|
|
Because, in some cases the rdr variable will not be set. If the ExecuteReader call fails, the rdr variable doesn't get a value. The compiler only lets you use a variable if it's certain that it always has a value.
You should also get the same error message on the line where you call rdr.Close().
In fact, you shouldn't call rdr.Close() at all in the catch section. If the code in the catch section is executed, the rdr variable certainly has no value.
Also, if you get an exception, you shouldn't let the code just go on and try to use the reader anyway, as there is no reader.
---
b { font-weight: normal; }
|
|
|
|
|
OK, I understand your reasoning. That still leaves the question, how do I handle this situation? I'm reading articles about this situation online and in Studio's online help but they all seem to deal with the very simplest of situations (e.g. just set a label control if an error occurs).
Thanks again.
|
|
|
|
|
Just don't let the code panic. Just because a database call failed, you don't need to drop everything and run. In the catch section just set the rdr variable to null and prepare the error message, then after the try--catch block you just check if the variable is null or not. If it's not null, loop thought the data. If it's null, just skip that part and go directly on to gracefully closing the database.
I always put the connection object in a using() block. That way, what ever happens, at least the database connection is closed correctly.
using (SqlConnection connection = new SqlConnection(...)) {<br />
...do the database stuff<br />
}
The using() block always calls the Dispose method of the connection, and as the Dispose method of the connection always calls the Close method, you don't have to do that either.
---
b { font-weight: normal; }
|
|
|
|
|
That worked! Thank you very much!!
|
|
|
|
|
I am using Visual Studio 2005. I wrote a Setup Project to install my application. After setup is complete, I need to get the destination folder that the user chose to install to (not the default destination folder, but the one the user actually chose during the install. I found an article that said in Visual Studio 2003, this was done by adding a registry entry (through the Setup project) and setting the value of the entry to [INSTALLDIR]. In Visual Studio 2005, I have no problem adding a registry entry and setting it's value, but [INSTALLDIR] is not recognized as a special tag, and is just treated as a literal string. Has the name of this tag changed in VS 2005? Anyone know how to do this in VS 2005
thanks!
|
|
|
|
|
i had the same need, what is your goal.
|
|
|
|
|
My goal is to be able to read the install dir. path from within the app at run time. So, having the Setup program write the path to the registry would be a perfectly acceptable way to accomplish this goal, only problem is I can't figure out how to do this.
|
|
|
|
|
i mean if you explain what have you to do, you may avoid to get the user setup path.
Anyway after the install you can run automatically a little .exe without form installed together your main app, that create a registry key
|
|
|
|
|
Yes, but how do I get the path to put it into the registry key?
|
|
|
|
|
What is the best way to update a database like Access, use oleDBcomand with parameters or use DataSet?
|
|
|
|
|