RunDllC# (RunDll.NET)

Overview

Commandline tool to run functions from .NET programs and libraries and pass their output to STDOUT or inject local variable with output to calling process. Demo C# library with some useful functions and complete source code is attached.
Basically it’s .NET equivalent of rundll32.

What is it good for?

I was facing problem with masked input in Windows batch files (for multiple TrueCrypt volume mounting in my case). I wrote some commandline tool in C# but then I want some color outputs and so on, so I decided to write some wrap library. But how to lunch it? There is probably some very ugly MSIL commandline tool to run some class from assembly and probably some similar tool like mine but I didn’t find any at the time. So I wrote my own.
Its syntax is similar to classic RunDll32, but mine RunDllC# has some „cool“ stuffs like parent process variable injection.
For example: you have some masked password input function which replaces actual characters with stars. The problem is how to pass password to calling process. You can store it in some file (unsecure), you can pass it as stdout, which has some very crucial limitations. Control characters and stars will be passed to stdout as well and final password will be shown (you can clear screen just after that) but how to deal with stdout in batch script? You cannot easily store it in variable and simultaneously write in console. You can probably think about pass password through stderr and catch error output in script. Again, it’s complicated to pass stderr to variable and it’s very ugly solution. All these problems are solved in RunDllC#.

How it works?

My tool consists of two parts. One is RunDllC# itself and second is SetEnvVar.exe, which is slightly modified code from Sarath (http://www.codeproject.com/KB/threads/DynEnvVar.aspx) to fit my needs (compatible with visual studio express edition and commandline interface). You need to have all three files (RunDllC#.exe, SetEnvVar.exe and SetEnvLib.dll) together. If you do not intend to use variable injection you can use RunDllC#.exe only. SetEnvVar part is just for variable injection and if you are interested what’s going on there, you should look at link above.

SetEnvVar.exe

It‘s commandline tool to inject process with custom variable. It’s based on Sarath’s code. I just removed MFC dependencies and compiled in Visual C++ 2010 Express as commandline tool. I’m quite rusty in Visual C++, so it’s probably very unoptimized and ugly but it works well so I let it be. However there is some issue in Windows 7 64-bit (and probably in 64-bit Vista as well). You cannot inject 64-bit version on cmd.exe, which is quite annoying (but solution is explained above). Even Sarath’s application was unable to do it. I tried easyhook which works somehow but there was another problems so I decided to use this. Which means that fixing this bug is possible but I don’t know how, so if you have any idea, please let me know.

RunDllC#.exe

This it the part where the all „fun“ is. According to commandline parameters it will take some actions:
It can view all the functions from your .NET assembly (exe, dll .... whatever).
It can run those functions.
And it can pass output from those functions to stdout or even inject calling process environment with variable containing ouput.

How to use RunDllC#

Program parses input parameters with following rules:

RunDllC# library,function[!variable] "[parameter,parameter...]"
RunDllC# library,function?
RunDllC# library,?
RunDllC# "batch file" "parameters"
RunDllC# library,function[!variable] "[parameter,parameter...]"
-------------------------------------------------------------
Run specified 'function' from 'library' with given 'parameters'. Output will be injected into local environment variable of calling process (if defined) or will be passed to STDOUT.
Examples:
	RunDllC# c:\my.dll,Merge "\"Things:, books\,pencils\,brushes\": he said"
	RunDllC# c:\my.dll,Merge!output "Hello ,Dexter Morgan!"
	RunDllC# c:\my.dll,Add!output "10,15"
	RunDllC# c:\my.dll,Add!output 10,15

RunDllC# library,function?
--------------------------
View all functions with 'function' name from 'library'.
Example:
	RunDllC# "c:\Program Files\My Project\mydll.dll",MergeStrings?

RunDllC# library,?
------------------
View all functions from 'library'.
Example:
	RunDllC# "c:\Program Files\My Project\mydll.dll",?

Note: [Description] attribute (if exists) will be shown as well.  

RunDllC# "batch file" "parameters"
----------------------------------
Variable injection doesn't work on 64-bit versions of cmd.exe. This will simply call your batch file with 32-bit version of cmd.exe which can be injected.
If you are using 64-bit Windows and try to run scripts directly from system (i.e. from startup), start your scripts with this if you intended to use variable injection (you can use it on 32-bit systems as well).
It's highly recommended to use this approach if you intended to run your scripts on 32-bit or 64-bit systems.
You can use this formula in batch file to open 32-bit cmdexe version first:
    if not defined ##PASS## (set ##PASS##=something 
    RunDllC#.exe %0
    exit)

Warning: Some applications (i.e. TotalCommander) use the same technique of running 32-bit version of cmd.exe even on 64-bit systems. It can be confused because from TotalCommander your scripts will work fine but from your system environment it won't!

-------------------------------------------------
Parameters are delimited by commas(,) hence all commas in parameters must be backlashed with (\).
Also quotes and of course backslashes must be backslashed too.
Do not use quotes to specify strings (all parameters are handled as strings) and then converted to appropriate type (if needed). 
!BUT all parameters needs to be wrapped together with quotes to preserve spaces! 
Currently supported function parameters conversions:
  System.String
  System.Int32
  System.Char
  System.Boolean
	

I hope you understood how to use this tool:)

How to build your own library

You can use any .NET library or program. Just write your code, compile and use in batch files using RunDllC#. You can use [Description] attribute in your code. Content of this attribute will be shown if you try to find some info about your function (using this: RunDllC# library,function?).

[Description("This function prints \“Hello world\“")]
public void HelloWorld()
{
        Console.Write(„Hello world“);
}
	

Demo functions

I wrote some functions to enrich windows shell scripting. You can get functions from this assembly to test RunDllC# tool.

GetPassword(int demask_key, char password_char, bool masked)
This function gets password. Input charecters are masked with ‚password_char‘. If you want to show password during typing (to verify), you can press ‚demask_key‘ to show or hide password instantly. Typical ‚demask_key‘ can be 27 for ESC key. Last ‚masked‘ variable means initial status (masked or non-masked).

Log(string text, string severity)
Logs output to console. It uses colors and everything:)
Function has [Description] attribute so you can try to show help for this function.
	

Example

@echo off
rundllc#.exe demo.exe,Log "|||Enter password please(you can view your password using ESC key) > ,h"
rundllc#.exe demo.exe,GetPassword!custom_password "27,*,true"
rundllc#.exe demo.exe,Log "<<<,d"
rundllc#.exe demo.exe,Log "<<<Your password is stored in 'custom_password' environment variable,i"
rundllc#.exe demo.exe,Log "<<<echo %%custom_password%%,i"
echo %custom_password%

rundllc#.exe demo.exe,Log "This is error,e"
rundllc#.exe demo.exe,Log "This is warning,w"
rundllc#.exe demo.exe,Log "This is information,i"
rundllc#.exe demo.exe,Log "This is debug,d"
rundllc#.exe demo.exe,Log "This is highlight,h"
rundllc#.exe demo.exe,Log "This is nothing,"

rundllc#.exe demo.exe,Log ">>>Doing something ,i"
for /l %%X in (1, 1, 10) do rundllc#.exe demo.exe,Log "|||.,i"
rundllc#.exe demo.exe,Log "<<< Done.,i"

pause
	

Final words

Hope it help someone.

Download

RunDllCsharp.src.zip

About

Author: Tomas Janirek (tomas.janirek'at'gmail.com)
Web: http://programator.org
License: This program is free for non-commercial use.