Lollisoft
Lollis Software Blog - Von der Idee schnell zur Software
Smart Client Software Factory generated with help of my tool and a XSLT template

Smart Client Software Factory generated with help of my tool and a XSLT template

I have evaluated the Smart Client Software Factory patterns & practices for Visual Studio 2008 and decided to begin a template to let it generate a full appliaction using the SCSF libraries. After some days reading, buying books and playing around with the guidance and samples, I started to create my XSLT template helping me to create as much as I can create. After four days of work I was surprised how easy it is to create a template for this library and I was ready to run the generated application.

In the background you will see the wxWrapper application running the prototype of the lbDMF Manager UML model. Using this prototype I created the application in front that actually has a very different layout and usability. (Except the very simple button list for the forms)

The result currently contains a mock for the data (three entries per entity), but it will be straight forward to add more templates to create a database backend entity model (maybe NHibernate or even other stuff). You only need to change the entity classes to be real database entities to any data source.

I think that this shows the full power of the XML and XSLT approach that I have choosen. Even others (and even I) use T4 templates, for sample, it will be generated nearly the same amount of code. I will publish this template in my project some days later. Contact me please if you are interested in participating to template development.

Today (4th Jul 2011) I have made the template publicy available in my CVS repository. Feel free to try it out. It works even with Sharp Develop 4.0.

Simple sample of how to use UML Activity diagrams to generate code

Simple sample of how to use UML Activity diagrams to generate code

Now I have done the rewriting to get a more flexible code generator. In my last post I have listed up some points I may have to do to enable this new feature in my next release.

I’ll shortly describe the activity:

1.) Using send signal action to trigger an existing event handler.

The new feature is possible because I have used the send signal action to trigger an existing event handler that is responsible to create a XML model in memory (into a variable named memorybuffer).

2.) Use another handler to write te buffer to a file.

I am using a file at the end, thus I store the memory buffer into a specific file named ‘lala.xml’. I’ll do the naming in the activity transformation. It is also possible to use the memorybuffer variable directly, but I have choosen to demonstrate using a two step file creation.

3.) Using another signal handler to trigger the actual XSLT transformation.

The XSLT transformation handler is a result of a separate handler I have created because my existing one does all the steps in one code function including asking for the XSLT template. The XSLT template is passed as a parameter in the signal activity step within another special parameter. The file is passed indirectly by using another variable within brackets source = {file}. These indirect usage is also applied in the parameters of step 2.

Conclusion

The sample demonstrates the ability to use predefined small activity steps (event handler spread around in my code). These includes making decisions, showing message boxes, writing a variable to a file, reading from a file into a variable. Short: All my event handlers can be used via the send signal activity step.

I hope that the possibilities are clear and you will find these new features useful.

Ersetzen von Address Angaben in Dateien ist aufwändig. Eigentlich können das auch gute Editoren. Hat man aber gerade keinen zur Hand, hilft auch folgendes Script:

#!/bin/sh

mv $1 $1temp
sed ’s/Von Straße 5/Zu Straße 6/g’ $1temp > $1
mv $1 $1temp
sed ’s/PLZ Ort/12345 Lala/g’ $1temp > $1
rm $1temp
# Script Ende

find . -name “*.cpp” -exec ~/bin/replace-address.sh {} \;

Music for lau, but you can donate

Dezember 31st, 2010

Twitter is a good place where you could randomly get new stuff. Today I got a new tweet that shows up a band doing it in a different way. You can download the music but may donate as you like. I find this a very good direction to, a) directly support the band and not other in between and b) you can decide how much. And I have donated :-)

http://www.severedfifth.com/

I would like to know about more such bands :-)

Hi,

Currently I am developing new activity steps to enable a more flexible code generator. Practically it is a code generator workflow. My old code generator is an activity step and does the stuff at one step. That steps in the code are as follows:

  • 1.) Get the identifier for the current application (by the value given as parameter ’source value’)
  • 2.) Save the current working directory
  • 3.) Get values ‘UMLImportDBName’, ‘UMLImportDBUser’ and ‘UMLImportDBPass’ from the active document (that by the active application). These are modifiable and stored by the properties of the application.
  • 4.) Save the current mode (database / local document file) and switch to database to export actual contents.
  • 5.) Reload the application model from database into the internal object model and set back the original mode.
  • 6.) Retrieve the application identifier from the applications model by it’s application name ’source value’ of the action and store it in a local variable.
  • 7.) Get the value of the XSLT directory where the action has to be performed ‘codegenbasedir’. Do this optionally by direct database read if it is not in the list of application parameters.
  • 8.) Put the identifier as a variable in the active document ‘SaveApplicationID’.
  • 9.) Call a registered event handler by it’s name ‘exportApplicationToXMLBuffer’
  • 10.) Get the result ‘memorybuffer’ that the handler has stored in the input parameter container (not the result container).
  • 11.) Also get the file name the handler has stored ‘filename’.
  • 12.) Change to the working directory the XSLT transformation should perform ‘codegenbasedir’.
  • 13.) Perform the XSLT transformation and save the result to stdout.

The enumeration doesn’t work :-)

You can spot the point of inflexibility as it is clear. The function does too much and expects the XSLT transformation generates files. The activity step cannot be used to cascade several code generators to enable M2M transformations. And extending the existing one is the wrong way, because it will become a monster and keep being not flexible.

It would be much more flexible if I split the steps and use them to model the code generator workflow in an UML Activity diagram. I have demonstrated workflow activities earlier by enabling validation in business forms (more in PDF version chapter ‘Applying business rules’ – sorry for the typo). That is, I enable modeling of validation rules rather than coding them. With a short view about that, it is much more work to ‘code’ in UML Activity diagrams, but at a longer and deeper view it raises the abstraction level and with a M2M transformation it will also ease the modeling.

That is exactly the cause I start writing new activity steps that could be used in an activity or to name it also workflow.

One action of the above steps would be getting the identifier from the current row in the database form. But it is more difficult than you may expect. It is the complexity of the SQL query I rely on. What I need is to get the primary key column out of the current query object that represents the value I match against ’source value’ – and it’s ’source column’. In my actual scope it is the application name to generate code for and it is not declared as an unique column.

A simple solution would be to make that column unique and complain if it is not. That would make the workflow more easy. That solved, I ask my self about the place where I implement the stuff to get that identifier.

So currently I think about extensions of my database classes to ease the modification of a given SQL query. But how to start and what solutions may be the best. When the database query is simple, I may choose simple string splitting to get the columns and then add new columns for sample. But what happens if the given query contains sub queries or joins?

If the given column and value points to a detail table it still may not complain about not unique values. But rather it is a design error of the code generator workflow parameter passing definition (don’t think about wrong templates used yet).

It simply points to a detail value not one of the master values in a join. The transformation may work but also may not work by the given identifier. It is a scope problem and it is not strongly typed.

So if a form contains SQL joins and I use columns from the detail side (I think the right side in the join), then the scope problem arises. Thus I must not only test against uniqueness but also against the fact not using values from the detail side (tables referencing to master side – or the left).

Some of the resulting code – I hope doing it right – will be in database classes, but other stuff may rather be placed in a separate action step to enable designing validation against the intention of the workflow. An action step to retrieve the identifier therefore may not only return the value, but also return some more values, such as what primary key column was used and what table the column is from. Also it may return the primary table if a join or other circumstance results in a multi table query.

So you see it is not easy to write this action step and you also see, it is only the first step :-)

And I cannot expect too much in the scope. What is if one uses a ready made workflow at the wrong place and tries to pass a value he / she configures? I cannot expect an ‘application name’ and try to get the identifier from the application table. It will fail on forms. A good use case to start generating code at the scope of a form would be predesigning the form in a different format – like DialogBlocks. The workflow therefore may create a single form project in DialogBlocks, let the user design while waiting for the application and then reverse the design to gather probably new fields to be optionally added to the database model. That said, you not only change the scope where to start code generation, you also need more flexibility by waiting for an application and using a reverse engineering step to collect new fields and possibly also a new order or complete new design that must use a XML based form in the prototype to directly present the design.

What I can say, you will get plenty of ideas if you can simply do it. Also a code generator model / workflow is language and implementation neutral, thus you could probably design you own tool by supporting a suitable code generator converting the model into real code of your choice.

For any questions, please contact my via Twitter.

wxRibbon on Mac

wxRibbon on Mac

Here is a sample about my work on wxRibbon code on Mac OS X Snow Leopard.

The code actually compiles, but uses the MSW art provider that probably is the cause for the drawing failures.

But at all it looks good for a one day porting work. On Mac I use wxMac 2.8.10 and on Windows I use Open Watcom and wxMSW 2.8.5.

It would be fine, if there are some Mac OS X developers willing to help fixing these issues.

When the window is much bigger, then the visible icons, now showing disapear, thus the window size is that small.

Edit: The missing reference: The wxRibbon project was developed by Peter Cawley: http://www.corsix.org/gsoc/ribbon.html

Hi,

after posting a question, I got an answer to the enum issue. Michal Necasek wrote that enums have different sizes. Open Watcom uses the smaller 8bit and MINGW uses the 32bit size and thus when returning an enum from OW, MINGW gets undefined bits from bit 9 onwards.

His solution is as follows:

enum lbErrCodes {

ERR_NONE = 0,

ERR_FAIL = 1,

ERR_SOWISO = 2,

ERR_LAST = 0×7FFFFFF

};

Or one could use compiler settings to solve this issue.

That helped me to cope with my porting attempt :-)

Hi,

I would like to blog an article about my current work on mixing compilers. I try to add support for MinGW compiler beside my current Open Watcom compiler. While porting my base library, adding some unit tests to check my base functionality, I encountered some trouble with mixing compilers.

I especially have problems when using a DLL loaded at runtime. This is because I load nearly all my DLL’s at runtime. The function in question that fails, only fails if I do not printf something on the screen in that function. That is strange. Also I only couldn’t use Open Watcom DLL’s from MinGW code, but I can on the opposite.

The listed code and makefile should be complete to follow this issue and I hope to get some answers in forums where I write about this blog. If not, the code can be reviewed here: http://lbdmf.cvs.sourceforge.net/viewvc/lbdmf/CPP/Test/Console/testmingw/minimaltest/

To follow the code, I will explain, what code compiles to which DLL or EXE.

testdll.cpp compiles to testdll.dll using MinGW to load the DLL at start time by linking against it.

testdll.cpp compiles to testdllmingw.dll using MinGW to load the DLL at run time.

testdllow.cpp compiles to testdllow.dll using Open Watcom compiler and it is loaded at runtime.

test.cpp compiles to testow.exe using Open Watcom and testmingw.exe using MinGW.

When running these applications I’ll get the following output (as documented in code):

// Q:\develop\Projects\CPP\Test\Console\testmingw\minimaltest>testow

// Hello from test DLL. Text is ‘From text.exe’.

// Instance of Test created.

// Hello from test DLL. Text is ‘From object out of test.exe’.

// Hello from test DLL. Text is ‘p2′.

// Have true.

// Success: ITest->getInt() returns 1

// Test::release() called.

// Instance of Test deleted.

// Test MINGW DLL.

// Loading testdllmingw DLL dynamically from Open Watcom EXE:

// Instance of Test created.

// Success: ITest->getInt() returns 1

// Test if value is not NULL.

// Test if value is not NULL.

// Success: ITest->getInt() returns 1

// Test OW DLL.

// Loading testdllow DLL dynamically from Open Watcom EXE:

// Test instance from OW DLL created via gettestow.

// Test instance from OW DLL created via _gettestow.

// OW Instance of Test created.

// Success: ITest->getInt() returns 1

// Test if value is not NULL.

// Test if value is not NULL.

// Success: ITest->getInt() returns 1

//

// Q:\develop\Projects\CPP\Test\Console\testmingw\minimaltest>testmingw

// Hello from test DLL. Text is ‘From text.exe’.

// Instance of Test created.

// Hello from test DLL. Text is ‘From object out of test.exe’.

// Hello from test DLL. Text is ‘p2′.

// Have true.

// Success: ITest->getInt() returns 1

// Test::release() called.

// Instance of Test deleted.

// Test MINGW DLL.

// Loading testdllmingw DLL dynamically from MINGW32 EXE:

// Instance of Test created.

// Success: ITest->getInt() returns 1

// Test if value is not NULL.

// Test if value is not NULL.

// Success: ITest->getInt() returns 1

// Test OW DLL.

// Loading testdllow DLL dynamically from MINGW32 EXE:

// Test instance from OW DLL created via gettestow.

// Test instance from OW DLL created via _gettestow.

// OW Instance of Test created.

// Error: ITest->getInt() doesn’t return 1

// Test if value is not NULL.

// Test if value is not NULL.

// Success: ITest->getInt() returns 1

Here is the code I am using to test this behaviour:

itest.h:

#define API __stdcall

//#define API __cdecl

enum lbErrCodes {

ERR_NONE = 0,

ERR_FAIL = 1,

ERR_SOWISO = 2

};

class ITest {

public:

virtual lbErrCodes API getInt(char* _int, bool showmsg) = 0;

virtual bool API getbool() = 0;

virtual void API test(char* text, char* p2) = 0;

virtual void API release() = 0;

};

owtestdll.h:

#undef DLLEXPORT

#ifdef OWDLL

#define DLLEXPORT __declspec(dllexport)

#endif

#ifndef OWDLL

#define DLLEXPORT __declspec(dllimport)

#endif

#ifdef __WATCOMC__

extern “C” DLLEXPORT ITest* API gettestow();

#endif

#ifdef __MINGW32__

extern “C” DLLEXPORT ITest* API _gettestow();

extern “C” DLLEXPORT ITest* API gettestow();

#endif

testdll.h:


#undef DLLEXPORT

#ifdef DLL

#define DLLEXPORT __declspec(dllexport)

#endif

#ifndef DLL

#define DLLEXPORT __declspec(dllimport)

#endif

#ifdef __WATCOMC__

extern “C” void DLLEXPORT API test(char* text);

#endif

#ifdef __MINGW32__

extern “C” void DLLEXPORT API _test(char* text);

extern “C” void DLLEXPORT API test(char* text);

#endif

#ifdef __WATCOMC__

extern “C” bool DLLEXPORT API getbool();

#endif

#ifdef __MINGW32__

extern “C” bool DLLEXPORT API _getbool();

extern “C” bool DLLEXPORT API getbool();

#endif

#ifdef __WATCOMC__

extern “C” DLLEXPORT ITest* API gettest();

#endif

#ifdef __MINGW32__

extern “C” DLLEXPORT ITest* API _gettest();

extern “C” DLLEXPORT ITest* API gettest();

#endif

testdll.cpp:

#define DLL

#include “itest.h”

#include “testdll.h”

#include <stdio.h>

class Test : public ITest {

public:

lbErrCodes API getInt(char* _int, bool showmsg);

bool API getbool();

void API test(char* text, char* p2);

void API release();

public:

Test();

virtual ~Test();

};

extern “C” DLLEXPORT ITest* API gettest() {

return _gettest();

}

extern “C” DLLEXPORT ITest* API _gettest() {

return new Test();

}

void test_impl(char* text) {

printf(“Hello from test DLL. Text is ‘%s’.\n”, text);

}

Test::Test() {

printf(“Instance of Test created.\n”);

}

Test::~Test() {

printf(“Instance of Test deleted.\n”);

}

bool API Test::getbool() {

return true;

}

lbErrCodes API Test::getInt(char* _int, bool showmsg) {

if (showmsg) printf(“Test if value is not NULL.\n”);

if (_int == NULL) return ERR_FAIL;

return ERR_NONE;

}

void API Test::test(char* text, char* p2) {

test_impl(text);

test_impl(p2);

}

void API Test::release() {

printf(“Test::release() called.\n”);

delete this;

}

DLLEXPORT void API _test(char* text) {

test_impl(text);

}

DLLEXPORT bool API _getbool() {

return true;

}

DLLEXPORT void API test(char* text) {

test_impl(text);

}

DLLEXPORT bool API getbool() {

return _getbool();

}

testdllow.cpp:

#define OWDLL

#include “itest.h”

#include “owtestdll.h”

#include <stdio.h>

class Test : public ITest {

public:

lbErrCodes API getInt(char* _int, bool showmsg);

bool API getbool();

void API test(char* text, char* p2);

void API release();

public:

Test();

virtual ~Test();

};

extern “C” DLLEXPORT ITest* API _gettestow() {

printf(“Test instance from OW DLL created via _gettestow.\n”);

return new Test();

}

extern “C” DLLEXPORT ITest* API gettestow() {

printf(“Test instance from OW DLL created via gettestow.\n”);

return _gettestow();

}

void test_impl(char* text) {

printf(“Hello from test DLL. Text is ‘%s’.\n”, text);

}

Test::Test() {

printf(“OW Instance of Test created.\n”);

}

Test::~Test() {

printf(“OW Instance of Test deleted.\n”);

}

bool API Test::getbool() {

return true;

}

lbErrCodes API Test::getInt(char* _int, bool showmsg) {

if (showmsg) printf(“Test if value is not NULL.\n”);

if (_int == NULL) return ERR_FAIL;

return ERR_NONE;

}

void API Test::test(char* text, char* p2) {

test_impl(text);

test_impl(p2);

}

void API Test::release() {

printf(“OW Test::release() called.\n”);

delete this;

}

test.cpp:

#include “itest.h”

#include “testdll.h”

#include “owtestdll.h”

#include <stdio.h>

#include <windows.h>

typedef ITest* (API *Functor)();

Functor getFunctor(char* name, char* dll) {

HINSTANCE hinst;

Functor functor;

hinst = LoadLibrary(dll);

if (hinst != NULL) {

functor = (Functor) GetProcAddress(hinst, name);

if (functor != NULL) {

return functor;

} else {

return NULL;

}

}

printf(“Error: Couln’t find DLL.\n”);

return NULL;

}

void testDynamicLoading(char* dll) {

Functor functor;

functor = getFunctor(“gettestow”, dll);

if (functor == NULL) {

functor = getFunctor(“_gettestow”, dll);

}

if (functor == NULL) {

functor = getFunctor(“gettestow@0″, dll);

}

if (functor == NULL) {

functor = getFunctor(“_gettestow@0″, dll);

}

if (functor == NULL) {

functor = getFunctor(“gettest”, dll);

}

if (functor == NULL) {

functor = getFunctor(“_gettest”, dll);

}

if (functor == NULL) {

functor = getFunctor(“gettest@0″, dll);

}

if (functor == NULL) {

functor = getFunctor(“_gettest@0″, dll);

}

if (functor != NULL) {

// Test loading Open Watcom DLL from application dynamically

#ifdef __MINGW32__

printf(“Loading %s DLL dynamically from MINGW32 EXE:\n”, dll);

#endif

#ifdef __WATCOMC__

printf(“Loading %s DLL dynamically from Open Watcom EXE:\n”, dll);

#endif

ITest* d = functor();

if (d == NULL) {

printf(“Couldn’t load object.\n”);

return;

}

if (d->getInt(NULL, false) != ERR_FAIL) printf(“Error: ITest->getInt() doesn’t return %d\n”, ERR_FAIL);

if (d->getInt(NULL, false) == ERR_FAIL) printf(“Success: ITest->getInt() returns %d\n”, ERR_FAIL);

if (d->getInt(NULL, true) != ERR_FAIL) printf(“Error: ITest->getInt() doesn’t return %d\n”, ERR_FAIL);

if (d->getInt(NULL, true) == ERR_FAIL) printf(“Success: ITest->getInt() returns %d\n”, ERR_FAIL);

} else {

printf(“Error: Couln’t find functor.\n”);

}

}

int main() {

test(“From text.exe”);

ITest* t = gettest();

t->test(“From object out of test.exe”, “p2″);

if (getbool()) printf(“Have true.\n”);

if (t->getInt(NULL, false) != ERR_FAIL) printf(“Error: ITest->getInt() doesn’t return %d\n”, ERR_FAIL);

if (t->getInt(NULL, false) == ERR_FAIL) printf(“Success: ITest->getInt() returns %d\n”, ERR_FAIL);

t->release();

printf(“Test MINGW DLL.\n”);

testDynamicLoading(“testdllmingw”);

printf(“Test OW DLL.\n”);

testDynamicLoading(“testdllow”);

return 0;

}

all: testdllow.dll testdll.dll testdllmingw.dll testow.exe testmingw.exe
CALL=-5r
testdll.o: testdll.cpp testdll.h
g++ -c testdll.cpp
test.obj: test.cpp testdll.h
wpp386 -DWINDOWS -w3 -e25 -zq -otexan $(CALL) -of+ -xr /DLBDMF_PRE test.cpp
testdllmingw.o: testdll.cpp testdll.h
g++ -c testdll.cpp -o testdllmingw.o
testdllmingw.dll: testdllmingw.o
g++ -shared -o testdllmingw.dll testdllmingw.o
wlib -q -n -b testdllmingw.lib +testdllmingw.dll
wlib -m testdllmingw.dll > exportsmingw.txt
testdllow.obj: testdllow.cpp testdll.h
wpp386 -DWINDOWS -bd -hd -w3 -e25 -zq -otexan $(CALL) -of+ -xr /DLBDMF_PRE testdllow.cpp
testdllow.dll.lnk: makefile testdllow.obj
echo NAME testdllow.dll > $@
echo FIL testdllow.obj >> $@
testdllow.dll: testdllow.obj testdllow.dll.lnk
@echo Link testdllow.dll
wlink op q op symf d dwarf SYS nt_dll op m op maxe=25 @testdllow.dll.lnk
@wlib -q -n -b testdllow.lib +testdllow.dll
test.o: test.cpp testdll.h
g++ -c test.cpp
testdll.dll: testdll.o
g++ -shared -o testdll.dll testdll.o
wlib -q -n -b testdll.lib +testdll.dll
wlib -m testdll.dll > exports.txt
testow.exe: test.obj
echo Link testow.exe
echo NAME testow.exe > test.lnk
echo FIL test.obj,testdll.lib >> test.lnk
cmd /C “attrib -r *.bak”
wlink op q op symf d dwarf   @test.lnk
testmingw.exe: test.o
rm testdll.lib
g++ -o testmingw.exe test.o -L. -ltestdll
clean:
-del *.err *.exe *.obj *.o *.dll *.bak *.sym *.lnk *.map *.lib exports.txt exportsmingw.txt
-rm *.err *.exe *.obj *.o *.dll *.bak *.sym *.lnk *.map *.lib exports.txt exportsmingw.txt

makefile:

all: testdllow.dll testdll.dll testdllmingw.dll testow.exe testmingw.exe
CALL=-5r
testdll.o: testdll.cpp testdll.h
g++ -c testdll.cpp
test.obj: test.cpp testdll.h
wpp386 -DWINDOWS -w3 -e25 -zq -otexan $(CALL) -of+ -xr /DLBDMF_PRE test.cpp
testdllmingw.o: testdll.cpp testdll.h
g++ -c testdll.cpp -o testdllmingw.o
testdllmingw.dll: testdllmingw.o
g++ -shared -o testdllmingw.dll testdllmingw.o
wlib -q -n -b testdllmingw.lib +testdllmingw.dll
wlib -m testdllmingw.dll > exportsmingw.txt
testdllow.obj: testdllow.cpp testdll.h
wpp386 -DWINDOWS -bd -hd -w3 -e25 -zq -otexan $(CALL) -of+ -xr /DLBDMF_PRE testdllow.cpp
testdllow.dll.lnk: makefile testdllow.obj
echo NAME testdllow.dll > $@
echo FIL testdllow.obj >> $@
testdllow.dll: testdllow.obj testdllow.dll.lnk
@echo Link testdllow.dll
wlink op q op symf d dwarf SYS nt_dll op m op maxe=25 @testdllow.dll.lnk
@wlib -q -n -b testdllow.lib +testdllow.dll
test.o: test.cpp testdll.h
g++ -c test.cpp
testdll.dll: testdll.o
g++ -shared -o testdll.dll testdll.o
wlib -q -n -b testdll.lib +testdll.dll
wlib -m testdll.dll > exports.txt
testow.exe: test.obj
echo Link testow.exe
echo NAME testow.exe > test.lnk
echo FIL test.obj,testdll.lib >> test.lnk
cmd /C “attrib -r *.bak”
wlink op q op symf d dwarf @test.lnk
testmingw.exe: test.o
rm testdll.lib
g++ -o testmingw.exe test.o -L. -ltestdll
clean:
-del *.err *.exe *.obj *.o *.dll *.bak *.sym *.lnk *.map *.lib exports.txt exportsmingw.txt
-rm *.err *.exe *.obj *.o *.dll *.bak *.sym *.lnk *.map *.lib exports.txt exportsmingw.txt

So,

ich habe nun festgestellt, dass offensichtlich am Anfang nicht alle Verzeichnisse angelegt werden. Worauf im weiteren Verlauf Folgefehler entstehen.

Betroffen ist bei mir die Version 0.16.6-1.29. Installiert ist das Ganze auf einem openSuSE 11.1.

Nun werde ich mal einen Bugreport erstellen, da es offensichtlich die aktuellste Version ist…

Ich versuche gerade, meine Webseite mit dem Tool sitecopy vom öffentlichen Server auf meinen Linux Server zu holen. Dabei stelle ich fest, dass es Probleme oder Fehlermeldungen gibt, die teilweise nicht begründet sind.

Nicht begründet sind Fehler, die durch eine leere Datei entstehen – denn die Datei wird geholt. Ein anderer Fehler hat offensichtlich damit zu tun, dass eine Datei mit einem Unterstrich beginnt. Diese kommen nicht an.

Nun stellt sich die Frage, ob das später zu Problemen führt, wenn ich die Seite synchronisiere. Also erstmal ein Backup der Site mit einem FTP tool machen und schauen, ob auch alle Dateien da sind…

Proudly powered by WordPress. Theme developed with WordPress Theme Generator.
Copyright © Lollis Software Blog. All rights reserved.