I'm creating a Windows Scheduled Task from a MVC app # by using the c# TaskService namespace.
It normally works fine if the IIS AppPool is set to run as the LocalService user, but every now and then we find a server where it fails to create the Scheduled Task. If we change the AppPool user to a local (admin) user, then it works. But I would prefer to run the AppPool under a system user of some kind.
I don't have any specific error message yet as I can't replicate the error myself.
Are there any rigths/settings/permissions that can cause the LocalService user not to be able to create the Scheduled Tasks?
(PS: LocalSystem and the IIS AppPool users also does not work)
using (TaskService ts = new TaskService())
{
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Description = "My Task";
var trigger = new RegistrationTrigger() { Delay = TimeSpan.FromSeconds(1) };
trigger.Repetition.Interval = new TimeSpan(1, 0, 0));
td.Triggers.Add(trigger);
td.Actions.Add(new ExecAction("C:\Folder\program.exe"));
td.Settings.AllowDemandStart = task.AllowDemandStart;
td.Settings.Hidden = task.Hidden;
ts.RootFolder.RegisterTaskDefinition("My Task", td); //Assumption is that error happens on this line
}
I cannot close this as duplicate because it has a bounty; but for reference this has been answered here
Permissions required to create/modify tasks in Windows Task Scheduler
"The account needs to have read/write permissions to the "Tasks" directory. Here's the path:
%SystemRoot%\system32\Tasks\
However, there was an additional problem where Windows Server 2003 didn't like me specifying Local System as the account that the task would run under. It seemed to not like me passing in a null password which is how you specify Local System. I worked around the problem by making a local account on the server for tasks to run under and specifying this new account."
Related
Hi I'm trying to make a C# app that can check for missing windows updates. I can get my code to work when a user is logged in as that seems to sort out my proxy authentication issues but I want it to run on startup, before a user logs in. Below is my code, it runs fine from visual studio or when I build it and run on another PC but when I set it to run on startup and restart the PC all I get is "System.Runtime.InteropServices.COMException (0x80240438): Exception from HRESULT: 0x80240438 at WUApiLib.IUpdateSearcher.Search(String criteria)"
IUpdateSession uSession = new UpdateSession();
uSession.WebProxy.AutoDetect = false;
uSession.WebProxy.Address = "http://ipAddress:port";
uSession.WebProxy.UserName = #"Domain\user";
string password = "password";
uSession.WebProxy.SetPassword(password);
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
ISearchResult uResult = uSearcher.Search("IsInstalled=0");
Your proxy is probably Active Directory integrated and does not accept this kind of login.
You may try to create a scheduled task which runs in the context of the wanted user and start your code there.
I'm creating Windows Scheduled Tasks dynamically from c# using the build-in TaskService and TaskDefinition libraries.
But for some of them, we need to create then to run as a different user (Local Service or Network Service). As the tasks are created and removed dynamically we cannot edit all of them manually to change the user. We need to do it via code.
Is is possible?
I've tried the following settings:
TaskDefinition.Principal.Id = "NETWORK SERVICE";
TaskDefinition.Principal.LogonType = TaskLogonType.ServiceAccount;
but this gives me the very descript error when creating the task:
System.Runtime.InteropServices.COMException: '(52,4):Task:'
Without those 2 lines, it works but creates them as the logged in user.
I've played around with the Task Scheduler stuff a bit and have replicated your problem. I believe I’ve found some things out, maybe they can help.
1. Firstly if your making Tasks in the debugger using Services Accounts, you'll want to ensure your Visual Studio or other IDE is launched as administrator to ensure you have the correct privileges to do this task.
2. I'm not sure if you do this later in your code but to make the task save and run as NETWORK SERVICE, I had to Identify Network Service as NT AUTHORITY\\NETWORKSERVICE in both the principle and on the RegisterTaskDefinition method:
TaskService tService = new TaskService();
TaskDefinition tDefinition = tService.NewTask();
tDefinition.Principal.Id = "NT AUTHORITY\\NETWORKSERVICE";
tDefinition.Principal.LogonType = TaskLogonType.ServiceAccount;
tDefinition.RegistrationInfo.Description = "Testing";
tDefinition.Triggers.Add(new DailyTrigger {DaysInterval = 2});
tDefinition.Actions.Add(new ExecAction("notepad.exe"));
tService.RootFolder.RegisterTaskDefinition(#"Test", tDefinition, TaskCreation.CreateOrUpdate,
"NT AUTHORITY\\NETWORKSERVICE", null,
TaskLogonType.ServiceAccount);
I used the above code to make a test Task that got successfully added to my scheduler as Network Service as shown below:
I'm guessing that one or both of the above points may have stopped the task from being added, hope that helps
I have this code:
[PermissionSet(SecurityAction.Assert, Name = "FullTrust")]
public List<WinInfo> GetWindows()
{
try
{
var isFullTrust = Assembly.GetExecutingAssembly().IsFullyTrusted;
if (isFullTrust)
{
return Process.GetProcesses().Where(z => !string.IsNullOrEmpty(z.MainWindowTitle))
.Select(z => new WinInfo
{
ProcessID = z.Id,
ProcessName = z.ProcessName,
WinID = z.MainWindowHandle,
WindowTitle = z.MainWindowTitle
}).ToList();
}
else
return null;
}
catch (Exception ex)
{
Trace.Write(ex.Message);
return null;
}
}
When I test in on my local computer under my current user (with admin rights) it works ok, displaying all the processes, that have windows. But when I call this code from a windows service, run under "Local Service" account, then the list is empty. I attached to the process, and through debug I found that "Process.GetProcesses()" returns all the processes, but all of them have MainWindowHandle as 0 and MainWindowTitle as empty, even when they do have windows. So what is wrong with my code?
Edit I edited code, so that it checks the assembly for full trust and have PemmissionSet that should grant the code the neccessary rights. Still the result is the same. When I debug, I can see, that "isFullTrust" is "True" and code executes with no exceptions. Still the list is empty, because none of the processes contains not-empty MainWindowTitle
According to this thread :
The problem you're seeing is because by default service don't have access to any interactive desktops. I don't recommend interacting with the desktop from a service (#1, there may not be any desktop, #2 there may be multiple desktops, #3 interacting with the desktop from service in Vista is not implemented) but, you can check the "Interace with desktop" in your services properties.
maybe you can try to create an hidden form?
Surely you need to run that under the user account! Why would applications with open windows be running under the local system account? That's for windows services etc
It could also be related to your process requiring full trust
From MSDN: The Process class has a LinkDemand and an
InheritenceDemand for FullTrust on it. This means that if your
assembly is not fully trusted, it will be unable to kick off new
Processes or get information about running processes
Maybe this is a question of priviliges.
According to this link LocalService has minimum privileges on the local computer.
you should use Local system Account
I would like to run a process from an intranet client on the WCF service side. In my case a client asks a server to create a new process on the server's machine under the provided credentials. WCF service is hosted on IIS 7.5 and I start a process using this code
var processInfo = new ProcessStartInfo("C:\\Windows\\System32\\notepad.exe")
{
UserName = "some user",
Password = MakeSecureString("some password"),
UseShellExecute = false,
LoadUserProfile = true
};
Process process = Process.Start(processInfo);
This code works if I host WCF service as a self-hosted console application running under admin user and I see the notepad started under another user. It fails on IIS with no exception, but process is immediately terminated
process.HasExited = true;
process.ExitCode = -1073741502;
On IIS WCF application is running under the user with admin rights and has got full trust defined in web.config. I cannot use self hosted application as it doesn't support easy continuous delivery (like WebDeploy with IIS web farms).
Q: How can I start a process on a server side from WCF service hosted on IIS?
EDIT:
I stumbled upon this post, with similar issues and I tried all the methods there, including all possible variations for Process.Start and P/Invoke with CreateProcessWithLogonW and CreateProcessAsUser I also tried granting additional permissions to users. Non of this would work with the error messages identical to the ones the guy had posted.
Oleksii, the point is that if you host the WCF service in a console application, there is a windows session (a user logged in and Windows Explorer loaded) for that user and the notepad is opened and shown for that user, so you see it in the UI.
when you host your WCF service in IIS, being a server, IIS requires and allows no user interaction and works also if no user is logged in; in that context there is no UI to host your notepad or other UI enabled applications, you could execute a process for elaboration or other batch jobs but not render a windows UI application, because Windows Explorer is not loaded for you and there is no place to render your process's UI.
here is what I use to call GnuPGP to do encryption. How does your setup compare?
private int ExecuteCommand(string arguments, string passPhrase, int timeout)
{
Process processObject;
ProcessStartInfo pInfo = new ProcessStartInfo(_executablePath, arguments);
pInfo.CreateNoWindow = true;
pInfo.UseShellExecute = false;
pInfo.RedirectStandardInput = true;
pInfo.RedirectStandardOutput = true;
pInfo.RedirectStandardError = true;
processObject = Process.Start(pInfo);
if (!string.IsNullOrEmpty(passPhrase))
{
processObject.StandardInput.WriteLine(passPhrase);
processObject.StandardInput.Flush();
}
string result = processObject.StandardOutput.ReadToEnd();
string error = processObject.StandardError.ReadToEnd();
if (!processObject.WaitForExit(timeout))
{
throw new TimeoutException("GnuPG operation timeout. Waited " + timeout + " milliseconds ");
}
int exitcode = processObject.ExitCode;
Error = error;
Output = result;
return exitcode;
}
There's an apppool setting to make sure it loads the user profile.
loadUserProfile Optional Boolean attribute.
Specifies whether IIS loads the user profile for the application pool identity. Setting
this value to false causes IIS to revert to IIS 6.0 behavior. IIS 6.0 does not load the
user profile for an application pool identity.
The default value is false.
That along with being a domain user as the identity with enough permissions might work?? I know that at a minimum the user will need a user profile.
That said, it's a little bit of an odd architecture. It seems like a better arch would be to have a persistent process like a windows service that the site communicates with but I'm not sure what your constraints are.
Hope that helps.
On my local machine I am running an administrative c# service as LocalSystem called Serv.exe which performs various tasks. One of the tasks it needs to perform is to launch an application under the USER account (currently logged on), not as admin - as this violates security.
The obvious solution would be simple impersonation when launching the application - however I run into a small problem whereas I am not priviledged to the user account credentials (Username & Password) and therefore am unable to impersonate in the conventional way.
So, using a C# service running as LocalSystem when logged on to a User account - is there anyway I can launch an application as that User?
From the comments:
what happens is that the Application itself asks the Service to do a job and then terminates. when the job is funished the application must restart itself - I thought the best way would be to have the service restart it when it was done ...
Any help would be greatly appreciated.
Thanks,
You can use Windows Scheduler to start your app as a user.
Take a look at this wrapper - http://www.firatatagun.com/c-windows-task-scheduler-wrapper-classes-c-sharp/2010/04/22/
and then you can simply create a scheduled task to run your software immediately, afterward you can delete this redundant task after 2 seconds.
Sample code:
using (TaskService ts = new TaskService())
{
// Create a new task
const string taskName = "RunMyProcessNowAsUser";
Task t = ts.AddTask(taskName,
new TimeTrigger() { StartBoundary = DateTime.Now, Enabled = false },
new ExecAction("YourProcess.exe");
t.Run();
// delete the task after 2 seconds.
new Action(() =>
{
Thread.Sleep(2000);
using (TaskService ts2 = new TaskService())
{
ts2.RootFolder.DeleteTask(taskName);
}
}).BeginInvoke(null, null);
}
Instead of breaching security this way you can make the application wait and then restart itself. See this SO question and this one.