2017-01-31 2 views
0

Ich arbeite an einem Projekt, das eine Reihe von Windows Aufgabenplanungsaufgaben installieren muss, und dafür habe ich ein Wix-Projekt und eine benutzerdefinierte Aktion erstellt, die sich um alle Details kümmert. Diese benutzerdefinierte Aktion wurde mit C++ erstellt, um Abhängigkeiten von .NET Framework zu vermeiden.TaskScheduler ExecAction put_WorkingDirectory kann seinen Wert nicht aktualisieren

Zuerst habe ich mit der Ausführung von SCHTASKS.EXE aus einer benutzerdefinierten Wix-Aktion begonnen, aber nachdem ich die richtige Befehlszeile zum korrekten Installieren einer Aufgabe erstellt hatte, erkannte ich, dass ich das Arbeitsverzeichnis der Aktion nicht festlegen konnte ('Start in'). in der Task Scheduler UI) von der SCHTASKS.EXE Kommandozeile, weil es einfach nicht die Option hatte ...

Ich entschied mich dann, COM in C++ (#import <taskschd.dll> raw_interfaces_only) zu verwenden, um an den Taskplaner zu gelangen und den zu optimieren WorkingFolder verwendet die API nach der Installation der Task mit SCHTASKS.EXE, die neben diesem Detail gut funktioniert. Ich schaffte es, die Aufgabe zu bekommen und seine Werte nach der Installation der Aufgabe korrekt zu lesen, aber wenn ich put_WorkingDirectory Methode mit dem aktuellen Wert ausgeführt, dass tatsächlich nicht fehlgeschlagen, aber der Wert wurde nicht in der Aufgabe gespeichert.

Hat jemand eine Ahnung, warum ich dort nicht hinkommen konnte? Dies ist Teil des Codes, den ich verwendet habe, um die ExecAction zu erhalten und den Wert erfolgreich festzulegen. Denken Sie daran, dass dies in einer benutzerdefinierten Wix-Aktion erfolgt, sodass einige der Methodenaufrufe Wix-Aufrufe sind.

Dieser Code funktioniert tatsächlich und das Protokoll zeigt den richtigen Pfad, den ich festlegen möchte, aber die Aufgabe wird nicht geändert. Was mache ich falsch?

HRESULT UpdateWorkingDirectory(TaskScheduler::ITaskFolderPtr rootFolder, BSTR taskName, BSTR installFolder) 
{ 
    HRESULT          hr   = S_OK; 
    TaskScheduler::IRegisteredTaskCollectionPtr taskCollection; 
    LONG          numTasks = 0; 
    TaskScheduler::IRegisteredTaskPtr   thisTask; 
    TaskScheduler::ITaskDefinitionPtr   definition; 
    TaskScheduler::IActionCollectionPtr   actions; 
    TaskScheduler::IActionPtr     action; 
    TaskScheduler::IExecActionPtr    execAction; 
    long          actionCount; 

    hr = rootFolder->GetTasks(NULL, &taskCollection); 
    ExitOnFailure(hr, "Cannot get task collection pointer"); 

    hr = taskCollection->get_Count(&numTasks); 
    ExitOnFailure(hr, "Cannot get task collection item count"); 

    for (LONG taskIdx = 0; taskIdx < numTasks; taskIdx++) { 
     TaskScheduler::IRegisteredTaskPtr registeredTask; 
     bstr_t        taskIdxName; 

     hr = taskCollection->get_Item(variant_t(taskIdx + 1), &registeredTask); 
     ExitOnFailure(hr, "Cannot get task item %d", taskIdx + 1); 

     hr = registeredTask->get_Name(&taskIdxName.GetBSTR()); 
     ExitOnFailure(hr, "Cannot get task name"); 
     WcaLog(LOGMSG_STANDARD, " registered task name = %s", (LPCSTR)taskIdxName); 

     if (strcmp(bstr_t(taskName), taskIdxName) == 0) { 
      thisTask = registeredTask; 
      break; 
     } 
    } 
    if (thisTask == NULL) { 
     hr = E_FAIL; 
     ExitOnFailure(hr, "task {%S} not found", taskName); 
    } 

    hr = thisTask->get_Definition(&definition); 
    ExitOnFailure(hr, "error getting task definition for {%S}", taskName); 

    hr = definition->get_Actions(&actions); 
    ExitOnFailure(hr, "error getting actions for {%S}", taskName); 
    WcaLog(LOGMSG_STANDARD, " got actions from %S", taskName); 

    hr = actions->get_Count(&actionCount); 
    ExitOnFailure(hr, "error getting action count for {%S}", taskName); 
    WcaLog(LOGMSG_STANDARD, " got count = %d from {%S}", actionCount, taskName); 

    if (actionCount > 0) { 
     bstr_t actionId; 
     bstr_t arguments; 
     bstr_t path; 

     hr = actions->get_Item(1, &action); 
     ExitOnFailure(hr, "error getting action[1] for {%S}", taskName); 

     hr = action->QueryInterface(&execAction); 
     ExitOnFailure(hr, "error getting ExecAction for {%S}", taskName); 

     hr = execAction->get_Id(&actionId.GetBSTR()); 
     ExitOnFailure(hr, "error getting Exec Action id for first exec action of {%S}", taskName); 
     WcaLog(LOGMSG_STANDARD, " first Exec Action Id is %s", (LPCSTR)actionId); 

     hr = execAction->get_Arguments(&arguments.GetBSTR()); 
     ExitOnFailure(hr, "error getting Exec Action arguments for first exec action of {%S}", taskName); 
     WcaLog(LOGMSG_STANDARD, " first Exec Action arguments are %s", (LPCSTR)arguments); 

     hr = execAction->get_Path(&path.GetBSTR()); 
     ExitOnFailure(hr, "error getting Exec Action path for first exec action of {%S}", taskName); 
     WcaLog(LOGMSG_STANDARD, " first Exec Action path is %s", (LPCSTR)path); 

     hr = execAction->put_WorkingDirectory(installFolder); 
     ExitOnFailure(hr, "error putting working directory for {%S}", taskName); 
     WcaLog(LOGMSG_STANDARD, " successful put working directory to %S", installFolder); 
    } 

LExit: 
    return hr; 
} 

HINWEIS: Alle C++ Proben fand ich einfache Schnittstelle Zeiger anstelle von Smart-Pointer verwendet, zog ich intelligente Zeiger von mir die Pflege Freisetzung zu vermeiden

Antwort

0

fand ich die Antwort

ich Benutzername und Passwort

HRESULT UpdateWorkingDirectory(TaskScheduler::ITaskFolderPtr rootFolder, BSTR taskName, BSTR installFolder, variant_t username, variant_t password) 

und fügen Sie diese fünf Zeilen

 thisTask = NULL; 

     hr = rootFolder->RegisterTaskDefinition(taskName, definition, TaskScheduler::_TASK_CREATION::TASK_UPDATE, username, password, TaskScheduler::_TASK_LOGON_TYPE::TASK_LOGON_PASSWORD, variant_t(), &thisTask); 
     ExitOnFailure(hr, "error updating task regisration for {%S}", taskName); 
     WcaLog(LOGMSG_STANDARD, " successful update of task regisration to %S", taskName); 

nach der Ausführung put_WorkingDirectory aufnehmen musste meine Methode Signatur ändern.

Dies aktualisiert die Registrierung der Task-Definition mit dem aktualisierten Wert, das war, was ich tun wollte, und es hat funktioniert !!!!

0

Es scheint mir, dass dies ein gutes Beispiel dafür ist:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa446854(v=vs.85).aspx

Genauer gesagt zeigt es, dass Sie ITask rufen :: Activate vor Dinge wie das Arbeitsverzeichnis zu ändern, und dass Sie IPersistFile aufrufen, um die Änderungen zu speichern. Ich kann keine davon in diesem geposteten Codebeispiel sehen. Ich habe diese Interfaces eine Weile nicht angeschaut, aber das könnte das Problem sein.

+0

Das ist für TaskScheduler 1.0 und ich möchte es in der Version 2.0 einstellen. Die neue Version hat eine komplexere Objekthierarchie und keine SetWorkingDirectory-Methode auf dieser Ebene. Vielen Dank trotzdem –

Verwandte Themen