模拟Windows 10服务

时间:2017-11-06 17:39:10

标签: c# visual-studio

以下是映射主驱动器和W驱动器的Windows服务。如果我在用户下执行代码,一切都很好。由于这是在本地系统下运行的服务,因此我使用模拟类来调用它。在为桌面上的驱动器创建快捷方式时,模拟可以很好地工作,但是它不会使用net use命令映射驱动器。我希望驱动器映射为非持久性。我在下面附上了我的完整代码以及模拟课程。有没有办法使用模拟在当前用户下映射这些非持久的驱动器?

namespace HdriveMapService2
{
public partial class Service1 : ServiceBase
{
    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {


        using (ImpersonationUtils.ImpersonateCurrentUser())


            //check if Hdrive exists

            if (!Directory.Exists(@"H:\"))

        {
            //ping Hdrive server

            try
            {   //find current domain controller
                using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                {

                    string controller = context.ConnectedServer;

                    //ping current domain controller
                    Ping ping = new Ping();
                    PingReply pingReply = ping.Send(controller);

                    if (pingReply.Status == IPStatus.Success)

                    {



                            try

                            {

                                    //get current username

                                    string username = Environment.UserName;

                                    Console.WriteLine(username);
                                    Console.ReadLine();

                                    //Lookup current username in AD

                                    DirectoryEntry myLdapConnection = createDirectoryEntry();
                                    DirectorySearcher search = new DirectorySearcher(myLdapConnection);
                                    search.Filter = "(cn=" + username + ")";


                                    //Search for User's Home Directory 

                                    string[] requiredProperties = new string[] { "homeDirectory" };
                                    foreach (String property in requiredProperties)
                                        search.PropertiesToLoad.Add(property);
                                    SearchResult result = search.FindOne();

                                    // If home directory info is not blank

                                    if (result != null)

                                    {


                                        //pass the homedirectory path into a variable

                                        string path = "";
                                        foreach (String property in requiredProperties)
                                            foreach (Object myCollection in result.Properties[property])
                                                path = (myCollection.ToString());


                                    //map Hdrive (non persistent map)




                                        //create a desktop shortcut to Hdrive

                                        var wsh = new IWshShell_Class();
                                        IWshRuntimeLibrary.IWshShortcut shortcut = wsh.CreateShortcut(
                                        Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\H Drive.lnk") as IWshRuntimeLibrary.IWshShortcut;
                                        shortcut.TargetPath = path;
                                        shortcut.Save();

                                        //map Wdrive (non persistent map)



                                        //create a desktop shortcut to Wdrive

                                        var wsh2 = new IWshShell_Class();
                                        IWshRuntimeLibrary.IWshShortcut shortcut2 = wsh2.CreateShortcut(
                                        Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\W Drive.lnk") as IWshRuntimeLibrary.IWshShortcut;
                                        shortcut2.TargetPath = @"\\path\path-groups";
                                        shortcut2.Save();

                                        System.Diagnostics.Process.Start("net.exe", "use /persistent:NO H: " + path);
                                        System.Diagnostics.Process.Start("net.exe", @"use /persistent:NO W: \\path\path-groups");

                                }

                                }

                            catch (Exception)

                            {
                                //do nothing
                            }
                    }
                }
            }

            catch (Exception)
            {
                //do nothing
            }
        }
  }


//Impersonation Class
public static class ImpersonationUtils
{
private const int SW_SHOW = 5;
private const int TOKEN_QUERY = 0x0008;
private const int TOKEN_DUPLICATE = 0x0002;
private const int TOKEN_ASSIGN_PRIMARY = 0x0001;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int STARTF_FORCEONFEEDBACK = 0x00000040;
private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
private const int TOKEN_IMPERSONATE = 0x0004;
private const int TOKEN_QUERY_SOURCE = 0x0010;
private const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
private const int TOKEN_ADJUST_GROUPS = 0x0040;
private const int TOKEN_ADJUST_DEFAULT = 0x0080;
private const int TOKEN_ADJUST_SESSIONID = 0x0100;
private const int STANDARD_RIGHTS_REQUIRED = 0x000F0000;
private const int TOKEN_ALL_ACCESS =
    STANDARD_RIGHTS_REQUIRED |
    TOKEN_ASSIGN_PRIMARY |
    TOKEN_DUPLICATE |
    TOKEN_IMPERSONATE |
    TOKEN_QUERY |
    TOKEN_QUERY_SOURCE |
    TOKEN_ADJUST_PRIVILEGES |
    TOKEN_ADJUST_GROUPS |
    TOKEN_ADJUST_DEFAULT |
    TOKEN_ADJUST_SESSIONID;

[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public int dwProcessId;
    public int dwThreadId;
}

[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_ATTRIBUTES
{
    public int nLength;
    public IntPtr lpSecurityDescriptor;
    public bool bInheritHandle;
}

[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
    public int cb;
    public string lpReserved;
    public string lpDesktop;
    public string lpTitle;
    public int dwX;
    public int dwY;
    public int dwXSize;
    public int dwYSize;
    public int dwXCountChars;
    public int dwYCountChars;
    public int dwFillAttribute;
    public int dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public IntPtr lpReserved2;
    public IntPtr hStdInput;
    public IntPtr hStdOutput;
    public IntPtr hStdError;
}

private enum SECURITY_IMPERSONATION_LEVEL
{
    SecurityAnonymous,
    SecurityIdentification,
    SecurityImpersonation,
    SecurityDelegation

}

private enum TOKEN_TYPE
{
    TokenPrimary = 1,
    TokenImpersonation
}

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
    IntPtr hToken,
    string lpApplicationName,
    string lpCommandLine,
    ref SECURITY_ATTRIBUTES lpProcessAttributes,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    bool bInheritHandles,
    int dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    ref STARTUPINFO lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool DuplicateTokenEx(
    IntPtr hExistingToken,
    int dwDesiredAccess,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    int ImpersonationLevel,
    int dwTokenType,
    ref IntPtr phNewToken);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
    IntPtr ProcessHandle,
    int DesiredAccess,
    ref IntPtr TokenHandle);

[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(
        ref IntPtr lpEnvironment,
        IntPtr hToken,
        bool bInherit);

[DllImport("userenv.dll", SetLastError = true)]
private static extern bool DestroyEnvironmentBlock(
        IntPtr lpEnvironment);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(
    IntPtr hObject);

private static void LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock, int sessionId)
{
    var pi = new PROCESS_INFORMATION();
    var saProcess = new SECURITY_ATTRIBUTES();
    var saThread = new SECURITY_ATTRIBUTES();
    saProcess.nLength = Marshal.SizeOf(saProcess);
    saThread.nLength = Marshal.SizeOf(saThread);

    var si = new STARTUPINFO();
    si.cb = Marshal.SizeOf(si);
    si.lpDesktop = @"WinSta0\Default";
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
    si.wShowWindow = SW_SHOW;

    if (!CreateProcessAsUser(
        token,
        null,
        cmdLine,
        ref saProcess,
        ref saThread,
        false,
        CREATE_UNICODE_ENVIRONMENT,
        envBlock,
        null,
        ref si,
        out pi))
    {
        throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateProcessAsUser failed");
    }
}

internal static void LaunchAsCurrentUser(Process process)
{
    throw new NotImplementedException();
}

internal static void LaunchAsCurrentUser(string v1, string v2)
{
    throw new NotImplementedException();
}

private static IDisposable Impersonate(IntPtr token)
{
    var identity = new WindowsIdentity(token);
    return identity.Impersonate();
}

private static IntPtr GetPrimaryToken(Process process)
{
    var token = IntPtr.Zero;
    var primaryToken = IntPtr.Zero;

    if (OpenProcessToken(process.Handle, TOKEN_DUPLICATE, ref token))
    {
        var sa = new SECURITY_ATTRIBUTES();
        sa.nLength = Marshal.SizeOf(sa);

        if (!DuplicateTokenEx(
            token,
            TOKEN_ALL_ACCESS,
            ref sa,
            (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
            (int)TOKEN_TYPE.TokenPrimary,
            ref primaryToken))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "DuplicateTokenEx failed");
        }

        CloseHandle(token);
    }
    else
    {
        throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed");
    }

    return primaryToken;
}

private static IntPtr GetEnvironmentBlock(IntPtr token)
{
    var envBlock = IntPtr.Zero;
    if (!CreateEnvironmentBlock(ref envBlock, token, false))
    {
        throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateEnvironmentBlock failed");
    }
    return envBlock;
}

public static void LaunchAsCurrentUser(string cmdLine)
{
    var process = Process.GetProcessesByName("explorer")[0];
    if (process != null)
    {
        var token = GetPrimaryToken(process);
        if (token != IntPtr.Zero)
        {
            var envBlock = GetEnvironmentBlock(token);
            if (envBlock != IntPtr.Zero)
            {
                LaunchProcessAsUser(cmdLine, token, envBlock, process.SessionId);
                if (!DestroyEnvironmentBlock(envBlock))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "DestroyEnvironmentBlock failed");
                }
            }

            CloseHandle(token);
        }
    }
}

public static IDisposable ImpersonateCurrentUser()
{
    var process = Process.GetProcessesByName("explorer")[0];
    if (process != null)
    {
        var token = GetPrimaryToken(process);
        if (token != IntPtr.Zero)
        {
            return Impersonate(token);
        }
    }

    throw new Exception("Could not find explorer.exe");
  }
}

2 个答案:

答案 0 :(得分:0)

  1. 您冒充当前的用户是什么?该服务是在本地系统下启动的,可能是在后台 - 当前用户是否为同一本地系统帐户?
  2. 要将UNC路径映射到驱动器,服务帐户(让我们说它的本地系统)需要对这些UNC共享的访问权限。它有吗?
  3. 我建议您添加一些调试跟踪,看看您的代码实际运行的帐户是什么,然后验证此帐户是否至少允许查看这些UNC路径/共享。

答案 1 :(得分:0)

我采取了不同的方法来解决问题。我将驱动器映射编译为可执行文件。用计时器建立了一个Windows服务。在服务设置项目中添加了可执行文件作为文件,并在模拟下进行了可执行的服务调用,并且一切正常。如果有人有任何问题或正在努力解决类似问题,这可能有所帮助。如果需要,我很乐意提供详细信息。

谢谢,