繁体   English   中英

如何从 c# 打开“Active Directory 用户和计算机”object 属性对话框?

[英]How to open the “Active Directory Users and Computers” object properties dialog from c#?

有没有办法从 c# 调用这个对话框?

活动目录对象属性

我跟踪了 api,但似乎没有一个调用调用了对话框。 Dsuiext.dll听起来很有希望,但我发现了一个 LDAP 浏览器。

Microsoft 示例提供了预期的结果。 您将 ADS 路径作为参数传递,它调用属性 window。

PropSheetHost.exe "LDAP://CN=user,DC=MyDomain,DC=MyTldDomain"

区分大小写很重要,因此“ldap://..”不起作用。 该代码绝对不是为了在终止之前被多次调用而设计的,因此它可能是使用 exe 而不进行类似更改的最佳方式:

ProcessStartInfo startInfo = new ProcessStartInfo();        
startInfo.FileName = @"PropSheetHost.exe";
startInfo.Arguments = @"LDAP://CN=user,DC=MyDomain,DC=MyTldDomain";
Process.Start(startInfo);

我写了一个包装器直接从 C# 调用它,并纠正了我发现的错误。 由于我已经将近 30 年没有编程 C,如果实现不正确,我将不胜感激。 所有更改都用//MW: ...进行解释和标记。 这在我的代码中有效,但是您一次只能打开一个 windows,并且需要在打开另一个 window 之前将其关闭。

入口点:

__declspec(dllexport) HRESULT __stdcall CallPropSheetHost(const char* ldapPath)
{
    TCHAR szTemp[MAX_ADSPATH_CHARS];
    LPWSTR pwszADsPath = NULL;
    HRESULT hr = E_FAIL; // MW: move before "if" and preset

    CoInitialize(NULL);

    {
        //MW: copy the parameter
        _tcsncpy_s(szTemp, ARRAYSIZE(szTemp), ldapPath, MAX_ADSPATH_CHARS - 1);
    }

    DWORD dwChars = lstrlen(szTemp) + 1;
    pwszADsPath = new WCHAR[dwChars];

    if (pwszADsPath)
    {
        HINSTANCE hInstance = NULL;
        HWND hwndConsole = GetConsoleWindow();
        if (hwndConsole)
        {
            hInstance = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hwndConsole, GWLP_HINSTANCE);
        }

        CPropSheetHost* pHost = new CPropSheetHost(hInstance);

        LocalToWideChar(pwszADsPath, dwChars, szTemp, dwChars);

        // Hold a reference count for the CPropSheetHost object.
        pHost->AddRef();

        hr = pHost->SetObject(pwszADsPath);
        if (FAILED(hr))
        {
            goto ExitMain;
        }

        //MW: My implmentation returns E_Fail when the registration fails
        hr = pHost->Run();
        if (FAILED(hr))
        {
            pHost->Release();
            goto ExitMain;
        }

        //Release the CPropSheetHost object. Other components may still hold a
        //reference to the object, so this cannot just be deleted here. Let
        //the object delete itself when all references are released.
        pHost->Release(); 
    }

ExitMain:
    if (pwszADsPath)
    {
        delete pwszADsPath;
        return hr; //MW: return th HRESULT
    }

    CoUninitialize();
    
    return hr; //MW: return th HRESULT
}

原始实现不会取消注册 class。 因此,当它被多次使用时它会失败。 这些是我在PropSheetHost.cpp中为了解决这个问题所做的更改。

//MW: new method
void CPropSheetHost::_UnregisterWndClass()
{ 
    UnregisterClass(m_szHiddenWindowClass, m_hInst);
}

//MW: added a HRESULT and calling of "_UnregisterWndClass"
HRESULT CPropSheetHost::Run()
{
    if (!m_spADObject.p)
    {
        return E_FAIL; //MW: added a return value
    }

    // Create the hidden window.
    m_hwndHidden = _CreateHiddenWindow();
    if (!m_hwndHidden)
    {
        return E_FAIL;  //MW: added a return value
    }

    /*
    Display the proeprty sheet. This is a modal call and will not return
    until the property sheet is dimissed.
    */
    _CreatePropertySheet();

    // Destroy the hidden window.
    DestroyWindow(m_hwndHidden);

    //WM: Unregister the class; this call was missing
    _UnregisterWndClass();

    return ERROR_SUCCESS;  //MW: added a return value
}

...以及来自 C# 的电话:

using System;
using System.Runtime.InteropServices;
using System.Windows;

const int MAX_ADSPATH_CHARS = 2047;

[DllImport("PropSheetHost.dll", EntryPoint = "CallPropSheetHost", CallingConvention = CallingConvention.Cdecl)]
private static extern int CallPropSheetHost(string ldapPath);

///CAUTION: 
///   * This call is modal and won't return until the called window is closed
///   * You can open only one window at a time. Trying opening a second window before closing the the first one fails
public static int Win32PropSheetHost(string distinguishedName, string serverOrDomain = null)
{
    if (string.IsNullOrEmpty(distinguishedName)) throw new ArgumentNullException("EXC262: the distinguished name must not be null nor empty");
    //<----------

    /// Caution: "LDAP" must be uppercase!
    string ldapPath = string.IsNullOrEmpty(serverOrDomain)
        ? $"LDAP://{ distinguishedName }"
        : $"LDAP://{ serverOrDomain }/{ distinguishedName }";


    if (ldapPath.Length > MAX_ADSPATH_CHARS) throw new ArgumentException($"EXC263: the complete lds path must not be longer than { MAX_ADSPATH_CHARS } characters (current path: \"{ ldapPath }\")");
    //<----------

    try
    {
        return CallPropSheetHost(ldapPath);
    }
    catch (DllNotFoundException ex)
    {
        /// Could't find a dll, mos likely our propsheethost.dll
        return ResultWin32.ERROR_DLL_NOT_FOUND;
    }
}

对于 Windows 错误代码的翻译,我使用此 class

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM