|
I'm new to C++ and have been tinkering with creating a small app that uses the CreateProcessAsUser function (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx). Now, everything works just fine and dandy when I'm double-clicking my .EXE to run it. The issue is that if I execute it from a Command Prompt that isn't the current directory, it errors.
This is what I'm currently using:
CreateProcessAsUser(
hPrimaryToken,
sFileToLaunch,
lpCommandLine,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
NULL,
lpCurrentDirectory,
&si,
&pi
);
I've got "lpCurrentDirectory" set to null, and so I thought that would solve this. Apparently it doesn't. Can anyone shed a little light on this for me? Thanks!
|
|
|
|
|
It would help a great deal if you were to disclose the exact error that you're getting.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I don't really get any errors as things are currently coded (I'm still new and figuring things out, so I still need to beef up on my error checking skills). The .EXE I compile just fails to succesfully execute the other process with the parameters passed to it. And I don't know how to debug/test things within Visual Studio as if they came from a command prompt other than the directory where the .EXE resides.
|
|
|
|
|
One thing you can do is call GetLastError after the CreateProcessAsUser function fails:
DWORD Error = GetLastError();
Then look up the error code, and that will tell you why it failed.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
It looks like I get an error code 3, the system cannot find the path specified. Anyone have any idea what I'm setting incorrectly?
|
|
|
|
|
I would verify the file name of the program that you're passing, if that's not found, it would give that error.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Yeah, but like I said in my first post, if I make a shortcut to the .EXE file and put the parameters in there, it works just fine when I double-click the shortcut. If I then Copy/Paste that info to a Command Prompt, it fails. So I'm passing the same info to the .EXE. It just seems to be the fact that the directory the Command Prompt is starting from is affecting things. I'll do some more digging, but if anyone has any suggestions, I'm all ears.
|
|
|
|
|
I'm not clear on some things:
When you refer to "the EXE" which program is that?
When you say you paste "that info" to a command prompt, what info?
Maybe you are not putting a fully qualified path, and the function can't find the target program.
List the following information:
1. What is the full path to the program that calls the "CreateProcessAsUser" function?
2. What is the full path to the program that it is attempting to launch?
3. Give the exact command line that you are using with all options
4. Tell the exact path from which you are entering this command line
The difficult we do right away...
...the impossible takes slightly longer.
modified 5-Jan-12 19:53pm.
|
|
|
|
|
I figured it out. I had coded my app to accept a command line argument for a file path, and to allow a path starting from where my app resided. So once I checked the file path being submitted, and added the full path onto any partial arguments, things worked.
Basically, I just had to make sure my app was using the full path to the file it was launching.
Thanks for helping point me in the right direction!
|
|
|
|
|
Glad you got it sorted out.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Hi,
Trying to convert my application to use the MFC's codejock toolkit pro library, I meet the following problem.
I have a CDialogBar derived class that has some buttons and its working like a main panel at the bottom of the main frame. I used to catch all button messages inside the main frame. While that worked in my old application without using the toolkit, now I can not catch the messages inside the main frame (now the main frame is derived from CXTPFrameWnd and the CDialogBar is inside a CXTPDockingPane).
Can I blame the toolkit lib or am I doing something wrong here ? How can I detect the message routing to find a solution ? Do I have to make some special command routing in my case ?
Regards,
sdancer75
|
|
|
|
|
Hi,
You would probably find more C++ software engineers with experience using the CXTPFrameWnd and CXTPDockingPane classes over at the CodeJock forum[^]. We don't hear much from Kirk Stowell[^] these days over here at the codeproject.
Best Wishes,
-David Delaune
|
|
|
|
|
I created structures to pass arrays of data to SQL Server to write a user record with no problem.
So I thought using the same method would work in reverse for retrieving an array of user records to populate a List Box.
But I can't figure out how to initialize the structure in my class as an array. I can Initialize the structure as a single record, and pass it to the function.
I created a sql server call to get the record count first, so I can size the array.
I thought it would be written like this ...
dbUA.UA_LISTBOX *uaList = new dbUA.UA_LISTBOX[dwCount];
My Class Strucure and function
class DB_UserAccount {
public:
struct UA_Listbox {
INT iUserID;
WCHAR *szFirstName;
WCHAR *szLastName;
WCHAR *szAccountName;
} UA_LISTBOX;
BOOL _get_UserAccount_Listbox_Count( DWORD &dwCount );
BOOL _get_UserAccount_Listbox_Info( UA_Listbox &pzUserList );
BOOL UserAccount_Index::_load_UserAccount_Index_Listbox( void )
{
DB_UserAccount dbUA;
DWORD dwCount;
dbUA._get_UserAccount_Listbox_Count( dwCount );
return TRUE;
}
|
|
|
|
|
turn your UA_Listbox struct into a class and add a constructor:
class UA_Listbox {
public:
INT iUserID;
WCHAR *szFirstName;
WCHAR *szLastName;
WCHAR *szAccountName;
UA_Listbox()
: iUserID(0)
, szFirstName(NULL)
, szLaszName(NULL)
, szAccountName(NULL)
{
}
} UA_LISTBOX;
If you mean, you want to initialize the items differently (so every item gets different values) then you won't be able to do it that way, you will need to have a pointer-array and add the items one-by-one, eg:
UA_Listbox **uaListBoxPtrArray;
...
uaListBoxPtrArray = new UA_ListBox*[dwCount];
for (DWORD i = 0; i < dwCount; i++)
{
uaListBoxPtrArray[i] = new UA_Listbox;
uaListBoxPtrArray[i]->iUserID = ...
}
You might try using std::vector too, like:
std::vector<UA_Listbox *> arListBox;
for (DWORD i = 0; i < dwCount; i++)
{
arListBox.push_back(new UA_Lostbox(...));
}
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> If it doesn't matter, it's antimatter.<
|
|
|
|
|
Code-o-mat wrote: turn your UA_Listbox struct into a class and add a constructor:
So make the class first. I'am storing different values in it
01 Joe Smoe jSmoe
02 John Doe jdoe
Then make the constructor
Are vectors the preferred way of packaging data?
|
|
|
|
|
jkirkerx wrote: So make the class first. I'am storing different values in it
01 Joe Smoe jSmoe
02 John Doe jdoe
Then make the constructor
I'm not sure i understand what you mean. Basicaly, structs and classes are the same in C++ except that the default access type for a class is "private" while for a struct it's "public". It's just personal preference -i guess- that i only use struct when all it does is to group a few data members together, but if it has a constructor/destructor or other methods defined, i use class.
I don't think there's a "prefered" way of "packaging data" as you said, it all depends on your needs, your requirements, your habits... you might as well use a linked list, a bi-directional linked list, hell, you could use a tree or a hash table if that is what best suits you.
P.S. if you use a pointer array, don't forget to delete your items before deallocating the struct itself.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> If it doesn't matter, it's antimatter.<
|
|
|
|
|
I wrote all the hard functions for my program first, like registry values, encrypting, creating a database, downloading programs, SQL ODBC Calls for Data.
Now I'm gluing it all together with the GUI interfaces, so because I came from VB Windows and the web world, I'm in new territory here as to best practices. I don't have any preferences yet, and I had no idea there was so many ways to do it.
Let me finish my Dialog Box first, so I can populate it and read the data entered, then I'll get back to the listbox and sql data packaging.
Thanks for the suggestions, I'm sure one of them will work out for me.
|
|
|
|
|
All right, good luck.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> If it doesn't matter, it's antimatter.<
|
|
|
|
|
Did I get this right?
I'm missing something here, I get a single structure, and not an array structure. I just keep writing the data to the same single structure. I must be missing something in the class, but I'm not sure what. Or maybe I didn't initialize it right.
This is for populating the array
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS) {
UA_Listbox **uaPtr;
uaPtr = new UA_Listbox*[dwCount];
INT i = 0;
INT pzUserID;
WCHAR pzFirstName[cbFirstName];
WCHAR pzLastName[cbLastName];
WCHAR pzUserName[cbUserName];
while (SQLFetch(hstmt) == SQL_SUCCESS) {
SQLGetData(hstmt, 1, SQL_C_ULONG, &pzUserID, 0, NULL );
SQLGetData(hstmt, 2, SQL_C_WCHAR, &pzFirstName, cbFirstName, NULL );
SQLGetData(hstmt, 3, SQL_C_WCHAR, &pzLastName, cbLastName, NULL );
SQLGetData(hstmt, 4, SQL_C_WCHAR, &pzUserName, cbUserName, NULL );
uaPtr[i] = new UA_Listbox;
uaPtr[i]->iUserID = pzUserID;
uaPtr[i]->szFirstName = pzFirstName;
uaPtr[i]->szLastName = pzLastName;
uaPtr[i]->szAccountName = pzUserName;
++i;
}
This is the class
class UA_Listbox {
public:
INT iUserID;
WCHAR *szFirstName;
WCHAR *szLastName;
WCHAR *szAccountName;
UA_Listbox():
iUserID(0),
szFirstName(NULL),
szLastName(NULL),
szAccountName(NULL)
{
// Constructor
}
~UA_Listbox()
{
// Deconstructor
}
};
|
|
|
|
|
jkirkerx wrote: uaPtr[i]->szFirstName = pzFirstName;
uaPtr[i]->szLastName = pzLastName;
uaPtr[i]->szAccountName = pzUserName;
You store pointers to the same buffers N times.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> If it doesn't matter, it's antimatter.<
|
|
|
|
|
Your database layer should be distinct from your display layer.
Your display layer uses the database layer. There is no display information/design in the database layer (noting of course that the application design of a simple app might seem to drive directly through the two layers.)
jkirkerx wrote: I thought it would be written like this ...
What exactly is the question?
You need a pointer. You need to new an array. Then you initialize each member in the array.
If you are asking how to access a member of the array then you do it as
uaList[0].iUserID
uaList[1].iUserID
etc.
(Presumably you are also providing code to clear up every single allocation.)
Also given that you are using C++ why are not just using a straight forward class with string members?
Formatting suggestions.
- Don't put underscores in the middle of names.
- Don't put underscores at the beginning of method names.
- If a method belongs to a class then don't prefix the class name to the method.
|
|
|
|
|
I probably should of just asked what the preferred method of packaging data is.
I'm still in c++ 100 here, I started in vb.
in vb, I would of just typed
Dim UserInfo(6, TheCount) As String
UserInfo = Users.Get_ListBoxInfo()
I'll try the post above and see how it works.
|
|
|
|
|
Minor suggestion
It is either struct - structure or an array of ... whatever.
Or an array of struct.
It appears that you are after single struct of strings.
Anyway, just a suggestion since you asked what is prefered.
And a really small suggestion - if the function finds a count of items, the return value should be the count and not just true / false. Unless of course you really do not need the count.
Vaclav
|
|
|
|
|
I thought I had to dimension the array first, guess that's not needed if I write better code.
Well here goes, finished my dialog form, so I'm back to the array now.
|
|
|
|
|
jkirkerx wrote: I thought I had to dimension the array first
You might want to experiment with some simpler arrays first. I would suggest an array of ints then an array of strings (the string class, not a char*).
Allocate the arrays, assign values to members of the array, then sequence through the array to verify, then deallocate the array.
After that your implementation is just a variation on the above (especially since string is a class so you will have already created an array of classes.)
|
|
|
|
|