无法调用函数,未命中断点,- 无法从 mscorlib 加载程序集

Function cannot be called, no breakpoint hit, - could not load assembly from mscorlib

问题

我有一个方法,可以调用但永远不会执行。

调用 'CreateHomeDrive' 的行如下所示:

FileInterface.HomeDriveCreation.CreateHomeDrive("my_domain","admin_user","admin_pwd", document.UserName);

成功到达该行,相应的中断指针停止

应该到达但从未到达以下 Break 指针。
只有 1 个方法引用此函数:

public class HomeDriveCreation
{
    public static void CreateHomeDrive(string domainName, string adminUser, string adminPassword, string userNameToCreate)
        {
            {/*Break pint here is never reached!*/ }
            // method logic here...
        }
}

知道为什么永远无法达到此代码吗?中断指针位于函数的第一行,因此根据我的理解,应该始终到达此中断标记。

确实抛出了一个错误,这对我没有帮助:

One or more errors occurred. 
(Could not load type 'System.Security.Principal.WindowsImpersonationContext' 
from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, 
PublicKeyToken=/*private?*/'.)

项目结构

项目结构如下所示:

FileInterface 是一个 .net Framework class 库,
调用 FileInterface.HomeDriveCreation 的 JiraBackgroundTasks 是一个 .net core 3.5 class 库。

添加了对 System.Security 的引用

具体class应该叫什么

要调用的代码源自 Microsoft 模拟参考 https://docs.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.impersonate?redirectedfrom=MSDN&view=netframework-4.8#System_Security_Principal_WindowsIdentity_Impersonate_System_IntPtr_ 这是完整的 class:

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Security;
using System.IO;
using System.Security.AccessControl;

namespace FileInterface
{
    public class HomeDriveCreation
    {
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        // Test harness.
        // If you incorporate this code into a DLL, be sure to demand FullTrust.
        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public static void CreateHomeDrive(string domainName, string adminUser, string adminPassword, string userNameToCreate)
        {
            { }
            SafeTokenHandle safeTokenHandle;
            const int LOGON32_PROVIDER_DEFAULT = 0;
            //This parameter causes LogonUser to create a primary token.
            const int LOGON32_LOGON_INTERACTIVE = 2;

            // Call LogonUser to obtain a handle to an access token.
            bool returnValue = LogonUser(adminUser, domainName, adminPassword,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out safeTokenHandle);

            if (false == returnValue)
            {
                int ret = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(ret);
            }
            using (safeTokenHandle)
            {
                // Use the token handle returned by LogonUser.
                using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()))
                {
                    string path = $@"\server\Data\Home\{userNameToCreate}";
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                        AddDirectorySecurity(path, $@"{domainName}\{userNameToCreate}", FileSystemRights.ReadAndExecute, AccessControlType.Allow);
                        AddDirectorySecurity(path, $@"{domainName}\{userNameToCreate}", FileSystemRights.Write, AccessControlType.Allow);
                        AddDirectorySecurity(path, $@"{domainName}\{userNameToCreate}", FileSystemRights.DeleteSubdirectoriesAndFiles, AccessControlType.Allow);
                        AddDirectorySecurity(path, $@"{domainName}\{userNameToCreate}", FileSystemRights.FullControl, AccessControlType.Allow);
                    }
                }
                // Releasing the context object stops the impersonation
                // Check the identity.
            }
        }
        // Adds an ACL entry on the specified directory for the specified account.
        public static void AddDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
        {
            // Create a new DirectoryInfo object.
            DirectoryInfo dInfo = new DirectoryInfo(FileName);

            // Get a DirectorySecurity object that represents the
            // current security settings.
            DirectorySecurity dSecurity = dInfo.GetAccessControl();

            // Add the FileSystemAccessRule to the security settings.
            dSecurity.AddAccessRule(new FileSystemAccessRule(Account,
                                                            Rights,
                                                            ControlType));

            // Set the new access settings.
            dInfo.SetAccessControl(dSecurity);
        }
    }
    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        {
        }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}

WindowsImpersonationContext 特定于 .Net Framework。 请注意您发布的文章中的“适用于”部分。

对于 .Net Core,您可以使用 WindowsIdentity.RunImpersonated .

另见 SO: WindowsImpersonationContext & Impersonate() not found in ASP.Core

这种情况下的问题是模拟在 .net core 中的处理方式不同

尽管该项目是 .net 框架,Visual Studio 无法满足多框架目标解决方案的要求。

有关如何在 .net 核心中模拟的更多信息,请参见此处: https://docs.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.runimpersonated?view=net-5.0

至于模拟文件夹访问权限的具体任务,在这里找到了很好的答案: How to provide user name and password when connecting to a network share(来自 Luke Quinane 的回答)

请记住,当网络位置映射到 Windows 中的不同用户时,这将不起作用。在这种情况下,程序将在内部映射网络驱动器并在使用后对其进行处理。

实施他的 class 然后像这样使用它:

using (new NetworkConnection(@"\server\Data\Home", cred))
{
    string path = $@"\server\Data\Home\testuserfolder";
    string domainName = "domain.com";
    string userNameToCreate = "testuser";
    Directory.CreateDirectory(path);
    SetFullPermission(path, userNameToCreate);
}