Avatar billede thomas-k Nybegynder
14. marts 2008 - 23:31 Der 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
Avatar billede winners79 Nybegynder
14. marts 2008 - 23:39 #1
Og hvad vil du gerne vide?
Avatar billede thomas-k Nybegynder
14. marts 2008 - 23:43 #2
Ja, spørgsmålet omhandler hvorledes jeg kan lave en service der kan udføre ovenstående.
Avatar billede kalp Novice
15. marts 2008 - 00:10 #3
det nemmeste er, at angive de der instillinger i app.config for din service.

og desuden så er der ikke meget, at sige om en service.. du kan jo vælge, at lave sådan et projekt i Visual Studio, så har du allerede skelletet klar.

Resten af den kode du snakker om med kopering af filer osv.
det er almindelig c# kode som man så må gå ud fra du selv kan finde ud af.

men en windows service i sig selv er der ingen ben i.
Avatar billede thomas-k Nybegynder
15. marts 2008 - 00:22 #4
Yes, det jeg klar over. Men er lidt i tvivl omkring brug af fx ini fil samt indførelse af data i DB.
Avatar billede kalp Novice
15. marts 2008 - 00:24 #5
har du aldrig overført data til en database før?

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.
Avatar billede thomas-k Nybegynder
15. marts 2008 - 00:32 #6
Fordi jeg vil have det dynamisk. Grunden til at jeg stiller spørgsmålstegn omkring DB, er fordi jeg skal have det til at spille sammen med INI filen.
Avatar billede kalp Novice
15. marts 2008 - 00:36 #7
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.

det er dynamisk
Avatar billede thomas-k Nybegynder
15. marts 2008 - 00:38 #8
Ahh, ok. Nej, det vidste jeg ikke - så det jo brugbart.
Avatar billede kalp Novice
15. marts 2008 - 00:43 #9
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#.
Avatar billede thomas-k Nybegynder
15. marts 2008 - 00:55 #10
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.
Avatar billede kalp Novice
15. marts 2008 - 01:03 #11
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;)
Avatar billede nielle Nybegynder
15. marts 2008 - 08:42 #12
Bare et par indskudte kommentarer:

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:

http://www.eksperten.dk/artikler/1166
Avatar billede thomas-k Nybegynder
16. marts 2008 - 00:23 #13
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.
Avatar billede kalp Novice
16. marts 2008 - 00:35 #14
Du skal bare smide din kode ind i en metode... oprette et Timer objekt, som kalder metoden efter et givent tidsinterval (som du selv skrev du ville)

på den måde vil processen bliver gentaget;)
Avatar billede thomas-k Nybegynder
16. marts 2008 - 02:06 #15
Super, det virker. Nu skal jeg bare have lavet timestamp på filnavn og lavet de omtalte dynamiske med en såkaldt .config-fil ;-)
Avatar billede nielle Nybegynder
16. marts 2008 - 06:52 #16
Du kan ogsåe prøve at tage et kig på FiseSystemWatcher klassen.
Avatar billede kalp Novice
16. marts 2008 - 11:18 #17
thomas-k >>

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.

og hvordan du benytter den kan du finde mange eksempler af på Google, men ellers se her.
http://www.codeguru.com/columns/DotNet/article.php/c7987/
Avatar billede thomas-k Nybegynder
16. marts 2008 - 15:14 #18
Kalp >>

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.

Takker for oplysningen omkring config filen.
Avatar billede thomas-k Nybegynder
16. marts 2008 - 16:42 #19
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";

            string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
            string destFile = System.IO.Path.Combine(targetPath, fileName);
         
            if (!System.IO.Directory.Exists(targetPath))
            {
                System.IO.Directory.CreateDirectory(targetPath);
            }

           
            string[] files = System.IO.Directory.GetFiles(sourcePath, "*.txt");

            SqlConnection con = new SqlConnection("server=DNSnavn;Integrated Security=SSPI;database=DBnavn");
            con.Open();

            foreach (string s in files)
            {

                fileName = System.IO.Path.GetFileName(s);

                destFile = System.IO.Path.Combine(targetPath, fileName);

                if (!System.IO.File.Exists(destFile))
                {
                    System.IO.File.Move(s, destFile);

                    SqlCommand sel = new SqlCommand("INSERT INTO data (filnavn, dato) values ('" + fileName + "', getDate())", con);
                    sel.ExecuteNonQuery();

                }
            }

            con.Close();
        }
Avatar billede kalp Novice
16. marts 2008 - 17:18 #20
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.

På den måde kan du se forskel.
Avatar billede thomas-k Nybegynder
20. marts 2008 - 14:59 #21
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);        }
        }

        public static void DisplayTimeEvent( object source, ElapsedEventArgs e )
        {
            string fileName = "test.txt";
            string fileNames = "test.txt";
            string sourcePath = ConfigurationSettings.AppSettings["kildesti"];
            string targetPath = ConfigurationSettings.AppSettings["destinationsti"];
         

            string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
            string destFile = System.IO.Path.Combine(targetPath, fileName);
            string destFiles = System.IO.Path.Combine(targetPath, fileName);

           
            if (!System.IO.Directory.Exists(targetPath))
            {
                System.IO.Directory.CreateDirectory(targetPath);
            }


            string[] files = System.IO.Directory.GetFiles(sourcePath, "*.txt");

            string forbindelse = ConfigurationSettings.AppSettings["forbind"];

            SqlConnection con = new SqlConnection(forbindelse);

            con.Open();

            foreach (string s in files)
            {

                fileName = System.IO.Path.GetFileName(s);

                destFile = System.IO.Path.Combine(targetPath, fileName);

                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);        }
        }
    }
}


----------
config
----------
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="forbind" value="server=servernavn;Integrated Security=SSPI;database=DB" />
    <add key="kildesti" value="C:\\test\\fra" />
    <add key="destinationsti" value="C:\\test\\til" />
    <add key="tid" value="2000" />
  </appSettings>
</configuration>
Avatar billede kalp Novice
20. marts 2008 - 15:05 #22
det er meget nemmere hvis du kunne sige noget andet end "fejl".. f.eks hvilke fejl og hvilke linjer. Tak.

men start med at flytte din timer op globalt - det vil hjælpe

System.Timers.Timer myTimer = new System.Timers.Timer();
public Service1()
        {
        ....
Avatar billede thomas-k Nybegynder
20. marts 2008 - 15:07 #23
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.
Avatar billede thomas-k Nybegynder
20. marts 2008 - 15:15 #24
Ja, ok. Fandt endnu en } for meget ved protected override void OnStop(). Jeg vender tilbage med mere detaljeret fejl meddelelse...
Avatar billede thomas-k Nybegynder
20. marts 2008 - 15:21 #25
Ok, jeg fik udbedret de fleste fejl, men står tilbage med en. Den siger:

The class name '?' is not a valid identifier for this language.

hmmm, kryptisk?
Avatar billede kalp Novice
20. marts 2008 - 15:24 #26
jeg tror du har været ivrig med din copy & paste.. istedet for, at tage den kode der skal bruges stille og roligt fra det ene projekt til det andet:)

f.eks den her
InitializeComponent();

er det ikke til en GUI komponenter? hvis ja hvad laver den så i din windows service?
Avatar billede thomas-k Nybegynder
20. marts 2008 - 15:26 #27
Jo, jeg tænkte det samme som dig, men når man laver en Windows service, står den der som standard?
Avatar billede kalp Novice
20. marts 2008 - 15:38 #28
så skal den forblive der.. jeg har ikke rodet med dem længe så derfor spørger jeg.
jeg kan ikke se koden til den;)

føres du ikke til et sted i koden når du trykker på den sidste fejl?
Avatar billede thomas-k Nybegynder
20. marts 2008 - 16:21 #29
Nej, for det som om den ikke ved hvor det er. Der står bare linje 0?
Avatar billede kalp Novice
20. marts 2008 - 16:27 #30
lav den forfra..
det er nemmest..
og flyt din over uden at haste for så virker det også
Avatar billede thomas-k Nybegynder
21. marts 2008 - 16:20 #31
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...
Avatar billede kalp Novice
21. marts 2008 - 16:53 #32
selv tak;)
Avatar billede nielle Nybegynder
21. marts 2008 - 20:34 #33
Min hjælp her er vist begrænset. Så jeg står over, men ellers tak for tilbudet. :^)
Avatar billede thomas-k Nybegynder
21. marts 2008 - 21:40 #34
Oki, det er bare i orden.
Avatar billede nielle Nybegynder
22. marts 2008 - 09:48 #35
Håber at du kunne bruge min artikel?
Avatar billede thomas-k Nybegynder
22. marts 2008 - 13:34 #36
Jeg må indrømme at jeg brugte en Microsoft til det, men jeg har skimmet den i gennem. Regner med at anvende den omkring meddelelser i logfilen.
Avatar billede nielle Nybegynder
22. marts 2008 - 19:57 #37
Ok :^)
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester