首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Process.Start()在模拟之后抛出“拒绝访问”

Process.Start()在模拟之后抛出“拒绝访问”
EN

Stack Overflow用户
提问于 2013-05-29 05:11:48
回答 1查看 5.5K关注 0票数 0

我在使用Process.Start() +模拟从文件服务器执行文件时遇到了问题。请帮我解决我的问题。还有别的办法吗?

这是按钮单击事件。

代码语言:javascript
复制
private void btnOpen_Click(object sender, EventArgs e)
    {
        try
        {
            newUser = cls.ImpersonateUser("username", "domain", "password");

            string fileName = @"\\network_computer\Test\Test.doc";

            System.Diagnostics.Process.Start(fileName);
        }
        catch (Exception ex) { throw ex; }
        finally
        {
            if (newUser != null)
                newUser.Undo();
        }
    }

这是模拟类。

代码语言:javascript
复制
public class clsImpersonate
    {
        #region 'Impersonation'

        // group type enum
        public enum SECURITY_IMPERSONATION_LEVEL : int
        {
            SecurityAnonymous = 0,
            SecurityIdentification = 1,
            SecurityImpersonation = 2,
            SecurityDelegation = 3
        }

        // obtains user token
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
            int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        // closes open handes returned by LogonUser
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        // creates duplicate token handle
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
            int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

        private System.Security.Principal.WindowsImpersonationContext newUser;

        public WindowsImpersonationContext ImpersonateUser(string sUsername, string sDomain, string sPassword)
        {
            // initialize tokens
            IntPtr pExistingTokenHandle = new IntPtr(0);
            IntPtr pDuplicateTokenHandle = new IntPtr(0);
            pExistingTokenHandle = IntPtr.Zero;
            pDuplicateTokenHandle = IntPtr.Zero;

            // if domain name was blank, assume local machine
            if (sDomain == "")
                sDomain = System.Environment.MachineName;

            try
            {
                string sResult = null;

                const int LOGON32_PROVIDER_DEFAULT = 0;

                // create token
                const int LOGON32_LOGON_INTERACTIVE = 2;
                //const int SecurityImpersonation = 2;

                // get handle to token
                bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);

                // did impersonation fail?
                if (false == bImpersonated)
                {
                    int nErrorCode = Marshal.GetLastWin32Error();
                    sResult = "LogonUser() failed with error code: " + nErrorCode + "\r\n";

                    // show the reason why LogonUser failed
                    //MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                // Get identity before impersonation
                sResult += "Before impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";

                bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);

                // did DuplicateToken fail?
                if (false == bRetVal)
                {
                    int nErrorCode = Marshal.GetLastWin32Error();
                    CloseHandle(pExistingTokenHandle); // close existing handle
                    sResult += "DuplicateToken() failed with error code: " + nErrorCode + "\r\n";

                    // show the reason why DuplicateToken failed
                    //MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return null;
                }
                else
                {
                    // create new identity using new primary token
                    WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle);
                    WindowsImpersonationContext impersonatedUser = newId.Impersonate();

                    // check the identity after impersonation
                    sResult += "After impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";

                    //MessageBox.Show(sResult, "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return impersonatedUser;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                // close handle(s)
                if (pExistingTokenHandle != IntPtr.Zero)
                    CloseHandle(pExistingTokenHandle);
                if (pDuplicateTokenHandle != IntPtr.Zero)
                    CloseHandle(pDuplicateTokenHandle);
            }
        }

        #endregion
    }
EN

回答 1

Stack Overflow用户

发布于 2013-05-29 06:47:01

如果您调试,是否在

代码语言:javascript
复制
bool bImpersonated = LogonUser(sUsername, sDomain, sPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);

或在

代码语言:javascript
复制
bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);

在您的按钮单击事件中,尝试添加一个Using语句:

代码语言:javascript
复制
private void btnOpen_Click(object sender, EventArgs e)
{
    try
    {
        using (newUser = cls.ImpersonateUser("username", "domain", "password"))
        {
            string fileName = @"\\network_computer\Test\Test.doc";
            System.Diagnostics.Process.Start(fileName);
        }
    }
    catch (Exception ex) { throw ex; }
    finally
    {
        if (newUser != null)
            newUser.Undo();
    }
}

应答更新(#01):

尝试以下代码:

代码语言:javascript
复制
public class clsImpersonate
{
    #region 'Impersonation'

    // obtains user token
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

    // closes open handes returned by LogonUser
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public extern static bool CloseHandle(IntPtr handle);

    public IntPtr ImpersonateUser(string sUsername, string sDomain, string sPassword)
    {
        // initialize token
        IntPtr pExistingTokenHandle = new IntPtr(0);

        // if domain name was blank, assume local machine
        if (sDomain == "")
            sDomain = System.Environment.MachineName;

        try
        {
            string sResult = null;

            const int LOGON32_PROVIDER_DEFAULT = 0;

            // create token
            const int LOGON32_LOGON_INTERACTIVE = 2;

            // get handle to token
            bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);

            // did impersonation fail?
            if (false == bImpersonated)
            {
                int nErrorCode = Marshal.GetLastWin32Error();
                sResult = "LogonUser() failed with error code: " + nErrorCode + "\r\n";

                // show the reason why LogonUser failed
                //MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            // Get identity before impersonation
            sResult += "Before impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";

            return pExistingTokenHandle;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public bool FreeImpersonationResource(IntPtr _token)
    {
        // close handle(s)
        if (_token != IntPtr.Zero)
            return CloseHandle(_token);
        else return true;
    }

    #endregion
}

然后,单击事件按钮:

代码语言:javascript
复制
private void btnOpen_Click(object sender, EventArgs e)
    {
        try
        {
            IntPtr token = cls.ImpersonateUser("username", "domain", "password");

            using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(token))
            {
                string fileName = @"\\network_computer\Test\Test.doc";
                System.Diagnostics.Process.Start(fileName);
            }

            cls.FreeImpersonationResource(token);
        }
        catch (Exception ex) { throw ex; }
    }

注意:

  • 如果在LOGON32_LOGON_INTERACTIVE函数中使用LogonUser,则不需要复制令牌,因为您获得的句柄是一个可以立即使用的主令牌。(看看此MSDN页面)。
  • 如果您对模拟上下文使用using语句,则不需要Undo,因为它在using的末尾“自动撤消”。
  • 如果它仍然不能工作,尝试使用服务器的IP地址而不是它的域名。
  • 如果它仍然不起作用,我建议的最后一件事是获取原始代码并将整个方法ImpersonateUser移动到单击按钮事件中,然后在指令System.Diagnostics.Process.Start(fileName);之后立即执行原始指令System.Diagnostics.Process.Start(fileName);

我希望这个答案至少有一定的帮助:)

更新(#02)

我自己已经试过了,它正在工作,使用了我以前编辑的代码,并做了以下修改:

  • 在类clsImpersonate中,必须将LogonUser函数的类型更改为LOGON32_LOGON_NEW_CREDENTIALS: //创建令牌const int LOGON32_LOGON_INTERACTIVE = 2;const int LOGON32_LOGON_NEW_CREDENTIALS = 9;// get句柄to token bool bImpersonated = LogonUser(sUsername、sDomain、sPassword、LOGON32_LOGON_NEW_CREDENTIALS、LOGON32_PROVIDER_DEFAULT、ref pExistingTokenHandle);
  • 在单击事件按钮内,您必须改变使用Process.Start()的方式。还可以查看此链接中关于Process.Start功能的一些示例 私有void button1_Click(对象发送方,EventArgs e) { IntPtr令牌=cls.ImpersonateUser(“用户名”、“域”、“密码”);使用(WindowsImpersonationContext impersonatedUser =WindowsIdentity.Impersonate(令牌)){ string fileName = @"Winword.exe";//您将用于打开文件的sw的名称,我认为MS字串参数= @"\network_computer\Test\Test.doc";//要打开进程进程=新进程();ProcessStartInfo info =新ProcessStartInfo();info.FileName = fileName;info.Arguments =参数;process.StartInfo = info;process.Start();}cls.FreeImpersonationResource(令牌);} catch (异常ex) {抛出ex;}}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16805952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档