Jump to content

Output Buffer in C++


premiso

Recommended Posts

Hello all,

 

The point of this message is I am learning C++ again by just simply creating a file and executing a script with popen. The issue I am having is when the vb script causes an error, the error is echo'ed to the console and not caught, I need to catch it so I can determine that there was an error and echo it out nicely, I just do not know what the function is to do this.

 

The code I am currently using is as follows:

 

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <unistd.h>

using namespace std;

int main() {
string networkPath = "badpath::f";
string letter;
int pos = 0;

pos = networkPath.find("::");
letter = networkPath.substr(pos + 2);
	networkPath = networkPath.substr(0, pos);
	networkPath = "\"\\\\" + networkPath + "\"";

	ofstream vbFile("test.vbs");
	vbFile << "Option Explicit" << endl << "Dim objNetwork" << endl;
	vbFile << "Set objNetwork = CreateObject(\"WScript.Network\")" << endl;
	vbFile << "objNetwork.MapNetworkDrive \"" << letter << "\", " << networkPath << endl; // intentional error
	vbFile << "WScript.Quit" << endl;
vbFile.close();

	size_t found;
	string line;
	char temp[500];
	FILE *fp = popen("cmd.exe /c cscript test.vbs", "r");

	pos = 0;
	while (fgets(temp, 500, fp) != NULL) {
	  line = static_cast<string>(temp);
	  found = line.find("WSHNetwork.");
//		  cout << "Line: " << line << endl << "Found: " << found << endl; 
	  if (found != string::npos) {
		     pos = 1;
	  	 break;	 		
	  } 
}

pclose(fp);

	remove("test.vbs");

	// always returns succesfull
	if (pos == 1) {
   cout << "There was an error mapping the drive." << endl;   		
}else {
   cout << "The drive mapped succesfully." << endl;	  
    }
    
    system("PAUSE");
    return 0;
}

 

Which outputs:

D:\c_proj\test.vbs(4, 1) WSHNetwork.MapNetworkDrive: The specified device name is invalid.

The drive mapped successfully.
Press any key to continue . . .

 

Which it obviously did not map, but aside from that if anyone knows or can point me in the right direction that would be awesome. Alternatively, I will continue my searches to find my solution.

 

Thanks.

 

Link to comment
Share on other sites

A rather ghetto way to do it would be:

 

system("command > tempfile.txt");

 

Then read the tempfile.txt contents.

 

It's horrendously ugly, but you're already writing a temporary VB file.

 

Ideally you want to grab a reference to the output and error stream of the program running, but apparently popen does not allow that.  It's actually kind of weird that popen just spits out the content if it's an error.  (I think what's going on is that the VB script is exiting with a code != 0, so popen is doing that...  Not sure though.)

 

 

This is the closest thing to useful I found while googling:

 

http://www.gamedev.net/community/forums/topic.asp?topic_id=440874&whichpage=1

 

Ohhh!  Perhaps this would be a way to go:

http://social.msdn.microsoft.com/Forums/en/windowssdk/thread/39144ece-dc37-4d5b-8c2c-a384034ffdc6

 

I would be worried about using a Windows API call, but if you're using VB script, you're already stuck on Windows, so I guess no problem with that.

 

The idea behind it is the same as popen except using CreateProcess and passing it pipes.

 

 

http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx

 

The LPSTARTUPINFO structure has properties called hStdInput and hStdOutput that are HANDLEs that I would assume can be used as stdin/stdout.

 

 

 

Well....  Not sure how useful this post has been or not haha.  Was just kind of curious since I tried to do this a few weeks ago, realized it wasn't as straight forward as I thought it would be, and gave up.

Link to comment
Share on other sites

Great info, thanks for that.

 

I read through it all and what I think I am going to do is attempt to implement an error catch in the VB script (I found a hack to do it with class) and see how that goes. If I can figure it out I will post some links on how to do that etc.  However, that createprocess may be what I am looking for. I guess the real deal is that it is not possible in C++ to do what I want, I just have to hack the script since VBScript is the one sending the error, I need to find a way to handle the error there.

 

I did not think it was possible because I have been trying this for the past 4 days and doing extensive research with a ton of trial and errors and yea. We will see in the days to come as I am determined to find a way :)

Link to comment
Share on other sites

Alright, well my solution is basically modifying the VBS file to do a clean error handle and output that, for now it will work just fine.

 

Here is the updated code:

 

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <stdio.h>

using namespace std;

int main() {
string networkPath = "badpath::f";
string letter;
int pos = 0;

pos = networkPath.find("::");
letter = networkPath.substr(pos + 2);
	networkPath = networkPath.substr(0, pos);
	networkPath = "\"\\\\" + networkPath + "\"";

	ofstream vbFile("test.vbs");
	vbFile << "On Error Resume Next" << endl << "Dim objNetwork" << endl;
	vbFile << "Set objNetwork = CreateObject(\"WScript.Network\")" << endl;
	vbFile << "objNetwork.MapNetworkDrive \"" << letter << ":\", " << networkPath << endl; // intentional error
	vbFile << "If Err.number <> 0 Then" << endl << "Wscript.Echo \"Error: \" & Err.Number" << endl << "End If" << endl;
	vbFile << "WScript.Quit" << endl;
vbFile.close();

	size_t found;
	string line;
	char temp[256];
	FILE *fp = popen("cmd.exe /c cscript test.vbs", "r");
while (fgets(temp, 256, fp) != NULL) {
	  line = static_cast<string>(temp);
	  found = line.find("Error:");
	  if (found != string::npos) {
 	    cout << "There was an error mapping the drive." << endl;   		
 	    break;
	  }
    }
pclose(fp);
	remove("test.vbs");

	// always returns succesfull

    
    system("PAUSE");
    return 0;
}

 

The gist of the VBS Error handling came from: http://technet.microsoft.com/en-us/library/ee692852.aspx#EHAA for anyone who is curious about that portion. Questions feel free to ask me as I will do my best to answer :)

Link to comment
Share on other sites

Ooo.....  I didn't think about modifying the source of the error instead of trying to catch it differently.  Nice.

 

 

As for C++ not being able to do it, capturing a spawned process's stdin/stdout/errout shouldn't be impossible by any means.  Seems to be a lot more difficult than I ever would have expected though haha.

Link to comment
Share on other sites

Yea, reminds me of something my first boss in a programming job said, "Handle errors where they are created."

 

I guess I should have just followed that. Now I can move on to more fun stuff and having people being able to add their own networks / edit and modify them! Then make it a GUI interface.

 

C++ is turning out to be fun now that I remember the little bits that you have to do, as PHP is way more lenient :) Either way thanks for the information Corbin, it got me on the right track.

Link to comment
Share on other sites

"I guess I should have just followed that. Now I can move on to more fun stuff and having people being able to add their own networks / edit and modify them! Then make it a GUI interface. "

 

 

Oooo sounds like a nifty little project.  I could never think of anything to do whenever I tried to get into C++ lol.  If you wanted to get really C++ with it, you could look do the drive mapping in C++ :)http://msdn.microsoft.com/en-us/library/aa385391(VS.85).aspx.

 

 

"C++ is turning out to be fun now that I remember the little bits that you have to do, as PHP is way more lenient"

 

Sometimes I love the strictness in C++/C/Java, so on, then other times I hate it with a passion.

 

 

Anyway, I don't think I helped much, but no problem haha.

Link to comment
Share on other sites

Interesting, yea using the wnetwork.h might be a better way to go, save me a bit of time. But the main thing I wanted to do was learn to work with files better, so yea. Once I get this done I will probably code the gui using the wnetwork.h.

 

As far as finding a project, yea that was why I never really got into C++, then at work I hate remembering my network servers and always having to map/unmap them all the time and finding that information. So I decided to create this application to manage them for me and give me the option to map / unmap them (unmap them because they slow the computer down if they stay mapped) and at work they disallow the NET command for security reasons, so yea.

 

Either way if I get it going should be great not having to go so slow cause of the network connections and being able to manage them with a click :)

Link to comment
Share on other sites

Hrmmm....  Mapped network drives should not slow down a computer x.x.  Then again, nothing makes sense in Windows.

 

 

The reason I found the WNet functions was because the other day I was looking for a way to write a program that would connect a disconnected network drive since I have a mapped drive to a backup USB drive on a networked computer, so I wrote a program that activates a mapped drive.  That was my latest little C++ project haha.  I fail at GUI stuff though.

Link to comment
Share on other sites

Hrmmm....  Mapped network drives should not slow down a computer x.x.  Then again, nothing makes sense in Windows.

 

Well consider mapping 5 different drives on different servers and the servers being in the following locations: Maryland, Colorado, California, Texas and Montana. Each site has a T1 line (yea T1). Now, imagine that one of these sites is randomly down and you try to open Windows Explorer....5 minutes later you are still trying to disconnect that damn drive to no avail.

 

This happens quite often due to a network outage somewhere or a server upgrade etc. and when it does I basically cannot work in windows till I get that drive disconnected, which this program would make it a lot easier to do, that and I only need them mapped when I need a file from them, so having them mapped all the time is just a waste. But yea, that WNet will probably be a bit cleaner then how I am doing it, but this is more just to learn about files and get a bit more in depth to C++

Link to comment
Share on other sites

Oooo didn't think about truly remote drives.  I wonder if disabling the option to browse for printers and what not would help. I don't remember what the option is called, but from what I understand, Windows has a weird habit of caching information about network drives and you can disable that.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.