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.
$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
winapiexec.zip (6.02 kB)
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.
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?
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
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 ?
You can check it with a debugger such as OllyDbg. Actually I did that before posting the code.
That’s probably what’s happening. You can try compiling it with a C compiler and checking it to be sure.
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.
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.
Fine. Many thanks RaMMicHaeL.
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?
Hi Monte,
You can use the following command:
winapiexec.exe shell32.dll@Control_RunDLLW 0 ( GetModuleHandleW 0 ) hotplug.dll 10
Based on this information and on debugging rundll32.exe. Note that the the second argument is actually the executable module handle, contrary to what the documentation says.
Thanks for your reply!
Still it’s not working for me (showing nothing), but now I’ve got it that rundll works differently and it’s not for calling winapi functions as one may think.
Works for me. That’s on Windows 10, I haven’t tried it on Windows 7.
I believe you, there’s no need in evidence 🙂
I’m on Windows 7, so maybe that’s the culprit.
I checked it, and it doesn’t work on Windows 7 because it expects the window argument to be non-zero.
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
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
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.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.
Hi Sam,
You’re welcome, thanks for the feedback!
Probably here 😉
I just reversed Windows 10 explorer for you, here’s an updated command:
winapiexec.exe u@SetForegroundWindow ( u@FindWindowW Shell_TrayWnd 0 ) , u@PostMessageW $$:3 0x5CE 0 0
Enjoy 🙂
Brilliant! Thank you so much, that’s perfectly!
….err, that works perfectly 🙂
please tell me some more good & tricky example uses of winapiexec
There are endless possible examples. You can refer to the Windows API Reference.
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
how can i take screenshot with this app
I don’t think you can come up with a sane command line for winapiexec to take a screenshot. You can check out the following links for third party command line tools to take a screenshot for you:
https://rammichael.com/a-command-line-screenshot-maker
https://superuser.com/questions/75614/take-a-screen-shot-from-command-line-in-windows
HOW 2 DISPLAY WINDOW TASKAR NOTIFICATIONS WITH THIS APP
You need to create a window and a tray icon for that. Should be possible, but not a 5-minute task.
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 theOpenVirtualDisk
function should be$b:8
.2. The parameter of the
AttachVirtualDisk
function where you pass1
requires a pointer. Of course1
is not a valid pointer.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
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.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..
I have no experience of mounting .vhdx containers. If you can show an example of C code and specify which parameter you need help with passing to winapiexec, I might be able to help with that.
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.
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?
Try the following:
winapiexec k@GetBinaryTypeW "C:\Program Files (x86)\Notepad++\notepad++.exe" $b:4 , InterlockedExchange $$:3 0
Thank you very much for this clever solution, works like a charm!
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
Hi,
One solution is to write the content to a temporary file with
WriteFile
, and then load the content in the batch script. I don’t have an idea of doing it without a temporary file, but looks likeWriteConsole
can’t be used for this.Thanks for the answer.
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
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
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.
You don’t need that for winapiexec, it’s for using the code in C/C++.
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!
Hi!
How to close/destroy a Window where handle is a form title for example “information”?
SendMessage/WM_CLOSE
Hi,
You can use the
FindWindow
function to get a window handle from window title or class.Here’s an example of finding a window with the title “Untitled – Notepad” and sending
WM_CLOSE
.winapiexec.exe u@SendMessageW ( u@FindWindowW 0 "Untitled - Notepad" ) 0x10 0 0
Thx.
Now, how to close it in an endless loop?
Look at the “Show a messagebox and then create a new instance of the process” example in the post above for some inspiration.
Look at the “Hide the taskbar for half a second, then show it” for implementing a delay.
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.
Probably not, unless there’s a Windows API function that allows to control the icon size, and I don’t think such a function exists.
The only lead I have been able to find, is that a program called 7taskbar tweaker can do it.
I’m the author of that program 🙂 and it allows to increase the size of the standard taskbar buttons, not the quick launch ones. It also uses code injection and function hooking, something the winapiexec tool can’t help with.
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.
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.