WinMain() to argv[] unter WinCE



  • Hi,

    ich muss ein Programm von Linux nach Windows CE portieren was bis jetzt geklappt hat. Ich bekomme es aber irgendwie nicht hin WinMain ( um genau zu sein LPSTR lpCmdLine ) nach argv[] zu parsen.

    Laut MSDN kann man GetCommandLine nutzen, da bekomme ich aber erstens alle Parameter als 1. String und es klappt auch irgendwie nicht.

    Bei einem Aufruf von hallo.exe param1 param2 liefert mir GetCommandLine einfach nur den ersten Buchstaben vom ersten Parameter also in diesem Fall ein p.

    Ich habe schon gegoogelt aber nichts passendes gefunden bzw. etwas , dass auch funktioniert.

    Es gibt ja auch CommandLineToArgvW aber laut MSDN und durch einen Versuch habe ich erfahren, dass dies unter Windows CE nicht funktioniert.

    Wer hat einen Tipp ?



  • guckst du hier:

    #include <windows.h>
    #include <cstring>
    
    int main(int argc, char** argv)
    {
        // Tu, was auch immer du tun willst...
        return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
        wchar_t* wCmdLine = GetCommandLineW();
        int iArgc, RetVal, counter;
        wchar_t** wArgv = CommandLineToArgvW(wCmdLine, &iArgc);
        char** aArgv = new char*[iArgc];
        for (counter = 0; counter < iArgc; counter++)
        {
            int len = wcslen(wArgv) + 1;
            aArgv[counter] = new char[len];
            WideCharToMultiByte(CP_ACP, 0, wArgv[counter], -1, aArgv[counter], len, NUL, NULL);
        }
        LocalFree(wArgv);
        RetVal = main(iArgc, aArgv);
        for (counter = 0; counter < iArgc; counter++)
        {
            delete[] aArgv[counter];
        }
        delete[] aArgv;
        return RetVal;
    }
    


  • sry, hab überlesen, dass CommandLineToArgvW bei Windows CE nich funzt...



  • naja, falls mein Beispiel von eben wirklich nicht funktioniert, versuch doch mal das hier:

    #include <windows.h>
    #include <cstring>
    
    wchar_t** __CommandLineToArgv(const wchar_t* lpCmdLine, int* pNumArgs)
    {
    	if (!lpCmdLine)
    		return NULL;
    	if (lpCmdLine[0] == L'\0')
    		return NULL;
    	wchar_t** pRetVal = NULL;
    	bool bTogether = false;
    	int iNumParts = 1;
    	int iLength = wcslen(lpCmdLine);
    	for (int n = 0; n < iLength; n++)
    	{
    		if (lpCmdLine[n] == L'\"')
    		{
    			bTogether = !bTogether;
    		}
    		if ((lpCmdLine[n] == L' ') && (!bTogether))
    		{
    			iNumParts++;
    		}
    	}
    	bTogether = false;
    	*pNumArgs = iNumParts;
    	pRetVal = reinterpret_cast<wchar_t**>(LocalAlloc(LPTR, (sizeof(wchar_t*) * iNumParts) + (sizeof(wchar_t) + iLength));
    	wchar_t* pCmdLine = reinterpret_cast<wchar_t*>(&(pRetVal[iNumParts]));
    	wcscpy(pCmdLine, lpCmdLine);
    	for (int c = 0; c < iLength; c++)
    	{
    		if (pCmdLine[c] == L'\"')
    		{
    			pCmdLine[c] = L'\0';
    			bTogether = !bTogether;
    		}
    		if ((pCmdLine[c] == L' ') && (!bTogether))
    		{
    			pCmdLine[c] = L'\0';
    		}
    	}
    	wchar_t wLast = L' ';
    	int iArg = 1;
    	pRetVal[0] = pCmdLine;
    	for (int i = 0; i < iLength; i++)
    	{
    		if ((wLast == L'\0') && (pCmdLine[i] != L'\0')
    		{
    			pRetVal[iArg] = &(pCmdLine[i]);
    			iArg++;
    			wLast = pCmdLine[i];
    		}
    	}
    	return pRetVal;
    }
    

    hat (mehr oder weniger) die selbe Funktionsweise wie CommandLineToArgv.

    der gesamte Code:

    #include <windows.h>
    #include <cstring>
    
    int main(int argc, char** argv)
    {
        // Tu, was auch immer du tun willst...
        return 0;
    }
    
    wchar_t** __CommandLineToArgv(const wchar_t* lpCmdLine, int* pNumArgs)
    {
    	if (!lpCmdLine)
    		return NULL;
    	if (lpCmdLine[0] == L'\0')
    		return NULL;
    	wchar_t** pRetVal = NULL;
    	bool bTogether = false;
    	int iNumParts = 1;
    	int iLength = wcslen(lpCmdLine);
    	for (int n = 0; n < iLength; n++)
    	{
    		if (lpCmdLine[n] == L'\"')
    		{
    			bTogether = !bTogether;
    		}
    		if ((lpCmdLine[n] == L' ') && (!bTogether))
    		{
    			iNumParts++;
    		}
    	}
    	bTogether = false;
    	*pNumArgs = iNumParts;
    	pRetVal = reinterpret_cast<wchar_t**>(LocalAlloc(LPTR, (sizeof(wchar_t*) * iNumParts) + (sizeof(wchar_t) + iLength));
    	wchar_t* pCmdLine = reinterpret_cast<wchar_t*>(&(pRetVal[iNumParts]));
    	wcscpy(pCmdLine, lpCmdLine);
    	for (int c = 0; c < iLength; c++)
    	{
    		if (pCmdLine[c] == L'\"')
    		{
    			pCmdLine[c] = L'\0';
    			bTogether = !bTogether;
    		}
    		if ((pCmdLine[c] == L' ') && (!bTogether))
    		{
    			pCmdLine[c] = L'\0';
    		}
    	}
    	wchar_t wLast = L' ';
    	int iArg = 1;
    	pRetVal[0] = pCmdLine;
    	for (int i = 0; i < iLength; i++)
    	{
    		if ((wLast == L'\0') && (pCmdLine[i] != L'\0')
    		{
    			pRetVal[iArg] = &(pCmdLine[i]);
    			iArg++;
    			wLast = pCmdLine[i];
    		}
    	}
    	return pRetVal;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
        wchar_t* wCmdLine = GetCommandLineW();
        int iArgc, RetVal, counter;
        wchar_t** wArgv = __CommandLineToArgv(wCmdLine, &iArgc);
        char** aArgv = new char*[iArgc];
        for (counter = 0; counter < iArgc; counter++)
        {
            int len = wcslen(wArgv) + 1;
            aArgv[counter] = new char[len];
            WideCharToMultiByte(CP_ACP, 0, wArgv[counter], -1, aArgv[counter], len, NUL, NULL);
        }
        LocalFree(wArgv);
        RetVal = main(iArgc, aArgv);
        for (counter = 0; counter < iArgc; counter++)
        {
            delete[] aArgv[counter];
        }
        delete[] aArgv;
        return RetVal;
    }
    

    MfG DrakoXP



  • Falls Du die MS-IDE verwendest, nimm einfach __argv .



  • wie ich dem Herrn, der mal wieder cross-posting betreibt, bereits vor Tagen gesagt habe.



  • @DrakoXP: Vielen Dank für Deinen argc/argv[] Ersatz-Algorithmus, leider compiliert noch funktioniert er, wenn man die offensichtlichen Syntaxfehler behebt. Hast Du da mittlerweile was aktuelles ?

    Danke!

    sgf42


  • Mod

    Lies was codefinder geschrieben hat.
    Die MS-CRT hat eingebaut __argv und __argc!
    Da muss man nichts konvertieren.



  • also 4 Dinge:

    1. Der Code hier von mir ist 4 Jahre alt.
    2. Welche "offensichtlichen" Syntaxfehler? 😕
    -> Kann es zwar jetzt gerade nicht mit aktuellem Compiler überprüfen,
    da ich gerade an einem Linux-PC sitze :S
    3. Fehlermeldungen wären schon hilfreich 🙄
    4. Auch, wenn sich Bibliotheksfunktionen oder die Standard-Konformität von Compilern sich ändern, so bleibt die dahinterstehende Grundlogik die gleiche.
    -> Selber nachdenken und Code anpassen ist also auch nicht verkehrt.

    MfG DrakoXP



  • DrakoXP schrieb:

    also 4 Dinge:

    1. Der Code hier von mir ist 4 Jahre alt.

    Yep.

    DrakoXP schrieb:

    2. Welche "offensichtlichen" Syntaxfehler? 😕
    -> Kann es zwar jetzt gerade nicht mit aktuellem Compiler überprüfen,
    da ich gerade an einem Linux-PC sitze :S

    Ich auch! 😉

    DrakoXP schrieb:

    3. Fehlermeldungen wären schon hilfreich 🙄

    Hier fehlen Klammern:

    pRetVal = reinterpret_cast<wchar_t**>(LocalAlloc(LPTR, (sizeof(wchar_t*) * iNumParts) + (sizeof(wchar_t) + iLength));
    
    if ((wLast == L'\0') && (pCmdLine[i] != L'\0')
    

    DrakoXP schrieb:

    4. Auch, wenn sich Bibliotheksfunktionen oder die Standard-Konformität von Compilern sich ändern, so bleibt die dahinterstehende Grundlogik die gleiche.
    -> Selber nachdenken und Code anpassen ist also auch nicht verkehrt.

    MfG DrakoXP

    Klar. 😉

    Ich habe mich nur gefragt, wie das zu Stande kommt, da Du einen "fertigen" Algorithmus aus der Tasche ziehst, dieser aber offensichtlich nie durch den Compiler ging!? Da stellt sich dann die Frage, macht es Sinn sich überhaupt damit zu beschäftigen, wenn der Autor den Algorithmus selber noch nicht ausprobiert hat!
    Verstehe mich nicht falsch, ich will Dich nicht angreifen, ich finde es toll von Dir, dass Du einen konstruktiven Lösungsvorschlag machst, aber ich möchte auf obiges hinweisen und zur Verbesserung des Sourcecodes motivieren und anderen zukünfigen Lesern die Antworten (von Dir) präsentieren, die meine Fragen aufgeworfen haben.

    Danke!

    sgf42



  • Kompiliert und getestet mit Visual Studio 2010, hier die Neuauflage:

    #include <Windows.h>
    
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <sstream>
    typedef TCHAR tchar;
    typedef std::basic_string<tchar> tstring;
    typedef std::basic_stringstream<tchar> tstringstream;
    typedef std::vector<tstring> arg_vector;
    
    bool filter(char c)
    {
    	return (c == '\"');
    }
    
    arg_vector cmdline_to_argv(tstring const & cmdline)
    {
    	arg_vector args;
    
    	if (cmdline.empty())
    		return args;
    
    	bool together = false;
    	bool only_spaces = true;
    	tstring::size_type laststart = 0;
    
    	for (tstring::size_type n = 0; n < cmdline.length(); ++n)
    	{
    		if (cmdline[n] == '\"')
    		{
    			together = !together;
    		}
    
    		bool space = !!isspace(cmdline[n]);
    
    		if (space && !together)
    		{
    			if (!only_spaces)
    			{
    				tstring arg = cmdline.substr(laststart, n - laststart + 1);
    				arg.resize(std::remove_if(arg.begin(), arg.end(), &filter) - arg.begin());
    				args.push_back(arg);
    			}
    			laststart = n + 1;
    		}
    
    		if (space)
    			only_spaces = true;
    		else
    			only_spaces = false;
    	}
    
    	if (!only_spaces)
    	{
    		tstring arg = cmdline.substr(laststart, cmdline.length() - laststart + 1);
    		arg.resize(std::remove_if(arg.begin(), arg.end(), &filter) - arg.begin());
    		args.push_back(arg);
    	}
    
    	return args;
    }
    
    // muhaha.... new fancy main :p
    int main(arg_vector const & args)
    {
    	tstringstream strm;
    	strm << args.size() << " arguments!\n";
    	for (arg_vector::size_type n = 0; n < args.size(); ++n)
    		strm << "Argument #" << (n + 1) << ": " << args[n] << "\n";
    	MessageBox(NULL, strm.str().c_str(), TEXT("Command Line Test"), MB_OK | MB_ICONINFORMATION);
    	return 0;
    }
    
    int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmdline, int show)
    {
    	return main(cmdline_to_argv(GetCommandLine()));
    }
    


  • Danke...passt aber nicht zum Thema:

    WinMain() to argv[] unter WinCE



  • wie gesagt, der Algorithmus ändert sich hier nicht.
    Wer C bzw. C++ kann, kann sich das selber in eine brauchbare Form umwandeln.



  • In Abwandlung Deines initialen Vorschlags, möchte ich folgende korrigierte Abwandlung anbieten, die mit VS2005 PB compiliert und unter WinCE 6.0 läuft:

    TCHAR** __CommandLineToArgv(const TCHAR* lpCmdLine, int* pNumArgs) {
    	if (!lpCmdLine)
    		return NULL;
    	if (lpCmdLine[0] == TEXT('\0'))
    		return NULL;
    	TCHAR** pRetVal = NULL;
    	bool bTogether = false;
    	int iNumParts = 1;
    	int iLength = _tcslen(lpCmdLine) + sizeof(TEXT('\0'));
    	for (int n = 0; n < iLength; n++) {
    		if (lpCmdLine[n] == TEXT('\"')) {
    			bTogether = !bTogether;
    		}
    		if ((lpCmdLine[n] == TEXT(' ')) && (!bTogether)) {
    			iNumParts++;
    		}
    	}
    	bTogether = false;
    	*pNumArgs = iNumParts;
    	pRetVal = reinterpret_cast<TCHAR**>(LocalAlloc(LPTR, (sizeof(TCHAR*) * iNumParts) + (sizeof(TCHAR) * iLength)));
    	TCHAR* pCmdLine = reinterpret_cast<TCHAR*>(&(pRetVal[iNumParts]));
    	_tcsncpy(pCmdLine, lpCmdLine, iLength);
    	for (int c = 0; c < iLength; c++) {
    		if (pCmdLine[c] == TEXT('\"')) {
    			pCmdLine[c] = TEXT('\0');
    			bTogether = !bTogether;
    		}
    		if ((pCmdLine[c] == TEXT(' ')) && (!bTogether)) {
    			pCmdLine[c] = TEXT('\0');
    		}
    	}
    	TCHAR wLast = TEXT(' ');
    	int iArg = 1;
    	if (pCmdLine[0] == TEXT('\0')) {
    		memmove(&(pCmdLine[0]),&(pCmdLine[1]),iLength - sizeof(pCmdLine[0]));
    	}
    	pRetVal[0] = pCmdLine;
    	for (int i = 0; i < iLength; i++) {
    		if ((wLast == TEXT('\0')) && (pCmdLine[i] != TEXT('\0'))){
    			pRetVal[iArg] = &(pCmdLine[i]);
    			iArg++;
    		}
    		wLast = pCmdLine[i];
    	}
    	return pRetVal;
    }
    

    Gruss sgf42


  • Mod

    Nochmal der Einwurf, weil es scheinbar jeder überliest. Warum sollman solchen Code schreiben, wenn es in der MS-CRT die Variablen __argv und __argc gibt?


Anmelden zum Antworten