“A specified logon session does not exist. It may already have been terminated.” when trying to copy a file using WindowsIdentity.Impersonate

試著忘記壹切 提交于 2019-12-22 10:12:04

问题


I am trying to copy a file from sharepoint to a unc path. I am using the following code:

 var id = new WindowsIdentity("administrator@mysite.com");
 var p = new WindowsPrincipal(id);
 var wic = id.Impersonate();
 File.Move(oldName, newName);
 wic.Undo();

oldname is C:\test.txt newName is \\server\folder\test.txt

I am getting the error

A specified logon session does not exist. It may already have been terminated.

How do I go about removing this error OR copy a file from A to B(UNC path) using sharepoint.


回答1:


You are not actually getting a logon token to impersonate. You need to call the LogonUser API to get a valid logon token, which you can use to impersonate that user.

See this blog entry for example code in c# on impersonating a windows user. You can also see this KB article that also contains c# code (and a duplicatetoken call for issues with .net 1.0)




回答2:


The following class will allow you to access SMB shares via a user-name and password. I use it all the time when copying files to network shares in both windows-to-windows and windows-to-unix environments. The benefit here is that you do not need to be authenticate as the user. In essence, you can use credentials that are local only to the target machine.

class WNetConnection : IDisposable
{
    public readonly string RemoteShare;

    public WNetConnection( string remoteHost, string remoteUser, string remotePassword )
    {
        Uri loc;
        if( !Uri.TryCreate( remoteHost, UriKind.Absolute, out loc ) || loc.IsUnc == false )
            throw new ApplicationException( "Not a valid UNC path: " + remoteHost );

        string auth = loc.Host;
        string[] segments = loc.Segments;

        // expected format is '\\machine\share'
        this.RemoteShare = String.Format( @"\\{0}\{1}", auth, segments[1].Trim( '\\', '/' ) );

        this.Connect( remoteUser, remotePassword );
    }

    ~WNetConnection()
    {
        Disconnect();
    }

    public void Dispose()
    {
        Disconnect();
        GC.SuppressFinalize( this );
    }

    #region Win32 API...

    [StructLayout( LayoutKind.Sequential )]
    internal struct NETRESOURCE
    {
        public int dwScope;
        public int dwType;
        public int dwDisplayType;
        public int dwUsage;
        [MarshalAs( UnmanagedType.LPWStr )]
        public string lpLocalName;
        [MarshalAs( UnmanagedType.LPWStr )]
        public string lpRemoteName;
        [MarshalAs( UnmanagedType.LPWStr )]
        public string lpComment;
        [MarshalAs( UnmanagedType.LPWStr )]
        public string lpProvider;
    }

    [DllImport( "mpr.dll", EntryPoint = "WNetAddConnection2W", CharSet = System.Runtime.InteropServices.CharSet.Unicode )]
    private static extern int WNetAddConnection2( ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, Int32 dwFlags );

    [DllImport( "mpr.dll", EntryPoint = "WNetCancelConnectionW", CharSet = System.Runtime.InteropServices.CharSet.Unicode )]
    private static extern int WNetCancelConnection( string lpRemoteName, bool bForce );

    private const int RESOURCETYPE_ANY = 0x00000000;
    private const int RESOURCETYPE_DISK = 0x00000001;
    private const int CONNECT_INTERACTIVE = 0x00000008;
    private const int CONNECT_PROMPT = 0x00000010;
    private const int NO_ERROR = 0;

    void Connect( string remoteUser, string remotePassword )
    {
        NETRESOURCE ConnInf = new NETRESOURCE();
        ConnInf.dwScope = 0;
        ConnInf.dwType = RESOURCETYPE_DISK;
        ConnInf.dwDisplayType = 0;
        ConnInf.dwUsage = 0;
        ConnInf.lpRemoteName = this.RemoteShare;
        ConnInf.lpLocalName = null;
        ConnInf.lpComment = null;
        ConnInf.lpProvider = null;

        // user must be qualified 'authority\user'
        if( remoteUser.IndexOf( '\\' ) < 0 )
            remoteUser = String.Format( @"{0}\{1}", new Uri(RemoteShare).Host, remoteUser );

        int dwResult = WNetAddConnection2( ref ConnInf, remotePassword, remoteUser, 0 );
        if( NO_ERROR != dwResult )
            throw new Win32Exception( dwResult );
    }

    void Disconnect()
    {
        int dwResult = WNetCancelConnection( this.RemoteShare, true );
        if( NO_ERROR != dwResult )
            throw new Win32Exception( dwResult );
    }

    #endregion
}


来源:https://stackoverflow.com/questions/1363679/a-specified-logon-session-does-not-exist-it-may-already-have-been-terminated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!