views:

13948

answers:

4

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?

A: 

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

Shiraz Bhaiji
The script is executed via a hosted desktop application (Citrix is involved). It does not run in the context of IIS, to my knowledge anyways.
Jason Alati
A: 

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.

Izzy
In my Active Directory utility class, I connect using a non-privileged account (can't change passwords, but can search on users). The name of the account and its encrypted password is stored in the app.config (or MyProgram.exe.config, rather). DirectoryEntry entry = new DirectoryEntry("LDAP://MyLDAP", "Non-Privileged Account", Decrypt("EncryptedPassword"), AuthenticationType.Secure);That's basically how I am connecting to AD. I then use a DirectorySearcher object with a filter for searching users. DirectorySearcher searcher = new DirectorySearcher(entry);
Jason Alati
In that case, I'm stumped. Have you done as Soonts suggests (below) and used Process Explorer to dig deeper?
Izzy
A: 

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.

Soonts
Thanks for the suggestion. I downloaded Process Explorer and found out that when running program via the VBScript, the Command Line and Current Directories were different. The latter in this case was some on mapped drive on the network used by the calling application. I'm not sure if that means I need to run my application from that directory or if I need to rethink my approach.
Jason Alati
A: 

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.

Jason Alati