Notifications
Clear all

[Closed] Problem with "custom" hiddenDosCommand

maybe VBScript can help… its works well for me and made hidden dos command compatible for older Max’s (below 9)

 ' task.vbs
Const strCommand = "CD C:\ & Dir > test.txt"
Dim oShell : Set oShell = WScript.CreateObject ("WSCript.shell")
Call oShell.Run("CMD /C " & strCommand, 0, True)
Set oShell = Nothing
 -- run it in MaxScript:
ShellLaunch "task.vbs" "" 

My experience with launching a process:

Many years ago I developed a ‘hidden’ version of the DosCommand plugin in order to get rid of the annoying dos box that appeared whenever I ran pipeline tools.

When .NET support arrived I dumped the plugin in favour of a synchronous System.Diagnostic.Process based solution. It was simple stuff: start a process, wait for it to complete, gather the redirected output and errors.

And it seemed to work just great.

…except every six months or so an artist would complain that a something referring to a ‘hidden dos command’ was crashing Max. The first thing I would do when I went to investigate was explain the difference between a ‘crash’ and a ‘hang’ as it always turned out that max was still running –it was just spinning in a loop waiting for a ‘hidden’ command to complete.

The second thing I’d do was verify that the machine in question had the latest version of “P4.exe”, the command line tool used to interact with the Perforce server. I always found that P4 was several versions out of date on the suspect machines – two to three years out of date was not unheard of! For me, updating the perforce tools was always the solution to a “HiddenDosCommand” that failed to return when accessing it. Once the artist had the latest version the deadlock went away. The problem was never with my command processing code, it was always the command!

Until the day came when a brand new machine with a perfectly up to date version of P4.exe deadlocked as well. I had to do the walk of shame back to my desk and look for a solution.

Depending on the query, P4.exe can send hundreds, even thousands of lines of information out to the stdout and stderr streams simultaneously. The wrapper functions that I had developed would submit changelists, reopen files in different changelists, create new changelists by reading from the standard input, and sending data back.

By switching to asynchronous processing of the output streams (in the manner I showed in my earlier post) I was able avoid the deadlocks I was encountering and ‘it just worked’. I still start a process, wait for it complete, then collect the results, but the way output gets handed under the covers is simply more robust.

For the record my first asynchronous efforts involved using AddEventHandler #OutputDataReceived and #ErrorDataReceived to add mxs output handler functions to stderr and stdout and avoid any embedded C# –but it never worked for me. I figured it was a threading issue of some sort with the callbacks as they entered back into maxscript land. Someone else may be able to get the AddEventHandler route to work, but I’d probably not trust it.

[…and before someone gets started, yes I know there are .NET tools for Perforce that access it through its API that would probably never have had this deadlock problem, but my solution was 100% mxs (still is, if you allow embedded C# ) and I was perhaps perversely proud of the fact that there was nothing extra to install into Max in order to query p4.]

.biddle

Interesing… i has not p4 and not met any problems with Max hiddenDosCommand,
so … can we draw a conclusion that this is just Perforce issue ?

1 Reply
(@norman3d)
Joined: 11 months ago

Posts: 0

nop definitely not a P4 issue only. I believe it has more to do with the fact that you are attempting to pass multiple strings to the command. And for whatever reason this seems to cause problems on some machines.

This would also not be an elegant solution. You could as well write bat files with the commands on-the-fly and then run the bat files through hiddenDosCommand, which in this case would work flawlessly. It’s only when the command needs multiple strings that stuff starts to break.

So yeah, just to sum it up, read biddle’s posts. Biddle’s code seems to be the only one that works so far 100% of the time.

Another thought… not that I have a reasonable explanation for this but have you tried running the hiddenDosCommand in a different thread using BackgroundWorker? Dunno… just a wild idea

hehe no problem. Nop, I haven’t tried it. It is also hard for me to test, since my PC is not one of the “mystery PCs” having the problem. But haavard does have the problem on his machine, perhaps he can test it for you.

Thanks for the reply. I’m sure Biddle done good work, just want to imagine if I needs his code.

But I not understand why you need bat files and hiddenDosCommand for VB. I send (one or multiple) DOS commands (in one go) with Run method using built-in WSH engine (Windows Scripting Host) and ‘execute’ my VB in Max with ShellLaunch.

About passing multiple strings to the command, am not sure, maybe you are right. I guess though the length of the strings maybe is more critical. (large directory paths for instance)

It’s not about who is right but to learn something (at least me)

yeah! I totally agree!
What I meant to say regarding the VB files, I’m not sure how that works exactly, it sounds like you need to have certain elements in your machine in order for it to work. And if you have to write a file and then launch it trough ShellLaunch you might as well just write the commands you want in a text file, rename to a bat file and run them through hiddenDosCommand. Since you won’t be passing any arguments to the “temp” bat file hiddenDosCommand will work properly with 3dsMax 9.

Yes perhaps it is the length of the string that is an issue.

Ok biddle, I’m having yet another problem with your DotNetProcessor. I tried PMing you but your inbox is full, so I’m just going to post it here in hopes that you read this. Perhaps others can help me out as well.

I’m using a tool called zipnote.exe by the same guys who did “maxzip.exe” (you can find it in 3dsMax root folder).
So zipnote allows me to “extract” and add comments to zip files. If you open a zip file with winrar, you’ll be able to see the comments on the right side.

So anyway, at one point in my script I extract the comments as a text file and attempt to add it back again. This would be the dos command for it:

zipnote.exe -w "theZipFile.zip" < "theComment.txt"

Now this is what I’m trying but does not seem to work:

theFile = getDir #userscripts + "\\GoMax.zip"
theCommentFile = getDir #userscripts + "\	est.txt"

theZipNote = getDir #userscripts + "\\zipnote.exe"

dnp = CreateDotNetProcessor()
dnp.execute theZipNote ("-w " + "\"" + theFile + "\"" + " < " + "\"" + theCommentFile + "\"") ""

I think the issue is with the arguments somehow. ZipNote is being executed, but the arguments are not passed correctly, the tool is telling me that I can only pick one zip file, which obviously does not make any sense. Perhaps some characters, (the quotes maybe?) are not being passed properly.

The ‘<’ in your sample command line would normally redirect input from a file, if we were actually running in a dos shell. The basic processor I showed passes data to the standard input of the exe using a string. You could go back and modify the C# processor code to read from a file, or you can read your comments in from the file and pass them along. This is probably a better option if you are writing out that comment file somewhere else in your code just so you can read it back here:

Something like:

theFile = (getdir #userscripts) + "\\GoMax.zip"
theCommentFile =  (getdir #userscripts) + "\	ext.txt"
theZipnote = (getdir #userscripts) + "\\zipnote.exe"

theArgs	= "-w \"" + theFile + "\""

-- Read the contents of the comment file into a string that can be passed as an argument.
stream = (dotnetobject "System.IO.StreamReader" theCommentFile)
theComments = stream.ReadToEnd()
stream.close()

dnp.execute theZipNote theArgs theComments

.biddle

Awesome! Thanks biddle!

Page 2 / 2