This works on my machine without issues (Winodws 8.1 VS2013). The problem has nothing to do with the console application. As Scott explained there is some blocking going on. 
It works when not run under a debugger
- As WPF Application
- As Console Application
It will hang when you are trying to debug the application. The deeper reason is that you are sending \0 over the pipe. A pipe has a send buffer (ca. 4 KB) before it blocks further writes to it. This is what you are seeing as a hanging WriteFile call in kernel32.dll. To be able to block there must be someone who wants to read from your pipe. In that case it is VS trying to get your stdout to the debugger output window. When no one is listening the pipe acts as null device which will never block. 
Now back to the question why it does work with all strings except \0? This has something to do how to stop reading from a a pipe. The receiver can stop reading from the pipe when it receives \0 as the only message. This is the signal that the process has exited and no further data will be written to it. With your \0 messages you violate that implicit contract and send further data over the pipe but your client (VS) has stopped listening to you. 
That is not actually an API but seems to be a common agreement. In .NET yout get for async pipe reads e.g. null as last message back. Other applications (e.g. VS) seem to handle \0 messages in a similar way and assume the writer has exited. 
It is legal to simply close the pipe handle in that case ReadFile returns false. Our you can also write a message of 0 bytes length to the pipe. Or you can write a 1024 KB null array to the pipe. It is up the reader of your messages to decide if this is the signal to stop reading from your pipe. 
Update 1
Since at least one commenter was thinking that logic is not enough here is the result of debugging VS. VS does read from the pipe via ReadFile 
vsdebug!CReader::ReadPipe
There is a check if the first byte is 0 which then leads to thread termination. If the first byte is not 0 it is treated as unicode string and copied to a string buffer which is displayed in the debugger output window. You can verify this easily by sending instead e.g. 1000 c chars which will show up in the buffer. Then you can follow the control flow where it differs from 1000 0 bytes. 
It turns out that the relevant piece is:
0:048> db ebp-420
1973f794  00 00 00 00 38 63 71 10-fe 03 00 00 92 82 b5 45  ....8cq........E
1973f7a4  63 63 63 63 63 63 63 63-63 63 63 63 63 63 63 63  cccccccccccccccc
1973f7b4  63 63 63 63 63 63 63 63-63 63 63 63 63 63 63 63  cccccccccccccccc
1973f7c4  63 63 63 63 63 63 63 63-63 63 63 63 63 63 63 63  cccccccccccccccc
1973f7d4  63 63 63 63 63 63 63 63-63 63 63 63 63 63 63 63  cccccccccccccccc
1973f7e4  63 63 63 63 63 63 63 63-63 63 63 63 63 63 63 63  cccccccccccccccc
1973f7f4  63 63 63 63 63 63 63 63-63 63 63 63 63 63 63 63  cccccccccccccccc
1973f804  63 63 63 63 63 63 63 63-63 63 63 63 63 63 63 63  cccccccccccccccc
Buffer contains data a ebp-410 where are our c characters. Before that there is the buffer size and file handle stored. 
    0:048> u 5667dd48  L50
    vsdebug!ReaderThreadStart+0x72:
    **5667dd48 80bdf0fbffff00  cmp     byte ptr [ebp-410h],0**  check if first byte is 0 
    5667dd4f 7446            je      vsdebug!ReaderThreadStart+0xc1 (5667dd97)
    5667dd51 899decfbffff    mov     dword ptr [ebp-414h],ebx
    5667dd57 897dfc          mov     dword ptr [ebp-4],edi
    5667dd5a 8d85f0fbffff    lea     eax,[ebp-410h]
    5667dd60 53              push    ebx
    5667dd61 53              push    ebx
    5667dd62 50              push    eax
    5667dd63 8d8decfbffff    lea     ecx,[ebp-414h]
    5667dd69 e8f5960200      call    vsdebug!CVSUnicodeString::CopyString (566a7463)
    5667dd6e c745fc02000000  mov     dword ptr [ebp-4],2
    5667dd75 8b4e30          mov     ecx,dword ptr [esi+30h]
    5667dd78 6aff            push    0FFFFFFFFh
    5667dd7a ffb5ecfbffff    push    dword ptr [ebp-414h]
    5667dd80 e84453f6ff      call    vsdebug!CMinimalStreamEx::AddStringW (565e30c9)
    5667dd85 834dfcff        or      dword ptr [ebp-4],0FFFFFFFFh
    5667dd89 8d8decfbffff    lea     ecx,[ebp-414h]
    5667dd8f 53              push    ebx
    5667dd90 e86339f5ff      call    vsdebug!CVSVoidPointer::Assign (565d16f8)
    5667dd95 eb03            jmp     vsdebug!ReaderThreadStart+0xc4 (5667dd9a)
   ** 5667dd97 897e28          mov     dword ptr [esi+28h],edi ** When 0 go here and sleep 200ms
    5667dd9a 68c8000000      push    0C8h
    5667dd9f ff151c228056    call    dword ptr [vsdebug!_imp__Sleep (5680221c)]
    5667dda5 e978caf9ff      jmp     vsdebug!ReaderThreadStart+0xd4 (5661a822)
    5667ddaa e87ffc0d00      call    vsdebug!__report_rangecheckfailure (5675da2e)
    5667ddaf cc              int     3
    5667ddb0 b9fe030000      mov     ecx,3FEh
    5667ddb5 899de4fbffff    mov     dword ptr [ebp-41Ch],ebx
    5667ddbb 3bc1            cmp     eax,ecx
    5667ddbd 7702            ja      vsdebug!CReader::Stop+0x84 (5667ddc1)
    5667ddbf 8bc8            mov     ecx,eax
    5667ddc1 53              push    ebx
    5667ddc2 8d85e4fbffff    lea     eax,[ebp-41Ch]
    5667ddc8 50              push    eax
    5667ddc9 51              push    ecx
    5667ddca 8d85f0fbffff    lea     eax,[ebp-410h]
    5667ddd0 50              push    eax
    5667ddd1 ff762c          push    dword ptr [esi+2Ch]
    5667ddd4 ff1590218056    call    dword ptr [vsdebug!_imp__ReadFile (56802190)]
    5667ddda 85c0            test    eax,eax
    5667dddc 0f845a80f9ff    je      vsdebug!CReader::Stop+0x117 (56615e3c)
    5667dde2 8b85e4fbffff    mov     eax,dword ptr [ebp-41Ch]
    5667dde8 85c0            test    eax,eax
    5667ddea 0f844c80f9ff    je      vsdebug!CReader::Stop+0x117 (56615e3c)
    5667ddf0 b900040000      mov     ecx,400h
    5667ddf5 3bc1            cmp     eax,ecx
    5667ddf7 736c            jae     vsdebug!CReader::Stop+0x125 (5667de65)
    5667ddf9 889c05f0fbffff  mov     byte ptr [ebp+eax-410h],bl
    5667de00 40              inc     eax
    5667de01 3bc1            cmp     eax,ecx
    5667de03 7360            jae     vsdebug!CReader::Stop+0x125 (5667de65)
    5667de05 889c05f0fbffff  mov     byte ptr [ebp+eax-410h],bl
    5667de0c 389df0fbffff    cmp     byte ptr [ebp-410h],bl
    5667de12 0f842480f9ff    je      vsdebug!CReader::Stop+0x117 (56615e3c)
    5667de18 899decfbffff    mov     dword ptr [ebp-414h],ebx
    5667de1e c745fc01000000  mov     dword ptr [ebp-4],1
    5667de25 8d85f0fbffff    lea     eax,[ebp-410h]
    5667de2b 53              push    ebx
    5667de2c 53              push    ebx
    5667de2d 50              push    eax
    5667de2e 8d8decfbffff    lea     ecx,[ebp-414h]
    5667de34 e82a960200      call    vsdebug!CVSUnicodeString::CopyString (566a7463)
    5667de39 c745fc02000000  mov     dword ptr [ebp-4],2
    5667de40 8b4e30          mov     ecx,dword ptr [esi+30h]
    5667de43 6aff            push    0FFFFFFFFh
    5667de45 ffb5ecfbffff    push    dword ptr [ebp-414h]
    5667de4b e87952f6ff      call    vsdebug!CMinimalStreamEx::AddStringW (565e30c9)
    5667de50 834dfcff        or      dword ptr [ebp-4],0FFFFFFFFh
    5667de54 8d8decfbffff    lea     ecx,[ebp-414h]
    5667de5a 53              push    ebx
    5667de5b e89838f5ff      call    vsdebug!CVSVoidPointer::Assign (565d16f8)
    5667de60 e9d77ff9ff      jmp     vsdebug!CReader::Stop+0x117 (56615e3c)
    5667de65 e8c4fb0d00      call    vsdebug!__report_rangecheckfailure (5675da2e)
    5667de6a cc              int     3
    5667de6b b81a7e5d56      mov     eax,offset vsdebug!ATL::CAtlMap<unsigned long,CScriptNode *,ATL::CElementTraits<unsigned long>,ATL::CElementTraits<CScriptNode *> >::~CAtlMap<unsigned long,CScriptNode *,ATL::CElementTraits<unsigned long>,ATL::CElementTraits<CScriptNode *> >+0x15 (565d7e1a)
    5667de70 c3              ret
    5667de71 b84c8e5d56      mov     eax,offset vsdebug!ATL::CAtlMap<unsigned long,ATL::CComPtr<IVsHierarchyEvents>,ATL::CElementTraits<unsigned long>,ATL::CElementTraits<ATL::CComPtr<IVsHierarchyEvents> > >::~CAtlMap<unsigned long,ATL::CComPtr<IVsHierarchyEvents>,ATL::CElementTraits<unsigned long>,ATL::CElementTraits<ATL::CComPtr<IVsHierarchyEvents> > >+0x15 (565d8e4c)
    5667de76 c3              ret
    5667de77 6857000780      push    80070057h
    5667de7c e8df0af6ff      call    vsdebug!treegrid::IGridView::CleanupItems (565de960)
**    0:048> u 5661a822  ** Jump here
    vsdebug!ReaderThreadStart+0xd4:
    5661a822 395e28          cmp     dword ptr [esi+28h],ebx
    5661a825 74d0            je      vsdebug!ReaderThreadStart+0x26 (5661a7f7)
    5661a827 ff7624          push    dword ptr [esi+24h]
    5661a82a ff157c228056    call    dword ptr [vsdebug!_imp__SetEvent (5680227c)]
    5661a830 53              push    ebx
**    5661a831 ff1508218056    call    dword ptr [vsdebug!_imp__ExitThread (56802108)]  ** Stop reading
That is the whole magic around that. The reader simply stops reading and you your application will block when the sender buffer is full. No magic involved. It is all depends on the behaviour of the reader.