How do I create a windows service as an exe file using C ?

I want to run a windows service which will notify me of any changes to a folder/file in the shared drive at my office. But mind you we don't have administrator privileges on our computers. Is there a way to write a program in C and create an exe file which will run on my office computer? Any help/suggestions would be welcome... Thanks

«13

Comments

  • as far as i see, you only need a program that you can start / stop with a filesystem watcher, or by "continuously" polling a file and check its date time stamp (with at least an interval of a second between checks, depending on how was you want to be notified).

    The question is, do you want to write it with C/C++, or are you fine with an easier language like C#, Vb.net?

    What do you mean, run like a service? You couldn't install it as a service, as you mentioned, you do not have administrator rights? Is it enough for you that the file notifications are only given to you when you are logged in on your computer? if it helps, most files contain a history which user updated it last

  • jcprogrammerjcprogrammer dubai
    edited August 2014

    @Icepickle said:
    as far as i see, you only need a program that you can start / stop with a filesystem watcher, or by "continuously" polling a file and check its date time stamp (with at least an interval of a second between checks, depending on how was you want to be notified).

    The question is, do you want to write it with C/C++, or are you fine with an easier language like C#, Vb.net?

    What do you mean, run like a service? You couldn't install it as a service, as you mentioned, you do not have administrator rights? Is it enough for you that the file notifications are only given to you when you are logged in on your computer? if it helps, most files contain a history which user updated it last

    Thanks. Actually I have just started learning C. I have no idea of C# or VB.net, though I am very good with vba for excel. I also don't have much knowledge on windows services either but I had come across this term online and thought that this was the only way to create a program which will reside in memory once my computer starts and update me of any changes in the shared folder. I am open to any new and simpler ideas which you can share as well.

    My basic requirement is a program which will run when I login to my office computer and notify me of any changes that happen to that particular folder while I am logged in. But my IT dept should not be aware that I am running such a program, that's why I wanted a simple c program written as an exe as exe's are portable.

  • You could use vbscript files, these are not executables, are used in most networked environments, and can safely do what you ask them to do :)

    if you save this script as Monitor.vbs and you double click it, it will check a folder each 5 seconds to see if a file was added/removed, or updated since last time it checked the folder

    It will run continuously until you decide to kill the process (it runs under WScript.exe inside of the taskmanager, with your user priviliges). Upon directory changed it will show a messagebox in front of your other programs. You can change the folder it watches, by changing the watchFolder argument

    You should recognise some vba in here ;)

    To start it manually, you could add it to your startup programs, by coping it into:

    C:\Users[UserName]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

    replacing [UserName] by your username

    Dim watchFolder
    watchFolder = "C:\Dev"
    
    Function DirectoryChanged(directory, byref lastDateStamp, byref lastCount)
        Dim result
        Dim fso, folder, files, len, dStamp, objFile
        result = false
    
        dStamp = lastDateStamp
    
        set fso = CreateObject("Scripting.FileSystemObject")
        set folder = fso.GetFolder(directory)
        set files = folder.Files
        len = 0
        For Each objFile in folder.Files
            if objFile.DateLastModified > dStamp then
                dStamp = objFile.DateLastModified
                if lastCount <> 0 then
                    result = true
                end if
            end if
            len = len + 1
        next
    
        if (lastCount <> len) then
            if (lastCount > 0) then
                result = true
            end if
            lastCount = len
        end if
    
        lastDateStamp = dStamp
    
        DirectoryChanged = result
        Exit Function
        error_occured:
        DirectoryChanged = false
    End Function
    
    Dim curDate, curCount
    curDate = Now()
    curCount = 0
    
    
    while true
        if DirectoryChanged(watchFolder, curDDate, curCount) = true then
            MsgBox "'" & watchFolder & "' changed!", vbSystemModal, "Change detected in folder"
        end if
        WScript.Sleep(5000)
    wend
    

    @tienkhoanguyen: how about staying on topic? You sound slightly cuckoo

  • @icepickle wow! thank you so much! I know vba as I use it to code excel files so I could understand the logic behind this code. Thank you so much again. So now I am thinking of giving up learning C and learn more about vb scripting. Could you recommend a good book to learn it? Also what I want to know is, is VB portable to Linux? I am also trying to learn system programming for Linux hence took up C... Thanks

  • @icepickle this code is great but when I tested it doesn't give alerts instantly. I created a folder on my desktop and when I added another folder inside it, it didn't give me any alert but I got 2 alerts when I deleted a folder. So it looks like it alerts you only when a file or folder is deleted. Also how do I modify the code to display the modified, created or deleted file/folder? Thanks

  • @jcprogrammer‌ i only went for changes in one folder, and it only checks if something happened to the files. It doesn't actually check the folders. To check the subfolders, you would have to iterate the subfolders, by reusing the same command to scan any folders that are deeper. Mind you this could be some work, depending on how complex the directory structure is

    without much changes, you should be able to find out which was the added/changed file. If you also iterate the Folders in the current folder, you should be able to follow the same algorithm i gave you to find out if there are differences.

    To know which file was deleted will be a bit more difficult, since its gone, you would have to keep a cache, and then again, depending on how complex the folder structure is, this could take some doing, it is possible though, and yes, possible in VBS

    VB is not portable to linux, don't even try it :) Sure, there used to be a project like Gambas, but bash shell scripting is more powerfull to me, than a vbscript

  • @Icepickle‌ just one quick question, why are we iterating through all the files in the folder? if there are changes to any of the files or sub folders wouldn't this change the DateLastModified of the main folder? So why can't I just use the code to check the DateLastModified of the folder rather than looping through all the files in it?

  • IcepickleIcepickle Germany
    edited August 2014

    Sadly enough, no, DateLastModified points to the actual node in the filesystem, it doesn't keep track of files that were changed inside the folder, so you have to:

    • count all the file/folder nodes inside a folder
    • compare every datemodified with the last time you checked it
  • @Icepickle said:
    Sadly enough, no, DateLastModified points to the actual node in the filesystem, it doesn't keep track of files that were changed inside the folder, so you have to:

    • count all the file/folder nodes inside a folder
    • compare every datemodified with the last time you checked it

    actually I tried it for only the folder and it works. Below is the modified code:

    Dim watchFolder
    watchFolder = "Z:\Sales"
    
    Function DirectoryChanged(directory, byref lastDateStamp, byref lastCount)
        Dim result
        Dim fso, folder, files, len, dStamp, objFile
        result = false
    
        dStamp = lastDateStamp
    
        set fso = CreateObject("Scripting.FileSystemObject")
        set folder = fso.GetFolder(directory)
        set files = folder.Files
        len = 0   
        if folder.DateLastModified > dStamp then
            dStamp = folder.DateLastModified
            if lastCount <> 0 then
               result = true
            end if
        end if
        len = len + 1    
    
        if (lastCount <> len) then
            if (lastCount > 0) then
                result = true
            end if
            lastCount = len
        end if
    
        lastDateStamp = dStamp
    
        DirectoryChanged = result
        Exit Function
        error_occured:
        DirectoryChanged = false
    End Function
    
    Dim curDate, curCount
    curDate = Now()
    curCount = 0
    
    
    while true
        if DirectoryChanged(watchFolder, curDDate, curCount) = true then
            WScript.Echo "'" & watchFolder & "' changed!", vbSystemModal, "Change detected in folder"
        end if
        WScript.Sleep(5000)
    wend
    
  • good, it could be that the network implementation of the last changed time is different (here on the network that doesn't work for me :D)

    in case you are leaving it out, you could also skip the lines 13 and 14, 21 to 29, and you don't need the lastCount parameter

    i guess it was also a typo but on row 44 CurDDate is being given as a parameter, though curDate is the defined one ;)

    happy to hear it works :)

  • jcprogrammerjcprogrammer dubai
    edited August 2014

    @Icepickle said:
    good, it could be that the network implementation of the last changed time is different (here on the network that doesn't work for me :D)

    in case you are leaving it out, you could also skip the lines 13 and 14, 21 to 29, and you don't need the lastCount parameter

    i guess it was also a typo but on row 44 CurDDate is being given as a parameter, though curDate is the defined one ;)

    happy to hear it works :)

    @icepickle I have some issues with this file. I put this file in the startup folder but whenever I login it gives an error saying the shared folder cannot be found. So I have to manually open the file to run it. I feel this is because the shared drive is not immediately accessible when the computer starts up. Is there a work around to this?

    Also I was wrong. Checking the last modified date doesn't work all the time. I noticed that the last modified date of our shared drive is much older than the modified date of some of the files in the subfolders.
    So what I am planning is to hard code the paths for some important files inside the shared drive in an array in the script and make the script only check their last modified dates.

    Also the script works only if a file from the folder is deleted. When a new file is created no alert is generated. So is it possible to modify the script so that it keeps a count of the files in the folder and subfolders and checks them against any new additions. So whenever there is a new file added to the shared folder it would alert me. The count should be kept by a counter which should remain static and not change even if I logout so that I can keep a track of the files when I log in the next day.

    One more thing, what vbscript is to windows, is python to Linux? Can I write scripts in python for Linux (the same way I write scripts in VB for windows) or do I have to use C?

    Thanks

  • IcepickleIcepickle Germany
    edited August 2014

    Well, i have spent some time on sunday coding for this, but i think this should do the trick

    it scans stille very 5 seconds (after you click ok on the messagebox)
    It will notify you of all changes (which files, consequently which directories) got updated, created or removed

    I would suggest to increase the timeout to not put to much queries to the network path :) or to scan only those directories you really want

    it now also does a deepscan, which means: if you scan a directory C:\dev\TestChanged and a new directory is created inside it, it will also scan that directory, and so on...

    it also does some error checking, so in case the folder is not there yet, it should just tell you in the beginning that the testfolder got removed, but once it is there, it should simply continue checking

    Your requirement to tell you the day after is a harder one, this should require a copy of the structure to be written to a file, and opened when starting the program

    linux supports a great many of shell scripts, but that depends what is installed on the system. bash shell scripting works in theorie always

    Here is the somewhat updated version of the code, mind you it got a lot bigger, but it also does a lot more now

    Class DirectoryEntry
        private mParent
        private mIsDirectory
        private mEntryName
        private mLastModified
        private objFSO
    
        Public Property Get FSO
            if Parent is Nothing then
                FSO = objFSO
                Exit Property
            end if
            FSO = Parent.FSO
        End Property
        Public Property Set FSO(byref newFSO)
            if Parent is Nothing then
                set objFSO = newFSO
                Exit Property
            end if
            Parent.FSO = newFSO
        End Property
    
        Public Property Get EntryName
            EntryName = mEntryName
        End Property
        Public Property Let EntryName(pEntryName)
            mEntryName = pEntryName
        End Property
    
        Public Property Get IsDirectory
            IsDirectory = mIsDirectory
        End Property
        Public Property Let IsDirectory(pIsDirectory)
            mIsDirectory = pIsDirectory
        End Property
    
        Public Property Get LastModified
            LastModified = mLastModified
        End Property
        Public Property Let LastModified(pLastModified)
            if mLastModified <> pLastModified then
                mLastModified = pLastModified
                AddChanged "CHANGED: " & Path
            End If
        End Property
    
        Public Property Get Root
            if Parent is Nothing then
                Root = Me
            end if
            Root = Parent.Root
        End Property
    
        private mChangedItems()
        private mChangedItemsCount
        private mChanged
        Public Property Get Changed
            If Parent is Nothing then
                Changed = mChanged
                Exit Property
            end If
            Changed = Parent.Changed
        End Property
        Public Property Let Changed(pChanged)
            If Parent is Nothing then
                mChanged = pChanged
                Exit Property
            end if
            Parent.Changed = pChanged
        End Property
    
        public sub AddChanged(pChanged)
            if Parent is Nothing then
                mChangedItemsCount = mChangedItemsCount + 1
                Redim preserve mChangedItems(mChangedItemsCount)
                mChangedItems(mChangedItemsCount) = pChanged
                Changed = true
                Exit Sub
            end if
            Parent.AddChanged pChanged
        end sub
    
        Public Sub Reset()
            ' reset changed items before a new scan '
            Changed = False
            mChangedItemsCount = -1
            Redim mChangedItems(mChangedItemsCount)
        End Sub
    
        private mChildren()
        private mChildrenCount
        private childrenInitialized
        public Property Get ChildrenCount
            ChildrenCount = mChildrenCount
        End Property
        Public Property Let ChildrenCount(pChildrenCount)
            mChildrenCount = pChildrenCount
        End Property
    
        Public MarkDeleted
    
        Public Property Get Children()
            Children = mChildren
        End Property
    
        Sub AddChild(child) 
            if not childrenInitialized then
                childrenInitialized = true
                mChildrenCount = -1
            end if
            mChildrenCount = mChildrenCount + 1
            Redim Preserve mChildren(mChildrenCount)
            child.ChildrenCount = -1
            set mChildren(mChildrenCount) = child
            AddChanged "CREATED: " & child.Path
        End Sub
    
        Public Function AddNotFound(pEntry)
            dim found, pEntryName, pIsDirectory, pLastModified
            pEntryName = pEntry.EntryName
            pIsDirectory = pEntry.IsDirectory
            pLastModified = pEntry.LastModified
            dim entry, index
            found = false
            index = 0
            for each entry in mChildren
                if pIsDirectory = entry.IsDirectory and pEntryName = entry.EntryName then
                    found = true
                    ' check and update LastModified if needed (also triggers a change)'
                    if entry.LastModified <> pLastModified then
                        entry.LastModified = pLastModified
                    end if
                End If
                index = index + 1
            next
            if not found then
                pEntry.Parent = Me
                AddChild pEntry
            end if
    
            AddNotFound = Not found
        End Function
    
        private parentInitialized 
    
        Public Property Get Parent
            if not parentInitialized then
                set Parent = Nothing
                Exit Property
            end if
            set Parent = mParent
        End Property
        Public Property Let Parent(pParent)
            set mParent = pParent
            parentInitialized = true
        End Property
    
        Public Function DirectoryEntry
            mChildrenCount = -1
        End Function
    
        Public Property Get Path
            if Parent is Nothing then
                Path = EntryName
                Exit Property
            end if
            Path = Parent.Path & "\" & EntryName
        End Property
    
        Public Function Message()
            dim msg
            msg = ""
            for each item in mChangedItems
                if msg <> "" then
                    msg = msg & vbCrLf
                end if
                msg = msg & vbTab & item
            next
            Message = msg
        End Function
    End Class
    
    Class Scanner
    
        Public Sub ScanDirectory(byref pEntry)
            on error resume next
            dim folder, files, file, folders, subFolder, fso
            set fso = CreateObject("Scripting.FileSystemObject")
            set folder = fso.GetFolder(pEntry.Path)
            if folder is nothing then
                ' either not found or error occured'
                if not pEntry.MarkDeleted then
                    pEntry.AddChanged "REMOVED: " & pEntry.Path
                    pEntry.MarkDeleted = true
                End If
                Exit Sub
            end if
            pEntry.MarkDeleted = false
            pEntry.LastModified = folder.DateLastModified
    
            set folders = folder.SubFolders
            for each subFolder in folders
                dim sf
                set sf = new DirectoryEntry
                sf.EntryName = subFolder.Name
                sf.IsDirectory = true
                sf.LastModified = subFolder.DateLastModified
                pEntry.AddNotFound sf
            Next
    
            set files = folder.Files
            for each file in files
                dim f
                set f = new DirectoryEntry
                f.EntryName = file.Name
                f.IsDirectory = false
                f.LastModified = file.DateLastModified
                pEntry.AddNotFound f
            next
    
            for each entry in pEntry.Children
                Scan entry, false
            next
        End Sub
    
        Public Sub ScanFile(byref pEntry)
            On Error Resume Next
            dim file, fso
            set fso = CreateObject("Scripting.FileSystemObject")
            set file = fso.GetFile(pEntry.Path)
            if file is nothing then
                ' either not found or error occured'
                if Not pEntry.MarkDeleted then
                    pEntry.MarkDeleted = true
                    pEntry.AddChanged "REMOVED: " & pEntry.Path
                End If
                Exit Sub
            End if
            pEntry.MarkDeleted = false
            pEntry.LastModified = file.DateLastModified
        End Sub
    
        private fsoInitialized
    
        Public Sub Scan(byref pEntry, pReset)
            if pReset then
                pEntry.Reset
            end if
            if pEntry.IsDirectory then
                ScanDirectory pEntry
            else
                ScanFile pEntry
            End if
        End Sub
    
    End Class
    
    dim rootFolder, fso, folderScanner
    set folderScanner = new Scanner
    set rootFolder = new DirectoryEntry
    set fso = createObject("Scripting.FileSystemObject")
    
    rootFolder.IsDirectory = true
    rootFolder.EntryName = "C:\dev\testchanged"
    rootFolder.Parent = Nothing
    
    while true
        folderScanner.Scan rootFolder, true
        if rootFolder.Changed then
            MsgBox rootFolder.Path & " changes to:" & vbCrLf & rootFolder.Message()
        end if
        WScript.Sleep(5000)
    wend
    
  • jcprogrammerjcprogrammer dubai
    edited August 2014

    @icepickle wow this code is just excellent. it is just simply brilliant. It even notifies you for multiple files/folders created, modified, deleted. Wow!!!

    I would just like to trouble you a little more. I am sorry your sunday got ruined because of me. Can you please put comments in the code so that beginners like me could learn something from it. Can this script also be modified to track changes to just one file (or a group of files)
    Also can you explain what wscript.exe does? If I were close this exe from the task manager would it create a problem?
    Can you also suggest a good book to learn VBScripting for windows hacking. most of the books I came across are for web scripting.

    Thanks

  • Thank you for the positive comments :)

    Meantime i even apdated to take the script to take parameters, like:
    /i:1000 -> to check every second (1000 ms)
    /o:filename -> where to check the items of previous scans / save the changes to the directory structure
    /s -> to generate just a directory structure
    /y -> when using cscript instead of wscript to also show a messagebox when changes occured (default, /y turns on silent mode to only log to the console) (cscript logs everything to a console window, instead of to message box)

    it also has a improved warnings, in that sence, it will also throw out files that got deleted when the top directory got deleted

    Wscript is a hosting environment for the script, similar to cscript, just it hosts the script in a windows host, causing all echo statements to generate messageboxes (cscript logs echo messages to the console). If you close the hosting container, the script will end.

    I can check to put more comments in the file (there are some in my defence :D), just what would you like to have commented. if you have questions about the current implementation, feel free to ask.

    I didn't learn it from books, i learned qbasic when i was younger, and kept it active by using vb (asp), vba, and from time to time vbs. So, i cannot really help you out there, the language is easy enough, and the resources on internet are plentyfull, google is your friend...

    The updated script i will put here at a later time, depending on the amount of comments you wish

    if you would point scanner to a directoryEntry wich is not a directory but a file, then it doesn't need changes, it can track as well directories as files per default. I found that the current speed is actually quite good, even for larger folders, also while loading/saving the data, it goes quite fast (though load/save was a bit tricky to keep a consistent dataset)

  • jcprogrammerjcprogrammer dubai
    edited August 2014

    @icepickle thanks for going through all the trouble but have you updated the existing code or will you be posting it? Oh! I just read your post again, so you will be posting it later... thanks (no need for extra comments, if I have doubts I will ask you later)

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories