News:

Download Pelles C here: http://www.pellesc.se

Main Menu

Recent posts

#91
Work in progress / Re: Task Schedule 2.0 examples
Last post by TimoVJL - December 10, 2025, 04:14:32 AM
My idea was to learn convert MS C++ code to Pelles C code.

Nice to have also MrBcx in this topic too.

I didn't use ComCpp2C2 for conversion.

One example:
https://learn.microsoft.com/en-us/windows/win32/api/taskschd/nf-taskschd-itaskservice-connect
    //  Connect to the task service.
    //hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    hr = pService->lpVtbl->Connect(pService, v1, v2, v3, v4);
those variants are optional, but C compiler don't allow NULL for them.
Just an one empty VARIANT could be used too ?

If you don't have msvcrt.libs, just remove USE_MSVCRT define from projects
#92
General discussion / Re: Pellesc site down?
Last post by alderman2 - December 09, 2025, 10:27:37 PM
Does anyone know why Pelle's website is not up?
Why is there an image with links on the page that lead to strange things?
#93
Work in progress / Re: Task Schedule 2.0 examples
Last post by John Z - December 09, 2025, 09:39:39 PM
Agree for Unix, I used cron for many things.  However the windows Task Scheduler interactive GUI is very easy to use and access.  Programmatically it is a bit harder.

Here is a powershell script creator in C to schedule a task...
typedef struct names{
  char AppPath[MAX_PATH];
  char VBSTime[50];
  char VBETime[50];
  char TaskName[50];
  char UserSTime[50];
  char Message[50];
}names;

names name;

/****************************************************************************
 *                                                                          *
 * Function: Create_Script_PS1                                              *
 *                                                                          *
 * Purpose : create runnable Powershell script for task                     *
 *                                                                          *
 * History : Date      Reason                                               *
 *           01/31/25  Created   John Z                                     *
 *                                                                          *
 * Globals :SYSTEMTIME dpst, SYSTEMTIME dpet;                               *
 ****************************************************************************/
void Create_Script_PS1(void)
{   int RetVal; 
char FileName [MAX_PATH*2]={0};
FILE *p_file;
    char buf2[4000]={0};
    char *p_buf2;

p_buf2 = buf2;  //wide char


    strcpy(FileName,name.AppPath);
strcat(FileName,"scr1.ps1");

p_file = fopen(FileName,"wb+"); //For Binary Access Write
    if (p_file == NULL)
      {
snprintf(buf2,MAX_PATH*2,"Unable to open file.\r\nFilename: %s",FileName);
MessageBoxA( NULL, buf2, "File Access Error",
MB_OK | MB_ICONERROR | MB_TOPMOST);
return;
  }

    snprintf(p_buf2, 3999,"%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A",
             "$TriggerTypeTime = 1",
             "$ActionTypeExec = 0",
             "$service = New-Object -ComObject Schedule.Service",
             "$service.Connect()"
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);


    snprintf(p_buf2, 3999,"%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A",
             "$rootFolder = $service.GetFolder(\"\\\")",
             "$taskDefinition = $service.NewTask(0)",
             "$taskDefinition.RegistrationInfo.Description = \"Start Alert at a certain time\""
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);
          fflush(p_file);

    snprintf(p_buf2, 3999,"%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A",
             "$taskDefinition.RegistrationInfo.Author = \"CalendarZ\"",
             "$taskDefinition.Principal.LogonType = 3",
             "$taskDefinition.Settings.Enabled = $true",
             "$taskDefinition.Settings.StartWhenAvailable = $true"
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);


    snprintf(p_buf2, 3999,"%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A",
             "$taskDefinition.Settings.Hidden = $false",
             "$taskDefinition.Settings.DeleteExpiredTaskAfter = \"PT10M\"",
             "$triggers = $taskDefinition.Triggers",
             "$trigger = $triggers.Create($TriggerTypeTime)"
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);
          fflush(p_file);

   snprintf(p_buf2, 3999,"%s'%s'\x0D\x0A%s'%s'\x0D\x0A%s\x0D\x0A%s\x0D\x0A",
             "$startTime = ",name.VBSTime,
             "$endTime = ",name.VBETime,
             "$trigger.StartBoundary = $startTime",
             "$trigger.EndBoundary = $endTime"
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);
          fflush(p_file);
   snprintf(p_buf2, 3999,"%s\x0D\x0A%s\x0D\x0A%s\"%s%s\"\x0D\x0A",
             "$actions = $taskDefinition.Actions",
             "$action = $actions.Create($ActionTypeExec)",
             "$action.Path = ",
              name.AppPath,
         "Alert.exe"
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);

   snprintf(p_buf2, 3999,"%s%s -%s\"\x0D\x0A",
             "$Action.Arguments = \"-",
          name.UserSTime,
          name.Message
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);

    snprintf(p_buf2, 3999,"%s\x0D\x0A%s,\x0D\x0A%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A%s\x0D\x0A)",
             "$rootFolder.RegisterTaskDefinition(",
         name.TaskName,
             "    $taskDefinition,",
             "    6, # Task creation flag (6 = CREATE_OR_UPDATE)",
             "    $null, # User",
         "    $null, # Password",
             "    $null, # Logon type",
             "    $null # SDDL"
             );
    RetVal = fwrite(p_buf2, sizeof(char), strlen(p_buf2), p_file);
          fflush(p_file);

    fclose(p_file);
//MessageBox(NULL,"Completed!","Create Alert",MB_OK);


}/* end create_script_ps1 */

Not too bad, I have one for VBS too if interested...
I would have preferred in C but couldn't quite manage, so I'll learn from Timo's effort.

John Z
#94
Work in progress / Re: Task Schedule 2.0 examples
Last post by Vortex - December 09, 2025, 09:18:57 PM
The cron jobs of UNIX\Linux are much more simple to maintain.
#95
Work in progress / Re: Task Schedule 2.0 examples
Last post by MrBcx - December 09, 2025, 04:53:36 PM
Quote from: Vortex on December 09, 2025, 11:26:23 AMAdditionaly, MrBcx created some useful applications too :

https://bcxbasiccoders.com/smf/index.php?topic=1443.0

To get at my code, one mostly needs to be a registered user and logged in.

Here is a list of my most recent uploads:

* Communicate with an AI Server using COM
* COM Demos For Using Windows Task Scheduler Services
* Send a JSON record via WinHttp
* Fetch a JSON record via WinHttp
* REST API toolkit in BCX
 
Only the BCX BASIC source code is provided for each. 
If you want the Pelles C compatible code, you'll need to use the BCX Translator.
#96
Expert questions / Re: PellesC_V13\Include\Win\oc...
Last post by TimoVJL - December 09, 2025, 03:33:59 PM
A that ocidl.h don't have usual safe guard for windows.h and ole2.h
Perhaps have a good reason for that.
#97
Expert questions / Re: PellesC_V13\Include\Win\oc...
Last post by Vortex - December 09, 2025, 01:54:36 PM
Sometimes, it's better to copy the confusing equates from the net and paste them to the source file. In this case, you have to omit the header file.
#98
Work in progress / Re: Task Schedule 2.0
Last post by TimoVJL - December 09, 2025, 12:56:10 PM
I just converted a MS code example from C++ to C.

TaskCreate2.c
This needs some fixing.
/********************************************************************
 This sample schedules a task to start on a daily basis.
********************************************************************/
#define WIN32_LEAN_AND_MEAN
#define _WIN32_DCOM

#include <windows.h>
//#include <iostream>
#include <stdio.h>
//#include <comdef.h>
#include <wincred.h>
//  Include the task header file.
#include <taskschd.h>
#pragma comment(lib, "taskschd.lib")
//#pragma comment(lib, "comsupp.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")
#pragma comment(lib, "credui.lib")

//using namespace std;

int __cdecl wmain(void)
{
    //  ------------------------------------------------------
    //  Initialize COM.
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if( FAILED(hr) )
    {
        printf("\nCoInitializeEx failed: %x", hr );
        return 1;
    }

    //  Set general COM security levels.
    hr = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        0,
        NULL);

    if( FAILED(hr) )
    {
        printf("\nCoInitializeSecurity failed: %x", hr );
        CoUninitialize();
        return 1;
    }

    //  ------------------------------------------------------
    //  Create a name for the task.
    LPCWSTR wszTaskName = L"Daily Trigger Test Task";

    //  Get the windows directory and set the path to notepad.exe.
    LPCWSTR wstrExecutablePath = _wgetenv( L"WINDIR");
    //wstrExecutablePath += L"\\SYSTEM32\\NOTEPAD.EXE";

   

    //  ------------------------------------------------------
    //  Create an instance of the Task Service.
    ITaskService *pService = NULL;
    hr = CoCreateInstance( &CLSID_TaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           &IID_ITaskService,
                           (void**)&pService ); 
    if (FAILED(hr))
    {
        printf("Failed to create an instance of ITaskService: %x", hr);
        CoUninitialize();
        return 1;
    }
    VARIANT v1, v2, v3, v4;
VariantInit(&v1);
VariantInit(&v2);
VariantInit(&v3);
VariantInit(&v4);
 
    //  Connect to the task service.
    //hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
hr = pService->lpVtbl->Connect(pService, v1, v2, v3, v4);
    if( FAILED(hr) )
    {
        printf("ITaskService::Connect failed: %x", hr );
        pService->lpVtbl->Release(pService);
        CoUninitialize();
        return 1;
    }

    //  ------------------------------------------------------
    //  Get the pointer to the root task folder.  This folder will hold the
    //  new task that is registered.
    ITaskFolder *pRootFolder = NULL;
    hr = pService->lpVtbl->GetFolder(pService, L"\\" , &pRootFolder );
    if( FAILED(hr) )
    {
        printf("Cannot get Root Folder pointer: %x", hr );
        pService->lpVtbl->Release(pService);
        CoUninitialize();
        return 1;
    }
   
    // If the same task exists, remove it.
    pRootFolder->lpVtbl->DeleteTask(pRootFolder, (wchar_t*)wszTaskName, 0  );
   
    //  Create the task builder object to create the task.
    ITaskDefinition *pTask = NULL;
    hr = pService->lpVtbl->NewTask(pService, 0, &pTask );
   
    pService->lpVtbl->Release(pService);  // COM clean up.  Pointer is no longer used.
    if (FAILED(hr))
    {
        printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
        pRootFolder->lpVtbl->Release(pRootFolder);
        CoUninitialize();
        return 1;
    }
           
    //  ------------------------------------------------------
    //  Get the registration info for setting the identification.
    IRegistrationInfo *pRegInfo= NULL;
    hr = pTask->lpVtbl->get_RegistrationInfo(pTask, &pRegInfo );
    if( FAILED(hr) )
    {
        printf("\nCannot get identification pointer: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();       
        return 1;
    }
   
    hr = pRegInfo->lpVtbl->put_Author(pRegInfo, L"Author Name" );
    pRegInfo->lpVtbl->Release(pRegInfo);  // COM clean up.  Pointer is no longer used.
    if( FAILED(hr) )
    {
        printf("\nCannot put identification info: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }
   
    //  ------------------------------------------------------
    //  Get the trigger collection to insert the daily trigger.
    ITriggerCollection *pTriggerCollection = NULL;
    hr = pTask->lpVtbl->get_Triggers(pTask, &pTriggerCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get trigger collection: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }
       
    //  Add the daily trigger to the task.
    ITrigger *pTrigger = NULL;   
    hr = pTriggerCollection->lpVtbl->Create(pTriggerCollection, TASK_TRIGGER_DAILY, &pTrigger );
    pTriggerCollection->lpVtbl->Release(pTriggerCollection);
    if( FAILED(hr) )
    {
        printf("\nCannot create the trigger: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }     
   
    IDailyTrigger *pDailyTrigger = NULL;
    hr = pTrigger->lpVtbl->QueryInterface(pTrigger,
        &IID_IDailyTrigger, (void**) &pDailyTrigger );
    pTrigger->lpVtbl->Release(pTrigger);
    if( FAILED(hr) )
    {
        printf("\nQueryInterface call on IDailyTrigger failed: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }
   
    hr = pDailyTrigger->lpVtbl->put_Id(pDailyTrigger, L"Trigger1" );
    if( FAILED(hr) )
        printf("\nCannot put trigger ID: %x", hr);

    //  Set the task to start daily at a certain time. The time
    //  format should be YYYY-MM-DDTHH:MM:SS(+-)(timezone).
    //  For example, the start boundary below
    //  is January 1st 2005 at 12:05
    hr = pDailyTrigger->lpVtbl->put_StartBoundary(pDailyTrigger, L"2005-01-01T12:05:00" );
    if( FAILED(hr) )
        printf("\nCannot put start boundary: %x", hr);
   
    //  Set the time when the trigger is deactivated.
    hr = pDailyTrigger->lpVtbl->put_EndBoundary(pDailyTrigger, L"2007-05-02T12:05:00" );
    if( FAILED(hr) )
        printf("\nCannot put the end boundary: %x", hr);
 
    //  Define the interval for the daily trigger. An interval of 2 produces an
    //  every other day schedule
    hr = pDailyTrigger->lpVtbl->put_DaysInterval(pDailyTrigger, (short)2 );
    if( FAILED(hr) )
    {
        printf("\nCannot put days interval: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pDailyTrigger->lpVtbl->Release(pDailyTrigger);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }

    // Add a repetition to the trigger so that it repeats
    // five times.
    IRepetitionPattern *pRepetitionPattern = NULL;
    hr = pDailyTrigger->lpVtbl->get_Repetition(pDailyTrigger, &pRepetitionPattern );
    pDailyTrigger->lpVtbl->Release(pDailyTrigger);
    if( FAILED(hr) )
    {
        printf("\nCannot get repetition pattern: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }
   
    hr = pRepetitionPattern->lpVtbl->put_Duration(pRepetitionPattern, L"PT4M");
    if( FAILED(hr) )
    {
        printf("\nCannot put repetition duration: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pRepetitionPattern->lpVtbl->Release(pRepetitionPattern);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }

    hr = pRepetitionPattern->lpVtbl->put_Interval(pRepetitionPattern, L"PT1M");
    pRepetitionPattern->lpVtbl->Release(pRepetitionPattern);
    if( FAILED(hr) )
    {
        printf("\nCannot put repetition interval: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }   
 

    //  ------------------------------------------------------
    //  Add an action to the task. This task will execute notepad.exe.     
    IActionCollection *pActionCollection = NULL;

    //  Get the task action collection pointer.
    hr = pTask->lpVtbl->get_Actions(pTask, &pActionCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get task collection pointer: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }
       
    //  Create the action, specifying that it is an executable action.
    IAction *pAction = NULL;
    hr = pActionCollection->lpVtbl->Create(pActionCollection, TASK_ACTION_EXEC, &pAction );
    pActionCollection->lpVtbl->Release(pActionCollection);
    if( FAILED(hr) )
    {
        printf("\nCannot create action: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }

    IExecAction *pExecAction = NULL;
    hr = pAction->lpVtbl->QueryInterface(pAction,
        &IID_IExecAction, (void**) &pExecAction );
    pAction->lpVtbl->Release(pAction);
    if( FAILED(hr) )
    {
        printf("\nQueryInterface call failed for IExecAction: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }

    //  Set the path of the executable to notepad.exe.
    hr = pExecAction->lpVtbl->put_Path(pExecAction, (wchar_t *)wstrExecutablePath );
    pExecAction->lpVtbl->Release(pExecAction);
    if( FAILED(hr) )
    {
        printf("\nCannot put the executable path: %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        return 1;
    }

    //  ------------------------------------------------------
    //  Securely get the user name and password. The task will
    //  be created to run with the credentials from the supplied
    //  user name and password.
    CREDUI_INFOW cui;
    WCHAR pszName[CREDUI_MAX_USERNAME_LENGTH] = L"";
    WCHAR pszPwd[CREDUI_MAX_PASSWORD_LENGTH] = L"";
    BOOL fSave;
    DWORD dwErr;

    cui.cbSize = sizeof(CREDUI_INFO);
    cui.hwndParent = NULL;
    //  Ensure that MessageText and CaptionText identify
    //  what credentials to use and which application requires them.
    cui.pszMessageText = L"Account information for task registration:";
    cui.pszCaptionText = L"Enter Account Information for Task Registration";
    cui.hbmBanner = NULL;
    fSave = FALSE;

    //  Create the UI asking for the credentials.
    dwErr = CredUIPromptForCredentialsW(
        &cui,                             //  CREDUI_INFO structure
        L"",                         //  Target for credentials
        NULL,                             //  Reserved
        0,                                //  Reason
        pszName,                          //  User name
        CREDUI_MAX_USERNAME_LENGTH,       //  Max number for user name
        pszPwd,                           //  Password
        CREDUI_MAX_PASSWORD_LENGTH,       //  Max number for password
        &fSave,                           //  State of save check box
        CREDUI_FLAGS_GENERIC_CREDENTIALS |  //  Flags
        CREDUI_FLAGS_ALWAYS_SHOW_UI |
        CREDUI_FLAGS_DO_NOT_PERSIST); 

    if(dwErr)
    {
        printf("Did not get credentials.\n");
        CoUninitialize();
        return 1;     
    }
   
    //  ------------------------------------------------------
    //  Save the task in the root folder.
VariantInit(&v1);
VariantInit(&v2);
VariantInit(&v3);
v1.vt = VT_BSTR;
v1.bstrVal = SysAllocString(pszName);
v2.vt = VT_BSTR;
v2.bstrVal = SysAllocString(pszPwd);

    IRegisteredTask *pRegisteredTask = NULL;
    hr = pRootFolder->lpVtbl->RegisterTaskDefinition(pRootFolder,
            (wchar_t *)wszTaskName,
            pTask,
            TASK_CREATE_OR_UPDATE,
            v1, //_variant_t(_bstr_t(pszName)),
            v2, //_variant_t(_bstr_t(pszPwd)),
            TASK_LOGON_PASSWORD,
            v3, //_variant_t(L""),
            &pRegisteredTask);
    if( FAILED(hr) )
    {
        printf("\nError saving the Task : %x", hr );
        pRootFolder->lpVtbl->Release(pRootFolder);
        pTask->lpVtbl->Release(pTask);
        CoUninitialize();
        SecureZeroMemory(pszName, sizeof(pszName));
        SecureZeroMemory(pszPwd, sizeof(pszPwd));
        return 1;
    }

    printf("\n Success! Task successfully registered. " );

    //  Clean up
    pRootFolder->lpVtbl->Release(pRootFolder);
    pTask->lpVtbl->Release(pTask);
    pRegisteredTask->lpVtbl->Release(pRegisteredTask);
    CoUninitialize();
    SecureZeroMemory(pszName, sizeof(pszName));
    SecureZeroMemory(pszPwd, sizeof(pszPwd));
    return 0;
}
#99
Work in progress / Re: Task Schedule 2.0
Last post by Vortex - December 09, 2025, 11:26:23 AM
Timo's work is nice. Additionaly, MrBcx created some useful applications too :

https://bcxbasiccoders.com/smf/index.php?topic=1443.0
#100
Work in progress / Re: Task Schedule 2.0
Last post by John Z - December 09, 2025, 11:21:21 AM
Timo - wow,

This is very interesting work. When I get through some other things I'll grab it.

In the past I've used vbs and ps scripts to enable applications to set schedules.  Your work might lead to using straight C to do the same thing.


John Z