Hoi,
Dit is geen vraag, maar een verslag van mijn ervaringen. Misschien bespaart het anderen wat tijd.
Als je een Windows Service wilt schrijven, dan kan dat prima in Delphi, met de .NET library en een geschikt workframe.
Voor tips D7-XE, zie http://stackoverflow.com/questions/5...e-using-delphi
De applicatie die ik wilde maken heeft de volgende taak:
- Op een non-Domain Windows 7 machine PROD verschijnen met regelmaat grote aantallen zeer kleine files, die moeten worden gebackupt
- De service moet dit materiaal naar onze Domain-bedrijfsserver SERVER schrijven en de gebruikte diskruimte op de non-Domain machine beperkt houden
PROTOTYPE FASE 1: Backup met CopyFile naar een share
Deze taak had ik in eerste instantie geschreven in Delphi-7 met behulp van CopyFile.
Dit bleek niet levensvatbaar. Er worden zeer grote hoeveelheden (>30000) kleine files geproduceerd en het gebruik van CopyFile
naar een share bleek zeer traag te worden bij meer dan 8000 files op de share. Een third party zipper was geen optie, die bleek te traag.
PROTOTYPE FASE 2: Eigen protocol, client en server
Na enige vergeefse omzwervingen met zippers (Abbrevia gaf teveel belasting..) had ik besloten om de CopyFile methode los te laten. De tweede versie van mijn programma bestond uit een Delphi-7 client en server en een eigen TCP/IP protocol. De files werden door de serverkant in een NON-share weggeschreven en dat werkte dus wel voor grote aantallen bestanden. Deze setup heeft een tijdje gefunctioneerd, alleen het nadeel was, dat mijn Clientserver zeer kwetsbaar was voor timeouts en netwerkstoringen.. ook kortstondige storingen. Als gevolg hiervan moest ik regelmatig opnieuw opstarten en waren de files aan de kant van de bedrijfsserver soms niet op tijd beschikbaar.
PROTOTYPE FASE 3: .NET met Ionic zipper
Op een bepaald punt is door het management besloten, om deze taak in Visual Studio en .NET te implementeren.
Het opzetten van een backup-programma met .NET zoals in fase 1 verliep gladjes.. maar ook met .NET had ik schalingsproblemen: grote hoeveelheden kleine files gaven slechte performance. Toen is onderzocht, of er een geschikte zipper was in .NET. Het bijbehorende zipper-platform (.NET Ionic) bleek zeer snel en geschikt voor mijn toepassing. Het zou kunnen, dat het native Delphi XE zipper (TZipFile) ook snel genoeg is hiervoor, maar ik heb geen beschikking over een Delphi-XE om dat te testen.
Download link voor Ionic: https://dotnetzip.codeplex.com/releases/view/68268
DEPLOYMENT: .NET, password protectie op de server, Windows service
Om het zaakje gladjes en veilig te laten verlopen, is het belangrijk om een password te hebben op de server-kant share. Dat had ik tot nu toe niet gedaan omdat e.e.a. in ontwikkeling was. De deployment nadert en daarvoor is het óók noodzakelijk, dat de applicatie voor de gebruiker verborgen is, d.w.z. geen icons, het mag niet worden afgesloten en het moet zich herstellen na een boot van de client. Een mogelijkheid hiervoor is, om een executable vanuit registry Windows/run met een tray-icon te gebruiken, maar de "officieele" weg (Windows Service) is netter.
Hier kwamen wat struikelpunten boven water:
1. Mijn service had geen toegang tot de registry.
2. Het lukte om de service te maken en daar de backup-procedure met zipper aan te koppelen. Maar toen ik een password op de share zette.. boem !
Oplossing ad. 1
Na enig googlen kwam ik er achter, dat de Service context gebruik maakt van registry LOCALMACHINE en niet van CURRENTUSER. De oplossing was dus, om mijn registratie in LOCALMACHINE/Software onder te brengen.
Oplossing ad. 2.
Deze was ingewikkelder ! Er is dus een login nodig, vanuit de Service OnStart procedure. Ga je googlen op wnetaddconnection2() en Windows Service.. een oerwoud van onopgeloste problemen. Er circuleren nogal wat oplossingen die niet werken. En broodje-aap verhalen. Een vaak gehoorde bewering is bijvoorbeeld, dat de Service-user te weinig permissies zou hebben voor externe bronnen. Dat is natuurlijk zo voor de Service-user zelf, maar in dit geval wilde ik inloggen met de eigen naam ("peter") en password en het mag niet uitmaken, wie dat doet. Op de server was de share correct ingesteld. Dus: wnetaddconnection2(NT, 'password', 'peter',1)
Zie diagram 1 hieronder. De login verloopt de eerste keer correct, maarrrr.. een service moet je kunnen starten, stoppen en weer opnieuw starten. Nu bleek, dat het uitloggen met de methode in diagram 1 niet werkt binnen een service. De volgende aanroep van wnetaddconnection2() resulteert in een 1312, óók als het uitloggen daarvoor met resultaat 0 terugkwam. De enige oplossing is om de server te rebooten. Waarom dat precies zo werkt.. het moet een fout zijn in de wnetcancelconnection2() uitlog-procedure. Diverse bronnen bevestigen dit bange vermoeden.
De tweede oplossing die ik heb geprobeerd, was het mounten van een network drive. Dat bleek wel te werken vanuit mijn testprogramma. Zie deze link voor aanwijzingen. De aanroep is weer wnetaddconnection2(), maar de voorbereiding van het Net Resource record is anders. Ik heb de aanwijzingen precies opgevolgd in mijn testprogramma. Het werkte prachtig buiten de Services-context en Explorer liet de aangemaakte drive zelfs zien en de drive verdween weer bij uitloggen. Mooi mooi..
Maar helaas.. vanuit de service geeft het maken van een network drive precies dezelfde problemen. Geen logout, dus de volgende keer resulteert de aanroep in een result=1312. De network-drive werd in Explorer ook niet correct weergegeven, wanneer ik hem aanmaakte vanuit de service.
Een network drive disconnect dus wel, maar was geen optie vanuit de Windows Service context..
De oplossing bleek uiteindelijk vrij simpel. Zie diagram 2. Wanneer "peter" een user is op de server, dan werkt het wel !!
Bottom line: wanneer je een backup-service maakt die naar een Domein-server moet copieeren, dan moet op de domein server daarvoor een gebruiker worden aangemaakt. De aanroep is dan wnetaddconnection2(NT, 'password', 'server\peter',1)
Met dank aan Walt op SO, die met deze tip kwam:
http://stackoverflow.com/questions/2...indows-service
Hopelijk heeft men hier iets aan,
Lex
Bookmarks