14. marts 2008 - 23:31Der er
36 kommentarer og 1 løsning
Windows service der kopiere filer og opretter rækker i MSSQL
Jeg har ikke før lavet en service, og søger derfor lidt assistance til at komme godt på vej, uden at skulle bruge oceaner af tid på det. Jeg vil gerne have lavet en Windows service som skal kunne følgende:
Kigge i en mappe efter filer med et forud diffineret interval - finder den nogle filer af formatet .DOC skal den flytte den/disse ind i en anden mappe. Samtidig skal der oprettes en række i en MSSQL DB, hvor filnavn og dato indsættes. Parametre skal fx komme fra en INI eller REG fil.
I denne INI/REG fil skal man så kunne angive:
1. Hvilken mappe sti der skal overvåges. 2. Interval i sekunder hvor tit denne mappe skal overvåges. 3. Hvilken mappe sti den skal flytte filen hen i. 4. En MSSQL connection streng som denne: Provider=SQLOLEDB.1;Password=secret;Persist Security Info=True;User ID=notsecret;Initial Catalog=Databasenavn;Data Source=IP/DNSnavn
og jeg kan slet ikke se hvorfor du skal bruge en INI eller REG fil når en windows service kommer med sin egen app.config fil hvor man kan gemme sådan nogle værdier i.
ved du hvad en app.config fil er? det er en fil hvor du opbevare indstillinger for det du udvikler. det vil sige hvis du vil ændre på din connectionstring, så åbner du bare app.config filen og laver din rettelser - genstarter din windows service og så slår indstillingerne igennem.
ja og det smarte er, at når man installere servicen (hvis du laver en installer) så følger app.config filen automatisk med.
window servicen er i sig selv meget simpel..
du starter din kode i metoden "Start" og sørger for, at den ikke dør ud ved f.eks at benytte en timer, som efter et given interval kalder en metode (lyder lidt som det du har tænkt dig alligevel).
det er sådan set det vigtigste for, at din service kan holde sig i live.. resten er ren c#.
Ja, men kan godt se at det ikke er lige til (for mig). Som jeg ser det, skal jeg lave skelet af service, lave en loop med tidsinterval som kigger i en mappe. Findes der filer af bestemt format, skal de flyttes til anden folder, evt. med timestamp i filnavn og oprette en tråd i DB med filnavn. Men jeg er ikke så bekendt med C# at jeg bare kan sætte mig og kode med det samme. Men nu det jo snart påskeferie ;-) - men små kodestumper tager jeg imod med kyshånd.
Windows Service skelletet laver Visual Studio for dig.. du skal som sagt blot vælge, at oprette sådan et projekt.
men som udgangspunkt så glem alt om den windows service. får det til, at spille uden først så er det ingenting at flytte koden over i en windows service;)
Først brugte man .ini-filer, så gik man over til at bruge registraturet, men fra og med .NET foretrækkes det at man bruger .config-filer. En .config-fil er simplethen en xml-fil og har den fordel over .ini at man har betydelig større muligheder mht. det man ønsker at konfigurere. Man kan rette i dem med VS eller man kan såmæn gøre det med notepad hvis man vil.
Jeg er enig i at du skal holde det så simpelt som du kan. Til at starte med er der ikke nogen grund til at tænke i Windows services. Lav først et program som kan gøre de ting du ønsker at få gjort. Når at du så har fuld styr på dette, så kan du begynde at flytte det over i en service.
Visual Studio hjælper meget med det sidste, men derfor er det nu ikke helt nemt alligevel. Der er ting man skal vide og faldgrupper man bør undgå. Når du engang er parat til at tage fat på den del af opgaven kan du jo f.eks. tage et kig på min artikel om emnet her på Eksperten:
Ja, indtil videre holder jeg mig lige til statiske værdier kan jeg se. Jeg har nu fået lavet et program, hvor den flytter alle .txt filer fra en mappe til en anden, og smider filnavn og dato i DB. Så langt så godt.
Men kan se sætte en slags timer på en foreach sætning? For sådan som det er nu, stopper den jo efter den har flyttet alle nuværende txt filer og stopper så derefter.
hvad mener du med, at lave timestamp? er det dato'en for hvornår du kopire filen? Alt info omkring en fil kan du få ud via. File eller FileInfo klassen (mener jeg der er en der hedder).
med hensyn til config filen skal du tilføje en fil "Application Configuration File" til dit projekt.
Ja, jeg ville gerne have dato og tid med i filnavnet når de flyttes, så de på den vis bliver unikke. Men jeg har store problemer med det, da jeg PT kun kan få ændret det i SQL sætningen når jeg flytter filerne. Men jeg må lege lidt med det.
Nu har jeg kæmpet for at få dato/tid med i filnavn, men må opgive. Jeg har prøvet utallige ting, uden held. Problemet opstår fordi jeg hele tiden har den fulde sti med i filnavn, så resultatet bliver dato-sti-filnavn, hvilket jo ikke godtages. Er der ikke en der kan hjælpe med mit gebrokken C# sprog, så jeg kan få delt sti/filnavn fra hinanden og få lov til at indføre dato i filnavn? Her er min kode:
public static void DisplayTimeEvent( object source, ElapsedEventArgs e ) {
DateTime Tid = new DateTime(); string fileName = "test.txt"; string sourcePath = @"C:\test\fra"; string targetPath = @"C:\test\til";
ja, men hvorfor kigger du ikke på den klasse jeg har nævnt til dig? FileInfo.
Du kan se hvornår en fil er oprettet hvis du bruger FileInfo klassen.. Den har propertien "CreationTime". eller "LastAccessTime"
men du skal vel bare bruge CreationTime.. for CreationTime fra den fil du kopire er ikke den samme, som det den vil være når du har kopiret den over i din nye mappe.
Nå, nu fandt jeg ud af det med et timestamp samt configuration file, og dette virker perfekt efter hensigten som almindeligt program. Jeg ville så overføre koden til en Windows service, men her opstår en masse fejl som jeg ikke forstår. Nogle der kan give mig nogle hints. Herunder kan man se min Service1.cs samt App.config, som er det eneste jeg har overført (ved ikke om dette er nok)?
using System; using System.Timers; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; using System.Configuration;
namespace Scanservice { public partial class Service1 : ServiceBase { public Service1() { InitializeComponent(); string interval = ConfigurationSettings.AppSettings["tid"]; System.Timers.Timer myTimer = new System.Timers.Timer(); myTimer.Elapsed += new ElapsedEventHandler( DisplayTimeEvent ); interval = myTimer.Interval.ToString(interval); }
protected override void OnStart(string[] args) {
myTimer.Start(); EventLog.WriteEntry(eventLogSourceName, "Scanservicen er blevet startet.", EventLogEntryType.Information); } }
DateTime tid = DateTime.Now; String tiden; tiden = tid.ToString("ddMMyyyy-HH.mm.ss.fff-");
destFiles = System.IO.Path.Combine(targetPath, tiden + fileName);
if (!System.IO.File.Exists(destFile)) { System.IO.File.Move(s, destFile);
System.IO.File.Move(destFile, destFiles);
fileNames = tiden + fileName;
SqlCommand sel = new SqlCommand("INSERT INTO data (filnavn, dato) values ('" + fileNames + "', getDate())", con); sel.ExecuteNonQuery(); } } con.Close();
protected override void OnStop() { // TODO: Add code here to perform any tear-down necessary to stop your service. myTimer.Stop(); EventLog.WriteEntry(eventLogSourceName, "Scanservicen er blevet stoppet.", EventLogEntryType.Information); } } } }
Efter jeg indsatte denne tråd, fandt jeg en stor fejl. Der var sneget sig en } for meget ind ved protected override void OnStart(string[] args)...Nu har jeg i stedet kun 1 fejl.
Så virker det hele sq... Da jeg startede Visuel Studio op i dag, var fejlen væk :-) Efter lidt besvær fik jeg lavet en installer til den, og det spiller bare. Jeg vil sige tusind tak til kalp og nielle for hjælpen til en nybegynder med elendig tålmodighed ;-) Smider i lige svar...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.