Calling external programs from D

Regan Heath regan at netwin.co.nz
Wed Apr 19 14:47:15 PDT 2006


On Wed, 19 Apr 2006 16:53:18 +0200, Tydr Schnubbis <fake at address.dude>  
wrote:
> Regan Heath wrote:
>> On Wed, 19 Apr 2006 03:57:44 +0200, Tydr Schnubbis <fake at address.dude>   
>> wrote:
>>> Tydr Schnubbis wrote:
>>>> Regan Heath wrote:
>>>>> On Thu, 6 Apr 2006 14:46:09 +0000 (UTC), Stuart Delaney    
>>>>> <Stuart_member at pathlink.com> wrote:
>>>>>> There's a bug in the makeBlock functions in process.d. The first    
>>>>>> parameter to
>>>>>> calloc should be 1 not 0. With that change (and the private  
>>>>>> readLine   one) it
>>>>>> works fine for me.  Don't have an answer to the OP's DNS problem   
>>>>>> though.
>>>>>  You're dead right. With those changes it works for me too.
>>>>  I've fixed the calloc calls too, but it doesn't help.  If I try to   
>>>> ping google's IP, which is 64.233.167.99 according to ping, I get   
>>>> "Pinging Error: 4invalid UTF-8 sequence".  Maybe my windows   
>>>> installation is screwed, it's getting really old...
>>>>  Btw, I use dmd 0.148, haven't tried this with any other version yet.
>>> Could it be that CreateProcessA is used wrong somehow?  I don't know  
>>> the  win32 api, but does anyone know if using it wrong (security  
>>> settings or  sth) could block new process from accessing the network?   
>>> Where would I  start looking if I want to fix this?  The msdn docs  
>>> didn't help much.  Couldn't even find mention of this function, only  
>>> CreateProcess, without  the trailing 'A'.  But it seems to be the same  
>>> function.
>>>
>>> Here's what the call looks like:
>>> CreateProcessA(null,std.string.toStringz(command),null,null,true,DETACHED_PROCESS,env,null,&startup,info)
>>  CreateProcessA is the ascii version.
>> CreateProcessW is the unicode (UTF-16) version.
>>  std.string.toStringz converts the UTF-8 char[] into ascii
>> std.string.toUTF16 can be used to convert the UTF-8 char[] into UTF-16  
>> if  you want to call CreateProcessW instead.
>>  The common cause of the "4invalid UTF-8 sequence" error is trying to   
>> output non-ascii characters to the windows console. Can you post your   
>> current code here.
>
> Sure.  As you can see it's full of weird characters...
>
> import lib.process;
> import std.stdio;
>
> void main()
> {
> 	Process proc;
> 	// ping my router
> 	proc = new Process("ping 192.168.0.1");
> 	writefln(proc.readLine());
> 	writefln(proc.readLine());
> 	writefln(proc.readLine());
> 	writefln(proc.readLine());
> }
>
>
> I have only made readLine public, and fixed the four calloc calls, no  
> other changes have been made to your files.
>
> Compile with: dmd test.d lib/process.d lib/pipestream.d
>
> This prints:
> Pinging Error: 4invalid UTF-8 sequence
>
>
> If I ping google.com instead, I get this:
> Ping request could not find host google.com. Please check the name and  
> try again
> .
>
> Error: ReadFile: The pipe has been ended.
>
> ---------
>
> Does both of these work for you?  I have no idea what would cause any of  
> these problems.  I have winxp SP2 US.  CreateProcessA is in  
> kernel32.dll, of which I have version 5.1.2600.2180  
> (xpsp_sp2_rtm.040803-2158).  dmd version 0.154, got the same results  
> with 0.148.

It's quite odd, try this:

import lib.process;
import std.stdio;
import std.string;
import std.c.string;

extern(C) extern char **_environ;

void main()
{
	Process proc;
	proc = new Process();
	for(int i = 0; _environ[i]; i++) {
		proc.addEnv(toString(_environ[i]).dup);
	}
	//proc.execute("ping www.google.com");
	proc.execute("ping 192.168.0.1");
	while(true) writefln("%s",proc.readLine());
}

without the addEnv calls above I get the behaviour you're describing. With  
them it works.

Without them, and using printf I can see that ping responds with:

"Pinging °ÿ with 32 bytes of data:"

note the weird characters there. At first I thought maybe the command line  
I was passing to CreateProcessA was temporary and being collected by the  
GC, so I changed process.d to use:

cmd = strdup(std.string.toStringz(command));

where cmd is a member of Process - so will persist as long as it does.  
That made no difference. I have no idea why it's doing that, perhaps it  
reads it's args in a strange way?? I might write a debug program and run  
that passing different args etc to see if I can replicate the odd  
behaviour and figure out where it comes from.

Regan



More information about the Digitalmars-d-learn mailing list