winapiexec

winapiexec is a small tool that allows to run WinAPI functions through command line parameters.

Syntax

The syntax is:
winapiexec.exe library.dll@FunctionName 123 unicode_text "a space"

If you don’t specify a library or use “k”, kernel32.dll is used.
If you specify “u” as a library, user32.dll is used.

Numbers are detected automatically. You can use hex numbers (like 0xFE) and use the minus sign (e.g. -5).
Strings are Unicode by default.

You can use special prefixes to specify parameter types:
$s:ansi – an ANSI string.
$u:unicode – a Unicode string (it’s Unicode by default, but you can use it to force numbers as strings).
$b:1024 – a zero-bytes buffer with the size you specify, in bytes.
$$:1 – a reference to another parameter, you can also use $$:0 for the program’s name (argv[0]).
$a:0,1,two,3 – an array of parameters, divided by commas. You can use all the prefixes here. Each parameter is a 32-bit number (64-bit for winapiexec64).
$a[1,2,$a[3,4],5] – an alternative syntax for an array of parameters. Allows to have nested arrays.
$$:3@2 – a reference to an item in an array of parameters, can have more than one indirection.

While referencing another parameter, note that they are processed by the order of execution, which means there’s no point to reference a parameter at the right side relative to the referencing one.
Also note that when a function returns, its first parameter (like library.dll@FunctionName) is replaced with the return value.

You can execute multiple WinAPI functions, one after the other, using a comma:
winapiexec.exe library.dll@FunctionName1 123 , library.dll@FunctionName2 456
You can also have nested functions, using parentheses:
winapiexec.exe library.dll@FunctionName1 ( library.dll@FunctionName2 456 )
In this case the return value of the internal function is passed as a parameter to the external function.

Download

zip winapiexec.zip (6.02 kB)

Source code

https://github.com/m417z/winapiexec

Examples

Here are some examples of what you can do:

Display temp path:
winapiexec.exe GetTempPathW 260 $b:520 , u@MessageBoxW 0 $$:3 $$:0 0x40

Greetings:
winapiexec.exe advapi32.dll@GetUserNameW $b:65534 $a:32767 , u@wsprintfW $b:2050 "Hello %s from %s" $$:2 $$:0 , u@MessageBoxW 0 $$:6 ... 0

Hide the taskbar for half a second, then show it:
winapiexec.exe u@ShowWindow ( u@FindWindowW Shell_TrayWnd 0 ) 0 , Sleep 500 , u@ShowWindow $$:3 5

Run Notepad for a second, then terminate it:
winapiexec.exe CreateProcessW 0 notepad.exe 0 0 0 0x20 0 0 $a:0x44,,,,,,,,,,,,,,,, $b:16 , Sleep 1000 , TerminateProcess $$:11@0 0

Show a message box and then create a new instance of the process:
winapiexec.exe u@MessageBoxW 0 Hello! :) 0 , CreateProcessW $$:0 ( GetCommandLineW ) 0 0 0 0x20 0 0 $a:0x44,,,,,,,,,,,,,,,, $b:16

Eject your disc drive 🙂
winapiexec.exe winmm.dll@mciSendStringW "open cdaudio" 0 0 0 , winmm.dll@mciSendStringW "set cdaudio door open" 0 0 0 , winmm.dll@mciSendStringW "close cdaudio" 0 0 0

And several more practical examples…

Copy some text into the clipboard:
winapiexec.exe lstrcpyW ( GlobalLock ( GlobalAlloc 0x0042 8192 ) ) "Sample text" , GlobalUnlock $$:5 , u@OpenClipboard 0 , u@SetClipboardData 13 $$:5 , u@CloseClipboard

Turn off and on monitor:
winapiexec.exe u@SendMessageW 0xFFFF 0x112 0xF170 2
winapiexec.exe u@SendMessageW 0xFFFF 0x112 0xF170 -1

Clear the icon cache:
winapiexec.exe shell32.dll@SHChangeNotify 0x08000000 0 0 0

Display the Start menu:
winapiexec.exe u@SendMessageW ( u@FindWindowW Shell_TrayWnd 0 ) 0x111 305 0
Run task manager:
winapiexec.exe u@SendMessageW ( u@FindWindowW Shell_TrayWnd 0 ) 0x111 420 0
More tricks like the last two can be found here.

Posted in Releases, Software by Michael (Ramen Software) on January 8th, 2011.
Tags:

222 Responses to “winapiexec”

  1. BeGreenMedia says:

    I love this tool! Thank you Michael!

    I want to create a shortcut for a file selected with right click in Explorer in My Shortcuts folder it’s possible with this tool?

  2. KT says:

    Hello RaMMicHaeL

    I’m trying to find a method in cmd.exe for getting an effect immediately after updating windows registry (system environment vars) and that needs send windows api as below.

    SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) “Environment”, SMTO_ABORTIFHUNG, 5000, &dwReturnValue);

    Then could you take a look below command. It doesn’t work.

    winapiexec.exe u@SendMessageTimeoutW HWND_BROADCAST WM_SETTINGCHANGE 0 (LPARAM) “Environment” SMTO_ABORTIFHUNG 5000 &dwReturnValue

    • Hi,

      The translation for your C code is:
      winapiexec.exe u@SendMessageTimeoutW 0xFFFF 0x1A 0 Environment 2 5000 $b:16

      • KT says:

        Thank you for the quick respond. However I’m not sure the translated command is working properly.

        I tried to add a new path to the value of “Path” in below registry keys.
        – HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

        HKEY_CURRENT_USER\Environment

        Then, did the command and echo %path% in cmd.exe.

        But the new path wasn’t added.

        How can I make sure it is right ?
        Or, Isn’t my C code which has been provided via Microsoft web page appropriate ?

        • How can I make sure it is right ?

          You can check it with a debugger such as OllyDbg. Actually I did that before posting the code.

          Or, Isn’t my C code which has been provided via Microsoft web page appropriate ?

          That’s probably what’s happening. You can try compiling it with a C compiler and checking it to be sure.

          • KT says:

            Thanks for the advice. I’ll check it.

            And One more question. What is the reference for translating C to the command for winapiexec.exe which would become very useful tool for me if I could make the most of it.

            Since I’m new to C and winapiexec.exe, I can’t find where “HWND_BROADCAST”, “WM_SETTINGCHANGE”, “SMTO_ABORTIFHUNG” has disappeared.

            • I can’t find where “HWND_BROADCAST”, “WM_SETTINGCHANGE”, “SMTO_ABORTIFHUNG” has disappeared.

              These are constants. You can find out their values in your compiler. Also, usually Googling something along the lines of “define HWND_BROADCAST” works.
              winapiexec is a tiny tool, 4 kB in size, so it’s not familiar with all these constants and their values.

  3. Monte says:

    Hu RaMMicHael!

    How to, for example, translate the following call to winapiexec variant?
    rundll32.exe shell32.dll,Control_RunDLL hotplug.dll

    “winapiexec shell32.dll@Control_RunDLL hotplug.dll” throws “Stack error on argument number 1” and opens Control Panel. Could you please look into it?

  4. auvist says:

    Hi,

    I see several “u@MessageBoxW” examples, but it would be useful to be able to get some output directly in the console where winapiexec.exe is run. Any ideas how to achieve this?

    For example:

    “winapiexec.exe advapi32.dll@GetUserNameW $b:65534 $a:32767 , u@wsprintfW $b:2050 “Hello %s from %s” $$:2 $$:0 , u@MessageBoxW 0 $$:6 … 0″

    from the description to be logically equivalent to:

    “winapiexec.exe advapi32.dll@GetUserNameW $b:65534 $a:32767 , u@wsprintfW $b:2050 “Hello %s from %s” $$:2 $$:0 , ?@??functionToPrintToConsole?? $$:6

    and print the “Hello …” text directly in the cmd.exe window where this command is run.

    And a second question: is it possible to get the value referenced by a pointer?
    For example “winapiexec.exe k@QueryPerformanceCounter $b:4, u@MessageBoxW 0 $$:2 text 0” returns the address, but it would be nice to dereference it and get the value

    • it would be useful to be able to get some output directly in the console where winapiexec.exe is run. Any ideas how to achieve this?

      Here you go:
      winapiexec.exe advapi32.dll@GetUserNameW $b:65534 $a:32767 , u@wsprintfW $b:2050 "Hello %s from %s" $$:2 $$:0 , AttachConsole -1 , WriteConsoleW ( GetStdHandle -11 ) $$:6 ( lstrlenW $$:6 ) $b:4 0

      See also this comment:
      http://rammichael.com/winapiexec/comment-page-1#comment-4420

      is it possible to get the value referenced by a pointer?

      You can use $b:4@0 and $b:4@1 to get the low and high double words of the large integer, respectively. Note that it’s a 64-bit integer, so you also need to use $b:8, not $b:4. And you’re missing a space after $b:4, which is critical.

  5. Sam says:

    Hi RaMMicHaeL,

    Firstly, thank you for creating such awesome software tools and sharing them and your knowledge with the world for free! I can’t live without 7+ Taskbar Tweaker anymore! 🙂

    I’ve been using winapiexec for some time now in conjunction with Samurize to show the systray clock calendar. However, since I moved to Win10 this has stopped working.

    The command I had been using was:
    winapiexec u@PostMessageW ( u@FindWindowExW ( u@FindWindowExW ( u@FindWindowW Shell_TrayWnd 0 ) 0 TrayNotifyWnd 0 ) 0 TrayClockWClass 0 ) 0x466 1 0

    I can’t remember where I got that command line, and I have no idea where I could go to find an updated version which works with Win10.

    If you could please direct me to where I could find this information or to an updated command to execute this function I would be most grateful!

    Thanks,

    Sam.

  6. am96 says:

    please tell me some more good & tricky example uses of winapiexec

  7. am96 says:

    PLEASE specify all possible uses of winapi & make some help file too
    i m finding it difficult to generate winapi commands. Any src to easily write such commands

  8. am96 says:

    how can i take screenshot with this app

  9. am96 says:

    HOW 2 DISPLAY WINDOW TASKAR NOTIFICATIONS WITH THIS APP

  10. Conquoro says:

    Hi Michael, wonderful is your work.. this is not working to attach a vhd. where am i wrong..
    winapiexec64.exe virtdisk.dll@OpenVirtualDisk $a:2,0 “C:\Test.vhd” 0x00020000 0 0 $b:4 , virtdisk.dll@AttachVirtualDisk $$:7@0 0 0 0 1 0

    • Hi Conquoro,
      I see at least two critical issues with your command:
      1. Since you’re using winapiexec64, a handle requires 8 bytes, so the last parameter of the OpenVirtualDisk function should be $b:8.
      2. The parameter of the AttachVirtualDisk function where you pass 1 requires a pointer. Of course 1 is not a valid pointer.

      • Conquoro says:

        thank you for a quick reply..
        after messing for a while,
        Attach VHD by winapiexec.exe finally worked..

        winapiexec64.exe virtdisk.dll@OpenVirtualDisk $a:2,0 “C:\Test.vhd” 0x00020000 0 0 $b:4 , virtdisk.dll@AttachVirtualDisk $$:7@0 0 0x00000004 0 0 0

      • Conquoro says:

        cool.. i have changed $b:4 to $b:8 as you corrected, though $b:4 is working fine..

        • You were just lucky. By specifying $b:4, you’re asking for at least 4 bytes. You might get more sometimes but you can’t rely on it. It’s also possible that you get only 4 bytes and then you override 4 other bytes you don’t own. Again, you can be lucky and it might not do any harm, but it might also have negative effects such as crashing the process before the mount takes place.

          • tefod says:

            can u guys give me a hint, how to mount a .vhdx container? trying since a few hours 😶
            I guess I have to define the Version 2 in the OPEN_VIRTUAL_DISK_PARAMETERS – but were not able to define/create the parameters.
            Could you help me with a working example? Thx..

  11. Fiddler says:

    I want to retrieve the bitness of notepad++.exe. I tried the following:

    winapiexec k@GetBinaryTypeW “C:\Program Files (x86)\Notepad++\notepad++.exe” $b:4 , u@wsprintfW $b:32 “Type: %d” $$:3 , u@MessageBoxW 0 $$:6 … 0

    Instead of using $$:3 I used $$:1 in the call to wsprintfW and was able to verify that the call to GetBinaryTypeW succeeds. But when using $$:3 the result is only random garbage. What is wrong?

    • Replace $$:3 with $$:3@0 🙂 $$:3 is not random garbage, but the address of the 4-bytes buffer.
      Let me know if you’d like a more detailed explanation.

      • Fiddler says:

        Ahh, thank you for your quick response and providing the solution. Sometimes the easiest things don’t come to mind.

        In the next step I would like to return the result of GetBinaryTypeW to the caller (a VBScript or Batch script). I could do that by allocating a console, printing the result to that console and parse the output by redirecting StdOut.

        But winapiexec can also return an integer value as return code. Do you have any idea how I can use that method?

  12. janxp says:

    Good day.
    How to put the result of this function to a variable, which can be used in the form of %variable%, such as echo %variable%?
    winapiexec.exe wininet.dll@InternetCanonicalizeUrlW “D:\System\Desktop\Folder  (2)” $b:1024 $a:0x00000400 0x00040000 , AttachConsole -1 , WriteConsoleW ( GetStdHandle -11 ) $$:3 ( lstrlenW $$:3 ) $b:4 0

  13. Matt Belson says:

    This was suggested on another website but I can’t figure out how to do it, how do I run this WinAPI function? SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,”C:\Windows\Fonts\desktop.ini”,0);

    • Try the following:
      winapiexec.exe shell32.dll@SHChangeNotify 4 5 "C:\Windows\Fonts\desktop.ini" 0

      • Matt Belson says:

        Thank you for the quick response! The command seems to go through but it doesn’t do anything unfortunately.
        To be more clear what I’m trying to do, I’m trying to recreate what happens when you go to the Customize tab on a folder, click Change Icon and then click Restore Defaults. The Fonts folder doesn’t show the Customize tab, and after searching for a long time the best answer I could find was here: https://stackoverflow.com/a/31642517

        • Matt Belson says:

          The linked site that I found it mentioned something about including Shlobj.h, is there maybe more that I need to add to the command to get it to work?

        • I’m not sure how to do what you’re trying to do, but the comments under the linked answer imply that the solution doesn’t work.

          The linked site that I found it mentioned something about including Shlobj.h

          You don’t need that for winapiexec, it’s for using the code in C/C++.

          • Matt Belson says:

            Yeah, one of the comments said it didn’t work, but it supposedly worked for the person who answered originally so I thought it was worth a try.

            I know you only need it for programing, but I didn’t know if there was some line or something in Shlobj.h or Shlwapi.h that had to be added to do it successfully in winapiexec.

            I guess I give up, thanks for your help though!

  14. abb says:

    Hi!
    How to close/destroy a Window where handle is a form title for example “information”?
    SendMessage/WM_CLOSE

  15. neil says:

    I was curious, is it possible to use this to increase the size of the quicklaunch icons in windows 10? they seem to be a bit smaller than other toolbar icons?

    thanks.

  16. neil says:

    OK, I guess I was perhaps getting my names mixed up. The taskbar buttons might be what I’m thinking of, they are slightly smaller than custom toolbar icons. I’ll be using 7TT for the task then 😛

    Thanks for the quick replay and the help.

  17. RFlash says:

    Hello Michael! Thanks for the cool utility!
    How do I run the app in the specified coordinates and sizes? It doesn’t work that way:
    winapiexec.exe CreateProcessW 0 notepad 0 0 0 32 0 0 $a:68,,0,,200,100,640,480,,,,,,,,, $b:16

    • Hi!

      You’re missing the corresponding flags as per the docs: winapiexec.exe CreateProcessW 0 notepad 0 0 0 32 0 0 $a:68,,0,,200,100,640,480,,,,6,,,,, $b:16

      But if you’ll try it, you’ll see that it still doesn’t work. The parameters are passed to the created process, but it’s up to the launched program whether to do anything with them. I’m not sure whether these parameters are still respected by at least some apps, or whether it’s completely legacy at this point.

      On the other hand, using the wShowWindow parameter works, at least for Notepad. For example, this command launches it maximized: winapiexec.exe CreateProcessW 0 notepad 0 0 0 32 0 0 $a:68,,0,,200,100,640,480,,,,7,3,,,, $b:16

      Edit: I see that cmd, for example, respects the position but not the size.

  18. John #2 says:

    So, when I extract to my machine, defender quarantines it and says that winapiexec64.exe is a threat because of “PUA:Win32/Presenoker”

    What’s that about?

    • Hi John,
      It’s a false positive detection, and PUA means “Potentially unwanted application”, which means it’s not an actual threat. It’s probably being detected this way because a while ago, winapiexec was used for malware distribution by some state group. See here and here for details. As they say, this is why we can’t have nice things…

  19. Paul says:

    I occasionally log in to a windows server which has all the notification tray icons hidden / disabled. They just never show up, no matter what I try, and the windows settings menu has reduced access. Would there be a winapiexec command that would show / unhide all the tray icons? I can get 7t tray tweaker to run on this server but just can’t see the icon to access its menus. Any link to a resource that shows what the different APIs do? Thanks.

    • Any link to a resource that shows what the different APIs do?

      You can refer to the Microsoft docs, e.g. FindWindowW, but the amount of APIs is huge.

      Would there be a winapiexec command that would show / unhide all the tray icons?

      I’m not sure, depending on the way the icons are hidden.

      • Paul says:

        Thanks for the link. Some bedtime reading there!

        After further digging, I’ve discovered the server uses group policy / registry settings (HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer) with the NoTrayItemsDisplay item set. And the permissions are set so I can’t change it.

        So that looks unresolvable to me.

  20. Steven says:

    Hi!

    Are you planning on release the source code for this utility?
    If not, would you mind sharing the reason?

    I’d like to know how you go from parsing the command-line to calling into the function of a loaded DLL. For instance, I’d like to know if the function prototypes are generated based on the command-line arguments or are they from the Windows headers, things of that nature.

    • Hi Steven,

      Are you planning on release the source code for this utility?

      I wasn’t planning on doing that. I did prepare a partial version for a journal article a couple of years ago, but it got delayed and at this point it’s unclear whether it will ever be released.

      If not, would you mind sharing the reason?

      Mostly because nobody ever asked for it.

      I’d like to know how you go from parsing the command-line to calling into the function of a loaded DLL.

      The basic idea is pushing the parameters, calling LoadLibrary, GetProcAddress, and then calling the function.

      I’d like to know if the function prototypes are generated based on the command-line arguments or are they from the Windows headers, things of that nature.

      It’s all done based on the command-line arguments. You can see that by the program size, there’s no way I could squeeze the Windows headers in a 4 KB binary. Also, it supports any function in any dll library, even functions which weren’t available when this tool was created or dlls which aren’t Microsoft’s.

      • Steven says:

        Thanks for the reply

        “The basic idea is pushing the parameters, calling LoadLibrary, GetProcAddress, and then calling the function.”

        That’s what I got by inspecting the imported function list.
        I still think there’s nice internal handling going on, like using function return value as input parameter for another one

        “Mostly because nobody ever asked for it.”

        It is the kind of small utilities that talks to me, you can count me as a ‘vote’ for it to be available. I wouldn’t mind receiving it by email if you think it is not GitHub ready. In fact I would really appreciate it.

      • Vitaliy D says:

        +1 vote from me.
        As Textify has already found its home on github, winapiexec can be its neighbour!

    • Hi Steven,
      I’ve just published the source code, enjoy 🙂
      https://github.com/m417z/winapiexec

  21. RedPill says:

    This is a fantastic tool, thanks a lot for sharing this, and also keeping active in the comments!

  22. Steven says:

    For a reason that escapes me, in MSYS2 there is no need to attach a console and the following will just work
    ./winapiexec64.exe msvcrt.dll@printf ‘$s:%i’ ‘(‘ u@GetDesktopWindow ‘)’
    so will redirection ‘>’, piping ‘|’ or variable assignment ‘var=$(..)’

    The above won’t work for a more classic console such as cmd.exe, but there is a way around that
    The subsystem of winapiexec can be changed from WINDOWS to CONSOLE using editbin that comes with Visual Studio
    Personally I make a copy of each of the 2 executables and change the extension to .com as Windows console will pick up .com before .exe
    editbin.exe /SUBSYSTEM:console winapiexec.com
    editbin.exe /SUBSYSTEM:console winapiexec64.com

    The following invokes winapiexec64.com and the desktop handle will be displayed in the console
    winapiexec64 msvcrt.dll@printf $s:%i ( u@GetDesktopWindow )
    It also allow to assign to a variable
    FOR /F %i IN (‘winapiexec64 msvcrt.dll@printf $s:%i ^( u@GetDesktopWindow ^)’) DO set VARIABLE=%i

    As I never was able to assign to a variable or pipe the output to another process when attaching a console, I figured I could share this
    I checked with the author before posting this, as editbin will change a range of 5 bytes in the originals executables

    Hope this helps

  23. poiuz says:

    Thanks for the handy tool. I use it for setting the taskbar grouping to “only when full” by tweaking the registry accordingly (REG ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v TaskbarGlomLevel /t REG_DWORD /d 1 /f) and then reseting the taskbar by calling winapiexec u@SendNotifyMessageW 0xFFFF 0x001A 0x0000 “TraySettings”.

    No for my question: How can I use winapiexec to send keystrokes via SendInput? I tried the following to type the letter D by pressing and releasing the virtual key D:

    winapiexec u@SendInput 2 $a:0x0000000100440000000000000000000000000000,0x0000000100440000000000020000000000000000 40

    Here is the explanation of how I composed the array (copy&paste to editor for easier reading):

    UINT SendInput(
    [in] UINT cInputs,
    [in] LPINPUT pInputs,
    [in] int cbSize
    );

    —— pInputs ——

    typedef struct tagINPUT {
    DWORD type;
    union {
    MOUSEINPUT mi;
    KEYBDINPUT ki;
    HARDWAREINPUT hi;
    } DUMMYUNIONNAME;
    } INPUT, *PINPUT, *LPINPUT;

    typedef struct tagKEYBDINPUT {
    WORD wVk;
    WORD wScan;
    DWORD dwFlags;
    DWORD time;
    ULONG_PTR dwExtraInfo;
    } KEYBDINPUT, *PKEYBDINPUT, *LPKEYBDINPUT;

    DWORD 32-bit unsigned integer. The range is 0 through FFFF FFFF hexadecimal
    WORD 16-bit unsigned integer. The range is 0 through FFFF hexadecimal
    ULONG_PTR 32-bit unsigned integer. The range is 0 through FFFF FFFF hexadecimal

    KeyboardInput Press Key “D”: 0x0000000100440000000000000000000000000000
    type, wVk, wScan, dwFlags, time, dwExtraInfo
    DWORD, WORD, WORD, DWORD, DWORD, ULONG_PTR
    32, 16, 16, 32, 32, 32
    INPUT_KEYBOARD, VK_D, 0, 0, 0, 0
    1, 0x44, 0, 0, 0, 0
    0x00000001, 0x0044, 0x0000, 0x00000000, 0x00000000, 0x00000000

    KeyboardInput Release Key “D”:0x0000000100440000000000020000000000000000
    type, wVk, wScan, dwFlags, time, dwExtraInfo
    DWORD, WORD, WORD, DWORD, DWORD, ULONG_PTR
    32, 16, 16, 32, 32, 32
    INPUT_KEYBOARD, VK_D, 0, KEYEVENTF_KEYUP, 0, 0
    1, 0x44, 0, 2, 0, 0
    0x00000001, 0x0044, 0x0000, 0x00000002, 0x00000000, 0x00000000

    —— cInputs ——

    ARRAYSIZE(pInputs): 2

    —— cbSize ——

    sizeof(pInputs): 40 Byte

    I know I can do this by using SendMessage, but I ultimately want to send hotkeys like CTRL-ALT-D, which is not possible with SendMessage.

    • winapiexec u@SendInput 2 $a:0x0000000100440000000000000000000000000000,0x0000000100440000000000020000000000000000 40

      The obvious bug here is that $a: expects a comma-separated list 32-bit/64-bit numbers (depending on whether it’s winapiexec or winapiexec64). I’ll improve the documentation to be more specific about that.

  24. Virginio says:

    Dear Michael first of all thank you for all your wonderful tools. They’ve been of great help all these years.

    I’m new to winapiexec and willing to improve my skills. Following the AdaptiveTaskbar project on GitHub I reproduced the taskbar size toggling on Windows 10 via a small batch script that you can get here: https://justpaste.it/9xdyz

    The toggling finally works without having to restart explorer.exe thanks to winapiexec but things got tricky for me as I’m still using “Quick Launch” extra toolbar. The batch only affects the main taskbar size unfortunately.

    The Quick Launch toolbar is a total different story:
    I’ve learnt that its settings are stored in “HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Streams\Desktop” /v “TaskbarWinXP”. In Windows 11 the key value has been renamed to “TaskbarWinEP” but it works the same.

    The strange thing of this value/data pair is that when any change occurs to Quick Launch nothing changes apparently in the registry. Changes are visible only after an explorer.exe restart.

    I found that the byte 45 is the one affected by the icons size. 0x02 for big icons 0x01 for small ones.
    I tried then to toggle byte 45 values by hand and see what happens. The script works when killing and restarting explorer.exe but I’d like to associate it to the previous script and I started looking at messages coming from Windows Spy++ (BTW for others interested I found a great collection of Spy++ versions here: https://github.com/westoncampbell/SpyPlusPlus)

    In this picture https://justpaste.it/blbx2 you can see the outputs I got from WinSpy. I’ve been trying playing with winapiexec to mimic the GUI changes that matter the most.

    I created some other batch scripts for my tests:
    QLB creation script (option size parameters “b” or “s” change the byte 45)
    https://justpaste.it/9czk9

    And the winapiexec/winspy batch:
    https://justpaste.it/9lafx

    Besides enabling QLB, as you can see in the picture, changes to the byte 45 and other parameters are done by hand at the moment, but if there’s a way to avoid restarting explorer.exe it will be easy to improve the scripts getting the right parameters and toggling that byte between 0x01 and 0x02.

    I’m afraid that I choosed not an easy challenge to start learning about these kind of things and I wonder if you have the time to give a look to my tests so far.

    I would greatly appreciate if you could give me your experienced advise.
    Thanks and have a nice day,
    V.

    For your convenience I zipped all the scripts and uploaded them here:
    https://anonymfile.com/7PKNo/taskbar-size-toggle.7z

    • Hi Virginio,
      From a quick glance, the TaskbarWinXP value is read in the BandSite_Load function, which is called when the taskbar is initialized, and is written in SaveTrayStuff, which is probably called when explorer shuts down. Therefore, I don’t think there’s an easy way to force explorer to read a modified value.

      • Virginio says:

        Many thanks for your prompt reply, if the real-time registry changes won’t affect the situation, the only way to avoid restarting explorer.exe will be to mimic control clicks. I’ll try to find a way with AutoIt or AutoHotKey. Thanks again.

        Cheers,
        V.

  25. Voldemar says:

    Hi all!

    Please tell me how I can get a numeric value and send it to the window, converting it to text?

    winapiexec u@SendMessageW 12345678 12 0 “Hello World!” (work)

    winapiexec u@SendMessageW 12345678 12 0 ( GetCurrentProcessId )
    winapiexec u@SendMessageW 12345678 12 0 ( $u: GetCurrentProcessId )
    winapiexec u@SendMessageW 12345678 12 0 $u: ( GetCurrentProcessId )
    (not work(( )

    Thank’s!

Leave a Reply