/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Update-TypeData (Democracy to the types) "," MSH directory watcher with popup-balloon "," StartRDP script "," convert images in MSH "," Style Problems "," ColorCoding MSH scripts on blog "," GUI folder copy tool "," MSHObjectViewer mentioned in More talking about Mo... "," MSH registry access "," Unix => MSH Translations: find and grep "," ")

Saturday, October 22, 2005

 


MSH access NT provider



I started this afer reading a post from Alex K. Angelopoulos (MVP)
in m.p.w.s.scripting

MSH: Accessing ADSI interfaces and Q on WinNT Provider

He concluded getting the NT provider from MSH is not possible.
you can connect to AD LDAP:// GC://, but not the NT provider :

this will all fail :

$entryPC = New-object System.DirectoryServices.DirectoryEntry
$entryPC.set_Path = "WinNT:\\."
$entryPC.mshbase.Path = "WinNT:\\."
$entryPC.path = "WinNT:\\."
$entryPC.get_path()

Strange thing is that if you do the same thing from .NET it WILL work.
(code below will show this:)

I used the Microsoft.VisualBasic.VBCodeProvider to compile
some inline VB.NET code on the fly and return the object back to MSH.

and if you pass back the created object to MSH it will work.

so after running this code, you can do things like this :
MSH C:\> $r.get_path()
WinNT://.

MSH C:\> $r.get_children() foreach {$_.name} select -first 5
ACTUser
Administrator
ASPNET
ASWM USER
Guest

MSH C:\> $r.get_path()

WinNT://.

MSH C:\> $r.set_path("WinNT://./administrators,group")
MSH C:\> $r.get_path()

WinNT://./administrators,group

so far so good.

but then :
Now I did want the members of the Group. hmm, because we still have the .NET wrapper (DirectoryEntry) around the WinNT provider I didn't see the Members .

but I can call Invoke and I get the Members Back (as Com Object)
$r.Invoke("members")

MSH C:\> $r.Invoke("members").getType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------True False __ComObject System.MarshalByR...

I can't do anything with it again ;-(


so I got to the winFX SDK-dir and imported the TypeLib :
F:\Data\PrepRoom>tlbimp c:\windows\system32\activeds.tlb /out:activedsNET.dll /namespace:ActiveDS

and loaded it into MSH [System.Reflection.Assembly]::LoadFile("g:\monad\activeDSnet.dll") GAC Version Location
--- ------- --------
False v2.0.50215 g:\monad\activeDSnet.dll

MSH C:\> [System.DirectoryServices.DirectoryEntry]$m = $r.Invoke("Members")
Cannot convert "System.__ComObject" to "System.DirectoryServices.DirectoryEntry". Error: "The value provided for adsObject does not implement IADs.".At line:1 char:44+ [System.DirectoryServices.DirectoryEntry]$m <<<< = $r.Invoke("Members")

MSH C:\> [ActiveDS.IADsMembers]$m = $r.Invoke("Members")
Cannot convert "System.__ComObject" to "ActiveDS.IADsMembers".At line:1 char:25+ [ActiveDS.IADsMembers]$m <<<< = $r.Invoke("Members")

Ofcourse it does work in the @' VD.NET block

'@. (dim group as ActiveDS.IADsGroup = entryPC.nativeobject)

PS 2 returning the ActiveDS.IADsGroup,TLB loaded also in MSH). gives this fine red error, and the shell will exit ( but the message is fair enough (only why quit the shell)

MSH G:\> $r gm An error has occurred that was not properly handled. Additional information is shown below. The command shell will exit. Unhandled Exception: System.Runtime.InteropServices.InvalidComObjectException: C OM object that has been separated from its underlying RCW cannot be used. .............. .............

so we need a way to bind the RCW in MSH,
anyone some Idees ?

anyway you still can do alot of things from the current workaraund :
start stop services, get local SID's etc. on the Winnt: provider.

only if you get an IADs object back it will not work.

for the rest I like the Way I can put the "VB.NET code online, ofcourse if you implemt this i na function you can better complile the DLL but this is nice for testing.

gr /\/\o\/\/
cls
$provider = new-object Microsoft.VisualBasic.VBCodeProvider
$params = new-object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","Microsoft.VisualBasic.dll","System.Data.DLL","System.management.dll","System.DirectoryServices.dll"
$params.ReferencedAssemblies.AddRange($refs)

# VB.NET EXAMPLE
$txtCode = @'

imports system
Class mow
function main() as System.DirectoryServices.DirectoryEntry

Dim entryPC As New System.DirectoryServices.DirectoryEntry
entryPC.Path = "WinNT://."
return entryPC
end function

end class

'@

$results = $provider.CompileAssemblyFromSource($params, $txtCode)
$mAssembly = $results.CompiledAssembly
$i = $mAssembly.CreateInstance("mow")
$r = $i.main()



Comments: Post a Comment

Links to this post:

Create a Link



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?