Got a bit of a problem:

Got a bit of a problem:

I am creating a Win32 Service to be run under Windows10. This Service will receive it's config via a Winsock connection from another application ( lets call it the UI app ). The Service will then need to write out it's config to an INI file and then it will also need to write detailed logs ( Windows event log will not cut it as it needs to write out quite a bit with regards to ongoing statuses )

WHAT WORKS: The UI can talk to the Service and vice versa; Config can be passed and I see evidence of this being used. The sub-folders underneath the Service folder for the debug and the config are created

WHAT IS BROKEN: The Service does not write out any debug or config. I am assuming this is a UAC thing. I have changed folder locations and folder permissions and have even changed the Logged on user to my account for the Service, as opposed to the Local system account; although I don't have Local Administrator rights so this might have been a pointless thing to do.

NOTE: I also tried to install the Service on an actual Windows 2012 Server where I had full Administrator permission and it still did not write out the debug or the config. When I did this I also changed the Logged on user to the Administrator!

Can anyone shed any light on this one please. I will be eternally grateful.

Comments

  1. Have you verified the folder that you are writing to? Services can be funny especially around things such as current folder. Have you tried attaching to the service while it's running and stepping through as it tries to write the ini file?

    ReplyDelete
  2. Thanks Paul Richardson​​ good advice I'll try that in the morning

    ReplyDelete
  3. Writing to files from services is no problem at all. You need to work our where you are trying to write and how it fails. Gather information. Log error codes etc. Basic debugging really.

    ReplyDelete
  4. David Heffernan​ I was basing everything from application. Exename

    ReplyDelete
  5. Tony Danby It is not a good idea to use Application.ExeName as the base because it usually sits in Program Files with restricted write access. I prefer to use something like this to get app-specific config:
    function GetAppConfigFile: TIniFile;
    var
      S: String;
      P: array[0..MAX_PATH] of Char;
    begin
      SHGetSpecialFolderPath(0,@P[0], CSIDL_APPDATA, TRUE);
      S := IncludeTrailingPathDelimiter(String(P)) + 'MyCoolApp\';
      ForceDirectories(S);
      Result := TIniFile.Create(S+'MyCoolApp.ini');
    end;

    ReplyDelete
  6. I've also learned the hard way not to trust relative paths with Services. Use global Windows constants (System.SysUtils.GetEnvironmentVariable) and build your absolute path that way. It's the only way to be sure that your service writes inside your desired dir every time.

    ReplyDelete
  7. Apostolis Tympakianakis  Relative paths work the same way in services as in desktop apps

    ReplyDelete
  8. David Heffernan I'm sorry, but that is not my experience. Services EXEs tend to get current dirs and ApplicationName paths completely random from one system to another.
    Also, depending on the OS version, type and setup, I was getting different results when getting the "working dir".
    So no, for me, relative paths should not be trusted in Services.

    ReplyDelete
  9. Apostolis Tympakianakis  Just the same as for desktop apps in other words.

    ReplyDelete
  10. Well Paul Richardson and Apostolis Tympakianakis you were both on the right path. It looks like a service does not have full access to the current folder by default and having read a ton of documents from Microsoft and many others it seems to be there are two places I can stick these files and these are C:\ProgramData and the Shared ( or Public ) Documents folder ( typically C:\Users\Public\Documents ). I have tested ProgramData and I appear to have full rights to read, write and make folders in there. I am about to test the Shared Documents folder and I'll post the outcome of the test here; but I suspect that will work too from everything I am reading. Once I have the results of testing for Shared Documents I'll post it here so all the /sub'bers can see

    ReplyDelete
  11. The problem is categorically not that services do not have write access the the working directory. Whether or not a process can write to the working directory depends on what that directory is.

    There seems to be a lot of confusion here. The real point is what the working directory is. If ever you want to use the working directory you need to be sure that it has been well-defined. For a service, it is typically started by the SCM and inherits the working directory from the SCM process. And that working directory is the system directory (system32 or syswow64).

    So the problem is that the working directory was not what you were expecting, a subtle difference from your process not being able to write in the working directory.

    But services aren't really special here. Just the same issue is true with a desktop app. A great many people make the false assumption that a desktop app starts up with the working directory being the directory where the executable lives. That is simply not true. When you start it from explorer by double clicking the exe file, explorer arranges that. But if you create it another way, e.g. with a call to CreateProcess, launching from a different shell such as cmd.exe, then the working directory may be different.

    There only time that you can rely on the working directory is where you have declared a contract with clients of your process that they must start it with a well-defined working directory. The most common example is a console application. So, if you are writing a program to list files (like the Unix ls program) then you would make such a contract.

    ReplyDelete
  12. Your choice should not be based on randomly finding a folder to which you have write access. If this really is configuration data then it must not be placed in shared documents. Machine wide config goes under ProgramData, FOLDERID_ProgramData or CSIDL_COMMON_APPDATA if you still use CSIDLs.

    There are guidelines for this. Don't make this stuff up when there is an established way to do it. https://blogs.msdn.microsoft.com/patricka/2010/03/18/where-should-i-store-my-data-and-configuration-files-if-i-target-multiple-os-versions/

    ReplyDelete
  13. David Heffernan I couldn't agree more; I was striving to understand which one of the many folders were for what purpose; it's clear Microsoft had given the folder organisation plenty of thought when I realised the current folder was locked down. Your link proved to be very useful and confirmed all of my findings; I will be keeping that link for future reference ! Shared documents is where we really need to be so users can access the logs being generated. I could have put them in ProgramData but that would not have been very user friendly. Once again thanks for the link I am reading it as I write this. I think our config will end up in ProgramData, but the logs will be in Shared Documents.

    ReplyDelete
  14. That makes sense. I thought you were referring to config only.

    ReplyDelete

Post a Comment