Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

C-Sharp - Umleiten des StandardOutput eines Process geht nicht

Frage Entwicklung

Mitglied: 94erBrom

94erBrom (Level 1) - Jetzt verbinden

23.12.2014, aktualisiert 14:37 Uhr, 1367 Aufrufe, 5 Kommentare

Hallo Zusammen.

Ich bin gerade am verzweifeln.

Ich habe hier ein Fremdprogramm samt seiner V-C++-Projektdateien.
Das Programm schaltet in Windows die Standart-Sound-Ausgabe auf das Gerät mit der entsprechenden, als Parameter übergebenen Nummer um.
Der Aufruf "run.exe 1" schaltet zum Beispiel auf HDMI um, "run.exe 2" auf Headset, etc.
Der Aufruf "run.exe", also ohne Parameter, erzeugt eine Liste, die alle aktiven Audio-Ausgabe-Geräte, von 0 an durchnummeriert, enthält.
Genau diese Liste möchte ich nun in die Variable DevicesList umleiten.

Beispiel für den Aufruf ohne Parameter
C:\AudioDeviceSwitcher>run.exe 
Audio Device 0: Lautsprecher (6- Logitech G430 Gaming Headset) 
Audio Device 1: Audials Sound Capturing (Audials Sound Capturing) 
Audio Device 2: Lautsprecher (Realtek High Definition Audio) 
Audio Device 3: GRUNDIG WXGA-4 (2- NVIDIA High Definition Audio)
Auf das Fremdprogramm (run.exe) greife ich aus meinem C#-Projekt mit System.Diagostics.Process zu und leite den StandardOutput in die String DevicesList um.
Im C++-Programm wird die Ausgabe mit printf erstellt, also auf die Standard-Ausgabe geschrieben, wenn ich das Programm mit CMD ausführe, erhalte ich auch eine Ausgabe.
In meinem Programm erhalte ich jedoch keine Ausgabe zurück.
Ich habe den Programmaufruf und die Umleitung auch schon mit einer test.bat-Datei des Inhalts

echo Hallo Welt
run.exe
echo ciao

getestet, das Ergebnis war dann, dass in der Variable nach >run.exe nichts mehr stand, echo ciao wurde also gar nicht ausgeführt.
In CMD funktionierte aber alles korrekt.
Habe sicherheitshalber auch mal den StandardError umgeleitet, aber auch ohne Ergebnis

Die Standard-Ausgabe fange ich mit folgendem Code-Fragment:
 
public static void getDevicesList() 
            Process p = new Process(); 
            p.StartInfo.FileName = exelocation; 
            p.StartInfo.RedirectStandardOutput = true; 
            p.StartInfo.CreateNoWindow = true; 
            p.StartInfo.UseShellExecute = false; 
            p.StartInfo.Arguments = ""; 
            Console.WriteLine(Environment.NewLine + exelocation + Environment.NewLine); //dient nur der Sicherstellung, dass der Pfad stimmt 
             
            try 
                p.Start(); 
                StreamReader reader = p.StandardOutput; 
                devicesList = reader.ReadToEnd(); 
                 
                p.WaitForExit(); 
            catch (Exception ex) 
                Console.WriteLine(Environment.NewLine + Environment.NewLine + ex + Environment.NewLine + Environment.NewLine); 
                MessageBox.Show("Exception!!!", null); 
 
            MessageBox.Show("Inhalt von DevicesList:" + Environment.NewLine + devicesList, "DevicesList"); 
 
Bei einem C++-Testprogramm, dass nur mit printf einmal "test" schreibt, konnte ich mit dieser Methode die Ausgabe umleiten.
Auch mit einer .bat-Datei ging es.
Das Umschalten auf andere Geräte geht mit dieser Methode auch. Der Pfad stimmt also.

Bitte um schnelle Hilfe, ich verzweifel hier.
Falls ihr noch weiteren Code braucht, sagt es mir.

LG 94erBrom
Mitglied: 114757
23.12.2014, aktualisiert um 15:23 Uhr
Moin,
versuch mal den Output deines c++ Programms stattdessen mit
01.
std::cout << "Hello World" << std::endl;
ausgeben zu lassen. Das sollte in jedem c++ funktionieren.

Gruß jodel32
Bitte warten ..
Mitglied: 94erBrom
23.12.2014 um 16:31 Uhr
Danke, werde ich mal ausprobieren.

Ich hatte bereits letzte Woche eine Version des C#-Projekt am laufen und im Praxiseinsatz, die funktioniert nur jetzt seltsamerweise nicht mehr(erinnere mich nicht, eine neue Version drüberinstalliert zu haben), und ich habe davon keine Datensicherung, weshalb ich alles neu programmieren muss (das ursprüngliche Projekt ist nach einigen Änderungen inzwischen unbrauchbar).
Es hat wie gesagt schon funktioniert, der Fehler dürfte also eigentlich nicht auf Seiten des C++-Programms liegen...
Bitte warten ..
Mitglied: 94erBrom
23.12.2014, aktualisiert um 17:23 Uhr
Ich habe jetzt eine neuere Version des C++Programms gefunden und heruntergeladen.
In der neuen Version ist es möglich, sich über den Parameter --help eine Hilfeseite ausgeben zu lassen. Dies geschieht wie auch bei der Geräte-Liste und den Fehler-Hinweisen mit wprintf_s.
Wenn ich das Programm aus C# mit dem Parameter --help aufrufe, funktioniert die Umleitung, ohne Parameter, mit absichtlich falscher Geräte-Nr. oder Parameter -a (zeigt alle Geräte, auch deaktivierte) jedoch geht es nicht. Der einzige Unterschied scheint mir zu sein, dass bei diesen Variablen mit in die Ausgabe geschrieben werden.
Über cmd funktioniert alles wie es soll
Bitte warten ..
Mitglied: 114757
23.12.2014, aktualisiert um 18:51 Uhr
Wenn du den C++ Quellcode hast warum setzt du dir das Prog nicht direkt in c# um, ohne den Umweg des Auslesens vom Standardout ??

Kompilierst du das Programm selber oder nimmst du immer nur ein bereits fertig kompiliertes Programm ? Ich schätze mal das Prog wurde nicht mit den richtigen Compiler-Schaltern kompiliert.

Meine Glaskugel hat leider schon Schicht und hängt am Christbaum, so dass ich hier leider keinen Quellcode aus ihr herzaubern kann
Bitte warten ..
Mitglied: 94erBrom
23.12.2014, aktualisiert um 19:48 Uhr
Ich habe vom C++ Programm sowohl die Projektdateien, sprich Quellcode, als auch eine fertig compilierte Release-Version.
Ich benutze die Version, die im Release-Verzeichnis des Projekts lag.
Die funktioniert auch auf der CMD ohne Probleme.

Was das umsetzen in C# angeht, muss ich gestehen, dass meine C++-Kenntnisse dafür nicht ausreichen. Mehr als einfache Grundlagen zu In- und Output sowie If, While, For, Arrays und Rechenoperationen kann ich in C++ nicht. Außerdem greift das Programm auf undokumentierte Systembibliotheken zu, was die Sache recht kompliziert macht.

Ich nehme fürchte, dass die Ausgabe auf den Console-Kanal (Also Kanal 3) läuft, und daher nicht umgeleitet wird.
Weiß aber nicht, ob das mit Visual C++ überhaupt geht

Der Quellcode des Hauptprogramms:

// EndPointController.cpp : Defines the entry point for the console application. 
// 
#include <stdio.h> 
#include <wchar.h> 
#include <tchar.h> 
#include <string> 
#include <iostream> 
#include "windows.h" 
#include "Mmdeviceapi.h" 
#include "PolicyConfig.h" 
#include "Propidl.h" 
#include "Functiondiscoverykeys_devpkey.h" 
 
// Format default string for outputing a device entry. The following parameters will be used in the following order: 
// Index, Device Friendly Name 
#define DEVICE_OUTPUT_FORMAT "Audio Device %d: %ws" 
 
typedef struct TGlobalState 
	HRESULT hr; 
	int option; 
	IMMDeviceEnumerator *pEnum; 
	IMMDeviceCollection *pDevices; 
	LPWSTR strDefaultDeviceID; 
	IMMDevice *pCurrentDevice; 
	LPCWSTR pDeviceFormatStr; 
	int deviceStateFilter; 
} TGlobalState; 
 
void createDeviceEnumerator(TGlobalState* state); 
void prepareDeviceEnumerator(TGlobalState* state); 
void enumerateOutputDevices(TGlobalState* state); 
HRESULT printDeviceInfo(IMMDevice* pDevice, int index, LPCWSTR outFormat, LPWSTR strDefaultDeviceID); 
std::wstring getDeviceProperty(IPropertyStore* pStore, const PROPERTYKEY key); 
HRESULT SetDefaultAudioPlaybackDevice(LPCWSTR devID); 
void invalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file,  
	unsigned int line, uintptr_t pReserved); 
 
// EndPointController.exe [NewDefaultDeviceID] 
int _tmain(int argc, LPCWSTR argv[]) 
	TGlobalState state; 
 
	// Process command line arguments 
	state.option = 0; // 0 indicates list devices. 
	state.strDefaultDeviceID = '\0'; 
	state.pDeviceFormatStr = _T(DEVICE_OUTPUT_FORMAT); 
	state.deviceStateFilter = DEVICE_STATE_ACTIVE; 
 
	for (int i = 1; i < argc; i++)  
		if (wcscmp(argv[i], _T("--help")) == 0) 
			wprintf_s(_T("Lists active audio end-point playback devices or sets default audio end-point\n")); 
			wprintf_s(_T("playback device.\n\n")); 
			wprintf_s(_T("USAGE\n")); 
			wprintf_s(_T("  EndPointController.exe [-a] [-f format_str]  Lists audio end-point playback\n")); 
			wprintf_s(_T("                                               devices that are enabled.\n")); 
			wprintf_s(_T("  EndPointController.exe device_index          Sets the default playvack device\n")); 
			wprintf_s(_T("                                               with the given index.\n")); 
			wprintf_s(_T("\n")); 
			wprintf_s(_T("OPTIONS\n")); 
			wprintf_s(_T("  -a             Display all devices, rather than just active devices.\n")); 
			wprintf_s(_T("  -f format_str  Outputs the details of each device using the given format\n")); 
			wprintf_s(_T("                 string. If this parameter is ommitted the format string\n")); 
			wprintf_s(_T("                 defaults to: \"%s\"\n\n"), _T(DEVICE_OUTPUT_FORMAT)); 
			wprintf_s(_T("                 Parameters that are passed to the 'printf' function are\n")); 
			wprintf_s(_T("                 ordered as follows:\n")); 
			wprintf_s(_T("                   - Device index (int)\n")); 
			wprintf_s(_T("                   - Device friendly name (wstring)\n")); 
			wprintf_s(_T("                   - Device state (int)\n")); 
			wprintf_s(_T("				     - Device default? (1 for true 0 for false as int)\n")); 
			wprintf_s(_T("                   - Device description (wstring)\n")); 
			wprintf_s(_T("                   - Device interface friendly name (wstring)\n")); 
			wprintf_s(_T("                   - Device ID (wstring)\n")); 
			exit(0); 
		else if (wcscmp(argv[i], _T("-a")) == 0) 
			state.deviceStateFilter = DEVICE_STATEMASK_ALL; 
			continue; 
		else if (wcscmp(argv[i], _T("-f")) == 0) 
			if ((argc - i) >= 2) { 
				state.pDeviceFormatStr = argv[++i]; 
				 
				// If printf is called with an invalid format string, jump to the invalidParameterHandler function. 
				_set_invalid_parameter_handler(invalidParameterHandler); 
				_CrtSetReportMode(_CRT_ASSERT, 0); 
				continue; 
			else 
				wprintf_s(_T("Missing format string")); 
				exit(1); 
	 
	if (argc == 2) state.option = _wtoi(argv[1]); 
 
	state.hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
	if (SUCCEEDED(state.hr)) 
		createDeviceEnumerator(&state); 
	return state.hr; 
 
// Create a multimedia device enumerator. 
void createDeviceEnumerator(TGlobalState* state) 
	state->pEnum = NULL; 
	state->hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), 
		(void**)&state->pEnum); 
	if (SUCCEEDED(state->hr)) 
		prepareDeviceEnumerator(state); 
 
// Prepare the device enumerator 
void prepareDeviceEnumerator(TGlobalState* state) 
	state->hr = state->pEnum->EnumAudioEndpoints(eRender, state->deviceStateFilter, &state->pDevices); 
	if SUCCEEDED(state->hr) 
		enumerateOutputDevices(state); 
	state->pEnum->Release(); 
 
// Enumerate the output devices 
void enumerateOutputDevices(TGlobalState* state) 
	UINT count; 
	state->pDevices->GetCount(&count); 
 
	// If option is less than 1, list devices 
	if (state->option < 1)  
 
		// Get default device 
		IMMDevice* pDefaultDevice; 
		state->hr = state->pEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDefaultDevice); 
		if (SUCCEEDED(state->hr)) 
			 
			state->hr = pDefaultDevice->GetId(&state->strDefaultDeviceID); 
 
			// Iterate all devices 
			for (int i = 1; i <= (int)count; i++) 
				state->hr = state->pDevices->Item(i - 1, &state->pCurrentDevice); 
				if (SUCCEEDED(state->hr)) 
					state->hr = printDeviceInfo(state->pCurrentDevice, i, state->pDeviceFormatStr, 
						state->strDefaultDeviceID); 
					state->pCurrentDevice->Release(); 
	// If option corresponds with the index of an audio device, set it to default 
	else if (state->option <= (int)count) 
		state->hr = state->pDevices->Item(state->option - 1, &state->pCurrentDevice); 
		if (SUCCEEDED(state->hr)) 
			LPWSTR strID = NULL; 
			state->hr = state->pCurrentDevice->GetId(&strID); 
			if (SUCCEEDED(state->hr)) 
				state->hr = SetDefaultAudioPlaybackDevice(strID); 
			state->pCurrentDevice->Release(); 
	// Otherwise inform user than option doesn't correspond with a device 
	else 
		wprintf_s(_T("Error: No audio end-point device with the index '%d'.\n"), state->option); 
	 
	state->pDevices->Release(); 
 
HRESULT printDeviceInfo(IMMDevice* pDevice, int index, LPCWSTR outFormat, LPWSTR strDefaultDeviceID) 
	// Device ID 
	LPWSTR strID = NULL; 
	HRESULT hr = pDevice->GetId(&strID); 
	if (!SUCCEEDED(hr)) 
		return hr; 
 
	int deviceDefault = (strDefaultDeviceID != '\0' && (wcscmp(strDefaultDeviceID, strID) == 0)); 
 
	// Device state 
	DWORD dwState; 
	hr = pDevice->GetState(&dwState); 
	if (!SUCCEEDED(hr)) 
		return hr; 
		 
	IPropertyStore *pStore; 
	hr = pDevice->OpenPropertyStore(STGM_READ, &pStore); 
	if (SUCCEEDED(hr)) 
		std::wstring friendlyName = getDeviceProperty(pStore, PKEY_Device_FriendlyName); 
		std::wstring Desc = getDeviceProperty(pStore, PKEY_Device_DeviceDesc); 
		std::wstring interfaceFriendlyName = getDeviceProperty(pStore, PKEY_DeviceInterface_FriendlyName); 
		 
		if (SUCCEEDED(hr)) 
			wprintf_s(outFormat, 
				index, 
				friendlyName.c_str(), 
				dwState, 
				deviceDefault, 
				Desc.c_str(), 
				interfaceFriendlyName.c_str(), 
				strID 
			); 
			wprintf_s(_T("\n")); 
 
		pStore->Release(); 
	return hr; 
 
std::wstring getDeviceProperty(IPropertyStore* pStore, const PROPERTYKEY key) 
	PROPVARIANT prop; 
	PropVariantInit(&prop); 
	HRESULT hr = pStore->GetValue(key, &prop); 
	if (SUCCEEDED(hr)) 
		std::wstring result (prop.pwszVal); 
		PropVariantClear(&prop); 
		return result; 
	else 
		return std::wstring (L""); 
 
HRESULT SetDefaultAudioPlaybackDevice(LPCWSTR devID) 
{	 
	IPolicyConfigVista *pPolicyConfig; 
	ERole reserved = eConsole; 
 
    HRESULT hr = CoCreateInstance(__uuidof(CPolicyConfigVistaClient),  
		NULL, CLSCTX_ALL, __uuidof(IPolicyConfigVista), (LPVOID *)&pPolicyConfig); 
	if (SUCCEEDED(hr)) 
		hr = pPolicyConfig->SetDefaultEndpoint(devID, reserved); 
		pPolicyConfig->Release(); 
	return hr; 
 
void invalidParameterHandler(const wchar_t* expression, 
   const wchar_t* function,  
   const wchar_t* file,  
   unsigned int line,  
   uintptr_t pReserved) 
   wprintf_s(_T("\nError: Invalid format_str.\n")); 
   exit(1); 
}
Bitte warten ..
Neuester Wissensbeitrag
Internet

Unbemerkt - Telekom Netzumschaltung!

(1)

Erfahrungsbericht von ashnod zum Thema Internet ...

Ähnliche Inhalte
Heiß diskutierte Inhalte
Switche und Hubs
Trunk für 2xCisco Switch. Wo liegt der Fehler? (15)

Frage von JayyyH zum Thema Switche und Hubs ...

DSL, VDSL
DSL-Signal bewerten (13)

Frage von SarekHL zum Thema DSL, VDSL ...

Backup
Clients als Server missbrauchen? (10)

Frage von 1410640014 zum Thema Backup ...