|
Why does "sadly" sometimes make me smile?
|
|
|
|
|
I've seen things.
We all have seen things.
GCS d--(d+) s-/++ a C++++ U+++ P- L+@ E-- W++ N+ o+ K- w+++ O? M-- V? PS+ PE- Y+ PGP t+ 5? X R+++ tv-- b+(+++) DI+++ D++ G e++ h--- r+++ y+++* Weapons extension: ma- k++ F+2 X
|
|
|
|
|
The overwhelming use of it is when you want to use unicode but have the code portable for the none unicode situation.
It isn't just TCHAR you use in that situation but you place all string literals inside the _T() or TEXT() macros so they also port and use the TCHAR string functions _tcslen for strlen, _tcscpy_s for strcpy_s etc so all the string functions port.
So being precise about this on Visual Studio with a project open goto the last debug menu which is the project properties then goto
Configuration Properties->Advanced->Character Set you now have 3 options not set (aka use ansi), use unicode and use multi-byte wide character. When you use TCHAR and the above macros and stuff in <tchar.h> you can compile your code in any of those modes and it will work completely seamlessly.
I use it a lot because I write many multilingual windows applications which have large use in non English language areas.
It becomes second nature like using stdint.h and proper sized integers rather than int, short, long etc which are problematic porting.
In vino veritas
modified 2-Apr-20 10:59am.
|
|
|
|
|
That sheeds light on it. Thanks for taking time to write that down and share your knowledge leon.
`DreamLand Page` on facebook
modified 2-Apr-20 12:34pm.
|
|
|
|
|
I noticed today when editing a program on Visual C++ 2015 that if I left a variable undeclared, it showed underlined in red, similar to misspellings in Word for Windows. That is useful. Thanks to whoever put that feature in.
|
|
|
|
|
I think this message is meant for Microsoft.
|
|
|
|
|
|
CodeProject did not write Visual Studio. But I agree, it's a good feature.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
Hi i am using following code for silent installation of MSI am getting 2203 error.
This is the code i am using.
Not working if i pass domain Administrator username and password, it is giving error like "The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2203".
Can anyone tell me how to resolve this issue.
Note: It is working fine if i pass the local/Built-in administrator username and password.
UAC is enabled in the PC.
strTempFolderToDownload = "msiexec /a "+ MSILocaltion + " ALLUSERS=0" + " TARGETDIR=" + '"' +Installlocation+ '"' + " /qb"
bLogonRet = LogonUser(strUserName, strDomainName, strPassWord, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT , &hToken);
if(bLogonRet && hToken!=NULL)
{
BOOL benvBlock = CreateEnvironmentBlock(&lpvEnv, hToken, TRUE);
if(benvBlock)
{
dwSize = sizeof(szUserProfile)/sizeof(WCHAR);
BOOL bUsrProDir = GetUserProfileDirectory(hToken, szUserProfile, &dwSize);
if(bUsrProDir)
{
bCreateRet = CreateProcessWithLogonW(strUserName, strDomainName, strPassWord, LOGON_WITH_PROFILE, NULL, CT2W(strTempFolderToDownload),CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, &si, &pi );
}
}
}
As well as i tried only with following code also no luck.
CreateProcessWithLogonW(strUserName, strDomainName, strPassWord, LOGON_WITH_PROFILE, NULL, CT2W(strTempFolderToDownload),CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi );
CreateProcessWithLogonW(strUserName, strDomainName, strPassWord, NULL, NULL, CT2W(strTempFolderToDownload),NULL, NULL, NULL, &si, &pi );
|
|
|
|
|
|
2203 in an administrative install usually means "access denied".
Where are you installing it to and is the account running the MSIEXEC command an administrator? Is the .MSI copied to the local machine before you launch it?
Also, "ALLUSERS=0" isn't really a thing. The behavior of ALLUSERS isn't defined for a value of 0. The behavior is defined for values 1 and 2 and for an empty string ("").
A value of 1 is for a "per-machine" install or "all users", which is typical if you're installing to Program Files.
A value of 2 is for letting MSIEXEC determine which type of installation it should do, checking the value of the MSIINSTALLPERUSER property.
See ALLUSERS property - Win32 apps | Microsoft Docs[^] for more.
|
|
|
|
|
Hi Dave,
Thanks for the posting.
1.) I am trying to install in C:\Program Files(x86)\ folder.
2.) I logged in as non admin user, am trying to install the MSI with domain Administrator credentials am using CreateProcessWithLogonW to do this.
3.) Yes, i copied the installer into temp location.
|
|
|
|
|
OK.
In that case, if the command line your code generated works if an admin on the machine runs it, the problem is going to be in your code that logs in as an admin, but apparently doesn't run anything as an admin. I couldn't tell you what the problem is there.
|
|
|
|
|
Thanks for your help to people who ask queries.
I know how to ask for a file to read from, or a file to write to :-
BOOL GetFileName(HWND wn,char*file,char*titl,char*filter,short write) {short j;
strcpy(file,title);
ofn.lStructSize=sizeof(OPENFILENAME); ofn.hwndOwner=wn;
ofn.lpstrFilter=filter; ofn.lpstrCustomFilter=0;
ofn.lpstrFile=file; ofn.nMaxFile=1024;
ofn.lpstrFileTitle=title; ofn.nMaxFileTitle=1024;
ofn.lpstrInitialDir=0; ofn.lpstrTitle=titl;
ofn.Flags=write?OFN_OVERWRITEPROMPT:OFN_FILEMUSTEXIST;
j=(write?GetSaveFileName(&ofn):GetOpenFileName(&ofn))?1:0;
return j;}
('ofn' and 'title' are declared globally.)
but when I need to ask for a directory / folder, I must do something like this:
K=GetFileName(wn, slidefilename, "name of a file in the directory to read slides from?", slidefiletype, 0);
Is there something like GetOpenFileName, but returning the name of a directory rather than the name of a file?
modified 30-Mar-20 0:49am.
|
|
|
|
|
|
Hi
What is the syntax when you want to pass an array as argument? I`m looking for syntax for both function call and function definition.
|
|
|
|
|
Much the same syntax as when passing anything, in this case a pointer is the norm:
int myFunction(char* anArrayOfChars) {
}
...
char anArray[32];
int value = myFunction(anArray)
|
|
|
|
|
Thanks
will modifying the array content within the function make the edit permanent i.e. the modification will remain after the function ceased to exist. i.e. "myFunction(&anArray)" won`t this edit outside the function. I need the edit to work backwards.
modified 29-Mar-20 5:32am.
|
|
|
|
|
Yes, if the function changes anything in the array then that data will remain when the function returns to the caller. Note: you do not need the addressof operator (& ) on an array name. Just code it as I showed in my example.
Try this simple test:
void myFunc(char* somedata)
{
strcpy(somedata, "Bad stuff");
return;
}
char myArray[] = "Good stuff";
myFunc(myArray);
printf("Returned value %s\n", myArray);
|
|
|
|
|
I edited my previous post a bit
also
void myFunc(char* somedata)
{
strcpy(somedata, "Good stuff");
return;
}
char myArray[] = "Bad stuff";
myFunc(myArray);
printf("Returned value %s\n", myArray);
Quote: void myFunc(char* somedata)
{
strcpy(somedata, "Good stuff");
return;
}
//...
char myArray[] = "Bad stuff";
myFunc(myArray);
printf("Returned value %s\n", myArray);
will this function? the array has 9 elements(bad stuff 9 chars.) "good stuff" is 10.
modified 29-Mar-20 6:10am.
|
|
|
|
|
Well, of course that breaks it so you may find that your code crashes. You must not overwrite arrays that are passed to you with more data than it can hold. But this conversation is missing some vital information. Maybe you can explain exactly what problem you are trying to solve.
|
|
|
|
|
@Richard Meh I`m really not doing anything worth much attention. My code is stashed with hacks so I`m just trying to fix on it.
"DreamLand Page" on facebook
|
|
|
|
|
fearless_ wrote: My code is stashed with hacks So it all needs a lot of attention.
|
|
|
|
|
Thanks for pointing how things are meant to be done Richard
"DreamLand Page" on facebook
|
|
|
|
|
Further to what Richard has said, you could also do some defensive programming by passing in the length of the array. eg:
void myFunc(int* somedata, size_t data_len)
{
for(size_t i = 0; i < data_len; ++i)
somedata[i] *= 2;
return;
}
int myArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
const size_t arrLen = sizeof(myArray)/sizeof(myArray[0]);
myFunc(myArray), arrLen);
This will prevent data overflows, and/or segfaults, when accessing myArray inside the function.
Things to note:
* we can get the compiler to tell us how many elements in the array using the sizeof(myArray)/sizeof(myArray[0]) construct. This is calculated at compile time and in release mode, in most cases it will be optimized out, so it does not add to your memory usage, if that's a concern.
* Using the constant arrLen means that if we change the number of elements in myArray, we don't need to go through the code and find all uses of myArray and make sure we're passing in the right number
* If we had used arrLen = sizeof(myArray)/sizeof(int) , we need to remember to change the definition of arrLen if we change the type of myArray . Using sizeof(myArray[0] mean that if we change the type of myArray from int[] to double[] , for example, we don't need to remember to change the definition of arrLen as well
Keep Calm and Carry On
|
|
|
|
|