This project has moved. For the latest updates, please go here.

Unable to connect to remote server

Mar 27, 2012 at 12:08 PM

I have my code working great on Windows XP both locally and remotely to another XP system using my current logon credentials. I am now trying to connect to a remote Windows 2003 (that is standalone) server using different credentials (but ones that have admin privileges on that system), but I am receiving 'Unknown username or bad password'. I am using the following code snippet

                    if (server.IsRemoteServer)
                    {
                        using (TaskService ts = new TaskService(server.Name, "userhere",server.Name,"passwordhere",true))
                        {
                            TaskFolder tf = ts.RootFolder;
                            foreach (Task tsk in tf.Tasks)
                            {
                                taskNames.Add(tsk.Name);
                            }
                        }
                    }

 etc

If I log onto the server running the application using credentials that are identical to the remote server using the following code then I can return a list of tasks running

                    if (server.IsRemoteServer)
                    {
                        using (TaskService ts = new TaskService())
                        {
                            ts.TargetServer = server.IP; 
                            TaskFolder tf = ts.RootFolder;
                            foreach (Task tsk in tf.Tasks)
                            {
                                taskNames.Add(tsk.Name);
                            }
                        }
etc

I can use the schtasks command with any credentials that have the correct privileges on the remote server and it returns the list of tasks fine

Any help appreciated

Coordinator
Mar 27, 2012 at 7:42 PM

For V1, I am using the Windows API call LogonUser to get a token and then am impersonating that identity for the call to the COM object. Here are the parameters I'm passing to that call:

LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out token)

I'm not sure how schtasks is doing it. I made a slight change to the impersonation code to match some Microsoft samples that I'll release in 1.8.2, but I'm doubtful that will address the problem you're having. My only guess is that it has something to do with the domain name being passed.

Mar 28, 2012 at 7:48 AM
Edited Mar 30, 2012 at 8:10 AM

Thanks for the quick reply

I have tried various ways to pass the domain name (null and ""), but so far have been unsuccessful

The remote server(s) are all stand-alone, so not part of a domain, so when you connect you either leave the domainName out completely or pass servername

What I believe is happening is that for the domainName it is passing my current logon domain which is why it will only work if log onto my PC (or where the application is running from) using a local account and not a domain account

Is there a way I can see what is being passed in the background to the API call


From: dahall

For V1, I am using the Windows API call LogonUser to get a token and then am impersonating that identity for the call to the COM object. Here are the parameters I'm passing to that call:

LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out token)

I'm not sure how schtasks is doing it. I made a slight change to the impersonation code to match some Microsoft samples that I'll release in 1.8.2, but I'm doubtful that will address the problem you're having. My only guess is that it has something to do with the domain name being passed.

Mar 28, 2012 at 10:41 AM

I also have another issue whereby if I create a new task and then edit that task (using the editor wizards), I receive the following error

'Tasks which have been registered previously with stored passwords must use the TaskFolder.RegisterTaskDefinition method for updates'

This is the code I use to edit a task

using (TaskService ts = new TaskService(server.Name, null, null, null, true))
                        {
                            Task tsk = ts.GetTask(task);
                            if (tsk != null)
                            {
                                TaskEditDialog editorform = new TaskEditDialog(tsk, true, true);
                                res = editorform.ShowDialog();
                            }
                            else
                            {
                                MessageBox.Show("No task has been selected", "Edit Scheduled Task", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }

Is there a way to register when using the editor wizard that is the same as when you create a new task (code for a new task below)

                    using (TaskService ts = new TaskService(server.Name, null, null, null, true))
                    {
                        using (TaskSchedulerWizard wiz = new TaskSchedulerWizard())
                        {
                            TaskDefinition newTaskDef = ts.NewTask();
                            wiz.Initialize(ts, newTaskDef);

                            if (wiz.ShowDialog() == DialogResult.OK)
                            {
                                // save task
                                ts.RootFolder.RegisterTaskDefinition(newTaskDef.Data, newTaskDef);
                            }
                        }
                    }
Thanks
Coordinator
Mar 28, 2012 at 6:13 PM

To answer the first question, whatever you pass into the TaskService constructor for domain is what is passed to LogonUser for the domain. If you don't pass any parameters into the constructor, then it grabs the token from the interactive account and doesn't call LogonUser. I think the code you presented in your first post is correct.

On your second question, you can set the TaskSchedulerWizard.RegisterTaskOnFinish property to True before calling ShowDialog and it will perform the same as TaskEditDialog.

Mar 30, 2012 at 8:08 AM

Could you please supply a snippet of code for the 'TaskSchedulerWizard.RegisterTaskOnFinish' and how to use it with the editor wizard

Thanks

Coordinator
Mar 31, 2012 at 2:02 AM

In your code above, are you intentionally making sure that all tasks are created with the V1 library? If not, then I would set the last parameter of the TaskService constructor to false thus allowing for the highest version of the library to be used to create the task. The code for using the wizard to create a new task is actually very simple:

using (TaskService ts = new TaskService(server.Name))
{
   TaskSchedulerWizard wiz = new TaskSchedulerWizard(ts);
   wiz.RegisterTaskOnFinish = true;
   wiz.ShowDialog();
}

In the next release of the library (1.8.2 probably), you will be able to simply do:

using (TaskService ts = new TaskService(server.Name))
{
   new TaskSchedulerWizard(ts, null, true).ShowDialog();
}