| Profilo di ArildRandom thoughts about An...BlogElenchi | Guida |
|
24 luglio Powershell can’t do arbitrary-signature delegates?I was asked the other day how to handle authentication in NSvn with Powershell. The scripts I’ve shown up until now([1], [2] have used the NSvn.Core.AuthenticationProvider.GetWindowsSimpleProvider() method to provide authentication when required by Subversion. Subversion uses a concept of “authentication providers” to handle the various forms of authentication it supports (querying the user for the password, SSL etc). GetWindowsSimpleProvider() returns an authentication provider that uses cached authentication info stored in the %APPDATA%\Subversion\auth directory on the user’s computer. It differs from the GetSimpleProvider() method in that the provider returned can handle authentication information that has been encrypted with the Windows Crypto API.
The problem with using only GetWindowsSimpleProvider() (or GetSimpleProvider()) is that it won’t work unless there is some authentication information already cached. In other words, you would have to access the repository in question using another Subversion client before you are able to use any of these scripts as written (if the repository actually demands authentication for the operations you perform, that is). To actually be able to query the user for authentication requires the provider returned by GetSimplePromptProvider(). GetSimplePromptProvider() has the following signature:
AuthenticationProvider GetSimplePromptProvider( SimplePromptDelegate promptDelegate, int retryLimit );
SimplePromptDelegate again is a callback used by Subversion to actually query the user for username and password. It has the following signature:
delegate SimpleCredential SimplePromptDelegate( String realm, String username, bool maySave );
I assumed that calling GetSimplePromptProvider() from Powershell would be a simple task; merely cast a scriptblock to[NSvn.Core.SimplePromptDelegate]. Alas, no such luck:
PS D:\mydocs\powershell> $del = [NSvn.Core.SimplePromptDelegate] { param($realm, $username, $maySave) $null }
Cannot convert value "param($realm, $username, $maySave) $null " to type "NSvn.Core.SimplePromptDelegate".
Error: "Error binding to target method."
At line:1 char:40
+ $del = [NSvn.Core.SimplePromptDelegate] <<<< { param($realm, $username, $maySave) $null }
After trying a couple of variants on this (including trying to cast a named function), I broke out Reflector see how Powershell actually creates this delegate. It turns out that Powershell is calling Delegate.CreateDelegate using a MethodInfo object that points to the following method:
private void invokeAsDelegate(object sender, object e)
As you can see, this method takes two arguments and has a void return type. It can obviously never match the signature of SimplePromptDelegate, which takes three arguments and returns a SimpleCredential object. This causes Delegate.CreateDelegate to throw an exception which gets passed up through the Powershell call chain and results in the error message shown.
Am I missing something here? Is there really no way to create such a delegate from a Powershell script block? Is there a way to do this with a named function?
This is not an insurmountable technical problem to solve. An approach similar to what I did with DynamicMethod
here would probably work.
Commenti (33)Per aggiungere un commento, accedi con il tuo Windows Live ID (se utilizzi Hotmail, Messenger o Xbox LIVE possiedi già un Windows Live ID). Accedi Non hai ancora un Windows Live ID? Registrati
Riferimenti (1)L'URL di riferimento per questo intervento è: http://arildf.spaces.live.com/blog/cns!E99F8B43533149B0!140.trak Blog che fanno riferimento a questo intervento
|
|
|