tags:

views:

73

answers:

1

I have this service that, when request is received, runs a powershell command and returns result. Here is the invoker class code:

public class PowerShellScript {

    public PowerShellScript() {
    }

    public Object[] Invoke( String strScriptName, NameValueCollection nvcParams ) {
        Boolean bResult = true;
        int n = 0;
        Object[] objResult = null;
        PowerShell ps = PowerShell.Create();
        String strScript = strScriptName;

        for (n = 0; n < nvcParams.Count; n++) {
            strScript += String.Format( " -{0} {1}", nvcParams.GetKey( n ), nvcParams[n] );
        }

        //ps.AddScript( @"E:\snapins\Init-profile.ps1" );
        ps.AddScript( strScript );
        Collection<PSObject> colpsOutput = ps.Invoke();
        if (colpsOutput.Count > 0)
            objResult = new Object[colpsOutput.Count];

        n = 0;
        foreach (PSObject psOutput in colpsOutput) {
            if (psOutput != null) {
                try {
                    objResult[n] = psOutput.BaseObject;
                }
                catch (Exception ex) { 
                    //exception should be handeled properly in powershell script
                }
            }
            n++;
        }
        colpsOutput.Clear();
        ps.Dispose();

        return objResult;
    }
}

Method Invoke returns all results returned by powershell script. The problem though is that if the called script contains Write-Progress either in imported module or script itself, the Powershell class somehow believes that this is real output and completes script execution instantly, thus returning null as an object.

Ideally, one could block output with Out-Null cmdlet, but it doesn't work for Write-Progress. Any ideas as ot how to block Write-Progress?

+1  A: 

I tried your code and it worked in a trivial Console application and even in a Windows application with a simple script with some output and calls of Write-Progress. Thus, the problem is not that easy reproducible...

Powershell class somehow believes that this is real output and completes script execution instantly

Hmm, perhaps it just fails, not “treats output differently” and that is why the output is empty. Can you check the error collection after execution?

Any ideas as ot how to block Write-Progress?

If you are just about blocking it then this should work: before invoking your worker script invoke a “profile” script with this command installing a dummy replacement:

function global:Write-Progress {}

Thus, when your script calls Write-Progress then the dummy function Write-Progress is actually called and this in fact “blocks Write-Progress” effectively.

Roman Kuzmin
This script loads microsoft AD module. I don't get any erra, I just get empty output. Just remotely debugged it and experience same issues. Output collection is empty.
Vladimir Kocjancic
I just wanted to double check your script does not fail. Anyway, the proposed solution blocking Write-Progress should work for you.
Roman Kuzmin
not really :(Added the function prior calling import-module and progress bar is still displayed.
Vladimir Kocjancic
You mentioned “remotely” (in the comment above). Is Write-Progress called in a remote session? Then the dummy function should be installed in that session to replace the suspect Write-Progress cmdlet.Can you provide perhaps a little bit more information about the scenario you use? The scenario described so far works just fine (well, for me).
Roman Kuzmin
It was a bit awkward thing to say. This class is part of windows service running on a server. Also all PS scripts are on the same server. So, by saying remotely, I just wanted to say that I also wrote a test program that I can debug remotely using VS on that server. Just to check if everythig works ok.
Vladimir Kocjancic
Still same issue. Everything works great, if script doesn't use Write-Progress.
Vladimir Kocjancic