2016-06-26 11 views
3

I Anmeldeinformationen in Active-Directory-Objekt-Picker (IDsObjectPicker) auf C# gesetzt haben. Aber ich kann nicht zwingen, die IDsObjectPickerCredentials zu arbeiten. Ich habe das gleiche auf C++ gemacht (msdn example) und es funktioniert gut.C# IDsObjectPickerCredentials scheitern

Ich habe „Header“ von hier ComInterop.cs and StructsFlags.cs

Bitte sagen Sie mir, was ich falsch mache. Wie Aufruf IDsObjectPickerCredentials.SetCredentials

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using Tulpep.ActiveDirectoryObjectPicker; 

namespace cred 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string szTargetComputer = @"10.0.9.115"; 
      string szUser = @"TST\test"; 
      string szPassword = @"123qazWSX"; 

      DSObjectPicker picker = new DSObjectPicker(); 
      IDsObjectPicker ipicker = (IDsObjectPicker)picker; 

      int res = InitObjectPicker(ipicker, szTargetComputer); 

      if (res == (int)HRESULT.S_OK) 
      { 
       try 
       { 
        // !!! HERE !!! 
        IDsObjectPickerCredentials cred = (ipicker as IDsObjectPickerCredentials); 
        res = cred.SetCredentials(szUser, szPassword); 

        // c++ like variant 
        // res = InitCredentials(ipicker, szUser, szPassword); 

        if (res != (int)HRESULT.S_OK) Console.WriteLine("SetCredentials Fail : 0x{0}", res.ToString("X4")); // On Win32 I get 0x80070057 - looks like E_INVALIDARG 

        IntPtr hwndParent = Process.GetCurrentProcess().MainWindowHandle; 
        IDataObject dataObj = null; 
        int hresult = ipicker.InvokeDialog(hwndParent, out dataObj); 

        Console.WriteLine(hresult == (int)HRESULT.S_OK ? "OK" : "Cancel"); 
        Console.ReadKey(); 
       } 
       finally 
       { 
        Marshal.ReleaseComObject(ipicker); 
       } 
      } 
     } 


     [ComImport, Guid("E2D3EC9B-D041-445A-8F16-4748DE8FB1CF"), 
      InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
     internal interface IDsObjectPickerCredentials 
     { 
      [PreserveSig()] 
      int SetCredentials(
       [In, MarshalAs(UnmanagedType.LPWStr)] string szUserName, 
       [In, MarshalAs(UnmanagedType.LPWStr)] string szPassword); 
     } 

     static int InitObjectPicker(IDsObjectPicker ipicker, string szTargetComputer) 
     {   
      int res = (int)HRESULT.S_FALSE; 

      DSOP_SCOPE_INIT_INFO[] aScopeInit = new DSOP_SCOPE_INIT_INFO[1]; 

      DSOP_INIT_INFO InitInfo = new DSOP_INIT_INFO(); 

      aScopeInit[0].cbSize = (uint)Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO)); 

      aScopeInit[0].flType = 
       DSOP_SCOPE_TYPE_FLAGS.DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | 
       DSOP_SCOPE_TYPE_FLAGS.DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN; 

      aScopeInit[0].FilterFlags.Uplevel.flBothModes = 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_COMPUTERS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_USERS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_WELL_KNOWN_PRINCIPALS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_BUILTIN_GROUPS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_WELL_KNOWN_PRINCIPALS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_INCLUDE_ADVANCED_VIEW; 

      aScopeInit[0].FilterFlags.flDownlevel = 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_COMPUTERS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_USERS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_WELL_KNOWN_PRINCIPALS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_BUILTIN_GROUPS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_WELL_KNOWN_PRINCIPALS | 
       DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_INCLUDE_ADVANCED_VIEW; 

      IntPtr refScopeInitInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO)) * aScopeInit.Length); 
      try 
      { 
       // Marshal structs to pointers 
       for (int index = 0; index < aScopeInit.Length; index++) 
       { 
        Marshal.StructureToPtr(aScopeInit[index], (IntPtr)((int)refScopeInitInfo + index * Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO))), false); 
       } 

       InitInfo.cbSize = (uint)Marshal.SizeOf(typeof(DSOP_INIT_INFO)); 
       InitInfo.cDsScopeInfos = (uint)aScopeInit.Length; //sizeof(aScopeInit)/sizeof(DSOP_SCOPE_INIT_INFO); 
       InitInfo.aDsScopeInfos = refScopeInitInfo; 
       InitInfo.flOptions = DSOP_INIT_INFO_FLAGS.DSOP_FLAG_MULTISELECT; 
       InitInfo.pwzTargetComputer = szTargetComputer; 

       res = ipicker.Initialize(ref InitInfo); 
      } 
      finally 
      { 
       Marshal.FreeHGlobal(refScopeInitInfo); 
      } 

      return res; 
     } 

     static int InitCredentials(IDsObjectPicker ipicker, string User, string Password) 
     { 
      IntPtr ptr = IntPtr.Zero; 

      Guid IID_IDsObjectPickerCredentials = new Guid("E2D3EC9B-D041-445A-8F16-4748DE8FB1CF"); 

      IntPtr pIUnk = Marshal.GetIUnknownForObject(ipicker);   

      int hr = Marshal.QueryInterface(pIUnk, ref IID_IDsObjectPickerCredentials, out ptr); 

      if (hr == HRESULT.S_OK) 
      { 
       try 
       { 
        IDsObjectPickerCredentials cred = (IDsObjectPickerCredentials)Marshal.GetObjectForIUnknown(ptr); 

        hr = cred.SetCredentials(User, Password); 
        if (hr != HRESULT.S_OK) 
        { 
         System.Diagnostics.Debugger.Break(); // Fail 
         return (int)HRESULT.S_FALSE; 
        } 
       } 
       catch (Exception ex) 
       { 
        return (int)HRESULT.S_FALSE; 
       } 
       finally 
       { 
        Marshal.Release(ptr); 
       } 
      } 
      return (int)HRESULT.S_OK; 
     } 
    } 
} 

Antwort

1

Die IDsObjectPickerCredentials Schnittstelle aus dem IDsObjectPicker ableitet. Ihr Beispiel ruft die Methode Initialize mit einem Benutzernamen und einem Kennwort anstelle von SetCredentials auf.

Hier ist eine richtige Erklärung ist:

[ComImport, Guid("e2d3ec9b-d041-445a-8f16-4748de8fb1cf"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
interface IDsObjectPickerCredentials 
{ 
    [PreserveSig] 
    int Initialize(ref DSOP_INIT_INFO pInitInfo); 
    [PreserveSig] 
    int InvokeDialog(IntPtr HWND, out IDataObject lpDataObject); 
    [PreserveSig] 
    int SetCredentials(string userName, string password); 
} 

Bitte beachten Sie, dass an Stelle von den IDsObjectPicker abzuleiten, repliziert der Code seine Methoden, in der gleichen Reihenfolge. Dies ist für .NET COM Interop erforderlich.

Sie brauchen dieses Handbuch nicht QueryInterface/Release Anrufe, var cred = (IDsObjectPickerCredentials)iobjectpicker; ist genug.

Auch ich fand, dass die SetCredentials vor der Initialize Methode aufgerufen werden sollte.

+0

Danke Paul. 100% richtig. Ich habe getestet - SetCredentials funktioniert in beiden Fällen ok: vor und nach dem Initialisieren. (x86 | x64) –