inkscapec.exe - A Command Line Wrapper for Win32

Inkscape 0.46 is finally out of the door and there are builds for all platforms (well, the important ones) available. Unfortunately I wasn't able to get this little executable into the Win32 builds. If you've read my previous posts you might have an idea what it's all about.

In a nutshell it's a tiny console application, which spawns Inkscape (with the specified arguments) and captures its stdout (default output) and stderr (default error output) streams and redirects it to this console. It also does the same with stdin for good measure. It's sole purpose is direct command line interaction (and determining which actions trigger GTK warnings). If you want to spawn Inkscape from other programs/scripts use inkscape.exe instead.

So, with this little application we get something that behaves like a console build of Inkscape, which means that we actually get some feedback if we're using some command line switches. All that for a mere 21kb. For comparison: a separate Inkscape build would have added another 12.5mb.

PNG export example:

C:\Inkscape-0.46>inkscapec.exe -e image.png ext.svg
Background RRGGBBAA: ffffff00
Area 0:0:64:64 exported to 64 x 64 pixels (90 dpi)
Bitmap saved as: image.png

It's written in C++ and a lot longer than the other 2 solutions. Unlike those old ones it's asynchronous, which means you get the messages right away instead having to wait for Inkscape's termination. This is nice if you want to check which action triggers a GTK warning for example.

A few of you may know it as "inker.exe". Aaron Spike suggested "inkscapec.exe", which is sort of along the lines of "java"/"javaw" or "python"/"pythonw"... just the other way around.

#include<windows.h>
#pragma comment(lib,"User32.lib")
void HandleOutput(HANDLE hPipeRead);
DWORD WINAPI RedirThread(LPVOID lpvThreadParam);

HANDLE hChildProcess=NULL;
HANDLE hStdIn=NULL;
BOOL bRunThread=TRUE;

int main(int argc,char *argv[]){
    HANDLE hOutputReadTemp,hOutputRead,hOutputWrite;
    HANDLE hInputWriteTemp,hInputRead,hInputWrite;
    HANDLE hErrorWrite;
    HANDLE hThread;
    DWORD ThreadId;
    SECURITY_ATTRIBUTES sa;

    sa.nLength=sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor=NULL;
    sa.bInheritHandle=TRUE;

    DWORD i;
    CHAR cmd[32767];
    cmd[0]='\0';
    strcat(cmd,"inkscape.exe");
    for(i=1;i<argc;i++){
        strcat(cmd," ");
        strcat(cmd,argv[i]);
    }

    CreatePipe(&hOutputReadTemp,&hOutputWrite,&sa,0);
    DuplicateHandle(GetCurrentProcess(),hOutputWrite,GetCurrentProcess(),&hErrorWrite,0,TRUE,DUPLICATE_SAME_ACCESS);
    CreatePipe(&hInputRead,&hInputWriteTemp,&sa,0);
    DuplicateHandle(GetCurrentProcess(),hOutputReadTemp,GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS);
    DuplicateHandle(GetCurrentProcess(),hInputWriteTemp,GetCurrentProcess(),&hInputWrite,0,FALSE,DUPLICATE_SAME_ACCESS);
    CloseHandle(hOutputReadTemp);
    CloseHandle(hInputWriteTemp);

    hStdIn=GetStdHandle(STD_INPUT_HANDLE);

    //-
    PROCESS_INFORMATION pi;
    STARTUPINFO si;

    ZeroMemory(&si,sizeof(STARTUPINFO));
    si.cb=sizeof(STARTUPINFO);
    si.dwFlags=STARTF_USESTDHANDLES;
    si.hStdOutput=hOutputWrite;
    si.hStdInput=hInputRead;
    si.hStdError=hErrorWrite;

    CreateProcess(NULL,cmd,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);

    hChildProcess=pi.hProcess;

    CloseHandle(pi.hThread);
    //-

    CloseHandle(hOutputWrite);
    CloseHandle(hInputRead);
    CloseHandle(hErrorWrite);

    hThread=CreateThread(NULL,0,RedirThread,(LPVOID)hInputWrite,0,&ThreadId);

    HandleOutput(hOutputRead);

    CloseHandle(hStdIn);

    bRunThread=FALSE;

    WaitForSingleObject(hThread,INFINITE);
    CloseHandle(hOutputRead);
    CloseHandle(hInputWrite);

    return 0;
}

void HandleOutput(HANDLE hPipeRead){
    CHAR lpBuffer[256];
    DWORD nRead;
    DWORD nWrote;

    while(TRUE){
        if(!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),&nRead,NULL)||!nRead)
            if(GetLastError()==ERROR_BROKEN_PIPE)
                break;
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,nRead,&nWrote,NULL);
    }
}

DWORD WINAPI RedirThread(LPVOID lpvThreadParam){
    CHAR buff[256];
    DWORD nRead,nWrote;
    HANDLE hPipeWrite=(HANDLE)lpvThreadParam;

    while(bRunThread){
        ReadConsole(hStdIn,buff,1,&nRead,NULL);

        buff[nRead]='\0';

        if(!WriteFile(hPipeWrite,buff,nRead,&nWrote,NULL)){
            if(GetLastError()==ERROR_NO_DATA)
                break;
        }
    }
    return 1;
}

As usual the code is available under a zero-clause BSD-style license. You can compile it with Dev-Cpp (mingw32) for example. The code itself is sort of bad, I guess (it works fine though). Well, I don't write a lot of C++. So, please excuse my sloppiness. ;)

Download: inkscapec.exe (21kb - put it into the Inkscape's main directory)

Comments

Thank you so very much!!!

This is exactly what I've been looking for to convert SVG to PDF.

Sorry Newbie no dev type needs some urgent help

Hi

From what you have written here and on this should do what I'm after - I am a graphic designer who simply needs to batch convert 100's of svg files to png's in a batch.

I have donwloaded the file here but have not goty a clue on how to carry out the batch process through the command line.. I have done start>run>cmd but can not workout what to do from there...

Please can you advise me with a simple step by step to batch convert a folder of svgs to pngs of a certain dpi and pixel size.

OR.. if a clever guy or girl could write a simple app I / my company would be happy to buy it!!

Many Thanks

Steve
my email if you wold like to contact about creating an app stephen[dawt]jones[awt]flowmaster[dawt]com

I can show you how to do that Steve.

Hi Steve,
I've sent you an email but i'll post on here too just for good measure.

Do you still need to know how to batch convert SVG's to PNG's or do you now know?

I will send a video via email showing how to do this if you still require it.

Just happy to help .

Thanks,
Alex

Inkscape batch PNG export under Windows

X:\svg\source\folder>FOR %? IN (*.svg) DO X:\inkscape4x\inkscape.exe -f X:\svg\source\folder\%? -e E:\png\target\folder\%?.png

Forgot to reply. Sorry. Well, that's how it can be done. Note that I used absolute paths all over the place.

Inkscape batch PS export under Windows

Thanks again from another SVG user for the inkscapec.exe command line client! It really made things much simpler, for example, batch converting SVG to PS images for use in Latex: http://www.jevon.org/wiki/SVG_in_Latex

I also had to use absolute paths, I have a feeling that Inkscape is the application struggling with them, not your client.

re: Inkscape batch PS export under Windows

Note that you do not need to call inkscapec.exe from scripts. You only need it if you're interested in Inkscape's messages. E.g. if you're trying to figure out if the supplied parameters are correct. Once this works you can go back to using inkscape.exe directly.

Post new comment

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options