I have a C# program that does this:
Directory.Exists(@"\\PcName\SomeDir");
and prints whether that path is accessible (exists) or not.
This is the problem: I run this app via the Task Scheduler
right after log-in (auto-log-in user), using the "On Login" trigger, and it returns false
, although that path IS accessible! (I manage to open that path using the explorer.exe few seconds before my app starts). It is marked to:
Run with highest privileges
If I run it manually it runs OK, even when I right click the task and select "Run" via the Task Scheduler
!
If I deselect "Run with highest privileges", there is no problem, but it must be ran with highest privileges (accesses registry and whole lot other stuff)
It runs under same user if I run it manually or automatically by the task scheduler - I made sure using Process Explorer
It happens on certain machines (Win8x64, admin-privileges-user with no password, auto-log-in, workgroup machines, not domain), but not on anothers (same: Win8x64, admin-privileges-user with no password, auto-log-in, workgroup machines, not domain).
Even if I insert Thread.Sleep(TimeSpan.FromMinutes(1));
or enter 1-min delay in the task (in the Task Scheduler) it still says this path does not exist
Problem solved. I had to "impersonate", although I’m not really sure why: if I use the scheduler without restarting, it accesses the remote share – exactly the same settings, one to one. Only after restart it fails to access the share (and a moment later, again – same settings, it is able to access).
The only difference in running it immediately after restart is that the app-process’s parent is services.exe
and not explorer.exe
as usual. My guess is that it has to log in immediately after the restart, so it must use services.exe
(explorer.exe
is not supposed to exist at that stage, if I'm not mistaken).
Below is the solution in C#
, roughly, to whom it may concern:
// LogonUser is a "P/Invoked" API:
// http://www.pinvoke.net/default.aspx/advapi32/LogonUser.html
// this solution works only with the LOGON32_LOGON_NEW_CREDENTIALS as the 4th parameter:
using (var h = LogonUser(username, domain, password,
LogonType.LOGON32_LOGON_NEW_CREDENTIALS,
LogonProvider.LOGON32_PROVIDER_DEFAULT))
{
using (var winImperson8Ctx = WindowsIdentity.Impersonate(h.DangerousGetHandle())) {
return Directory.Exists(path); // now works fine...
}
}