VBScript: Using WScript.Shell to Execute a Command Line Program That Accesses Active Directory

StackOverflow https://stackoverflow.com/questions/1050293

  •  20-08-2019
  •  | 
  •  

Question

I'm attempting to execute a .NET (3.5) command line program from within a VBScript file which does two main things:

  • Connects to an Active Directory that is on the same domain as the server the script is hosted to retrieve an attribute value. I search AD using the first command line argument which is a username.
  • Creates a DTO using said attribute value and the second command line argument which is then used in a WCF service call.

When I run the application explicitly, everything works. Active Directory is accessed, the attribute is retrieved and the WCF service is called with the correct result (as verified by looking at the database).

(Edit: I apologize, I forgot to put what the actual issue was.)

When I run the script, it seems as though I can't access Active Directory in my .NET code (the MyProgram app).

The VBScript code:

Dim objResult

Set objShell = WScript.CreateObject("WScript.Shell")    
objResult = objShell.Run("MyProgram " & strUsername & " 0", 1, True) 

Does the WScript.Shell object need special permissions on the file? I've checked them and the Execute permission is there. Typically, the second argument I am passing to the .Run() method would be 6, I wanted it to be 1 for debugging.

Is there another way for me to execute a program in VBScript?

Was it helpful?

Solution 2

The issue turned out to be certificate-related. The WCF service called by the console app uses an X509 cert for authentication, which is installed on the servers that this script is hosted and run from.

On other servers, where the same services are consumed, the certificates were configured as follows:

winhttpcertcfg.exe -g -c LOCAL_MACHINE\My -s "certificate-name" -a "NETWORK SERVICE"

As they ran within the context of IIS. However, when the script was being run as it would in production, it's under the context of the user themselves. So, the script needed to be modified to the following:

winhttpcertcfg.exe -g -c LOCAL_MACHINE\My -s "certificate-name" -a "USERS"

Once that change was made, all was well. Thanks to everyone who offered assistance.

OTHER TIPS

This is not a reply (I cant post comments), just few random ideas might be helpful. Unfortunately I've never dealt with citrix, only with regular windows servers.

_0. Ensure you're not a victim of Windows Firewall, or any other personal firewall that selectively blocks processes.

Add 10 minutes Sleep() to the first line of your .NET app, then run both VBScript file and your stand-alone application, run sysinternals process explorer, and compare 2 processes.

_1. Same tab, "command line" and "current directory". Make sure they are the same.

_2. "Environment" tab. Make sure they are the same. Normally child processes inherit the environment, but this behaviour can be easily altered.

The following check is required if by "run my script" you mean anything else then double-clicking the .VBS file:

_3. Image tab, "User". If they differ - it may mean user has no access to the network (like localsystem), or user token restricted to delegation and thus can only access local resources (like in the case of IIS NTLM auth), or user has no access to some local files it wants.

When you run WScript.Shell it runs under the local system account, this account has full rights on the machine, but no rights in Active Directory.

http://support.microsoft.com/kb/278319

Taking Shiraz's idea and running with it...

In your application, are you explicitly defining a domain User Account and Password to access AD?

When you are executing the application explicitly it may be inherently using your credentials (your currently logged in domain account) to interrogate AD. However, when calling the application from the script, I'm not sure if the application is in the System context.

A VBScript example would be as follows:

  Dim objConnection As ADODB.Connection
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Properties("User ID") = "MyDomain\MyAccount"
    objConnection.Properties("Password") = "MyPassword"
    objConnection.Open "Active Directory Provider"

If this works, of course it would be best practice to create and use a service account specifically for this task, and to deny interactive login to that account.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top