Jump to content











Photo
- - - - -

Understanding the internals of the API...


  • Please log in to reply
6 replies to this topic

#1 sbaeder

sbaeder

    Gold Member

  • .script developer
  • 1338 posts
  • Location:usa - massachusettes
  •  
    United States

Posted 05 January 2011 - 04:17 AM

So, in the discussion of the future of the API, I learned that the WAND info comes from the API File...at least that is what I think was the point of Homes32 in pointing out how many lines went to that...

OK, so how does WB know which things are for the wand and which ones to "skip"...

For example, I see

[Api_Def]

%APIVAR%=ApiVar

%APIDEF%=API

%APISUBDEF%=_Calculate,AddAutoRun,*AddPostConfig,*AddPreConfig...

Is this how WB finds the section names used to add to the wand? And why it can "skip" the section with "CANCELLED" in it? (since there is no name like that inside the variable

[CapiC]

FileDelete="CapiC,FileDelete,<file>   (DO NOT USE WILDCARDS (? and *)"

DirDelete="CapiC,DirDelete,<directory>   (DO NOT USE WILDCARDS (? and *))"

ConvertToAnsi="CapiC,ConvertToAnsi,<file>,[<tofile>]"

VariableToMacro="CapiC,VariableToMacro,<macrovariable>,<parameter1>,<parameter2>,<parameter3>,<parameter4>"



[CapiC_CANCELLED]

Copy="CapiC,Copy,<source>,<target>,[Directory][File][All],[ExcludeList]"

Exist="CapiC,Exist,CheckFile|CheckDir,<file>|<Dir>,[VariableName]"

And is it also why the API for "CheckCD, while defined, doesn't have a wand entry?

That would all seem to make sense...i.e. that the section [API_DEF] has the pointer to the APIVAR, which has more normal variables as well as a mapping of the actual API commands, many of them just implemented as "Run" commands into the API script file. The APISUBDEF variable has a listing of the section names to use for the MagicWand...BUT, a trial and error says this ISN'T the case...

I can add text to the wand that shows up below any of the currently defined items (i.e. add another line inside _Calculate), but I can't seem to make it add another routine... :unsure: So how is that done, if not based on the definition of the APISUBDEF? Do I have to somehow refresh WB? Or will it load this (somehow) when the project is loaded? or do I have to execute the project at least once for the Wand to be effective or ???

And also, what is the purpose of the APIDEF variable?

Eventually, maybe I can put all this into a neater format...since I think this would be good to have documented...

Scott

#2 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 05 January 2011 - 02:42 PM

I'm currently rather busy with other things. Therefore please excuse that I do not take the time to explain.
But maybe the source code helps a bit:
procedure TForm1.ApiMenu(project: string);

var

  i, j, p: integer;

  subitm, itm, api: TMenuItem;

  men: TPopupMenu;

  apiscript, apidef, apivar, apisub: string;

  ini: TIniFile;

  subs, cmds: TStringList;

  sub, cmd: string;

  capt: string;

  delete: boolean;

  TempRunner: TScriptRunner;

begin

  //  First free an eventually present menu entry

  men := PluginEdit.Popup_Source;

  delete := false;

  for i := men.Items.Count - 1 downto 0 do

  begin

    itm := men.Items[i];

    if delete then

    begin

      Men.Items.Remove(itm);

      delete := true;

    end

    else

    begin

      capt := AnsiReplaceText(itm.Caption, &#39;&&#39;, &#39;&#39;);

      if AnsiSameText(capt, &#39;API&#39;) then

      begin

        Men.Items.Remove(itm);

        delete := False;

      end

    end;

  end;

  // Create a &#39;quick&#39; Scriptrunner. It does do only the functions necessary here

  TempRunner.Create(&#39;&#39;, &#39;&#39;, &#39;&#39;, project, &#39;&#39;, Form1.ProgressBar1, Form1.ProgressBar3, lblComment, Log_box.lvLog,

    log_box.lvVariables, tvProgress, True);

  TempRunner.refreshGlobals := True;

  TempRunner.buildScriptVars;

  // now the name of the API section

  apiscript := TempRunner.scriptVars.TranslateVars(&#39;%API%&#39;, &#39;%&#39;);

  CodeBoxAPI := &#39;&#39;;

  hasAPI := False;

  if apiscript <> &#39;%API%&#39; then // Only if %API% is defined

  begin

    apidef := TempRunner.scriptVars.TranslateVars(&#39;%APIDEF%&#39;, &#39;%&#39;);

    apivar := TempRunner.scriptVars.TranslateVars(&#39;%APIVAR%&#39;, &#39;%&#39;);

    apisub := TempRunner.scriptVars.TranslateVars(&#39;%APISUBDEF%&#39;, &#39;%&#39;);

    if apidef <> &#39;%APIDEF%&#39; then // Only if %APIDEF% is defined

    begin

      // we have to create the menu

      api := TMenuItem.Create(men);

      api.Caption := &#39;-&#39;;

      men.Items.Add(api);

      api := TMenuItem.Create(men);

      api.Caption := apidef;

      men.Items.Add(api);

      CodeBoxAPI := &#39;AddVariables,"&#39; + apiscript + &#39;",&#39; + apivar + &#39;,GLOBAL&#39;;

      cmds := TStringList.Create;

      ini := TiniFile.Create(apiscript);

      ini.ReadSectionValues(apidef, cmds);

      for i := 0 to cmds.Count - 1 do

      begin

        cmd := cmds[i];

        p := AnsiPos(&#39;=&#39;, cmd);

        itm := TMenuItem.Create(api);

        itm.Caption := AnsiLeftStr(cmd, p - 1);

        itm.Hint := AnsiMidStr(cmd, p + 1, MaxInt);

        itm.OnClick := PluginEdit.APIClick;

        api.add(itm);

      end;

      if apisub <> &#39;%APISUBDEF%&#39; then

      begin

        subs := TStringList.Create;

        subs.CommaText := apisub;

        for i := 0 to subs.Count - 1 do

        begin

          sub := subs[i];

          itm := TMenuItem.Create(api);

          itm.Caption := sub;

          api.add(itm);

          ini.ReadSectionValues(sub, cmds);

          for j := 0 to cmds.Count - 1 do

          begin

            cmd := cmds[j];

            p := AnsiPos(&#39;=&#39;, cmd);

            subitm := TMenuItem.Create(itm);

            subitm.Caption := AnsiLeftStr(cmd, p - 1);

            subitm.Hint := AnsiMidStr(cmd, p + 1, MaxInt);

            subitm.OnClick := PluginEdit.APIClick;

            itm.add(subitm);

          end;

        end;

        subs.Free;

      end;

      cmds.Free;

      ini.Free;

      hasAPI := True;

    end;

  end;

  // now free all grabbed ressources

  TempRunner.FreeAll;

end;


Peter

#3 homes32

homes32

    Gold Member

  • .script developer
  • 1035 posts
  • Location:Minnesota
  •  
    United States

Posted 05 January 2011 - 07:20 PM

Ok here it goes.
we will start by looking at what makes the common api "turn on"

If you look in script.project you will see the following lines


//-- API File and Some Api project settings

%API%=%ProjectDir%\Build\Common_Api.script

this line tells us what file contains the api


%APIVAR%=ApiVar

this is the name of the section in common_api that contains that actual definitions of the api commands. aka what to do when you Add_shortcut etc.
we will look at this section in the common api later.


%APIDEF%=API

this is simply the name that will be displayed for the api menu in the magic wand


%API_TYPE%=2

this variable is used to tell the common api that we are project type 2 (Vista/Win7) and is used to decide what functions in the common api to run when a command is called.
1=Gena/LiveXP/NativeEx/PE1 based projects
2=Vista/Win7 based projects
98=Windows98 based projects


%APISUBDEF%=_Calculate,AddAutoRun,*AddPostConfig,*AddPreConfig,*AddToPEShell,Add_Shortcut,Add_Asso,*Add_Pin,Add_URL,Arch,Associate_File,Ask_License,CapiC,*CopyDrv,CopyProgram,ExtractAndRunc,Others,*ReadENV,Registry,Require_File,*RequireSysFile,RunFrom,Unpack,Variable

this is the api submenu definitions. each entry is a top level menu in the api menu


[Process]

AddVariables,%API%,ApiVar,GLOBAL

this command loads all commands in the common_api.script [ApiVar] as GLOBAL. we will get into this a bit more later. but know that this needs to happen in order for scripts to use the common api commands.


Ok now on to Common_API.script


[Api_Def]

%APIVAR%=ApiVar

%APIDEF%=API

%APISUBDEF%=_Calculate,AddAutoRun,*AddPostConfig,*AddPreConfig,*AddToPEShell,Add_Shortcut,Add_Asso,*Add_Pin,Add_URL,Arch,Associate_File,Ask_License,CapiC,*CopyDrv,CopyProgram,ExtractAndRunc,Others,*ReadENV,Registry,Require_File,*RequireSysFile,RunFrom,Unpack,Variable

this section doesn't do anything. it is simply a reminder that you need to set these variables in script.project in order to use the Common api
editing this section will not do anything!!!!!!!



[ApiVar]

%ToRoot%=

%CapiArchApi%=

%CapiAdd_ShortcutProcess%=

%CapiSubFoldersToRoot%=Falsy

%CapiNoShortcutSubfolders%=

%CapiBSExplorerFix%=Nope

%CapiNowarnPreserveNodebugwarn%=

%reg_temp%=wb-hive

%reg%=%reg_temp%

%CopyMui%=Off

%WarnWhenSetApi%=False

%Shc_Mode%=0

_Calculate=Run,%API%,Calculate

Add_Asso=Run,%API%,Association%API_TYPE%

Add_Shortcut=Run,%API%,AddShortcut%Capi_Shortcut_TYPE%%CapiAdd_ShortcutProcess%

Add_Pin=Run,%Api%,Add_Pin_Process%API_TYPE%

Add_URL=Run,%API%,Add_URL%API_TYPE%

AddAutoRun=Run,%API%,Add_Auto_Run%API_TYPE%

AddPostConfig=Run,%API%,Add_Post_Config%API_TYPE%

----ETC ETC ETC---------

this is the section we defined with the line %APIVAR%=ApiVar back in script.project
and loaded into memory with the command
[Process]

AddVariables,%API%,ApiVar,GLOBAL

this is the part where the commands actually get mapped to their functions.

an easy way to think of it is that whenever winbuilder sees the command _Calculate in any script it internally replaces the _Calculate with Run,%API%,Calculate which will execute the [Calculate] section in %API% which we defined earlier in script.project as being %ProjectDir%\Build\Common_Api.script


next we define the menu entries for the magic wand

[API]

[_Calculate]

Full Syntax="//_Calculate,AutoIT Command(expression),ReturnVar(without %)"

Note="//Allways use simple quote in expression ,use [#$c] in place of [,] and use  %ReturnVar% (with %) as result in your code . See AutoIT doc"

-=

MsgBox="_Calculate,MsgBox(2#$c&#39;Test Calculate&#39;#$c&#39;Choice:&#39;#$c5),Choice"

InputBox="_Calculate,InputBox(&#39;Question&#39;#$c &#39;Where were you born?&#39;#$c &#39;Planet Earth&#39;#$c &#39;&#39;#$c -1#$c -1#$c -1#$c -1),Answer"



[Add_URL]

Default Value="Add_URL,Favorites,<filename>,<webaddress>"

Full Syntax="Add_URL,[Favorites][Links]<TargetPath>,<filename>,<webaddress>,[UrlDll][None]<url icon address>,[None]<IconIndex>,[None]<HotKey>"

-=

Sample Favorites="Add_Url,,Google.url,http://www.google.com"

Sample Links="Add_Url,Links,Google.url,http://www.google.com"

-=

Sample Favorites SubF="Add_Url,Favorites\My Folder,Google.url,http://www.google.com"

Sample AnyFolder="Add_Url,%target_win%,Google.url,http://www.google.com"

Sample Icon Url.dll="Add_Url,,Google.url,http://www.google.com,UrlDLL"

Sample Icon Ico="Add_Url,,Google.url,#$psystemroot#$p\system32\blabla.ico"



[*Add_Pin]

Full Syntax="//Add_Pin,Type,Order(0,1,2,..,8,9),(path\)FileName,Title,Work Folder,Parameters,(path\)IconFile#$cIconIndex,StartMode=(1,2,3)#$cHotKey,ToolTipText"

Default Value="Add_Pin,StartMenu,,%PE_Programs%\%ProgramFolder%\%ProgramExe%,%ProgramTitle%"

-=

Sample File="Add_Pin,Taskbar,,#$pSystemRoot#$p\calc.exe"

Sample Lnk="Add_Pin,StartMenu,0,"$Desktop\My Computer.lnk""

-=

StartMenu="Add_Pin,StartMenu"

TaskBar="Add_Pin,Taskbar"

the line [API] doesn't do anything. its just a reminder to developers that the next sections are menu definitions and not actually functions

now you will se a bunch of sections all with names corresponding to the submenus we defined in %APISUBDEF%
this is where we actually define the commands to be displayed in the API magic wand menu

when winbuilder builds the api menu it looks at %APISUBDEF% and makes the top level entries based on the contents of this variable. next it looks for sections with the name of the top level entries and fills the top level menus with the lines in each section.
the sections are layed out like so:
name of command as shown in api menu = command to paste into the code editor when you select the command.
-= makes a line/divider.


and thats the quick and dirty to the common api. the rest of the code is functions for actually doing the work.



answers to specific questions

OK, so how does WB know which things are for the wand and which ones to "skip"...

winbuilder does not scan the sections. it only displays the contents of the section referenced by the corresponding name defined in %APISUBDEF%

And is it also why the API for "CheckCD, while defined, doesn't have a wand entry?

because it is not listed in any of the sections referenced by %APISUBDEF%

I can't seem to make it add another routine... :sos: So how is that done, if not based on the definition of the APISUBDEF? Do I have to somehow refresh WB? Or will it load this (somehow) when the project is loaded? or do I have to execute the project at least once for the Wand to be effective or ???

APISUBDEF is only used by winbuilder itself for building the API menu entries
routines/functions are added in the [ApiVar] section


hope it helps. I know its a lot of information to absorb all at once.

-Homes32

#4 sbaeder

sbaeder

    Gold Member

  • .script developer
  • 1338 posts
  • Location:usa - massachusettes
  •  
    United States

Posted 05 January 2011 - 07:40 PM

I'm currently rather busy with other things. Therefore please excuse that I do not take the time to explain.
But maybe the source code helps a bit:

Thanks - I don't really know delphi :-) But doesn't look too terrible...let me look it over, and if further questions, I'll ask...

One quick thing...When does this get executed? i.e. if there are multiple projects inside WB, when does this get executed?

APISUBDEF is only used by winbuilder itself for building the API menu entries
routines/functions are added in the [ApiVar] section


hope it helps. I know its a lot of information to absorb all at once.

THANKS...To Both (ALL?) of you for the information...

From all of this, it is now a lot clearer, and it looks like there is definitely room for some cleanups and maybe other code changes, but I'm starting to see how it all works :sos:

While reading through the code last night was a bit 'scary', this is certainly interesting to see not only how the system provided a way to have documentation provided to the end user, but also seeing what is done in each of the individual API functions...


Scott

#5 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 05 January 2011 - 07:59 PM

One quick thing...When does this get executed? i.e. if there are multiple projects inside WB, does it wait until the API script has been called? Or when it starts up or ???

It is executed when you either click the "Edit" green triangle or click the "Codebox" tab, that means, just before you get any "magic wand".
And due to your question: It is allways referring the actual project (and corresponding API).

Peter

#6 pscEx

pscEx

    Platinum Member

  • Team Reboot
  • 12707 posts
  • Location:Korschenbroich, Germany
  • Interests:What somebody else cannot do.
  •  
    European Union

Posted 05 January 2011 - 08:29 PM

Ok here it goes.

Thanks, Homes32! :sos:

You explained in detail what I refused in my previous post because of not having the time for that!
And I think, that there is nothing important to add to your post!

Peter :thumbsup:

#7 sbaeder

sbaeder

    Gold Member

  • .script developer
  • 1338 posts
  • Location:usa - massachusettes
  •  
    United States

Posted 05 January 2011 - 08:34 PM

It is executed when you either click the "Edit" green triangle or click the "Codebox" tab, that means, just before you get any "magic wand".
And due to your question: It is allways referring the actual project (and corresponding API).

Peter

Thanks !




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users